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()