Revert "FIX (#2283)" (#2298)

This reverts commit 7b8ddf9685a25d3e9d5ece681560cfc8d7d0cb9e.

Omar Hatem committed May 29, 2025 at 16:54 UTC d332377a2b9d75fb32c549ff3e31d2257e65b8f8
36 files changed +402 -667
cw_bitcoin/lib/address_from_output.dart
+13 -8
@@ -17,16 +17,21 @@ BitcoinBaseAddress addressFromScript(Script script,
17
18 switch (addressType) {
19 case P2pkhAddressType.p2pkh:
20 - return P2pkhAddress.fromScriptPubkey(script: script);
20 + return P2pkhAddress.fromScriptPubkey(
21 + script: script, network: BitcoinNetwork.mainnet);
22 case P2shAddressType.p2pkhInP2sh:
23 case P2shAddressType.p2pkInP2sh:
23 - return P2shAddress.fromScriptPubkey(script: script);
24 - case SegwitAddressType.p2wpkh:
25 - return P2wpkhAddress.fromScriptPubkey(script: script);
26 - case SegwitAddressType.p2wsh:
27 - return P2wshAddress.fromScriptPubkey(script: script);
28 - case SegwitAddressType.p2tr:
29 - return P2trAddress.fromScriptPubkey(script: script);
24 + return P2shAddress.fromScriptPubkey(
25 + script: script, network: BitcoinNetwork.mainnet);
26 + case SegwitAddresType.p2wpkh:
27 + return P2wpkhAddress.fromScriptPubkey(
28 + script: script, network: BitcoinNetwork.mainnet);
29 + case SegwitAddresType.p2wsh:
30 + return P2wshAddress.fromScriptPubkey(
31 + script: script, network: BitcoinNetwork.mainnet);
32 + case SegwitAddresType.p2tr:
33 + return P2trAddress.fromScriptPubkey(
34 + script: script, network: BitcoinNetwork.mainnet);
35 }
36
37 throw ArgumentError("Invalid script");
cw_bitcoin/lib/bitcoin_address_record.dart
+1 -1
@@ -82,7 +82,7 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
82 type: decoded['type'] != null && decoded['type'] != ''
83 ? BitcoinAddressType.values
84 .firstWhere((type) => type.toString() == decoded['type'] as String)
85 - : SegwitAddressType.p2wpkh,
85 + : SegwitAddresType.p2wpkh,
86 scriptHash: decoded['scriptHash'] as String?,
87 network: network,
88 );
cw_bitcoin/lib/bitcoin_receive_page_option.dart
+8 -8
@@ -36,9 +36,9 @@ class BitcoinReceivePageOption implements ReceivePageOption {
36 BitcoinAddressType toType() {
37 switch (this) {
38 case BitcoinReceivePageOption.p2tr:
39 - return SegwitAddressType.p2tr;
39 + return SegwitAddresType.p2tr;
40 case BitcoinReceivePageOption.p2wsh:
41 - return SegwitAddressType.p2wsh;
41 + return SegwitAddresType.p2wsh;
42 case BitcoinReceivePageOption.p2pkh:
43 return P2pkhAddressType.p2pkh;
44 case BitcoinReceivePageOption.p2sh:
@@ -46,20 +46,20 @@ class BitcoinReceivePageOption implements ReceivePageOption {
46 case BitcoinReceivePageOption.silent_payments:
47 return SilentPaymentsAddresType.p2sp;
48 case BitcoinReceivePageOption.mweb:
49 - return SegwitAddressType.mweb;
49 + return SegwitAddresType.mweb;
50 case BitcoinReceivePageOption.p2wpkh:
51 default:
52 - return SegwitAddressType.p2wpkh;
52 + return SegwitAddresType.p2wpkh;
53 }
54 }
55
56 factory BitcoinReceivePageOption.fromType(BitcoinAddressType type) {
57 switch (type) {
58 - case SegwitAddressType.p2tr:
58 + case SegwitAddresType.p2tr:
59 return BitcoinReceivePageOption.p2tr;
60 - case SegwitAddressType.p2wsh:
60 + case SegwitAddresType.p2wsh:
61 return BitcoinReceivePageOption.p2wsh;
62 - case SegwitAddressType.mweb:
62 + case SegwitAddresType.mweb:
63 return BitcoinReceivePageOption.mweb;
64 case P2pkhAddressType.p2pkh:
65 return BitcoinReceivePageOption.p2pkh;
@@ -67,7 +67,7 @@ class BitcoinReceivePageOption implements ReceivePageOption {
67 return BitcoinReceivePageOption.p2sh;
68 case SilentPaymentsAddresType.p2sp:
69 return BitcoinReceivePageOption.silent_payments;
70 - case SegwitAddressType.p2wpkh:
70 + case SegwitAddresType.p2wpkh:
71 default:
72 return BitcoinReceivePageOption.p2wpkh;
73 }
cw_bitcoin/lib/bitcoin_wallet.dart
+40 -24
@@ -73,8 +73,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
73 initialBalance: initialBalance,
74 seedBytes: seedBytes,
75 encryptionFileUtils: encryptionFileUtils,
76 - currency:
77 - networkParam == BitcoinNetwork.testnet ? CryptoCurrency.tbtc : CryptoCurrency.btc,
76 + currency: networkParam == BitcoinNetwork.testnet
77 + ? CryptoCurrency.tbtc
78 + : CryptoCurrency.btc,
79 alwaysScan: alwaysScan,
80 ) {
81 // in a standard BIP44 wallet, mainHd derivation path = m/84'/0'/0'/0 (account 0, index unspecified here)
@@ -93,12 +94,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
94 mainHd: hd,
95 sideHd: accountHD.childKey(Bip32KeyIndex(1)),
96 network: networkParam ?? network,
96 - masterHd: seedBytes != null ? Bip32Slip10Secp256k1.fromSeed(seedBytes) : null,
97 + masterHd:
98 + seedBytes != null ? Bip32Slip10Secp256k1.fromSeed(seedBytes) : null,
99 isHardwareWallet: walletInfo.isHardwareWallet,
100 payjoinManager: payjoinManager);
101
102 autorun((_) {
101 - this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
103 + this.walletAddresses.isEnabledAutoGenerateSubaddress =
104 + this.isEnabledAutoGenerateSubaddress;
105 });
106 }
107
@@ -133,7 +136,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
136 break;
137 case DerivationType.electrum:
138 default:
136 - seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
139 + seedBytes =
140 + await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
141 break;
142 }
143
@@ -206,8 +210,10 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
210 walletInfo.derivationInfo ??= DerivationInfo();
211
212 // set the default if not present:
209 - walletInfo.derivationInfo!.derivationPath ??= snp?.derivationPath ?? electrum_path;
210 - walletInfo.derivationInfo!.derivationType ??= snp?.derivationType ?? DerivationType.electrum;
213 + walletInfo.derivationInfo!.derivationPath ??=
214 + snp?.derivationPath ?? electrum_path;
215 + walletInfo.derivationInfo!.derivationType ??=
216 + snp?.derivationType ?? DerivationType.electrum;
217
218 Uint8List? seedBytes = null;
219 final mnemonic = keysData.mnemonic;
@@ -216,7 +222,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
222 if (mnemonic != null) {
223 switch (walletInfo.derivationInfo!.derivationType) {
224 case DerivationType.electrum:
219 - seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
225 + seedBytes =
226 + await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
227 break;
228 case DerivationType.bip39:
229 default:
@@ -262,7 +269,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
269 late final PayjoinManager payjoinManager;
270
271 bool get isPayjoinAvailable => unspentCoinsInfo.values
265 - .where((element) => element.walletId == id && element.isSending && !element.isFrozen)
272 + .where((element) =>
273 + element.walletId == id && element.isSending && !element.isFrozen)
274 .isNotEmpty;
275
276 Future<PsbtV2> buildPsbt({
@@ -279,8 +287,10 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
287 }) async {
288 final psbtReadyInputs = <PSBTReadyUtxoWithAddress>[];
289 for (final utxo in utxos) {
282 - final rawTx = await electrumClient.getTransactionHex(hash: utxo.utxo.txHash);
283 - final publicKeyAndDerivationPath = publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
290 + final rawTx =
291 + await electrumClient.getTransactionHex(hash: utxo.utxo.txHash);
292 + final publicKeyAndDerivationPath =
293 + publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
294
295 psbtReadyInputs.add(PSBTReadyUtxoWithAddress(
296 utxo: utxo.utxo,
@@ -292,7 +302,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
302 ));
303 }
304
295 - return PSBTTransactionBuild(inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF)
305 + return PSBTTransactionBuild(
306 + inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF)
307 .psbt;
308 }
309
@@ -331,7 +342,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
342 Future<PendingTransaction> createTransaction(Object credentials) async {
343 credentials = credentials as BitcoinTransactionCredentials;
344
334 - final tx = (await super.createTransaction(credentials)) as PendingBitcoinTransaction;
345 + final tx = (await super.createTransaction(credentials))
346 + as PendingBitcoinTransaction;
347
348 final payjoinUri = credentials.payjoinUri;
349 if (payjoinUri == null) return tx;
@@ -354,12 +366,12 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
366 publicKeys: tx.publicKeys!,
367 masterFingerprint: Uint8List(0));
368
357 - final originalPsbt =
358 - await signPsbt(base64.encode(transaction.asPsbtV0()), getUtxoWithPrivateKeys());
369 + final originalPsbt = await signPsbt(
370 + base64.encode(transaction.asPsbtV0()), getUtxoWithPrivateKeys());
371
372 tx.commitOverride = () async {
361 - final sender =
362 - await payjoinManager.initSender(payjoinUri, originalPsbt, int.parse(tx.feeRate));
373 + final sender = await payjoinManager.initSender(
374 + payjoinUri, originalPsbt, int.parse(tx.feeRate));
375 payjoinManager.spawnNewSender(
376 sender: sender, pjUrl: payjoinUri, amount: BigInt.from(tx.amount));
377 };
@@ -375,7 +387,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
387 Future<void> commitPsbt(String finalizedPsbt) {
388 final psbt = PsbtV2()..deserializeV0(base64.decode(finalizedPsbt));
389
378 - final btcTx = BtcTransaction.fromRaw(BytesUtils.toHexString(psbt.extract()));
390 + final btcTx =
391 + BtcTransaction.fromRaw(BytesUtils.toHexString(psbt.extract()));
392
393 return PendingBitcoinTransaction(
394 btcTx,
@@ -389,11 +402,12 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
402 ).commit();
403 }
404
392 - Future<String> signPsbt(String preProcessedPsbt, List<UtxoWithPrivateKey> utxos) async {
405 + Future<String> signPsbt(
406 + String preProcessedPsbt, List<UtxoWithPrivateKey> utxos) async {
407 final psbt = PsbtV2()..deserializeV0(base64Decode(preProcessedPsbt));
408
409 await psbt.signWithUTXO(utxos, (txDigest, utxo, key, sighash) {
396 - return utxo.utxo.isP2tr
410 + return utxo.utxo.isP2tr()
411 ? key.signTapRoot(
412 txDigest,
413 sighash: sighash,
@@ -414,15 +428,17 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
428 Future<String> signMessage(String message, {String? address = null}) async {
429 if (walletInfo.isHardwareWallet) {
430 final addressEntry = address != null
417 - ? walletAddresses.allAddresses.firstWhere((element) => element.address == address)
431 + ? walletAddresses.allAddresses
432 + .firstWhere((element) => element.address == address)
433 : null;
434 final index = addressEntry?.index ?? 0;
435 final isChange = addressEntry?.isHidden == true ? 1 : 0;
436 final accountPath = walletInfo.derivationInfo?.derivationPath;
422 - final derivationPath = accountPath != null ? "$accountPath/$isChange/$index" : null;
437 + final derivationPath =
438 + accountPath != null ? "$accountPath/$isChange/$index" : null;
439
424 - final signature = await _bitcoinLedgerApp!
425 - .signMessage(message: ascii.encode(message), signDerivationPath: derivationPath);
440 + final signature = await _bitcoinLedgerApp!.signMessage(
441 + message: ascii.encode(message), signDerivationPath: derivationPath);
442 return base64Encode(signature);
443 }
444
cw_bitcoin/lib/bitcoin_wallet_addresses.dart
+2 -2
@@ -47,10 +47,10 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
47 if (addressType == P2pkhAddressType.p2pkh)
48 return generateP2PKHAddress(hd: hd, index: index, network: network);
49
50 - if (addressType == SegwitAddressType.p2tr)
50 + if (addressType == SegwitAddresType.p2tr)
51 return generateP2TRAddress(hd: hd, index: index, network: network);
52
53 - if (addressType == SegwitAddressType.p2wsh)
53 + if (addressType == SegwitAddresType.p2wsh)
54 return generateP2WSHAddress(hd: hd, index: index, network: network);
55
56 if (addressType == P2shAddressType.p2wpkhInP2sh)
cw_bitcoin/lib/electrum_wallet.dart
+59 -284
@@ -5,6 +5,7 @@ import 'dart:isolate';
5
6 import 'package:bitcoin_base/bitcoin_base.dart';
7 import 'package:cw_bitcoin/bitcoin_amount_format.dart';
8 +import 'package:cw_core/format_amount.dart';
9 import 'package:cw_core/utils/print_verbose.dart';
10 import 'package:cw_bitcoin/bitcoin_wallet.dart';
11 import 'package:cw_bitcoin/litecoin_wallet.dart';
@@ -17,7 +18,7 @@ import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
18 import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
19 import 'package:cw_bitcoin/bitcoin_unspent.dart';
20 import 'package:cw_bitcoin/bitcoin_wallet_keys.dart';
20 -import 'package:cw_bitcoin/electrum.dart' as electrum;
21 +import 'package:cw_bitcoin/electrum.dart';
22 import 'package:cw_bitcoin/electrum_balance.dart';
23 import 'package:cw_bitcoin/electrum_derivations.dart';
24 import 'package:cw_bitcoin/electrum_transaction_history.dart';
@@ -68,7 +69,7 @@ abstract class ElectrumWalletBase
69 Uint8List? seedBytes,
70 this.passphrase,
71 List<BitcoinAddressRecord>? initialAddresses,
71 - electrum.ElectrumClient? electrumClient,
72 + ElectrumClient? electrumClient,
73 ElectrumBalance? initialBalance,
74 CryptoCurrency? currency,
75 this.alwaysScan,
@@ -95,7 +96,7 @@ abstract class ElectrumWalletBase
96 this.isTestnet = !network.isMainnet,
97 this._mnemonic = mnemonic,
98 super(walletInfo) {
98 - this.electrumClient = electrumClient ?? electrum.ElectrumClient();
99 + this.electrumClient = electrumClient ?? ElectrumClient();
100 this.walletInfo = walletInfo;
101 transactionHistory = ElectrumTransactionHistory(
102 walletInfo: walletInfo,
@@ -166,7 +167,7 @@ abstract class ElectrumWalletBase
167 @observable
168 bool isEnabledAutoGenerateSubaddress;
169
169 - late electrum.ElectrumClient electrumClient;
170 + late ElectrumClient electrumClient;
171 Box<UnspentCoinsInfo> unspentCoinsInfo;
172
173 @override
@@ -181,7 +182,7 @@ abstract class ElectrumWalletBase
182 SyncStatus syncStatus;
183
184 Set<String> get addressesSet => walletAddresses.allAddresses
184 - .where((element) => element.type != SegwitAddressType.mweb)
185 + .where((element) => element.type != SegwitAddresType.mweb)
186 .map((addr) => addr.address)
187 .toSet();
188
@@ -332,14 +333,14 @@ abstract class ElectrumWalletBase
333
334 final receivePort = ReceivePort();
335 _isolate = Isolate.spawn(
335 - _handleScanSilentPayments,
336 + startRefresh,
337 ScanData(
338 sendPort: receivePort.sendPort,
339 silentAddress: walletAddresses.silentAddress!,
340 network: network,
341 height: height,
342 chainTip: chainTip,
342 - electrumClient: electrum.ElectrumClient(),
343 + electrumClient: ElectrumClient(),
344 transactionHistoryIds: transactionHistory.transactions.keys.toList(),
345 node: (await getNodeSupportsSilentPayments()) == true
346 ? ScanNode(node!.uri, node!.useSSL)
@@ -438,6 +439,7 @@ abstract class ElectrumWalletBase
439 BigintUtils.fromBytes(BytesUtils.fromHexString(unspent.silentPaymentLabel!)),
440 )
441 : silentAddress.B_spend,
442 + network: network,
443 );
444
445 final addressRecord = walletAddresses.silentAddresses
@@ -562,7 +564,7 @@ abstract class ElectrumWalletBase
564 node!.save();
565 return node!.supportsSilentPayments!;
566 }
565 - } on electrum.RequestFailedTimeoutException catch (_) {
567 + } on RequestFailedTimeoutException catch (_) {
568 node!.supportsSilentPayments = false;
569 node!.save();
570 return node!.supportsSilentPayments!;
@@ -623,9 +625,9 @@ abstract class ElectrumWalletBase
625
626 switch (coinTypeToSpendFrom) {
627 case UnspentCoinType.mweb:
626 - return utx.bitcoinAddressRecord.type == SegwitAddressType.mweb;
628 + return utx.bitcoinAddressRecord.type == SegwitAddresType.mweb;
629 case UnspentCoinType.nonMweb:
628 - return utx.bitcoinAddressRecord.type != SegwitAddressType.mweb;
630 + return utx.bitcoinAddressRecord.type != SegwitAddresType.mweb;
631 case UnspentCoinType.any:
632 return true;
633 }
@@ -633,7 +635,7 @@ abstract class ElectrumWalletBase
635 final unconfirmedCoins = availableInputs.where((utx) => utx.confirmations == 0).toList();
636
637 // sort the unconfirmed coins so that mweb coins are last:
636 - availableInputs.sort((a, b) => a.bitcoinAddressRecord.type == SegwitAddressType.mweb ? 1 : -1);
638 + availableInputs.sort((a, b) => a.bitcoinAddressRecord.type == SegwitAddresType.mweb ? 1 : -1);
639
640 for (int i = 0; i < availableInputs.length; i++) {
641 final utx = availableInputs[i];
@@ -641,7 +643,7 @@ abstract class ElectrumWalletBase
643
644 if (paysToSilentPayment) {
645 // Check inputs for shared secret derivation
644 - if (utx.bitcoinAddressRecord.type == SegwitAddressType.p2wsh) {
646 + if (utx.bitcoinAddressRecord.type == SegwitAddresType.p2wsh) {
647 throw BitcoinTransactionSilentPaymentsNotSupported();
648 }
649 }
@@ -676,7 +678,7 @@ abstract class ElectrumWalletBase
678 if (privkey != null) {
679 inputPrivKeyInfos.add(ECPrivateInfo(
680 privkey,
679 - address.type == SegwitAddressType.p2tr,
681 + address.type == SegwitAddresType.p2tr,
682 tweak: !isSilentPayment,
683 ));
684
@@ -1162,7 +1164,7 @@ abstract class ElectrumWalletBase
1164 throw Exception(error);
1165 }
1166
1165 - if (utxo.utxo.isP2tr) {
1167 + if (utxo.utxo.isP2tr()) {
1168 hasTaprootInputs = true;
1169 return key.privkey.signTapRoot(
1170 txDigest,
@@ -1174,18 +1176,20 @@ abstract class ElectrumWalletBase
1176 }
1177 });
1178
1177 - return PendingBitcoinTransaction(transaction, type,
1178 - electrumClient: electrumClient,
1179 - amount: estimatedTx.amount,
1180 - fee: estimatedTx.fee,
1181 - feeRate: feeRateInt.toString(),
1182 - network: network,
1183 - hasChange: estimatedTx.hasChange,
1184 - isSendAll: estimatedTx.isSendAll,
1185 - hasTaprootInputs: hasTaprootInputs,
1186 - utxos: estimatedTx.utxos,
1187 - publicKeys: estimatedTx.publicKeys)
1188 - ..addListener((transaction) async {
1179 + return PendingBitcoinTransaction(
1180 + transaction,
1181 + type,
1182 + electrumClient: electrumClient,
1183 + amount: estimatedTx.amount,
1184 + fee: estimatedTx.fee,
1185 + feeRate: feeRateInt.toString(),
1186 + network: network,
1187 + hasChange: estimatedTx.hasChange,
1188 + isSendAll: estimatedTx.isSendAll,
1189 + hasTaprootInputs: hasTaprootInputs,
1190 + utxos: estimatedTx.utxos,
1191 + publicKeys: estimatedTx.publicKeys
1192 + )..addListener((transaction) async {
1193 transactionHistory.addOne(transaction);
1194 if (estimatedTx.spendsSilentPayment) {
1195 transactionHistory.transactions.values.forEach((tx) {
@@ -1229,7 +1233,7 @@ abstract class ElectrumWalletBase
1233 'change_address_index': walletAddresses.currentChangeAddressIndexByType,
1234 'addresses': walletAddresses.allAddresses.map((addr) => addr.toJSON()).toList(),
1235 'address_page_type': walletInfo.addressPageType == null
1232 - ? SegwitAddressType.p2wpkh.toString()
1236 + ? SegwitAddresType.p2wpkh.toString()
1237 : walletInfo.addressPageType.toString(),
1238 'balance': balance[currency]?.toJSON(),
1239 'derivationTypeIndex': walletInfo.derivationInfo?.derivationType?.index,
@@ -1369,7 +1373,7 @@ abstract class ElectrumWalletBase
1373 List<BitcoinUnspent> updatedUnspentCoins = [];
1374
1375 final previousUnspentCoins = List<BitcoinUnspent>.from(unspentCoins.where((utxo) =>
1372 - utxo.bitcoinAddressRecord.type != SegwitAddressType.mweb &&
1376 + utxo.bitcoinAddressRecord.type != SegwitAddresType.mweb &&
1377 utxo.bitcoinAddressRecord is! BitcoinSilentPaymentAddressRecord));
1378
1379 if (hasSilentPaymentsScanning) {
@@ -1383,13 +1387,13 @@ abstract class ElectrumWalletBase
1387
1388 // Set the balance of all non-silent payment and non-mweb addresses to 0 before updating
1389 walletAddresses.allAddresses
1386 - .where((element) => element.type != SegwitAddressType.mweb)
1390 + .where((element) => element.type != SegwitAddresType.mweb)
1391 .forEach((addr) {
1392 if (addr is! BitcoinSilentPaymentAddressRecord) addr.balance = 0;
1393 });
1394
1395 final addressFutures = walletAddresses.allAddresses
1392 - .where((element) => element.type != SegwitAddressType.mweb)
1396 + .where((element) => element.type != SegwitAddresType.mweb)
1397 .map((address) => fetchUnspent(address))
1398 .toList();
1399
@@ -1830,7 +1834,7 @@ abstract class ElectrumWalletBase
1834 throw Exception("Cannot find private key");
1835 }
1836
1833 - if (utxo.utxo.isP2tr) {
1837 + if (utxo.utxo.isP2tr()) {
1838 return key.signTapRoot(txDigest, sighash: sighash);
1839 } else {
1840 return key.signInput(txDigest, sigHash: sighash);
@@ -1980,7 +1984,7 @@ abstract class ElectrumWalletBase
1984 .map((type) => fetchTransactionsForAddressType(historiesWithDetails, type)));
1985 } else if (type == WalletType.litecoin) {
1986 await Future.wait(LITECOIN_ADDRESS_TYPES
1983 - .where((type) => type != SegwitAddressType.mweb)
1987 + .where((type) => type != SegwitAddresType.mweb)
1988 .map((type) => fetchTransactionsForAddressType(historiesWithDetails, type)));
1989 }
1990
@@ -2169,7 +2173,7 @@ abstract class ElectrumWalletBase
2173 final unsubscribedScriptHashes = walletAddresses.allAddresses.where(
2174 (address) =>
2175 !_scripthashesUpdateSubject.containsKey(address.getScriptHash(network)) &&
2172 - address.type != SegwitAddressType.mweb,
2176 + address.type != SegwitAddresType.mweb,
2177 );
2178
2179 await Future.wait(unsubscribedScriptHashes.map((address) async {
@@ -2392,9 +2396,9 @@ abstract class ElectrumWalletBase
2396 derivationPath.substring(0, derivationPath.lastIndexOf("'") + 1);
2397
2398 @action
2395 - void _onConnectionStatusChange(electrum.ConnectionStatus status) {
2399 + void _onConnectionStatusChange(ConnectionStatus status) {
2400 switch (status) {
2397 - case electrum.ConnectionStatus.connected:
2401 + case ConnectionStatus.connected:
2402 if (syncStatus is NotConnectedSyncStatus ||
2403 syncStatus is LostConnectionSyncStatus ||
2404 syncStatus is ConnectingSyncStatus) {
@@ -2402,19 +2406,19 @@ abstract class ElectrumWalletBase
2406 }
2407
2408 break;
2405 - case electrum.ConnectionStatus.disconnected:
2409 + case ConnectionStatus.disconnected:
2410 if (syncStatus is! NotConnectedSyncStatus &&
2411 syncStatus is! ConnectingSyncStatus &&
2412 syncStatus is! SyncronizingSyncStatus) {
2413 syncStatus = NotConnectedSyncStatus();
2414 }
2415 break;
2412 - case electrum.ConnectionStatus.failed:
2416 + case ConnectionStatus.failed:
2417 if (syncStatus is! LostConnectionSyncStatus) {
2418 syncStatus = LostConnectionSyncStatus();
2419 }
2420 break;
2417 - case electrum.ConnectionStatus.connecting:
2421 + case ConnectionStatus.connecting:
2422 if (syncStatus is! ConnectingSyncStatus) {
2423 syncStatus = ConnectingSyncStatus();
2424 }
@@ -2526,7 +2530,7 @@ class ScanData {
2530 final ScanNode? node;
2531 final BasedUtxoNetwork network;
2532 final int chainTip;
2529 - final electrum.ElectrumClient electrumClient;
2533 + final ElectrumClient electrumClient;
2534 final List<String> transactionHistoryIds;
2535 final Map<String, String> labels;
2536 final List<int> labelIndexes;
@@ -2570,234 +2574,6 @@ class SyncResponse {
2574 SyncResponse(this.height, this.syncStatus);
2575 }
2576
2573 -Future<void> _handleScanSilentPayments(ScanData scanData) async {
2574 - try {
2575 - // if (scanData.shouldSwitchNodes) {
2576 - var scanningClient = await ElectrumProvider.connect(
2577 - ElectrumTCPService.connect(
2578 - Uri.parse("tcp://electrs.cakewallet.com:50001"),
2579 - ),
2580 - );
2581 - // }
2582 -
2583 - int syncHeight = scanData.height;
2584 - int initialSyncHeight = syncHeight;
2585 -
2586 - final receiver = Receiver(
2587 - scanData.silentAddress.b_scan.toHex(),
2588 - scanData.silentAddress.B_spend.toHex(),
2589 - scanData.network == BitcoinNetwork.testnet,
2590 - scanData.labelIndexes,
2591 - );
2592 -
2593 - int getCountToScanPerRequest(int syncHeight) {
2594 - if (scanData.isSingleScan) {
2595 - return 1;
2596 - }
2597 -
2598 - final amountLeft = scanData.chainTip - syncHeight + 1;
2599 - return amountLeft;
2600 - }
2601 -
2602 - // Initial status UI update, send how many blocks in total to scan
2603 - scanData.sendPort.send(SyncResponse(syncHeight, StartingScanSyncStatus(syncHeight)));
2604 -
2605 - final req = ElectrumTweaksSubscribe(
2606 - height: syncHeight,
2607 - count: getCountToScanPerRequest(syncHeight),
2608 - historicalMode: false,
2609 - );
2610 -
2611 - var _scanningStream = await scanningClient.subscribe(req);
2612 -
2613 - void listenFn(Map<String, dynamic> event, ElectrumTweaksSubscribe req) {
2614 - final response = req.onResponse(event);
2615 -
2616 - if (response == null || _scanningStream == null) {
2617 - return;
2618 - }
2619 -
2620 - // is success or error msg
2621 - final noData = response.message != null;
2622 -
2623 - if (noData) {
2624 - if (scanData.isSingleScan) {
2625 - return;
2626 - }
2627 -
2628 - // re-subscribe to continue receiving messages, starting from the next unscanned height
2629 - final nextHeight = syncHeight + 1;
2630 -
2631 - if (nextHeight <= scanData.chainTip) {
2632 - final nextStream = scanningClient.subscribe(
2633 - ElectrumTweaksSubscribe(
2634 - height: nextHeight,
2635 - count: getCountToScanPerRequest(nextHeight),
2636 - historicalMode: false,
2637 - ),
2638 - );
2639 -
2640 - if (nextStream != null) {
2641 - nextStream.listen((event) => listenFn(event, req));
2642 - } else {
2643 - scanData.sendPort.send(
2644 - SyncResponse(scanData.height, LostConnectionSyncStatus()),
2645 - );
2646 - }
2647 - }
2648 -
2649 - return;
2650 - }
2651 -
2652 - final tweakHeight = response.block;
2653 -
2654 - if (initialSyncHeight < tweakHeight) initialSyncHeight = tweakHeight;
2655 -
2656 - // Continuous status UI update, send how many blocks left to scan
2657 - final syncingStatus = scanData.isSingleScan
2658 - ? SyncingSyncStatus(1, 0)
2659 - : SyncingSyncStatus.fromHeightValues(scanData.chainTip, initialSyncHeight, tweakHeight);
2660 -
2661 - scanData.sendPort.send(SyncResponse(syncHeight, syncingStatus));
2662 -
2663 - try {
2664 - final blockTweaks = response.blockTweaks;
2665 -
2666 - for (final txid in blockTweaks.keys) {
2667 - final tweakData = blockTweaks[txid];
2668 - final outputPubkeys = tweakData!.outputPubkeys;
2669 - final tweak = tweakData.tweak;
2670 -
2671 - try {
2672 - final addToWallet = {};
2673 -
2674 - // receivers.forEach((receiver) {
2675 - // NOTE: scanOutputs, from sp_scanner package, called from rust here
2676 - final scanResult = scanOutputs([outputPubkeys.keys.toList()], tweak, receiver);
2677 -
2678 - if (scanResult.isEmpty) {
2679 - continue;
2680 - }
2681 -
2682 - if (addToWallet[receiver.BSpend] == null) {
2683 - addToWallet[receiver.BSpend] = scanResult;
2684 - } else {
2685 - addToWallet[receiver.BSpend].addAll(scanResult);
2686 - }
2687 - // });
2688 -
2689 - if (addToWallet.isEmpty) {
2690 - // no results tx, continue to next tx
2691 - continue;
2692 - }
2693 -
2694 - // initial placeholder ElectrumTransactionInfo object to update values based on new scanned unspent(s) on the following loop
2695 - final txInfo = ElectrumTransactionInfo(
2696 - WalletType.bitcoin,
2697 - id: txid,
2698 - height: tweakHeight,
2699 - amount: 0,
2700 - fee: 0,
2701 - direction: TransactionDirection.incoming,
2702 - isReplaced: false,
2703 - date: DateTime.fromMillisecondsSinceEpoch(
2704 - DateTime.now().millisecondsSinceEpoch * 1000,
2705 - ),
2706 - confirmations: scanData.chainTip - tweakHeight + 1,
2707 - isReceivedSilentPayment: true,
2708 - isPending: false,
2709 - unspents: [],
2710 - );
2711 -
2712 - List<BitcoinUnspent> unspents = [];
2713 -
2714 - addToWallet.forEach((BSpend, scanResultPerLabel) {
2715 - scanResultPerLabel.forEach((label, scanOutput) {
2716 - final labelValue = label == "None" ? null : label.toString();
2717 -
2718 - (scanOutput as Map<String, dynamic>).forEach((outputPubkey, tweak) {
2719 - final t_k = tweak as String;
2720 -
2721 - final receivingOutputAddress = ECPublic.fromHex(outputPubkey)
2722 - .toTaprootAddress(tweak: false)
2723 - .toAddress(scanData.network);
2724 -
2725 - final matchingOutput = outputPubkeys[outputPubkey]!;
2726 - final amount = matchingOutput.amount;
2727 - final pos = matchingOutput.vout;
2728 -
2729 - // final matchingSPWallet = scanData.silentPaymentsWallets.firstWhere(
2730 - // (receiver) => receiver.B_spend.toHex() == BSpend.toString(),
2731 - // );
2732 -
2733 - // final labelIndex = labelValue != null ? scanData.labels[label] : 0;
2734 - // final balance = ElectrumBalance();
2735 - // balance.confirmed = amount;
2736 -
2737 - final receivedAddressRecord = BitcoinSilentPaymentAddressRecord(
2738 - receivingOutputAddress,
2739 - index: 0,
2740 - isHidden: false,
2741 - isUsed: true,
2742 - network: scanData.network,
2743 - silentPaymentTweak: t_k,
2744 - type: SegwitAddressType.p2tr,
2745 - txCount: 1,
2746 - balance: amount,
2747 - );
2748 -
2749 - final unspent = BitcoinSilentPaymentsUnspent(
2750 - receivedAddressRecord,
2751 - txid,
2752 - amount,
2753 - pos,
2754 - silentPaymentTweak: t_k,
2755 - silentPaymentLabel: labelValue,
2756 - );
2757 -
2758 - unspents.add(unspent);
2759 - txInfo.unspents!.add(unspent);
2760 - txInfo.amount += unspent.value;
2761 - });
2762 - });
2763 - });
2764 -
2765 - scanData.sendPort.send({txInfo.id: txInfo});
2766 - } catch (e, stacktrace) {
2767 - printV(stacktrace);
2768 - printV(e.toString());
2769 - }
2770 - }
2771 - } catch (e, stacktrace) {
2772 - printV(stacktrace);
2773 - printV(e.toString());
2774 - }
2775 -
2776 - syncHeight = tweakHeight;
2777 -
2778 - if ((tweakHeight >= scanData.chainTip) || scanData.isSingleScan) {
2779 - if (tweakHeight >= scanData.chainTip)
2780 - scanData.sendPort.send(
2781 - SyncResponse(syncHeight, SyncedTipSyncStatus(scanData.chainTip)),
2782 - );
2783 -
2784 - if (scanData.isSingleScan) {
2785 - scanData.sendPort.send(SyncResponse(syncHeight, SyncedSyncStatus()));
2786 - }
2787 -
2788 - _scanningStream?.close();
2789 - _scanningStream = null;
2790 - return;
2791 - }
2792 - }
2793 -
2794 - _scanningStream?.listen((event) => listenFn(event, req));
2795 - } catch (e) {
2796 - printV("Error in _handleScanSilentPayments: $e");
2797 - scanData.sendPort.send(SyncResponse(scanData.height, LostConnectionSyncStatus()));
2798 - }
2799 -}
2800 -
2577 Future<void> startRefresh(ScanData scanData) async {
2578 int syncHeight = scanData.height;
2579 int initialSyncHeight = syncHeight;
@@ -2810,7 +2586,7 @@ Future<void> startRefresh(ScanData scanData) async {
2586 useSSL: scanData.node?.useSSL ?? false,
2587 );
2588
2813 - int getCountToScanPerRequest(int syncHeight) {
2589 + int getCountPerRequest(int syncHeight) {
2590 if (scanData.isSingleScan) {
2591 return 1;
2592 }
@@ -2825,10 +2601,11 @@ Future<void> startRefresh(ScanData scanData) async {
2601 scanData.silentAddress.B_spend.toHex(),
2602 scanData.network == BitcoinNetwork.testnet,
2603 scanData.labelIndexes,
2604 + scanData.labelIndexes.length,
2605 );
2606
2607 // Initial status UI update, send how many blocks in total to scan
2831 - final initialCount = getCountToScanPerRequest(syncHeight);
2608 + final initialCount = getCountPerRequest(syncHeight);
2609 scanData.sendPort.send(SyncResponse(syncHeight, StartingScanSyncStatus(syncHeight)));
2610
2611 tweaksSubscription = await electrumClient.tweaksSubscribe(
@@ -2839,24 +2616,22 @@ Future<void> startRefresh(ScanData scanData) async {
2616 Future<void> listenFn(t) async {
2617 final tweaks = t as Map<String, dynamic>;
2618 final msg = tweaks["message"];
2842 -
2843 - // is success or error msg
2619 + // success or error msg
2620 final noData = msg != null;
2621
2622 if (noData) {
2847 - if (scanData.isSingleScan) {
2848 - return;
2849 - }
2850 -
2623 // re-subscribe to continue receiving messages, starting from the next unscanned height
2624 final nextHeight = syncHeight + 1;
2625 + final nextCount = getCountPerRequest(nextHeight);
2626 +
2627 + if (nextCount > 0) {
2628 + tweaksSubscription?.close();
2629
2854 - if (nextHeight <= scanData.chainTip) {
2855 - final nextStream = electrumClient.tweaksSubscribe(
2630 + final nextTweaksSubscription = electrumClient.tweaksSubscribe(
2631 height: nextHeight,
2857 - count: getCountToScanPerRequest(nextHeight),
2632 + count: nextCount,
2633 );
2859 - nextStream?.listen(listenFn);
2634 + nextTweaksSubscription?.listen(listenFn);
2635 }
2636
2637 return;
@@ -2938,7 +2713,7 @@ Future<void> startRefresh(ScanData scanData) async {
2713 isUsed: true,
2714 network: scanData.network,
2715 silentPaymentTweak: t_k,
2941 - type: SegwitAddressType.p2tr,
2716 + type: SegwitAddresType.p2tr,
2717 txCount: 1,
2718 balance: amount!,
2719 );
@@ -3031,15 +2806,15 @@ BitcoinAddressType _getScriptType(BitcoinBaseAddress type) {
2806 } else if (type is P2shAddress) {
2807 return P2shAddressType.p2wpkhInP2sh;
2808 } else if (type is P2wshAddress) {
3034 - return SegwitAddressType.p2wsh;
2809 + return SegwitAddresType.p2wsh;
2810 } else if (type is P2trAddress) {
3036 - return SegwitAddressType.p2tr;
2811 + return SegwitAddresType.p2tr;
2812 } else if (type is MwebAddress) {
3038 - return SegwitAddressType.mweb;
2813 + return SegwitAddresType.mweb;
2814 } else if (type is SilentPaymentsAddresType) {
2815 return SilentPaymentsAddresType.p2sp;
2816 } else {
3042 - return SegwitAddressType.p2wpkh;
2817 + return SegwitAddresType.p2wpkh;
2818 }
2819 }
2820
cw_bitcoin/lib/electrum_wallet_addresses.dart
+27 -31
@@ -17,16 +17,16 @@ part 'electrum_wallet_addresses.g.dart';
17 class ElectrumWalletAddresses = ElectrumWalletAddressesBase with _$ElectrumWalletAddresses;
18
19 const List<BitcoinAddressType> BITCOIN_ADDRESS_TYPES = [
20 - SegwitAddressType.p2wpkh,
20 + SegwitAddresType.p2wpkh,
21 P2pkhAddressType.p2pkh,
22 - SegwitAddressType.p2tr,
23 - SegwitAddressType.p2wsh,
22 + SegwitAddresType.p2tr,
23 + SegwitAddresType.p2wsh,
24 P2shAddressType.p2wpkhInP2sh,
25 ];
26
27 const List<BitcoinAddressType> LITECOIN_ADDRESS_TYPES = [
28 - SegwitAddressType.p2wpkh,
29 - SegwitAddressType.mweb,
28 + SegwitAddresType.p2wpkh,
29 + SegwitAddresType.mweb,
30 ];
31
32 const List<BitcoinAddressType> BITCOIN_CASH_ADDRESS_TYPES = [
@@ -62,7 +62,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
62 _addressPageType = initialAddressPageType ??
63 (walletInfo.addressPageType != null
64 ? BitcoinAddressType.fromValue(walletInfo.addressPageType!)
65 - : SegwitAddressType.p2wpkh),
65 + : SegwitAddresType.p2wpkh),
66 silentAddresses = ObservableList<BitcoinSilentPaymentAddressRecord>.of(
67 (initialSilentAddresses ?? []).toSet()),
68 currentSilentAddressIndex = initialSilentAddressIndex,
@@ -71,12 +71,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
71 super(walletInfo) {
72 if (masterHd != null) {
73 silentAddress = SilentPaymentOwner.fromPrivateKeys(
74 - b_scan: ECPrivate.fromHex(
75 - masterHd.derivePath("m/352'/1'/0'/1'/0").privateKey.toHex(),
76 - ),
77 - b_spend: ECPrivate.fromHex(
78 - masterHd.derivePath("m/352'/1'/0'/0'/0").privateKey.toHex(),
79 - ),
74 + b_scan: ECPrivate.fromHex(masterHd.derivePath(SCAN_PATH).privateKey.toHex()),
75 + b_spend: ECPrivate.fromHex(masterHd.derivePath(SPEND_PATH).privateKey.toHex()),
76 + network: network,
77 );
78
79 if (silentAddresses.length == 0) {
@@ -147,13 +144,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
144 return silentAddress.toString();
145 }
146
150 - final typeMatchingAddresses =
151 - _addresses.where((addr) => !addr.isHidden && _isAddressPageTypeMatch(addr)).toList();
152 - final typeMatchingReceiveAddresses =
153 - typeMatchingAddresses.where((addr) => !addr.isUsed).toList();
147 + final typeMatchingAddresses = _addresses.where((addr) => !addr.isHidden && _isAddressPageTypeMatch(addr)).toList();
148 + final typeMatchingReceiveAddresses = typeMatchingAddresses.where((addr) => !addr.isUsed).toList();
149
150 if (!isEnabledAutoGenerateSubaddress) {
156 - if (previousAddressRecord != null && previousAddressRecord!.type == addressPageType) {
151 + if (previousAddressRecord != null &&
152 + previousAddressRecord!.type == addressPageType) {
153 return previousAddressRecord!.address;
154 }
155
@@ -253,17 +249,17 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
249 if (walletInfo.type == WalletType.bitcoinCash) {
250 await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
251 } else if (walletInfo.type == WalletType.litecoin) {
256 - await _generateInitialAddresses(type: SegwitAddressType.p2wpkh);
252 + await _generateInitialAddresses(type: SegwitAddresType.p2wpkh);
253 if ((Platform.isAndroid || Platform.isIOS) && !isHardwareWallet) {
258 - await _generateInitialAddresses(type: SegwitAddressType.mweb);
254 + await _generateInitialAddresses(type: SegwitAddresType.mweb);
255 }
256 } else if (walletInfo.type == WalletType.bitcoin) {
257 await _generateInitialAddresses();
258 if (!isHardwareWallet) {
259 await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
260 await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
265 - await _generateInitialAddresses(type: SegwitAddressType.p2tr);
266 - await _generateInitialAddresses(type: SegwitAddressType.p2wsh);
261 + await _generateInitialAddresses(type: SegwitAddresType.p2tr);
262 + await _generateInitialAddresses(type: SegwitAddresType.p2wsh);
263 }
264 }
265
@@ -327,7 +323,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
323 BaseBitcoinAddressRecord generateNewAddress({String label = ''}) {
324 if (addressPageType == SilentPaymentsAddresType.p2sp && silentAddress != null) {
325 final currentSilentAddressIndex = silentAddresses
330 - .where((addressRecord) => addressRecord.type != SegwitAddressType.p2tr)
326 + .where((addressRecord) => addressRecord.type != SegwitAddresType.p2tr)
327 .length -
328 1;
329
@@ -385,7 +381,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
381 void addBitcoinAddressTypes() {
382 final lastP2wpkh = _addresses
383 .where((addressRecord) =>
388 - _isUnusedReceiveAddressByType(addressRecord, SegwitAddressType.p2wpkh))
384 + _isUnusedReceiveAddressByType(addressRecord, SegwitAddresType.p2wpkh))
385 .toList()
386 .last;
387 if (lastP2wpkh.address != address) {
@@ -411,7 +407,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
407 }
408
409 final lastP2tr = _addresses.firstWhere(
414 - (addressRecord) => _isUnusedReceiveAddressByType(addressRecord, SegwitAddressType.p2tr));
410 + (addressRecord) => _isUnusedReceiveAddressByType(addressRecord, SegwitAddresType.p2tr));
411 if (lastP2tr.address != address) {
412 addressesMap[lastP2tr.address] = 'P2TR';
413 } else {
@@ -419,7 +415,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
415 }
416
417 final lastP2wsh = _addresses.firstWhere(
422 - (addressRecord) => _isUnusedReceiveAddressByType(addressRecord, SegwitAddressType.p2wsh));
418 + (addressRecord) => _isUnusedReceiveAddressByType(addressRecord, SegwitAddresType.p2wsh));
419 if (lastP2wsh.address != address) {
420 addressesMap[lastP2wsh.address] = 'P2WSH';
421 } else {
@@ -444,7 +440,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
440 void addLitecoinAddressTypes() {
441 final lastP2wpkh = _addresses
442 .where((addressRecord) =>
447 - _isUnusedReceiveAddressByType(addressRecord, SegwitAddressType.p2wpkh))
443 + _isUnusedReceiveAddressByType(addressRecord, SegwitAddresType.p2wpkh))
444 .toList()
445 .last;
446 if (lastP2wpkh.address != address) {
@@ -454,7 +450,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
450 }
451
452 final lastMweb = _addresses.firstWhere(
457 - (addressRecord) => _isUnusedReceiveAddressByType(addressRecord, SegwitAddressType.mweb));
453 + (addressRecord) => _isUnusedReceiveAddressByType(addressRecord, SegwitAddresType.mweb));
454 if (lastMweb.address != address) {
455 addressesMap[lastMweb.address] = 'MWEB';
456 } else {
@@ -564,14 +560,14 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
560 addressRecord.isHidden &&
561 !addressRecord.isUsed &&
562 // TODO: feature to change change address type. For now fixed to p2wpkh, the cheapest type
567 - (walletInfo.type != WalletType.bitcoin || addressRecord.type == SegwitAddressType.p2wpkh));
563 + (walletInfo.type != WalletType.bitcoin || addressRecord.type == SegwitAddresType.p2wpkh));
564 changeAddresses.addAll(newAddresses);
565 }
566
567 @action
568 Future<void> discoverAddresses(List<BitcoinAddressRecord> addressList, bool isHidden,
569 Future<String?> Function(BitcoinAddressRecord) getAddressHistory,
574 - {BitcoinAddressType type = SegwitAddressType.p2wpkh}) async {
570 + {BitcoinAddressType type = SegwitAddresType.p2wpkh}) async {
571 final newAddresses = await _createNewAddresses(gap,
572 startIndex: addressList.length, isHidden: isHidden, type: type);
573 addAddresses(newAddresses);
@@ -585,7 +581,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
581 }
582
583 Future<void> _generateInitialAddresses(
588 - {BitcoinAddressType type = SegwitAddressType.p2wpkh}) async {
584 + {BitcoinAddressType type = SegwitAddresType.p2wpkh}) async {
585 var countOfReceiveAddresses = 0;
586 var countOfHiddenAddresses = 0;
587
@@ -662,7 +658,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
658
659 void _validateAddresses() {
660 _addresses.forEach((element) async {
665 - if (element.type == SegwitAddressType.mweb) {
661 + if (element.type == SegwitAddresType.mweb) {
662 // this would add a ton of startup lag for mweb addresses since we have 1000 of them
663 return;
664 }
cw_bitcoin/lib/electrum_wallet_snapshot.dart
+4 -4
@@ -87,8 +87,8 @@ class ElectrumWalletSnapshot {
87
88 final balance = ElectrumBalance.fromJSON(data['balance'] as String?) ??
89 ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0);
90 - var regularAddressIndexByType = {SegwitAddressType.p2wpkh.toString(): 0};
91 - var changeAddressIndexByType = {SegwitAddressType.p2wpkh.toString(): 0};
90 + var regularAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0};
91 + var changeAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0};
92 var silentAddressIndex = 0;
93
94 final derivationType = DerivationType
@@ -97,10 +97,10 @@ class ElectrumWalletSnapshot {
97
98 try {
99 regularAddressIndexByType = {
100 - SegwitAddressType.p2wpkh.toString(): int.parse(data['account_index'] as String? ?? '0')
100 + SegwitAddresType.p2wpkh.toString(): int.parse(data['account_index'] as String? ?? '0')
101 };
102 changeAddressIndexByType = {
103 - SegwitAddressType.p2wpkh.toString():
103 + SegwitAddresType.p2wpkh.toString():
104 int.parse(data['change_address_index'] as String? ?? '0')
105 };
106 silentAddressIndex = int.parse(data['silent_address_index'] as String? ?? '0');
cw_bitcoin/lib/litecoin_wallet.dart
+8 -9
@@ -16,6 +16,7 @@ import 'package:fixnum/fixnum.dart';
16 import 'package:bip39/bip39.dart' as bip39;
17 import 'package:bitcoin_base/bitcoin_base.dart';
18 import 'package:blockchain_utils/blockchain_utils.dart';
19 +import 'package:blockchain_utils/signer/ecdsa_signing_key.dart';
20 import 'package:cw_bitcoin/bitcoin_address_record.dart';
21 import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
22 import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
@@ -970,9 +971,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
971 List<ECPrivateInfo>? inputPrivKeyInfos,
972 List<Outpoint>? vinOutpoints,
973 }) async {
973 - bool spendsMweb = utxos.any((utxo) => utxo.utxo.scriptType == SegwitAddressType.mweb);
974 + bool spendsMweb = utxos.any((utxo) => utxo.utxo.scriptType == SegwitAddresType.mweb);
975 bool paysToMweb = outputs
975 - .any((output) => output.toOutput.scriptPubKey.getAddressType() == SegwitAddressType.mweb);
976 + .any((output) => output.toOutput.scriptPubKey.getAddressType() == SegwitAddresType.mweb);
977
978 bool isRegular = !spendsMweb && !paysToMweb;
979 bool isMweb = spendsMweb || paysToMweb;
@@ -1063,9 +1064,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
1064 tx.isMweb = mwebEnabled;
1065
1066 if (!mwebEnabled) {
1066 - tx.changeAddressOverride = (await (walletAddresses as LitecoinWalletAddresses)
1067 - .getChangeAddress(coinTypeToSpendFrom: UnspentCoinType.nonMweb))
1068 - .address;
1067 + tx.changeAddressOverride =
1068 + (await (walletAddresses as LitecoinWalletAddresses).getChangeAddress(coinTypeToSpendFrom: UnspentCoinType.nonMweb))
1069 + .address;
1070 return tx;
1071 }
1072 await waitForMwebAddresses();
@@ -1107,7 +1108,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
1108
1109 // check if mweb inputs are used:
1110 for (final utxo in tx.utxos) {
1110 - if (utxo.utxo.scriptType == SegwitAddressType.mweb) {
1111 + if (utxo.utxo.scriptType == SegwitAddresType.mweb) {
1112 hasMwebInput = true;
1113 }
1114 }
@@ -1118,9 +1119,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
1119 bool isRegular = !hasMwebInput && !hasMwebOutput;
1120 bool shouldNotUseMwebChange = isPegIn || isRegular || !hasMwebInput;
1121 tx.changeAddressOverride = (await (walletAddresses as LitecoinWalletAddresses)
1121 - .getChangeAddress(
1122 - coinTypeToSpendFrom:
1123 - shouldNotUseMwebChange ? UnspentCoinType.nonMweb : UnspentCoinType.any))
1122 + .getChangeAddress(coinTypeToSpendFrom: shouldNotUseMwebChange ? UnspentCoinType.nonMweb : UnspentCoinType.any))
1123 .address;
1124 if (isRegular) {
1125 tx.isMweb = false;
cw_bitcoin/lib/litecoin_wallet_addresses.dart
+5 -5
@@ -106,7 +106,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
106 .map((e) => BitcoinAddressRecord(
107 e.value,
108 index: e.key,
109 - type: SegwitAddressType.mweb,
109 + type: SegwitAddresType.mweb,
110 network: network,
111 ))
112 .toList();
@@ -128,7 +128,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
128 required Bip32Slip10Secp256k1 hd,
129 BitcoinAddressType? addressType,
130 }) {
131 - if (addressType == SegwitAddressType.mweb) {
131 + if (addressType == SegwitAddresType.mweb) {
132 return hd == sideHd ? mwebAddrs[0] : mwebAddrs[index + 1];
133 }
134 return generateP2WPKHAddress(hd: hd, index: index, network: network);
@@ -140,7 +140,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
140 required Bip32Slip10Secp256k1 hd,
141 BitcoinAddressType? addressType,
142 }) async {
143 - if (addressType == SegwitAddressType.mweb) {
143 + if (addressType == SegwitAddresType.mweb) {
144 await ensureMwebAddressUpToIndexExists(index);
145 }
146 return getAddress(index: index, hd: hd, addressType: addressType);
@@ -195,7 +195,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
195 return BitcoinAddressRecord(
196 mwebAddrs[0],
197 index: 0,
198 - type: SegwitAddressType.mweb,
198 + type: SegwitAddresType.mweb,
199 network: network,
200 );
201 }
@@ -207,7 +207,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
207 String get addressForExchange {
208 // don't use mweb addresses for exchange refund address:
209 final addresses = receiveAddresses
210 - .where((element) => element.type == SegwitAddressType.p2wpkh && !element.isUsed);
210 + .where((element) => element.type == SegwitAddresType.p2wpkh && !element.isUsed);
211 return addresses.first.address;
212 }
213 }
cw_bitcoin/lib/payjoin/manager.dart
+18 -10
@@ -31,8 +31,8 @@ class PayjoinManager {
31 'https://ohttp.cakewallet.com',
32 ];
33
34 - static Future<PayjoinUri.Url> randomOhttpRelayUrl() =>
35 - PayjoinUri.Url.fromStr(ohttpRelayUrls[Random.secure().nextInt(ohttpRelayUrls.length)]);
34 + static Future<PayjoinUri.Url> randomOhttpRelayUrl() => PayjoinUri.Url.fromStr(
35 + ohttpRelayUrls[Random.secure().nextInt(ohttpRelayUrls.length)]);
36
37 static const payjoinDirectoryUrl = 'https://payjo.in';
38
@@ -59,7 +59,8 @@ class PayjoinManager {
59 Future<Sender> initSender(
60 String pjUriString, String originalPsbt, int networkFeesSatPerVb) async {
61 try {
62 - final pjUri = (await PayjoinUri.Uri.fromStr(pjUriString)).checkPjSupported();
62 + final pjUri =
63 + (await PayjoinUri.Uri.fromStr(pjUriString)).checkPjSupported();
64 final minFeeRateSatPerKwu = BigInt.from(networkFeesSatPerVb * 250);
65 final senderBuilder = await SenderBuilder.fromPsbtAndUri(
66 psbtBase64: originalPsbt,
@@ -78,7 +79,8 @@ class PayjoinManager {
79 bool isTestnet = false,
80 }) async {
81 final pjUri = Uri.parse(pjUrl).queryParameters['pj']!;
81 - await _payjoinStorage.insertSenderSession(sender, pjUri, _wallet.id, amount);
82 + await _payjoinStorage.insertSenderSession(
83 + sender, pjUri, _wallet.id, amount);
84
85 return _spawnSender(isTestnet: isTestnet, sender: sender, pjUri: pjUri);
86 }
@@ -138,9 +140,11 @@ class PayjoinManager {
140 return completer.future;
141 }
142
141 - Future<Receiver> initReceiver(String address, [bool isTestnet = false]) async {
143 + Future<Receiver> initReceiver(String address,
144 + [bool isTestnet = false]) async {
145 try {
143 - final payjoinDirectory = await PayjoinUri.Url.fromStr(payjoinDirectoryUrl);
146 + final payjoinDirectory =
147 + await PayjoinUri.Url.fromStr(payjoinDirectoryUrl);
148
149 final ohttpKeys = await PayjoinUri.fetchOhttpKeys(
150 ohttpRelay: await randomOhttpRelayUrl(),
@@ -195,7 +199,8 @@ class PayjoinManager {
199 _payjoinStorage.markReceiverSessionInProgress(receiver.id());
200
201 final inputScript = message['input_script'] as Uint8List;
198 - final isOwned = _wallet.isMine(Script.fromRaw(bytes: inputScript));
202 + final isOwned =
203 + _wallet.isMine(Script.fromRaw(byteData: inputScript));
204 mainToIsolateSendPort?.send({
205 'requestId': message['requestId'],
206 'result': isOwned,
@@ -204,7 +209,8 @@ class PayjoinManager {
209
210 case PayjoinReceiverRequestTypes.checkIsReceiverOutput:
211 final outputScript = message['output_script'] as Uint8List;
207 - final isReceiverOutput = _wallet.isMine(Script.fromRaw(bytes: outputScript));
212 + final isReceiverOutput =
213 + _wallet.isMine(Script.fromRaw(byteData: outputScript));
214 mainToIsolateSendPort?.send({
215 'requestId': message['requestId'],
216 'result': isReceiverOutput,
@@ -237,13 +243,15 @@ class PayjoinManager {
243 }
244 } catch (e) {
245 _cleanupSession(receiver.id());
240 - await _payjoinStorage.markReceiverSessionUnrecoverable(receiver.id(), e.toString());
246 + await _payjoinStorage.markReceiverSessionUnrecoverable(
247 + receiver.id(), e.toString());
248 completer.completeError(e);
249 }
250 } else if (message is PayjoinSessionError) {
251 _cleanupSession(receiver.id());
252 if (message is UnrecoverableError) {
246 - await _payjoinStorage.markReceiverSessionUnrecoverable(receiver.id(), message.message);
253 + await _payjoinStorage.markReceiverSessionUnrecoverable(
254 + receiver.id(), message.message);
255 completer.complete();
256 } else if (message is RecoverableError) {
257 completer.complete();
cw_bitcoin/lib/psbt/signer.dart
+49 -29
@@ -40,7 +40,8 @@ extension PsbtSigner on PsbtV2 {
40 return tx.buffer();
41 }
42
43 - Future<void> signWithUTXO(List<UtxoWithPrivateKey> utxos, UTXOSignerCallBack signer,
43 + Future<void> signWithUTXO(
44 + List<UtxoWithPrivateKey> utxos, UTXOSignerCallBack signer,
45 [UTXOGetterCallBack? getTaprootPair]) async {
46 final raw = BytesUtils.toHexString(extractUnsignedTX(getSegwit: false));
47 final tx = BtcTransaction.fromRaw(raw);
@@ -50,10 +51,10 @@ extension PsbtSigner on PsbtV2 {
51 List<BigInt> taprootAmounts = [];
52 List<Script> taprootScripts = [];
53
53 - if (utxos.any((e) => e.utxo.isP2tr)) {
54 + if (utxos.any((e) => e.utxo.isP2tr())) {
55 for (final input in tx.inputs) {
55 - final utxo = utxos
56 - .firstWhereOrNull((u) => u.utxo.txHash == input.txId && u.utxo.vout == input.txIndex);
56 + final utxo = utxos.firstWhereOrNull(
57 + (u) => u.utxo.txHash == input.txId && u.utxo.vout == input.txIndex);
58
59 if (utxo == null) {
60 final trPair = await getTaprootPair!.call(input.txId, input.txIndex);
@@ -75,29 +76,37 @@ extension PsbtSigner on PsbtV2 {
76 /// We receive the owner's ScriptPubKey
77 final script = _findLockingScript(utxo, false);
78
78 - final int sighash =
79 - utxo.utxo.isP2tr ? BitcoinOpCodeConst.sighashDefault : BitcoinOpCodeConst.sighashAll;
79 + final int sighash = utxo.utxo.isP2tr()
80 + ? BitcoinOpCodeConst.TAPROOT_SIGHASH_ALL
81 + : BitcoinOpCodeConst.SIGHASH_ALL;
82
83 /// We generate transaction digest for current input
82 - final digest =
83 - _generateTransactionDigest(script, i, utxo.utxo, tx, taprootAmounts, taprootScripts);
84 + final digest = _generateTransactionDigest(
85 + script, i, utxo.utxo, tx, taprootAmounts, taprootScripts);
86
87 /// now we need sign the transaction digest
88 final sig = signer(digest, utxo, utxo.privateKey, sighash);
89
88 - if (utxo.utxo.isP2tr) {
90 + if (utxo.utxo.isP2tr()) {
91 setInputTapKeySig(i, Uint8List.fromList(BytesUtils.fromHexString(sig)));
92 } else {
91 - setInputPartialSig(i, Uint8List.fromList(BytesUtils.fromHexString(utxo.public().toHex())),
93 + setInputPartialSig(
94 + i,
95 + Uint8List.fromList(BytesUtils.fromHexString(utxo.public().toHex())),
96 Uint8List.fromList(BytesUtils.fromHexString(sig)));
97 }
98 }
99 }
100
97 - List<int> _generateTransactionDigest(Script scriptPubKeys, int input, BitcoinUtxo utxo,
98 - BtcTransaction transaction, List<BigInt> taprootAmounts, List<Script> tapRootPubKeys) {
99 - if (utxo.isSegwit) {
100 - if (utxo.isP2tr) {
101 + List<int> _generateTransactionDigest(
102 + Script scriptPubKeys,
103 + int input,
104 + BitcoinUtxo utxo,
105 + BtcTransaction transaction,
106 + List<BigInt> taprootAmounts,
107 + List<Script> tapRootPubKeys) {
108 + if (utxo.isSegwit()) {
109 + if (utxo.isP2tr()) {
110 return transaction.getTransactionTaprootDigset(
111 txIndex: input,
112 scriptPubKeys: tapRootPubKeys,
@@ -107,7 +116,8 @@ extension PsbtSigner on PsbtV2 {
116 return transaction.getTransactionSegwitDigit(
117 txInIndex: input, script: scriptPubKeys, amount: utxo.value);
118 }
110 - return transaction.getTransactionDigest(txInIndex: input, script: scriptPubKeys);
119 + return transaction.getTransactionDigest(
120 + txInIndex: input, script: scriptPubKeys);
121 }
122
123 Script _findLockingScript(UtxoWithAddress utxo, bool isTaproot) {
@@ -119,23 +129,23 @@ extension PsbtSigner on PsbtV2 {
129 switch (utxo.utxo.scriptType) {
130 case PubKeyAddressType.p2pk:
131 return senderPub.toRedeemScript();
122 - case SegwitAddressType.p2wsh:
132 + case SegwitAddresType.p2wsh:
133 if (isTaproot) {
134 return senderPub.toP2wshAddress().toScriptPubKey();
135 }
136 return senderPub.toP2wshRedeemScript();
137 case P2pkhAddressType.p2pkh:
138 return senderPub.toP2pkhAddress().toScriptPubKey();
129 - case SegwitAddressType.p2wpkh:
139 + case SegwitAddresType.p2wpkh:
140 if (isTaproot) {
141 return senderPub.toP2wpkhAddress().toScriptPubKey();
142 }
143 return senderPub.toP2pkhAddress().toScriptPubKey();
134 - case SegwitAddressType.p2tr:
144 + case SegwitAddresType.p2tr:
145 return senderPub
146 .toTaprootAddress(tweak: utxo.utxo.isSilentPayment != true)
147 .toScriptPubKey();
138 - case SegwitAddressType.mweb:
148 + case SegwitAddresType.mweb:
149 return Script(script: []);
150 case P2shAddressType.p2pkhInP2sh:
151 if (isTaproot) {
@@ -162,10 +172,11 @@ extension PsbtSigner on PsbtV2 {
172 }
173 }
174
165 -typedef UTXOSignerCallBack = String Function(
166 - List<int> trDigest, UtxoWithAddress utxo, ECPrivate privateKey, int sighash);
175 +typedef UTXOSignerCallBack = String Function(List<int> trDigest,
176 + UtxoWithAddress utxo, ECPrivate privateKey, int sighash);
177
168 -typedef UTXOGetterCallBack = Future<TaprootAmountScriptPair> Function(String txId, int vout);
178 +typedef UTXOGetterCallBack = Future<TaprootAmountScriptPair> Function(
179 + String txId, int vout);
180
181 class TaprootAmountScriptPair {
182 final BigInt value;
@@ -205,17 +216,23 @@ class UtxoWithPrivateKey extends UtxoWithAddress {
216 }
217
218 return UtxoWithPrivateKey(
208 - utxo: input.utxo, ownerDetails: input.ownerDetails, privateKey: key.privkey);
219 + utxo: input.utxo,
220 + ownerDetails: input.ownerDetails,
221 + privateKey: key.privkey);
222 }
223
211 - factory UtxoWithPrivateKey.fromUnspent(BitcoinUnspent input, BitcoinWalletBase wallet) {
212 - final address = RegexUtils.addressTypeFromStr(input.address, BitcoinNetwork.mainnet);
224 + factory UtxoWithPrivateKey.fromUnspent(
225 + BitcoinUnspent input, BitcoinWalletBase wallet) {
226 + final address =
227 + RegexUtils.addressTypeFromStr(input.address, BitcoinNetwork.mainnet);
228
214 - final newHd = input.bitcoinAddressRecord.isHidden ? wallet.sideHd : wallet.hd;
229 + final newHd =
230 + input.bitcoinAddressRecord.isHidden ? wallet.sideHd : wallet.hd;
231
232 ECPrivate privkey;
233 if (input.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord) {
218 - final unspentAddress = input.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord;
234 + final unspentAddress =
235 + input.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord;
236 privkey = wallet.walletAddresses.silentAddress!.b_spend.tweakAdd(
237 BigintUtils.fromBytes(
238 BytesUtils.fromHexString(unspentAddress.silentPaymentTweak!),
@@ -223,7 +240,9 @@ class UtxoWithPrivateKey extends UtxoWithAddress {
240 );
241 } else {
242 privkey = generateECPrivate(
226 - hd: newHd, index: input.bitcoinAddressRecord.index, network: BitcoinNetwork.mainnet);
243 + hd: newHd,
244 + index: input.bitcoinAddressRecord.index,
245 + network: BitcoinNetwork.mainnet);
246 }
247
248 return UtxoWithPrivateKey(
@@ -232,7 +251,8 @@ class UtxoWithPrivateKey extends UtxoWithAddress {
251 value: BigInt.from(input.value),
252 vout: input.vout,
253 scriptType: input.bitcoinAddressRecord.type,
235 - isSilentPayment: input.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord,
254 + isSilentPayment:
255 + input.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord,
256 ),
257 ownerDetails: UtxoAddressDetails(
258 publicKey: privkey.getPublic().toHex(),
cw_bitcoin/lib/psbt/transaction_builder.dart
+19 -15
@@ -9,9 +9,7 @@ class PSBTTransactionBuild {
9 final PsbtV2 psbt = PsbtV2();
10
11 PSBTTransactionBuild(
12 - {required List<PSBTReadyUtxoWithAddress> inputs,
13 - required List<BitcoinBaseOutput> outputs,
14 - bool enableRBF = true}) {
12 + {required List<PSBTReadyUtxoWithAddress> inputs, required List<BitcoinBaseOutput> outputs, bool enableRBF = true}) {
13 psbt.setGlobalTxVersion(2);
14 psbt.setGlobalInputCount(inputs.length);
15 psbt.setGlobalOutputCount(outputs.length);
@@ -19,20 +17,20 @@ class PSBTTransactionBuild {
17 for (var i = 0; i < inputs.length; i++) {
18 final input = inputs[i];
19
22 - printV(input.utxo.isP2tr);
23 - printV(input.utxo.isSegwit);
24 - printV(input.utxo.isP2shSegwit);
20 + printV(input.utxo.isP2tr());
21 + printV(input.utxo.isSegwit());
22 + printV(input.utxo.isP2shSegwit());
23
26 - psbt.setInputPreviousTxId(
27 - i, Uint8List.fromList(hex.decode(input.utxo.txHash).reversed.toList()));
24 + psbt.setInputPreviousTxId(i, Uint8List.fromList(hex.decode(input.utxo.txHash).reversed.toList()));
25 psbt.setInputOutputIndex(i, input.utxo.vout);
26 psbt.setInputSequence(i, enableRBF ? 0x1 : 0xffffffff);
27
31 - if (input.utxo.isSegwit) {
28 +
29 + if (input.utxo.isSegwit()) {
30 setInputSegwit(i, input);
33 - } else if (input.utxo.isP2shSegwit) {
31 + } else if (input.utxo.isP2shSegwit()) {
32 setInputP2shSegwit(i, input);
35 - } else if (input.utxo.isP2tr) {
33 + } else if (input.utxo.isP2tr()) {
34 // ToDo: (Konsti) Handle Taproot Inputs
35 } else {
36 setInputP2pkh(i, input);
@@ -51,14 +49,20 @@ class PSBTTransactionBuild {
49
50 void setInputP2pkh(int i, PSBTReadyUtxoWithAddress input) {
51 psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx)));
54 - psbt.setInputBip32Derivation(i, Uint8List.fromList(hex.decode(input.ownerPublicKey)),
55 - input.ownerMasterFingerprint, BIPPath.fromString(input.ownerDerivationPath).toPathArray());
52 + psbt.setInputBip32Derivation(
53 + i,
54 + Uint8List.fromList(hex.decode(input.ownerPublicKey)),
55 + input.ownerMasterFingerprint,
56 + BIPPath.fromString(input.ownerDerivationPath).toPathArray());
57 }
58
59 void setInputSegwit(int i, PSBTReadyUtxoWithAddress input) {
60 psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx)));
60 - psbt.setInputBip32Derivation(i, Uint8List.fromList(hex.decode(input.ownerPublicKey)),
61 - input.ownerMasterFingerprint, BIPPath.fromString(input.ownerDerivationPath).toPathArray());
61 + psbt.setInputBip32Derivation(
62 + i,
63 + Uint8List.fromList(hex.decode(input.ownerPublicKey)),
64 + input.ownerMasterFingerprint,
65 + BIPPath.fromString(input.ownerDerivationPath).toPathArray());
66
67 psbt.setInputWitnessUtxo(i, Uint8List.fromList(bigIntToUint64LE(input.utxo.value)),
68 Uint8List.fromList(input.ownerDetails.address.toScriptPubKey().toBytes()));
cw_bitcoin/lib/psbt/utils.dart
+1 -1
@@ -21,7 +21,7 @@ String getOutputAmountFromPsbt(String psbtV0, BitcoinWalletBase wallet) {
21 int amount = 0;
22 for (var i = 0; i < psbt.getGlobalOutputCount(); i++) {
23 final script = psbt.getOutputScript(i);
24 - if (wallet.isMine(Script.fromRaw(bytes: script))) {
24 + if (wallet.isMine(Script.fromRaw(byteData: script))) {
25 amount += psbt.getOutputAmount(i);
26 }
27 }
cw_bitcoin/pubspec.lock
+11 -11
@@ -79,20 +79,20 @@ packages:
79 dependency: "direct overridden"
80 description:
81 path: "."
82 - ref: cake-update-v15
83 - resolved-ref: "29160733cbc4ef2c7b8c8fe9ed0297c9bffecfe2"
82 + ref: cake-update-v9
83 + resolved-ref: "86969a14e337383e14965f5fb45a72a63e5009bc"
84 url: "https://github.com/cake-tech/bitcoin_base"
85 source: git
86 - version: "6.1.0"
86 + version: "4.7.0"
87 blockchain_utils:
88 dependency: "direct main"
89 description:
90 path: "."
91 - ref: cake-update-v4
92 - resolved-ref: "437dadd0bd9bf73ec6a551299577799341f6486a"
91 + ref: cake-update-v2
92 + resolved-ref: "59fdf29d72068e0522a96a8953ed7272833a9f57"
93 url: "https://github.com/cake-tech/blockchain_utils"
94 source: git
95 - version: "4.3.0"
95 + version: "3.3.0"
96 bluez:
97 dependency: transitive
98 description:
@@ -681,11 +681,11 @@ packages:
681 dependency: transitive
682 description:
683 path: "."
684 - ref: cake-update-v4
685 - resolved-ref: "084fb7bf13ec42d74f26ac08c883ce07c10fca7e"
684 + ref: cake-update-v2
685 + resolved-ref: "93440dc5126369b873ca1fccc13c3c1240b1c5c2"
686 url: "https://github.com/cake-tech/on_chain.git"
687 source: git
688 - version: "6.2.0"
688 + version: "3.7.0"
689 package_config:
690 dependency: transitive
691 description:
@@ -968,8 +968,8 @@ packages:
968 dependency: "direct main"
969 description:
970 path: "."
971 - ref: cake-update-v4
972 - resolved-ref: f3c172a7dc5155f5e745e4630b05f197e098a5cd
971 + ref: "sp_v4.0.0"
972 + resolved-ref: "2554cb8bd3ee1d026bc63e76a30d1226960c7cb4"
973 url: "https://github.com/cake-tech/sp_scanner"
974 source: git
975 version: "0.0.1"
cw_bitcoin/pubspec.yaml
+3 -3
@@ -29,14 +29,14 @@ dependencies:
29 blockchain_utils:
30 git:
31 url: https://github.com/cake-tech/blockchain_utils
32 - ref: cake-update-v4
32 + ref: cake-update-v2
33 cw_mweb:
34 path: ../cw_mweb
35 grpc: ^4.0.1
36 sp_scanner:
37 git:
38 url: https://github.com/cake-tech/sp_scanner
39 - ref: cake-update-v4
39 + ref: sp_v4.0.0
40 bech32:
41 git:
42 url: https://github.com/cake-tech/bech32.git
@@ -69,7 +69,7 @@ dependency_overrides:
69 bitcoin_base:
70 git:
71 url: https://github.com/cake-tech/bitcoin_base
72 - ref: cake-update-v15
72 + ref: cake-update-v9
73 pointycastle: 3.7.4
74 ffi: 2.1.0
75
cw_bitcoin_cash/pubspec.yaml
+2 -2
@@ -28,7 +28,7 @@ dependencies:
28 blockchain_utils:
29 git:
30 url: https://github.com/cake-tech/blockchain_utils
31 - ref: cake-update-v4
31 + ref: cake-update-v2
32
33 dev_dependencies:
34 flutter_test:
@@ -42,7 +42,7 @@ dependency_overrides:
42 bitcoin_base:
43 git:
44 url: https://github.com/cake-tech/bitcoin_base
45 - ref: cake-update-v15
45 + ref: cake-update-v9
46
47 # For information on the generic Dart part of this file, see the
48 # following page: https://dart.dev/tools/pub/pubspec
cw_core/lib/solana_rpc_http_service.dart
+13 -20
@@ -1,33 +1,26 @@
1 +import 'dart:convert';
2 import 'package:http/http.dart';
3 import 'package:on_chain/solana/solana.dart';
4
4 -class SolanaRPCHTTPService implements SolanaServiceProvider {
5 +class SolanaRPCHTTPService implements SolanaJSONRPCService {
6 SolanaRPCHTTPService(
7 {required this.url, Client? client, this.defaultRequestTimeout = const Duration(seconds: 30)})
8 : client = client ?? Client();
8 -
9 + @override
10 final String url;
11 final Client client;
12 final Duration defaultRequestTimeout;
13
14 @override
14 - Future<SolanaServiceResponse<T>> doRequest<T>(SolanaRequestDetails params,
15 - {Duration? timeout}) async {
16 - if (!params.type.isPostRequest) {
17 - final response = await client.get(
18 - params.toUri(url),
19 - headers: {'Content-Type': 'application/json'},
20 - ).timeout(timeout ?? defaultRequestTimeout);
21 - return params.toResponse(response.bodyBytes, response.statusCode);
22 - }
23 -
24 - final response = await client
25 - .post(
26 - params.toUri(url),
27 - headers: {'Content-Type': 'application/json'},
28 - body: params.body(),
29 - )
30 - .timeout(timeout ?? defaultRequestTimeout);
31 - return params.toResponse(response.bodyBytes, response.statusCode);
15 + Future<Map<String, dynamic>> call(SolanaRequestDetails params, [Duration? timeout]) async {
16 + final response = await client.post(
17 + Uri.parse(url),
18 + body: params.toRequestBody(),
19 + headers: {
20 + 'Content-Type': 'application/json',
21 + },
22 + ).timeout(timeout ?? defaultRequestTimeout);
23 + final data = json.decode(response.body) as Map<String, dynamic>;
24 + return data;
25 }
26 }
cw_core/pubspec.lock
+6 -6
@@ -50,11 +50,11 @@ packages:
50 dependency: transitive
51 description:
52 path: "."
53 - ref: cake-update-v4
54 - resolved-ref: "437dadd0bd9bf73ec6a551299577799341f6486a"
53 + ref: cake-update-v2
54 + resolved-ref: "59fdf29d72068e0522a96a8953ed7272833a9f57"
55 url: "https://github.com/cake-tech/blockchain_utils"
56 source: git
57 - version: "4.3.0"
57 + version: "3.3.0"
58 boolean_selector:
59 dependency: transitive
60 description:
@@ -478,11 +478,11 @@ packages:
478 dependency: "direct main"
479 description:
480 path: "."
481 - ref: cake-update-v4
482 - resolved-ref: "084fb7bf13ec42d74f26ac08c883ce07c10fca7e"
481 + ref: cake-update-v2
482 + resolved-ref: "93440dc5126369b873ca1fccc13c3c1240b1c5c2"
483 url: "https://github.com/cake-tech/on_chain.git"
484 source: git
485 - version: "6.2.0"
485 + version: "3.7.0"
486 package_config:
487 dependency: transitive
488 description:
cw_core/pubspec.yaml
+1 -1
@@ -30,7 +30,7 @@ dependencies:
30 on_chain:
31 git:
32 url: https://github.com/cake-tech/on_chain.git
33 - ref: cake-update-v4
33 + ref: cake-update-v2
34 # tor:
35 # git:
36 # url: https://github.com/cake-tech/tor.git
cw_decred/pubspec.lock
+6 -6
@@ -50,11 +50,11 @@ packages:
50 dependency: transitive
51 description:
52 path: "."
53 - ref: cake-update-v4
54 - resolved-ref: "437dadd0bd9bf73ec6a551299577799341f6486a"
53 + ref: cake-update-v2
54 + resolved-ref: "59fdf29d72068e0522a96a8953ed7272833a9f57"
55 url: "https://github.com/cake-tech/blockchain_utils"
56 source: git
57 - version: "4.3.0"
57 + version: "3.3.0"
58 boolean_selector:
59 dependency: transitive
60 description:
@@ -501,11 +501,11 @@ packages:
501 dependency: transitive
502 description:
503 path: "."
504 - ref: cake-update-v4
505 - resolved-ref: "084fb7bf13ec42d74f26ac08c883ce07c10fca7e"
504 + ref: cake-update-v2
505 + resolved-ref: "93440dc5126369b873ca1fccc13c3c1240b1c5c2"
506 url: "https://github.com/cake-tech/on_chain.git"
507 source: git
508 - version: "6.2.0"
508 + version: "3.7.0"
509 package_config:
510 dependency: transitive
511 description:
cw_monero/pubspec.lock
+6 -6
@@ -66,11 +66,11 @@ packages:
66 dependency: transitive
67 description:
68 path: "."
69 - ref: cake-update-v4
70 - resolved-ref: "437dadd0bd9bf73ec6a551299577799341f6486a"
69 + ref: cake-update-v2
70 + resolved-ref: "59fdf29d72068e0522a96a8953ed7272833a9f57"
71 url: "https://github.com/cake-tech/blockchain_utils"
72 source: git
73 - version: "4.3.0"
73 + version: "3.3.0"
74 bluez:
75 dependency: transitive
76 description:
@@ -598,11 +598,11 @@ packages:
598 dependency: transitive
599 description:
600 path: "."
601 - ref: cake-update-v4
602 - resolved-ref: "084fb7bf13ec42d74f26ac08c883ce07c10fca7e"
601 + ref: cake-update-v2
602 + resolved-ref: "93440dc5126369b873ca1fccc13c3c1240b1c5c2"
603 url: "https://github.com/cake-tech/on_chain.git"
604 source: git
605 - version: "6.2.0"
605 + version: "3.7.0"
606 package_config:
607 dependency: transitive
608 description:
cw_nano/pubspec.lock
+6 -6
@@ -61,11 +61,11 @@ packages:
61 dependency: transitive
62 description:
63 path: "."
64 - ref: cake-update-v4
65 - resolved-ref: "437dadd0bd9bf73ec6a551299577799341f6486a"
64 + ref: cake-update-v2
65 + resolved-ref: "59fdf29d72068e0522a96a8953ed7272833a9f57"
66 url: "https://github.com/cake-tech/blockchain_utils"
67 source: git
68 - version: "4.3.0"
68 + version: "3.3.0"
69 boolean_selector:
70 dependency: transitive
71 description:
@@ -550,11 +550,11 @@ packages:
550 dependency: transitive
551 description:
552 path: "."
553 - ref: cake-update-v4
554 - resolved-ref: "084fb7bf13ec42d74f26ac08c883ce07c10fca7e"
553 + ref: cake-update-v2
554 + resolved-ref: "93440dc5126369b873ca1fccc13c3c1240b1c5c2"
555 url: "https://github.com/cake-tech/on_chain.git"
556 source: git
557 - version: "6.2.0"
557 + version: "3.7.0"
558 package_config:
559 dependency: transitive
560 description:
cw_solana/lib/solana_client.dart
+16 -16
@@ -19,7 +19,7 @@ import '.secrets.g.dart' as secrets;
19
20 class SolanaWalletClient {
21 final httpClient = http.Client();
22 - SolanaProvider? _provider;
22 + SolanaRPC? _provider;
23
24 bool connect(Node node) {
25 try {
@@ -38,7 +38,7 @@ class SolanaWalletClient {
38 formattedUrl = '$protocolUsed://${node.uriRaw}';
39 }
40
41 - _provider = SolanaProvider(SolanaRPCHTTPService(url: formattedUrl));
41 + _provider = SolanaRPC(SolanaRPCHTTPService(url: formattedUrl));
42
43 return true;
44 } catch (e) {
@@ -49,7 +49,7 @@ class SolanaWalletClient {
49 Future<double> getBalance(String walletAddress) async {
50 try {
51 final balance = await _provider!.requestWithContext(
52 - SolanaRequestGetBalance(
52 + SolanaRPCGetBalance(
53 account: SolAddress(walletAddress),
54 ),
55 );
@@ -68,11 +68,11 @@ class SolanaWalletClient {
68 String mintAddress, String publicKey) async {
69 try {
70 final result = await _provider!.request(
71 - SolanaRequestGetTokenAccountsByOwner(
71 + SolanaRPCGetTokenAccountsByOwner(
72 account: SolAddress(publicKey),
73 mint: SolAddress(mintAddress),
74 commitment: Commitment.confirmed,
75 - encoding: SolanaRequestEncoding.base64,
75 + encoding: SolanaRPCEncoding.base64,
76 ),
77 );
78
@@ -96,7 +96,7 @@ class SolanaWalletClient {
96
97 for (var tokenAccount in tokenAccounts) {
98 final tokenAmountResult = await _provider!.request(
99 - SolanaRequestGetTokenAccountBalance(account: tokenAccount.pubkey),
99 + SolanaRPCGetTokenAccountBalance(account: tokenAccount.pubkey),
100 );
101
102 final balance = tokenAmountResult.uiAmountString;
@@ -112,7 +112,7 @@ class SolanaWalletClient {
112 Future<double> getFeeForMessage(String message, Commitment commitment) async {
113 try {
114 final feeForMessage = await _provider!.request(
115 - SolanaRequestGetFeeForMessage(
115 + SolanaRPCGetFeeForMessage(
116 encodedMessage: message,
117 commitment: commitment,
118 ),
@@ -342,7 +342,7 @@ class SolanaWalletClient {
342 List<SolanaTransactionModel> transactions = [];
343 try {
344 final signatures = await _provider!.request(
345 - SolanaRequestGetSignaturesForAddress(
345 + SolanaRPCGetSignaturesForAddress(
346 account: address,
347 commitment: commitment,
348 ),
@@ -357,9 +357,9 @@ class SolanaWalletClient {
357 final batchResponses = await Future.wait(batch.map((signature) async {
358 try {
359 return await _provider!.request(
360 - SolanaRequestGetTransaction(
360 + SolanaRPCGetTransaction(
361 transactionSignature: signature['signature'],
362 - encoding: SolanaRequestEncoding.jsonParsed,
362 + encoding: SolanaRPCEncoding.jsonParsed,
363 maxSupportedTransactionVersion: 0,
364 ),
365 );
@@ -482,7 +482,7 @@ class SolanaWalletClient {
482
483 void stop() {}
484
485 - SolanaProvider? get getSolanaProvider => _provider;
485 + SolanaRPC? get getSolanaProvider => _provider;
486
487 Future<PendingSolanaTransaction> signSolanaTransaction({
488 required String tokenTitle,
@@ -523,7 +523,7 @@ class SolanaWalletClient {
523
524 Future<SolAddress> _getLatestBlockhash(Commitment commitment) async {
525 final latestBlockhash = await _provider!.request(
526 - const SolanaRequestGetLatestBlockhash(),
526 + const SolanaRPCGetLatestBlockhash(),
527 );
528
529 return latestBlockhash.blockhash;
@@ -599,7 +599,7 @@ class SolanaWalletClient {
599 required double fee,
600 }) async {
601 final rent = await _provider!.request(
602 - SolanaRequestGetMinimumBalanceForRentExemption(
602 + SolanaRPCGetMinimumBalanceForRentExemption(
603 size: SolanaTokenAccountUtils.accountSize,
604 ),
605 );
@@ -732,7 +732,7 @@ class SolanaWalletClient {
732 SolanaAccountInfo? accountInfo;
733 try {
734 accountInfo = await _provider!.request(
735 - SolanaRequestGetAccountInfo(account: associatedTokenAccount.address),
735 + SolanaRPCGetAccountInfo(account: associatedTokenAccount.address),
736 );
737 } catch (e) {
738 accountInfo = null;
@@ -890,7 +890,7 @@ class SolanaWalletClient {
890 }) async {
891 /// Sign the transaction with the owner's private key.
892 final ownerSignature = ownerPrivateKey.sign(transaction.serializeMessage());
893 -
893 +
894 transaction.addSignature(ownerPrivateKey.publicKey().toAddress(), ownerSignature);
895
896 /// Serialize the transaction.
@@ -906,7 +906,7 @@ class SolanaWalletClient {
906 try {
907 /// Send the transaction to the Solana network.
908 final signature = await _provider!.request(
909 - SolanaRequestSendTransaction(
909 + SolanaRPCSendTransaction(
910 encodedTransaction: serializedTransaction,
911 commitment: commitment,
912 ),
cw_solana/lib/solana_wallet.dart
+1 -1
@@ -611,7 +611,7 @@ abstract class SolanaWalletBase
611 );
612 }
613
614 - SolanaProvider? get solanaProvider => _client.getSolanaProvider;
614 + SolanaRPC? get solanaProvider => _client.getSolanaProvider;
615
616 @override
617 String get password => _password;
cw_solana/pubspec.yaml
+2 -2
@@ -23,11 +23,11 @@ dependencies:
23 on_chain:
24 git:
25 url: https://github.com/cake-tech/on_chain.git
26 - ref: cake-update-v4
26 + ref: cake-update-v2
27 blockchain_utils:
28 git:
29 url: https://github.com/cake-tech/blockchain_utils
30 - ref: cake-update-v4
30 + ref: cake-update-v2
31
32 dev_dependencies:
33 flutter_test:
cw_tron/lib/tron_client.dart
+4 -4
@@ -235,7 +235,7 @@ class TronClient {
235 String contractAddress = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
236 String constantAmount =
237 '0'; // We're using 0 as the base amount here as we get an error when balance is zero i.e for new wallets.
238 - final contract = ContractABI.fromJson(trc20Abi);
238 + final contract = ContractABI.fromJson(trc20Abi, isTron: true);
239
240 final function = contract.functionFromName("transfer");
241
@@ -405,7 +405,7 @@ class TronClient {
405 String contractAddress,
406 BigInt tronBalance,
407 ) async {
408 - final contract = ContractABI.fromJson(trc20Abi);
408 + final contract = ContractABI.fromJson(trc20Abi, isTron: true);
409
410 final function = contract.functionFromName("transfer");
411
@@ -483,7 +483,7 @@ class TronClient {
483
484 final tokenAddress = TronAddress(contractAddress);
485
486 - final contract = ContractABI.fromJson(trc20Abi);
486 + final contract = ContractABI.fromJson(trc20Abi, isTron: true);
487
488 final function = contract.functionFromName("balanceOf");
489
@@ -510,7 +510,7 @@ class TronClient {
510
511 final ownerAddress = TronAddress(userAddress);
512
513 - final contract = ContractABI.fromJson(trc20Abi);
513 + final contract = ContractABI.fromJson(trc20Abi, isTron: true);
514
515 final name =
516 (await getTokenDetail(contract, "name", ownerAddress, tokenAddress) as String?) ?? '';
cw_tron/lib/tron_http_provider.dart
+24 -25
@@ -1,6 +1,8 @@
1 +import 'dart:convert';
2 +
3 import 'package:http/http.dart' as http;
2 -import '.secrets.g.dart' as secrets;
4 import 'package:on_chain/tron/tron.dart';
5 +import '.secrets.g.dart' as secrets;
6
7 class TronHTTPProvider implements TronServiceProvider {
8 TronHTTPProvider(
@@ -8,37 +10,34 @@ class TronHTTPProvider implements TronServiceProvider {
10 http.Client? client,
11 this.defaultRequestTimeout = const Duration(seconds: 30)})
12 : client = client ?? http.Client();
11 -
13 + @override
14 final String url;
15 final http.Client client;
16 final Duration defaultRequestTimeout;
17
18 @override
17 - Future<TronServiceResponse<T>> doRequest<T>(TronRequestDetails params,
18 - {Duration? timeout}) async {
19 - if (!params.type.isPostRequest) {
20 - final response = await client.get(
21 - params.toUri(url),
22 - headers: {
23 - 'Content-Type': 'application/json',
24 - if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
25 - if (url.contains("nownodes")) 'api-key': secrets.tronNowNodesApiKey,
26 - },
27 - ).timeout(timeout ?? defaultRequestTimeout);
28 - return params.toResponse(response.bodyBytes, response.statusCode);
29 - }
19 + Future<Map<String, dynamic>> get(TronRequestDetails params, [Duration? timeout]) async {
20 + final response = await client.get(Uri.parse(params.url(url)), headers: {
21 + 'Content-Type': 'application/json',
22 + if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
23 + if (url.contains("nownodes")) 'api-key': secrets.tronNowNodesApiKey,
24 + }).timeout(timeout ?? defaultRequestTimeout);
25 + final data = json.decode(response.body) as Map<String, dynamic>;
26 + return data;
27 + }
28
29 + @override
30 + Future<Map<String, dynamic>> post(TronRequestDetails params, [Duration? timeout]) async {
31 final response = await client
32 - .post(
33 - params.toUri(url),
34 - headers: {
35 - 'Content-Type': 'application/json',
36 - if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
37 - if (url.contains("nownodes")) 'api-key': secrets.tronNowNodesApiKey,
38 - },
39 - body: params.body(),
40 - )
32 + .post(Uri.parse(params.url(url)),
33 + headers: {
34 + 'Content-Type': 'application/json',
35 + if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
36 + if (url.contains("nownodes")) 'api-key': secrets.tronNowNodesApiKey,
37 + },
38 + body: params.toRequestBody())
39 .timeout(timeout ?? defaultRequestTimeout);
42 - return params.toResponse(response.bodyBytes, response.statusCode);
40 + final data = json.decode(response.body) as Map<String, dynamic>;
41 + return data;
42 }
43 }
cw_tron/lib/tron_transaction_model.dart
+1 -2
@@ -1,6 +1,5 @@
1 import 'package:blockchain_utils/hex/hex.dart';
2 import 'package:on_chain/on_chain.dart';
3 -import 'package:on_chain/solidity/address/core.dart';
3
4 class TronTRC20TransactionModel extends TronTransactionModel {
5 String? transactionId;
@@ -189,7 +188,7 @@ class Value {
188 output = output.replaceFirst('0x', '').substring(8);
189 final abiCoder = ABICoder.fromType('address');
190 final decoded = abiCoder.decode(AbiParameter.bytes, hex.decode(output));
192 - final tronAddress = TronAddress.fromEthAddress((decoded.result as SolidityAddress).toBytes());
191 + final tronAddress = TronAddress.fromEthAddress((decoded.result as ETHAddress).toBytes());
192
193 return tronAddress.toString();
194 }
cw_tron/lib/tron_wallet.dart
+20 -23
@@ -31,7 +31,7 @@ import 'package:cw_tron/tron_transaction_info.dart';
31 import 'package:cw_tron/tron_wallet_addresses.dart';
32 import 'package:hive/hive.dart';
33 import 'package:mobx/mobx.dart';
34 -import 'package:on_chain/on_chain.dart' as on_chain;
34 +import 'package:on_chain/on_chain.dart';
35
36 part 'tron_wallet.g.dart';
37
@@ -74,13 +74,13 @@ abstract class TronWalletBase
74
75 late final Box<TronToken> tronTokensBox;
76
77 - late final on_chain.TronPrivateKey _tronPrivateKey;
77 + late final TronPrivateKey _tronPrivateKey;
78
79 - late final on_chain.TronPublicKey _tronPublicKey;
79 + late final TronPublicKey _tronPublicKey;
80
81 - on_chain.TronPublicKey get tronPublicKey => _tronPublicKey;
81 + TronPublicKey get tronPublicKey => _tronPublicKey;
82
83 - on_chain.TronPrivateKey get tronPrivateKey => _tronPrivateKey;
83 + TronPrivateKey get tronPrivateKey => _tronPrivateKey;
84
85 late String _tronAddress;
86
@@ -190,7 +190,7 @@ abstract class TronWalletBase
190
191 String idFor(String name, WalletType type) => '${walletTypeToString(type).toLowerCase()}_$name';
192
193 - Future<on_chain.TronPrivateKey> getPrivateKey({
193 + Future<TronPrivateKey> getPrivateKey({
194 String? mnemonic,
195 String? privateKey,
196 required String password,
@@ -198,7 +198,7 @@ abstract class TronWalletBase
198 }) async {
199 assert(mnemonic != null || privateKey != null);
200
201 - if (privateKey != null) return on_chain.TronPrivateKey(privateKey);
201 + if (privateKey != null) return TronPrivateKey(privateKey);
202
203 final seed = bip39.mnemonicToSeed(mnemonic!, passphrase: passphrase ?? '');
204
@@ -207,7 +207,7 @@ abstract class TronWalletBase
207
208 final childKey = bip44.deriveDefaultPath;
209
210 - return on_chain.TronPrivateKey.fromBytes(childKey.privateKey.raw);
210 + return TronPrivateKey.fromBytes(childKey.privateKey.raw);
211 }
212
213 @override
@@ -242,10 +242,10 @@ abstract class TronWalletBase
242
243 Future<void> _getEstimatedFees() async {
244 final nativeFee = await _getNativeTxFee();
245 - nativeTxEstimatedFee = on_chain.TronHelper.fromSun(BigInt.from(nativeFee));
245 + nativeTxEstimatedFee = TronHelper.fromSun(BigInt.from(nativeFee));
246
247 final trc20Fee = await _getTrc20TxFee();
248 - trc20EstimatedFee = on_chain.TronHelper.fromSun(BigInt.from(trc20Fee));
248 + trc20EstimatedFee = TronHelper.fromSun(BigInt.from(trc20Fee));
249
250 log('Native Estimated Fee: $nativeTxEstimatedFee');
251 log('TRC20 Estimated Fee: $trc20EstimatedFee');
@@ -323,7 +323,7 @@ abstract class TronWalletBase
323 totalAmount = walletBalanceForCurrency;
324 } else {
325 final totalOriginalAmount = double.parse(output.cryptoAmount ?? '0.0');
326 - totalAmount = on_chain.TronHelper.toSun(totalOriginalAmount.toString());
326 + totalAmount = TronHelper.toSun(totalOriginalAmount.toString());
327 }
328
329 if (walletBalanceForCurrency < totalAmount || totalAmount < BigInt.zero) {
@@ -338,7 +338,7 @@ abstract class TronWalletBase
338 toAddress: tronCredentials.outputs.first.isParsedAddress
339 ? tronCredentials.outputs.first.extractedAddress!
340 : tronCredentials.outputs.first.address,
341 - amount: on_chain.TronHelper.fromSun(totalAmount),
341 + amount: TronHelper.fromSun(totalAmount),
342 currency: transactionCurrency,
343 tronBalance: tronBalance,
344 sendAll: shouldSendAll,
@@ -355,9 +355,9 @@ abstract class TronWalletBase
355
356 final Map<String, TronTransactionInfo> result = {};
357
358 - final contract = on_chain.ContractABI.fromJson(trc20Abi);
358 + final contract = ContractABI.fromJson(trc20Abi, isTron: true);
359
360 - final ownerAddress = on_chain.TronAddress(_tronAddress);
360 + final ownerAddress = TronAddress(_tronAddress);
361
362 for (var transactionModel in transactions) {
363 if (transactionModel.isError) {
@@ -371,7 +371,7 @@ abstract class TronWalletBase
371
372 String? tokenSymbol;
373 if (transactionModel.contractAddress != null) {
374 - final tokenAddress = on_chain.TronAddress(transactionModel.contractAddress!);
374 + final tokenAddress = TronAddress(transactionModel.contractAddress!);
375
376 tokenSymbol = (await _client.getTokenDetail(
377 contract,
@@ -385,10 +385,9 @@ abstract class TronWalletBase
385 result[transactionModel.hash] = TronTransactionInfo(
386 id: transactionModel.hash,
387 tronAmount: transactionModel.amount ?? BigInt.zero,
388 - direction:
389 - on_chain.TronAddress(transactionModel.from!, visible: false).toAddress() == address
390 - ? TransactionDirection.outgoing
391 - : TransactionDirection.incoming,
388 + direction: TronAddress(transactionModel.from!, visible: false).toAddress() == address
389 + ? TransactionDirection.outgoing
390 + : TransactionDirection.incoming,
391 blockTime: transactionModel.date,
392 txFee: transactionModel.fee,
393 tokenSymbol: tokenSymbol ?? "TRX",
@@ -605,13 +604,11 @@ abstract class TronWalletBase
604 if (address == null) {
605 return false;
606 }
608 - on_chain.TronPublicKey pubKey =
609 - on_chain.TronPublicKey.fromPersonalSignature(ascii.encode(message), signature)!;
607 + TronPublicKey pubKey = TronPublicKey.fromPersonalSignature(ascii.encode(message), signature)!;
608 return pubKey.toAddress().toString() == address;
609 }
610
613 - String getTronBase58AddressFromHex(String hexAddress) =>
614 - on_chain.TronAddress(hexAddress).toAddress();
611 + String getTronBase58AddressFromHex(String hexAddress) => TronAddress(hexAddress).toAddress();
612
613 void updateScanProviderUsageState(bool isEnabled) {
614 if (isEnabled) {
cw_tron/pubspec.yaml
+2 -2
@@ -18,11 +18,11 @@ dependencies:
18 on_chain:
19 git:
20 url: https://github.com/cake-tech/on_chain.git
21 - ref: cake-update-v4
21 + ref: cake-update-v2
22 blockchain_utils:
23 git:
24 url: https://github.com/cake-tech/blockchain_utils
25 - ref: cake-update-v4
25 + ref: cake-update-v2
26 mobx: ^2.3.0+1
27 bip39: ^1.0.6
28 hive: ^2.2.3
cw_wownero/pubspec.lock
+6 -6
@@ -45,11 +45,11 @@ packages:
45 dependency: transitive
46 description:
47 path: "."
48 - ref: cake-update-v4
49 - resolved-ref: "437dadd0bd9bf73ec6a551299577799341f6486a"
48 + ref: cake-update-v2
49 + resolved-ref: "59fdf29d72068e0522a96a8953ed7272833a9f57"
50 url: "https://github.com/cake-tech/blockchain_utils"
51 source: git
52 - version: "4.3.0"
52 + version: "3.3.0"
53 boolean_selector:
54 dependency: transitive
55 description:
@@ -505,11 +505,11 @@ packages:
505 dependency: transitive
506 description:
507 path: "."
508 - ref: cake-update-v4
509 - resolved-ref: "084fb7bf13ec42d74f26ac08c883ce07c10fca7e"
508 + ref: cake-update-v2
509 + resolved-ref: "93440dc5126369b873ca1fccc13c3c1240b1c5c2"
510 url: "https://github.com/cake-tech/on_chain.git"
511 source: git
512 - version: "6.2.0"
512 + version: "3.7.0"
513 package_config:
514 dependency: transitive
515 description:
cw_zano/pubspec.lock
+6 -6
@@ -45,11 +45,11 @@ packages:
45 dependency: transitive
46 description:
47 path: "."
48 - ref: cake-update-v4
49 - resolved-ref: "437dadd0bd9bf73ec6a551299577799341f6486a"
48 + ref: cake-update-v2
49 + resolved-ref: "59fdf29d72068e0522a96a8953ed7272833a9f57"
50 url: "https://github.com/cake-tech/blockchain_utils"
51 source: git
52 - version: "4.3.0"
52 + version: "3.3.0"
53 boolean_selector:
54 dependency: transitive
55 description:
@@ -502,11 +502,11 @@ packages:
502 dependency: transitive
503 description:
504 path: "."
505 - ref: cake-update-v4
506 - resolved-ref: "084fb7bf13ec42d74f26ac08c883ce07c10fca7e"
505 + ref: cake-update-v2
506 + resolved-ref: "93440dc5126369b873ca1fccc13c3c1240b1c5c2"
507 url: "https://github.com/cake-tech/on_chain.git"
508 source: git
509 - version: "6.2.0"
509 + version: "3.7.0"
510 package_config:
511 dependency: transitive
512 description:
lib/bitcoin/cw_bitcoin.dart
+9 -9
@@ -213,9 +213,9 @@ class CWBitcoin extends Bitcoin {
213 return bitcoinWallet.unspentCoins.where((element) {
214 switch (coinTypeToSpendFrom) {
215 case UnspentCoinType.mweb:
216 - return element.bitcoinAddressRecord.type == SegwitAddressType.mweb;
216 + return element.bitcoinAddressRecord.type == SegwitAddresType.mweb;
217 case UnspentCoinType.nonMweb:
218 - return element.bitcoinAddressRecord.type != SegwitAddressType.mweb;
218 + return element.bitcoinAddressRecord.type != SegwitAddresType.mweb;
219 case UnspentCoinType.any:
220 return true;
221 }
@@ -296,14 +296,14 @@ class CWBitcoin extends Bitcoin {
296 case BitcoinReceivePageOption.p2sh:
297 return P2shAddressType.p2wpkhInP2sh;
298 case BitcoinReceivePageOption.p2tr:
299 - return SegwitAddressType.p2tr;
299 + return SegwitAddresType.p2tr;
300 case BitcoinReceivePageOption.p2wsh:
301 - return SegwitAddressType.p2wsh;
301 + return SegwitAddresType.p2wsh;
302 case BitcoinReceivePageOption.mweb:
303 - return SegwitAddressType.mweb;
303 + return SegwitAddresType.mweb;
304 case BitcoinReceivePageOption.p2wpkh:
305 default:
306 - return SegwitAddressType.p2wpkh;
306 + return SegwitAddresType.p2wpkh;
307 }
308 }
309
@@ -527,7 +527,7 @@ class CWBitcoin extends Bitcoin {
527 List<ElectrumSubAddress> getSilentPaymentAddresses(Object wallet) {
528 final bitcoinWallet = wallet as ElectrumWallet;
529 return bitcoinWallet.walletAddresses.silentAddresses
530 - .where((addr) => addr.type != SegwitAddressType.p2tr)
530 + .where((addr) => addr.type != SegwitAddresType.p2tr)
531 .map((addr) => ElectrumSubAddress(
532 id: addr.index,
533 name: addr.name,
@@ -542,7 +542,7 @@ class CWBitcoin extends Bitcoin {
542 List<ElectrumSubAddress> getSilentPaymentReceivedAddresses(Object wallet) {
543 final bitcoinWallet = wallet as ElectrumWallet;
544 return bitcoinWallet.walletAddresses.silentAddresses
545 - .where((addr) => addr.type == SegwitAddressType.p2tr)
545 + .where((addr) => addr.type == SegwitAddresType.p2tr)
546 .map((addr) => ElectrumSubAddress(
547 id: addr.index,
548 name: addr.name,
@@ -712,7 +712,7 @@ class CWBitcoin extends Bitcoin {
712 try {
713 final electrumWallet = wallet as ElectrumWallet;
714 final segwitAddress = electrumWallet.walletAddresses.allAddresses
715 - .firstWhere((element) => !element.isUsed && element.type == SegwitAddressType.p2wpkh);
715 + .firstWhere((element) => !element.isUsed && element.type == SegwitAddresType.p2wpkh);
716 return segwitAddress.address;
717 } catch (_) {
718 return null;
pubspec_base.yaml
+3 -3
@@ -115,12 +115,12 @@ dependencies:
115 on_chain:
116 git:
117 url: https://github.com/cake-tech/on_chain.git
118 - ref: cake-update-v4
118 + ref: cake-update-v2
119 reown_walletkit: ^1.1.2
120 blockchain_utils:
121 git:
122 url: https://github.com/cake-tech/blockchain_utils
123 - ref: cake-update-v4
123 + ref: cake-update-v2
124 flutter_daemon:
125 git:
126 url: https://github.com/MrCyjaneK/flutter_daemon
@@ -160,7 +160,7 @@ dependency_overrides:
160 bitcoin_base:
161 git:
162 url: https://github.com/cake-tech/bitcoin_base
163 - ref: cake-update-v15
163 + ref: cake-update-v9
164 ffi: 2.1.0
165 ledger_flutter_plus:
166 git:
tool/download_moneroc_prebuilds.py deleted
-76
@@ -1,76 +0,0 @@
1 -#!/usr/bin/env python3
2 -
3 -import os
4 -import subprocess
5 -import requests
6 -import lzma
7 -import shutil
8 -
9 -
10 -
11 -# Define triplets list
12 -triplets = [
13 - "x86_64-linux-gnu",
14 - "x86_64-linux-android",
15 - "aarch64-linux-android",
16 - "armv7a-linux-androideabi",
17 - # "x86_64-w64-mingw32",
18 - # "aarch64-apple-darwin",
19 - # "x86_64-apple-darwin",
20 - "aarch64-host-apple-darwin",
21 - # "aarch64-apple-ios",
22 - # "aarch64-apple-iossimulator",
23 -]
24 -
25 -
26 -def main():
27 - # Get the latest release data
28 - resp = requests.get("https://api.github.com/repos/mrcyjanek/monero_c/releases")
29 - data = resp.json()[0]
30 - tag_name = data["tag_name"]
31 - print(f"Downloading artifacts for: {tag_name}")
32 -
33 - assets = data["assets"]
34 - for asset in assets:
35 - for triplet in triplets:
36 - filename = asset["name"]
37 - if triplet not in filename:
38 - continue
39 -
40 - coin = filename.split("_")[0]
41 - local_filename = filename.replace(f"{coin}_{triplet}_", "")
42 - local_filename = (
43 - f"scripts/monero_c/release/{coin}/{triplet}_{local_filename}"
44 - )
45 -
46 - # Create directory if it doesn't exist
47 - os.makedirs(os.path.dirname(local_filename), exist_ok=True)
48 -
49 - url = asset["browser_download_url"]
50 - print(f"- downloading {local_filename}")
51 -
52 - # Download the file
53 - response = requests.get(url)
54 - with open(local_filename, "wb") as f:
55 - f.write(response.content)
56 -
57 - # Extract if it's an .xz file
58 - if local_filename.endswith(".xz"):
59 - print(f" extracting {local_filename}")
60 - with lzma.open(local_filename) as f_in:
61 - with open(local_filename.replace(".xz", ""), "wb") as f_out:
62 - shutil.copyfileobj(f_in, f_out)
63 -
64 - # Generate iOS framework if on macOS
65 - if os.uname().sysname == "Darwin": # Check if on macOS
66 - print("Generating ios framework")
67 - result = subprocess.run(
68 - ["bash", "-c", "cd scripts/ios && ./gen_framework.sh && cd ../.."],
69 - capture_output=True,
70 - text=True,
71 - )
72 - print(result.stdout.strip() + result.stderr.strip())
73 -
74 -
75 -if __name__ == "__main__":
76 - main()