Line data Source code
1 : import 'package:bip32/bip32.dart';
2 : import 'package:walletkit_dart/walletkit_dart.dart';
3 :
4 : /// TODO: Make sure this only has the privateKey when used for signing. Else EpubKey should be used.
5 :
6 : sealed class NodeWithAddress {
7 : final int type;
8 : final BIP32? bip32Node;
9 : final String address;
10 : final String derivationPath;
11 : final Map<AddressType, String> addresses;
12 : final HDWalletPurpose? walletPurpose;
13 : final String publicKey;
14 :
15 0 : bool get isNeutered => bip32Node?.isNeutered() ?? true;
16 :
17 32 : List<String> get addressesList => addresses.values.toList();
18 :
19 0 : int get index => derivationPath.split("/").last.toInt;
20 :
21 0 : int get chainIndex => switch (this) {
22 0 : ReceiveNode() => EXTERNAL_CHAIN_INDEX,
23 0 : ChangeNode() => INTERNAL_CHAIN_INDEX,
24 0 : EmptyNode() => -1,
25 : };
26 :
27 0 : NodeWithAddress get neutered => switch (this) {
28 0 : ReceiveNode() => ReceiveNode(
29 0 : bip32Node: bip32Node?.neutered(),
30 0 : address: address,
31 0 : derivationPath: derivationPath,
32 0 : addresses: addresses,
33 0 : walletPurpose: walletPurpose,
34 0 : publicKey: publicKey,
35 : ),
36 0 : ChangeNode() => ChangeNode(
37 0 : bip32Node: bip32Node?.neutered(),
38 0 : address: address,
39 0 : derivationPath: derivationPath,
40 0 : addresses: addresses,
41 0 : walletPurpose: walletPurpose,
42 0 : publicKey: publicKey,
43 : ),
44 0 : EmptyNode() => EmptyNode(),
45 : };
46 :
47 9 : factory NodeWithAddress.fromChainIndex({
48 : required BIP32 node,
49 : required String address,
50 : required int chainIndex,
51 : required String derivationPath,
52 : required Map<AddressType, String> addresses,
53 : HDWalletPurpose? walletPurpose,
54 : }) {
55 9 : if (chainIndex == EXTERNAL_CHAIN_INDEX) {
56 9 : return ReceiveNode(
57 : bip32Node: node,
58 : address: address,
59 : derivationPath: derivationPath,
60 : addresses: addresses,
61 : walletPurpose: walletPurpose,
62 18 : publicKey: node.publicKey.toHex,
63 : );
64 : }
65 9 : if (chainIndex == INTERNAL_CHAIN_INDEX) {
66 9 : return ChangeNode(
67 : bip32Node: node,
68 : address: address,
69 : derivationPath: derivationPath,
70 : addresses: addresses,
71 : walletPurpose: walletPurpose,
72 18 : publicKey: node.publicKey.toHex,
73 : );
74 : }
75 0 : throw UnsupportedError("unexpected chainIndex");
76 : }
77 :
78 2 : Json toJson() => {
79 1 : 'type': type,
80 1 : 'address': address,
81 1 : 'derivationPath': derivationPath,
82 1 : 'addresses': {
83 7 : for (final entry in addresses.entries) entry.key.index.toString(): entry.value,
84 : },
85 1 : 'walletPurpose': walletPurpose?.index,
86 1 : 'publicKey': publicKey,
87 : };
88 :
89 1 : factory NodeWithAddress.fromJson(Map json) {
90 1 : final type = json['type'] as int;
91 :
92 1 : if (type == 2) {
93 1 : return EmptyNode();
94 : }
95 :
96 : if (json
97 : case {
98 2 : 'type': int type,
99 2 : 'address': String address,
100 2 : 'derivationPath': String derivationPath,
101 2 : 'addresses': Map addresses,
102 2 : 'walletPurpose': int? walletPurpose,
103 2 : 'publicKey': String publicKey,
104 : }) {
105 : return switch (type) {
106 2 : 0 => ReceiveNode(
107 : address: address,
108 : derivationPath: derivationPath,
109 1 : addresses: {
110 3 : for (final MapEntry(:key, :value) in addresses.entries)
111 3 : AddressType.fromIndex(int.parse(key as String)): value as String
112 : },
113 0 : walletPurpose: walletPurpose != null ? HDWalletPurpose.values[walletPurpose] : null,
114 : publicKey: publicKey,
115 : ),
116 0 : 1 => ChangeNode(
117 : address: address,
118 : derivationPath: derivationPath,
119 0 : addresses: {
120 0 : for (final MapEntry(:key, :value) in addresses.entries)
121 0 : AddressType.fromIndex(int.parse(key as String)): value as String
122 : },
123 0 : walletPurpose: walletPurpose != null ? HDWalletPurpose.values[walletPurpose] : null,
124 : publicKey: publicKey,
125 : ),
126 0 : _ => throw UnimplementedError(),
127 : };
128 : }
129 :
130 0 : throw UnimplementedError();
131 : }
132 :
133 11 : const NodeWithAddress({
134 : this.bip32Node,
135 : this.walletPurpose,
136 : required this.address,
137 : required this.derivationPath,
138 : required this.addresses,
139 : required this.publicKey,
140 : required this.type,
141 : });
142 : }
143 :
144 : final class ReceiveNode extends NodeWithAddress {
145 10 : const ReceiveNode({
146 : super.bip32Node,
147 : required super.address,
148 : required super.derivationPath,
149 : required super.addresses,
150 : required super.walletPurpose,
151 : required super.publicKey,
152 10 : }) : super(type: 0);
153 : }
154 :
155 : final class ChangeNode extends NodeWithAddress {
156 9 : const ChangeNode({
157 : super.bip32Node,
158 : required super.address,
159 : required super.derivationPath,
160 : required super.addresses,
161 : required super.walletPurpose,
162 : required super.publicKey,
163 9 : }) : super(type: 1);
164 : }
165 :
166 : final class EmptyNode extends NodeWithAddress {
167 1 : @override
168 : Json toJson() {
169 1 : return {
170 1 : "type": type,
171 : };
172 : }
173 :
174 10 : const EmptyNode()
175 10 : : super(
176 : bip32Node: null,
177 : address: "",
178 : derivationPath: "",
179 : addresses: const {},
180 : walletPurpose: null,
181 : publicKey: "",
182 : type: 2,
183 : );
184 : }
|