| 1 | import 'dart:convert'; |
| 2 | import 'package:bitcoin_base/bitcoin_base.dart'; |
| 3 | import 'package:cw_bitcoin/bitcoin_address_record.dart'; |
| 4 | import 'package:cw_bitcoin/electrum_balance.dart'; |
| 5 | import 'package:cw_core/amount/money.dart'; |
| 6 | import 'package:cw_core/currency_for_wallet_type.dart'; |
| 7 | import 'package:cw_core/encryption_file_utils.dart'; |
| 8 | import 'package:cw_bitcoin/electrum_derivations.dart'; |
| 9 | import 'package:cw_core/pathForWallet.dart'; |
| 10 | import 'package:cw_core/wallet_info.dart'; |
| 11 | import 'package:cw_core/wallet_type.dart'; |
| 12 | |
| 13 | class ElectrumWalletSnapshot { |
| 14 | ElectrumWalletSnapshot({ |
| 15 | required this.name, |
| 16 | required this.type, |
| 17 | required this.password, |
| 18 | required this.mnemonic, |
| 19 | required this.xpub, |
| 20 | required this.addresses, |
| 21 | required this.balance, |
| 22 | required this.regularAddressIndex, |
| 23 | required this.changeAddressIndex, |
| 24 | required this.addressPageType, |
| 25 | required this.silentAddresses, |
| 26 | required this.silentAddressIndex, |
| 27 | required this.mwebAddresses, |
| 28 | required this.alwaysScan, |
| 29 | required this.useLightning, |
| 30 | this.cachedLightningAddress, |
| 31 | this.passphrase, |
| 32 | this.derivationType, |
| 33 | this.derivationPath, |
| 34 | this.lightningBalance, |
| 35 | }); |
| 36 | |
| 37 | final String name; |
| 38 | final String password; |
| 39 | final WalletType type; |
| 40 | final String? addressPageType; |
| 41 | |
| 42 | @deprecated |
| 43 | String? mnemonic; |
| 44 | |
| 45 | @deprecated |
| 46 | String? xpub; |
| 47 | |
| 48 | @deprecated |
| 49 | String? passphrase; |
| 50 | |
| 51 | List<BitcoinAddressRecord> addresses; |
| 52 | List<BitcoinSilentPaymentAddressRecord> silentAddresses; |
| 53 | List<BitcoinAddressRecord> mwebAddresses; |
| 54 | bool alwaysScan; |
| 55 | bool useLightning; |
| 56 | String? cachedLightningAddress; |
| 57 | |
| 58 | ElectrumBalance balance; |
| 59 | ElectrumBalance? lightningBalance; |
| 60 | Map<String, int> regularAddressIndex; |
| 61 | Map<String, int> changeAddressIndex; |
| 62 | int silentAddressIndex; |
| 63 | DerivationType? derivationType; |
| 64 | String? derivationPath; |
| 65 | |
| 66 | static Future<ElectrumWalletSnapshot> load(EncryptionFileUtils encryptionFileUtils, String name, |
| 67 | WalletType type, String password, BasedUtxoNetwork network) async { |
| 68 | final path = await pathForWallet(name: name, type: type); |
| 69 | final jsonSource = await encryptionFileUtils.read(path: path, password: password); |
| 70 | final data = json.decode(jsonSource) as Map; |
| 71 | final mnemonic = data['mnemonic'] as String?; |
| 72 | final xpub = data['xpub'] as String?; |
| 73 | final passphrase = data['passphrase'] as String? ?? ''; |
| 74 | |
| 75 | final addressesTmp = data['addresses'] as List? ?? <Object>[]; |
| 76 | final addresses = addressesTmp |
| 77 | .whereType<String>() |
| 78 | .map((addr) => BitcoinAddressRecord.fromJSON(addr, network: network)) |
| 79 | .toList(); |
| 80 | |
| 81 | final silentAddressesTmp = data['silent_addresses'] as List? ?? <Object>[]; |
| 82 | final silentAddresses = silentAddressesTmp |
| 83 | .whereType<String>() |
| 84 | .map((addr) => BitcoinSilentPaymentAddressRecord.fromJSON(addr, network: network)) |
| 85 | .toList(); |
| 86 | |
| 87 | final mwebAddressTmp = data['mweb_addresses'] as List? ?? <Object>[]; |
| 88 | final mwebAddresses = mwebAddressTmp |
| 89 | .whereType<String>() |
| 90 | .map((addr) => BitcoinAddressRecord.fromJSON(addr, network: network)) |
| 91 | .toList(); |
| 92 | |
| 93 | final alwaysScan = data['alwaysScan'] as bool? ?? false; |
| 94 | final useLightning = data['useLightning'] as bool? ?? true; |
| 95 | final cachedLightningAddress = data['cachedLightningAddress'] as String?; |
| 96 | |
| 97 | final currency = walletTypeToCryptoCurrency(type); |
| 98 | final balance = ElectrumBalance.fromJSON(data['balance'] as String?, currency) ?? |
| 99 | ElectrumBalance( |
| 100 | confirmed: Money.zero(currency), |
| 101 | unconfirmed: Money.zero(currency), |
| 102 | frozen: Money.zero(currency), |
| 103 | ); |
| 104 | final lightningBalance = |
| 105 | ElectrumBalance.fromJSON(data['lightningBalance'] as String?, currency); |
| 106 | |
| 107 | var regularAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; |
| 108 | var changeAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; |
| 109 | var silentAddressIndex = 0; |
| 110 | |
| 111 | final derivationType = DerivationType |
| 112 | .values[(data['derivationTypeIndex'] as int?) ?? DerivationType.electrum.index]; |
| 113 | final derivationPath = data['derivationPath'] as String? ?? electrum_path; |
| 114 | |
| 115 | try { |
| 116 | regularAddressIndexByType = { |
| 117 | SegwitAddresType.p2wpkh.toString(): int.parse(data['account_index'] as String? ?? '0') |
| 118 | }; |
| 119 | changeAddressIndexByType = { |
| 120 | SegwitAddresType.p2wpkh.toString(): |
| 121 | int.parse(data['change_address_index'] as String? ?? '0') |
| 122 | }; |
| 123 | silentAddressIndex = int.parse(data['silent_address_index'] as String? ?? '0'); |
| 124 | } catch (_) { |
| 125 | try { |
| 126 | regularAddressIndexByType = data["account_index"] as Map<String, int>? ?? {}; |
| 127 | changeAddressIndexByType = data["change_address_index"] as Map<String, int>? ?? {}; |
| 128 | } catch (_) {} |
| 129 | } |
| 130 | |
| 131 | return ElectrumWalletSnapshot( |
| 132 | name: name, |
| 133 | type: type, |
| 134 | password: password, |
| 135 | passphrase: passphrase, |
| 136 | mnemonic: mnemonic, |
| 137 | xpub: xpub, |
| 138 | addresses: addresses, |
| 139 | balance: balance, |
| 140 | lightningBalance: lightningBalance, |
| 141 | regularAddressIndex: regularAddressIndexByType, |
| 142 | changeAddressIndex: changeAddressIndexByType, |
| 143 | addressPageType: data['address_page_type'] as String?, |
| 144 | derivationType: derivationType, |
| 145 | derivationPath: derivationPath, |
| 146 | silentAddresses: silentAddresses, |
| 147 | silentAddressIndex: silentAddressIndex, |
| 148 | mwebAddresses: mwebAddresses, |
| 149 | alwaysScan: alwaysScan, |
| 150 | useLightning: useLightning, |
| 151 | cachedLightningAddress: cachedLightningAddress, |
| 152 | ); |
| 153 | } |
| 154 | } |