Skip to content

Commit e8bcf6a

Browse files
committed
fix: debugging keystone integration
feat: support for zpub view only restore
1 parent cb9ac69 commit e8bcf6a

File tree

17 files changed

+261
-62
lines changed

17 files changed

+261
-62
lines changed

cw_bitcoin/lib/bitcoin_wallet.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import 'package:cw_core/payjoin_session.dart';
2626
import 'package:cw_core/pending_transaction.dart';
2727
import 'package:cw_core/unspent_coins_info.dart';
2828
import 'package:cw_core/utils/print_verbose.dart';
29+
import 'package:cw_core/utils/zpub.dart';
2930
import 'package:cw_core/wallet_info.dart';
3031
import 'package:cw_core/wallet_keys_file.dart';
3132
import 'package:flutter/foundation.dart';
@@ -241,7 +242,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
241242

242243
return BitcoinWallet(
243244
mnemonic: mnemonic,
244-
xpub: keysData.xPub,
245+
xpub: keysData.xPub != null ? convertZpubToXpub(keysData.xPub!) : null,
245246
password: password,
246247
passphrase: passphrase,
247248
walletInfo: walletInfo,

cw_bitcoin/lib/bitcoin_wallet_service.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
77
import 'package:cw_core/encryption_file_utils.dart';
88
import 'package:cw_core/payjoin_session.dart';
99
import 'package:cw_core/unspent_coins_info.dart';
10+
import 'package:cw_core/utils/zpub.dart';
1011
import 'package:cw_core/wallet_base.dart';
1112
import 'package:cw_core/wallet_service.dart';
1213
import 'package:cw_bitcoin/bitcoin_wallet.dart';
@@ -150,9 +151,12 @@ class BitcoinWalletService extends WalletService<
150151
credentials.walletInfo?.network = network.value;
151152
credentials.walletInfo?.derivationInfo?.derivationPath =
152153
credentials.hwAccountData.derivationPath;
154+
155+
final xpub = convertZpubToXpub(credentials.hwAccountData.xpub!);
156+
153157
final wallet = await BitcoinWallet(
154158
password: credentials.password!,
155-
xpub: credentials.hwAccountData.xpub,
159+
xpub: xpub,
156160
walletInfo: credentials.walletInfo!,
157161
unspentCoinsInfo: unspentCoinsInfoSource,
158162
networkParam: network,
@@ -166,13 +170,15 @@ class BitcoinWalletService extends WalletService<
166170

167171
@override
168172
Future<BitcoinWallet> restoreFromKeys(BitcoinWalletFromKeysCredentials credentials,
169-
{bool? isTestnet}) async {
173+
{bool? isTestnet}) async {
170174
final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet;
171175
credentials.walletInfo?.network = network.value;
172176

177+
final xpub = convertZpubToXpub(credentials.xpub);
178+
173179
final wallet = await BitcoinWallet(
174180
password: credentials.password!,
175-
xpub: credentials.xpub,
181+
xpub: xpub,
176182
walletInfo: credentials.walletInfo!,
177183
unspentCoinsInfo: unspentCoinsInfoSource,
178184
networkParam: network,

cw_bitcoin/lib/utils.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:typed_data';
12
import 'package:bitcoin_base/bitcoin_base.dart';
23
import 'package:blockchain_utils/blockchain_utils.dart';
34

@@ -51,4 +52,4 @@ String generateP2TRAddress({
5152
}) =>
5253
ECPublic.fromBip32(hd.childKey(Bip32KeyIndex(index)).publicKey)
5354
.toTaprootAddress()
54-
.toAddress(network);
55+
.toAddress(network);

cw_bitcoin/pubspec.lock

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ packages:
4242
dependency: transitive
4343
description:
4444
name: async
45-
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
45+
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
4646
url: "https://pub.dev"
4747
source: hosted
48-
version: "2.12.0"
48+
version: "2.11.0"
4949
bbqrdart:
5050
dependency: "direct main"
5151
description:
@@ -93,8 +93,8 @@ packages:
9393
dependency: "direct overridden"
9494
description:
9595
path: "."
96-
ref: "490046a3e074dd7b9aaf7098a5efe61b6246d3b2"
97-
resolved-ref: "46e5a2d8a5438cb523a6104b70f5e5125a5663b3"
96+
ref: cake-update-v11
97+
resolved-ref: bda0e2904effa799ec835b4578cc3fc5d31caa78
9898
url: "https://github.com/cake-tech/bitcoin_base"
9999
source: git
100100
version: "4.7.0"
@@ -119,10 +119,10 @@ packages:
119119
dependency: transitive
120120
description:
121121
name: boolean_selector
122-
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
122+
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
123123
url: "https://pub.dev"
124124
source: hosted
125-
version: "2.1.2"
125+
version: "2.1.1"
126126
bs58check:
127127
dependency: transitive
128128
description:
@@ -216,10 +216,10 @@ packages:
216216
dependency: transitive
217217
description:
218218
name: characters
219-
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
219+
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
220220
url: "https://pub.dev"
221221
source: hosted
222-
version: "1.4.0"
222+
version: "1.3.0"
223223
checked_yaml:
224224
dependency: transitive
225225
description:
@@ -240,10 +240,10 @@ packages:
240240
dependency: transitive
241241
description:
242242
name: clock
243-
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
243+
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
244244
url: "https://pub.dev"
245245
source: hosted
246-
version: "1.1.2"
246+
version: "1.1.1"
247247
code_builder:
248248
dependency: transitive
249249
description:
@@ -256,10 +256,10 @@ packages:
256256
dependency: transitive
257257
description:
258258
name: collection
259-
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
259+
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
260260
url: "https://pub.dev"
261261
source: hosted
262-
version: "1.19.1"
262+
version: "1.19.0"
263263
convert:
264264
dependency: transitive
265265
description:
@@ -350,10 +350,10 @@ packages:
350350
dependency: transitive
351351
description:
352352
name: fake_async
353-
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
353+
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
354354
url: "https://pub.dev"
355355
source: hosted
356-
version: "1.3.2"
356+
version: "1.3.1"
357357
ffi:
358358
dependency: "direct overridden"
359359
description:
@@ -573,18 +573,18 @@ packages:
573573
dependency: transitive
574574
description:
575575
name: leak_tracker
576-
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
576+
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
577577
url: "https://pub.dev"
578578
source: hosted
579-
version: "10.0.8"
579+
version: "10.0.7"
580580
leak_tracker_flutter_testing:
581581
dependency: transitive
582582
description:
583583
name: leak_tracker_flutter_testing
584-
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
584+
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
585585
url: "https://pub.dev"
586586
source: hosted
587-
version: "3.0.9"
587+
version: "3.0.8"
588588
leak_tracker_testing:
589589
dependency: transitive
590590
description:
@@ -647,10 +647,10 @@ packages:
647647
dependency: transitive
648648
description:
649649
name: matcher
650-
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
650+
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
651651
url: "https://pub.dev"
652652
source: hosted
653-
version: "0.12.17"
653+
version: "0.12.16+1"
654654
material_color_utilities:
655655
dependency: transitive
656656
description:
@@ -663,10 +663,10 @@ packages:
663663
dependency: transitive
664664
description:
665665
name: meta
666-
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
666+
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
667667
url: "https://pub.dev"
668668
source: hosted
669-
version: "1.16.0"
669+
version: "1.15.0"
670670
mime:
671671
dependency: transitive
672672
description:
@@ -728,10 +728,10 @@ packages:
728728
dependency: transitive
729729
description:
730730
name: path
731-
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
731+
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
732732
url: "https://pub.dev"
733733
source: hosted
734-
version: "1.9.1"
734+
version: "1.9.0"
735735
path_provider:
736736
dependency: "direct main"
737737
description:
@@ -1000,10 +1000,10 @@ packages:
10001000
dependency: transitive
10011001
description:
10021002
name: source_span
1003-
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
1003+
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
10041004
url: "https://pub.dev"
10051005
source: hosted
1006-
version: "1.10.1"
1006+
version: "1.10.0"
10071007
sp_scanner:
10081008
dependency: "direct main"
10091009
description:
@@ -1025,18 +1025,18 @@ packages:
10251025
dependency: transitive
10261026
description:
10271027
name: stack_trace
1028-
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
1028+
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
10291029
url: "https://pub.dev"
10301030
source: hosted
1031-
version: "1.12.1"
1031+
version: "1.12.0"
10321032
stream_channel:
10331033
dependency: transitive
10341034
description:
10351035
name: stream_channel
1036-
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
1036+
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
10371037
url: "https://pub.dev"
10381038
source: hosted
1039-
version: "2.1.4"
1039+
version: "2.1.2"
10401040
stream_transform:
10411041
dependency: transitive
10421042
description:
@@ -1049,26 +1049,26 @@ packages:
10491049
dependency: transitive
10501050
description:
10511051
name: string_scanner
1052-
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
1052+
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
10531053
url: "https://pub.dev"
10541054
source: hosted
1055-
version: "1.4.1"
1055+
version: "1.3.0"
10561056
term_glyph:
10571057
dependency: transitive
10581058
description:
10591059
name: term_glyph
1060-
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
1060+
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
10611061
url: "https://pub.dev"
10621062
source: hosted
1063-
version: "1.2.2"
1063+
version: "1.2.1"
10641064
test_api:
10651065
dependency: transitive
10661066
description:
10671067
name: test_api
1068-
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
1068+
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
10691069
url: "https://pub.dev"
10701070
source: hosted
1071-
version: "0.7.4"
1071+
version: "0.7.3"
10721072
timing:
10731073
dependency: transitive
10741074
description:
@@ -1153,10 +1153,10 @@ packages:
11531153
dependency: transitive
11541154
description:
11551155
name: vm_service
1156-
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
1156+
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
11571157
url: "https://pub.dev"
11581158
source: hosted
1159-
version: "14.3.1"
1159+
version: "14.3.0"
11601160
watcher:
11611161
dependency: "direct overridden"
11621162
description:
@@ -1222,5 +1222,5 @@ packages:
12221222
source: hosted
12231223
version: "2.2.2"
12241224
sdks:
1225-
dart: ">=3.7.0-0 <4.0.0"
1225+
dart: ">=3.6.2 <4.0.0"
12261226
flutter: ">=3.27.0"

cw_core/lib/utils/zpub.dart

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
import 'dart:typed_data';
3+
4+
import 'package:blockchain_utils/blockchain_utils.dart';
5+
6+
String convertZpubToXpub(String zpub) {
7+
try {
8+
final decoded = Base58Decoder.checkDecode(zpub);
9+
10+
if (decoded.length < 4) {
11+
throw ArgumentError('Invalid extended public key length');
12+
}
13+
14+
final versionBytes = decoded.sublist(0, 4);
15+
final zpubVersionBytes = [0x04, 0xb2, 0x47, 0x46]; // zpub mainnet version
16+
final zpubTestnetVersionBytes = [0x04, 0x5f, 0x1c, 0xf6]; // vpub testnet version
17+
18+
bool isZpub = listEquals(versionBytes, zpubVersionBytes);
19+
bool isVpub = listEquals(versionBytes, zpubTestnetVersionBytes);
20+
21+
if (!isZpub && !isVpub) {
22+
return zpub;
23+
}
24+
25+
final xpubVersionBytes = isZpub ?
26+
[0x04, 0x88, 0xb2, 0x1e] : // xpub mainnet
27+
[0x04, 0x35, 0x87, 0xcf]; // tpub testnet
28+
29+
final newExtendedKey = Uint8List.fromList([
30+
...xpubVersionBytes,
31+
...decoded.sublist(4),
32+
]);
33+
34+
return Base58Encoder.checkEncode(newExtendedKey);
35+
} catch (e) {
36+
throw ArgumentError('Failed to convert zpub to xpub: $e');
37+
}
38+
}
39+
40+
bool listEquals<T>(List<T> a, List<T> b) {
41+
if (a.length != b.length) return false;
42+
for (int i = 0; i < a.length; i++) {
43+
if (a[i] != b[i]) return false;
44+
}
45+
return true;
46+
}

cw_core/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ packages:
4747
source: hosted
4848
version: "2.11.0"
4949
blockchain_utils:
50-
dependency: transitive
50+
dependency: "direct main"
5151
description:
5252
path: "."
5353
ref: cake-update-v2

cw_core/pubspec.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ dependencies:
4040
ref: e6232c53c1595469931ababa878759a067c02e94
4141
torch_dart:
4242
path: ../scripts/torch_dart
43+
blockchain_utils:
44+
git:
45+
url: https://github.com/cake-tech/blockchain_utils
46+
ref: cake-update-v2
4347

4448
dev_dependencies:
4549
flutter_test:

0 commit comments

Comments
 (0)