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 2 : for (final entry in addresses.entries)
84 5 : entry.key.index.toString(): entry.value,
85 : },
86 1 : 'walletPurpose': walletPurpose?.index,
87 1 : 'publicKey': publicKey,
88 : };
89 :
90 1 : factory NodeWithAddress.fromJson(Map json) {
91 1 : final type = json['type'] as int;
92 :
93 1 : if (type == 2) {
94 1 : return EmptyNode();
95 : }
96 :
97 : if (json
98 : case {
99 2 : 'type': int type,
100 2 : 'address': String address,
101 2 : 'derivationPath': String derivationPath,
102 2 : 'addresses': Map addresses,
103 2 : 'walletPurpose': int? walletPurpose,
104 2 : 'publicKey': String publicKey,
105 : }) {
106 : return switch (type) {
107 2 : 0 => ReceiveNode(
108 : address: address,
109 : derivationPath: derivationPath,
110 1 : addresses: {
111 3 : for (final MapEntry(:key, :value) in addresses.entries)
112 3 : AddressType.fromIndex(int.parse(key as String)): value as String
113 : },
114 : walletPurpose: walletPurpose != null
115 0 : ? HDWalletPurpose.values[walletPurpose]
116 : : null,
117 : publicKey: publicKey,
118 : ),
119 0 : 1 => ChangeNode(
120 : address: address,
121 : derivationPath: derivationPath,
122 0 : addresses: {
123 0 : for (final MapEntry(:key, :value) in addresses.entries)
124 0 : AddressType.fromIndex(int.parse(key as String)): value as String
125 : },
126 : walletPurpose: walletPurpose != null
127 0 : ? HDWalletPurpose.values[walletPurpose]
128 : : null,
129 : publicKey: publicKey,
130 : ),
131 0 : _ => throw UnimplementedError(),
132 : };
133 : }
134 :
135 0 : throw UnimplementedError();
136 : }
137 :
138 11 : const NodeWithAddress({
139 : this.bip32Node,
140 : this.walletPurpose,
141 : required this.address,
142 : required this.derivationPath,
143 : required this.addresses,
144 : required this.publicKey,
145 : required this.type,
146 : });
147 : }
148 :
149 : final class ReceiveNode extends NodeWithAddress {
150 10 : const ReceiveNode({
151 : super.bip32Node,
152 : required super.address,
153 : required super.derivationPath,
154 : required super.addresses,
155 : required super.walletPurpose,
156 : required super.publicKey,
157 10 : }) : super(type: 0);
158 : }
159 :
160 : final class ChangeNode extends NodeWithAddress {
161 9 : const ChangeNode({
162 : super.bip32Node,
163 : required super.address,
164 : required super.derivationPath,
165 : required super.addresses,
166 : required super.walletPurpose,
167 : required super.publicKey,
168 9 : }) : super(type: 1);
169 : }
170 :
171 : final class EmptyNode extends NodeWithAddress {
172 1 : @override
173 : Json toJson() {
174 1 : return {
175 1 : "type": type,
176 : };
177 : }
178 :
179 10 : const EmptyNode()
180 10 : : super(
181 : bip32Node: null,
182 : address: "",
183 : derivationPath: "",
184 : addresses: const {},
185 : walletPurpose: null,
186 : publicKey: "",
187 : type: 2,
188 : );
189 : }
|