mainnet-js 2.7.34 → 3.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.html +1 -1
- package/dist/{mainnet-2.7.34.js → mainnet-3.0.0-next.1.js} +728 -708
- package/dist/module/cache/MemoryCache.d.ts +0 -1
- package/dist/module/cache/MemoryCache.d.ts.map +1 -1
- package/dist/module/cache/MemoryCache.js +5 -7
- package/dist/module/cache/MemoryCache.js.map +1 -1
- package/dist/module/cache/index.d.ts +1 -0
- package/dist/module/cache/index.d.ts.map +1 -1
- package/dist/module/cache/index.js +1 -0
- package/dist/module/cache/index.js.map +1 -1
- package/dist/module/cache/walletCache.d.ts +45 -0
- package/dist/module/cache/walletCache.d.ts.map +1 -0
- package/dist/module/cache/walletCache.js +140 -0
- package/dist/module/cache/walletCache.js.map +1 -0
- package/dist/module/chain.d.ts +1 -1
- package/dist/module/chain.js +1 -1
- package/dist/module/chain.js.map +1 -1
- package/dist/module/constant.d.ts +1 -1
- package/dist/module/constant.d.ts.map +1 -1
- package/dist/module/constant.js +1 -1
- package/dist/module/constant.js.map +1 -1
- package/dist/module/enum.d.ts +1 -7
- package/dist/module/enum.d.ts.map +1 -1
- package/dist/module/enum.js +0 -6
- package/dist/module/enum.js.map +1 -1
- package/dist/module/history/{electrumTransformer.d.ts → getHistory.d.ts} +3 -3
- package/dist/module/history/getHistory.d.ts.map +1 -0
- package/dist/module/history/{electrumTransformer.js → getHistory.js} +17 -14
- package/dist/module/history/getHistory.js.map +1 -0
- package/dist/module/index.d.ts +3 -1
- package/dist/module/index.d.ts.map +1 -1
- package/dist/module/index.js +3 -1
- package/dist/module/index.js.map +1 -1
- package/dist/module/interface.d.ts +7 -2
- package/dist/module/interface.d.ts.map +1 -1
- package/dist/module/interface.js.map +1 -1
- package/dist/module/message/interface.d.ts +2 -2
- package/dist/module/message/interface.d.ts.map +1 -1
- package/dist/module/message/interface.js +0 -3
- package/dist/module/message/interface.js.map +1 -1
- package/dist/module/message/signed.d.ts +5 -5
- package/dist/module/message/signed.d.ts.map +1 -1
- package/dist/module/message/signed.js +8 -8
- package/dist/module/message/signed.js.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.d.ts +2 -2
- package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.js +3 -2
- package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
- package/dist/module/network/NetworkProvider.d.ts +2 -2
- package/dist/module/network/NetworkProvider.d.ts.map +1 -1
- package/dist/module/network/constant.js +4 -4
- package/dist/module/network/constant.js.map +1 -1
- package/dist/module/network/getRelayFeeCache.js +2 -2
- package/dist/module/network/getRelayFeeCache.js.map +1 -1
- package/dist/module/rate/ExchangeRate.d.ts +2 -1
- package/dist/module/rate/ExchangeRate.d.ts.map +1 -1
- package/dist/module/rate/ExchangeRate.js +4 -1
- package/dist/module/rate/ExchangeRate.js.map +1 -1
- package/dist/module/transaction/Wif.d.ts +25 -23
- package/dist/module/transaction/Wif.d.ts.map +1 -1
- package/dist/module/transaction/Wif.js +26 -25
- package/dist/module/transaction/Wif.js.map +1 -1
- package/dist/module/transaction/allocateFee.d.ts +3 -3
- package/dist/module/transaction/allocateFee.d.ts.map +1 -1
- package/dist/module/transaction/allocateFee.js +5 -6
- package/dist/module/transaction/allocateFee.js.map +1 -1
- package/dist/module/util/amountInSatoshi.d.ts +1 -1
- package/dist/module/util/amountInSatoshi.d.ts.map +1 -1
- package/dist/module/util/amountInSatoshi.js +3 -9
- package/dist/module/util/amountInSatoshi.js.map +1 -1
- package/dist/module/util/asSendRequestObject.d.ts.map +1 -1
- package/dist/module/util/asSendRequestObject.js +10 -7
- package/dist/module/util/asSendRequestObject.js.map +1 -1
- package/dist/module/util/checkUtxos.d.ts +2 -2
- package/dist/module/util/checkUtxos.d.ts.map +1 -1
- package/dist/module/util/checkUtxos.js +11 -12
- package/dist/module/util/checkUtxos.js.map +1 -1
- package/dist/module/util/convert.d.ts +3 -0
- package/dist/module/util/convert.d.ts.map +1 -1
- package/dist/module/util/convert.js +12 -0
- package/dist/module/util/convert.js.map +1 -1
- package/dist/module/util/deriveCashaddr.d.ts.map +1 -1
- package/dist/module/util/deriveCashaddr.js +6 -0
- package/dist/module/util/deriveCashaddr.js.map +1 -1
- package/dist/module/util/deriveNetwork.js +1 -1
- package/dist/module/util/deriveNetwork.js.map +1 -1
- package/dist/module/util/hd.d.ts +3 -0
- package/dist/module/util/hd.d.ts.map +1 -0
- package/dist/module/util/hd.js +11 -0
- package/dist/module/util/hd.js.map +1 -0
- package/dist/module/util/index.d.ts +3 -3
- package/dist/module/util/index.d.ts.map +1 -1
- package/dist/module/util/index.js +3 -3
- package/dist/module/util/index.js.map +1 -1
- package/dist/module/util/satoshiToAmount.d.ts +1 -1
- package/dist/module/util/satoshiToAmount.d.ts.map +1 -1
- package/dist/module/util/satoshiToAmount.js +3 -9
- package/dist/module/util/satoshiToAmount.js.map +1 -1
- package/dist/module/util/sumSendRequestAmounts.d.ts.map +1 -1
- package/dist/module/util/sumSendRequestAmounts.js +3 -4
- package/dist/module/util/sumSendRequestAmounts.js.map +1 -1
- package/dist/module/util/sumUtxoValue.d.ts +3 -3
- package/dist/module/util/sumUtxoValue.d.ts.map +1 -1
- package/dist/module/util/sumUtxoValue.js +2 -2
- package/dist/module/util/sumUtxoValue.js.map +1 -1
- package/dist/module/wallet/Base.d.ts +45 -103
- package/dist/module/wallet/Base.d.ts.map +1 -1
- package/dist/module/wallet/Base.js +99 -298
- package/dist/module/wallet/Base.js.map +1 -1
- package/dist/module/wallet/HDWallet.d.ts +164 -0
- package/dist/module/wallet/HDWallet.d.ts.map +1 -0
- package/dist/module/wallet/HDWallet.js +486 -0
- package/dist/module/wallet/HDWallet.js.map +1 -0
- package/dist/module/wallet/Util.js +1 -1
- package/dist/module/wallet/Util.js.map +1 -1
- package/dist/module/wallet/Watch.d.ts +151 -0
- package/dist/module/wallet/Watch.d.ts.map +1 -0
- package/dist/module/wallet/Watch.js +307 -0
- package/dist/module/wallet/Watch.js.map +1 -0
- package/dist/module/wallet/Wif.d.ts +23 -29
- package/dist/module/wallet/Wif.d.ts.map +1 -1
- package/dist/module/wallet/Wif.js +204 -267
- package/dist/module/wallet/Wif.js.map +1 -1
- package/dist/module/wallet/createWallet.d.ts +7 -1
- package/dist/module/wallet/createWallet.d.ts.map +1 -1
- package/dist/module/wallet/createWallet.js +26 -17
- package/dist/module/wallet/createWallet.js.map +1 -1
- package/dist/module/wallet/interface.d.ts +5 -6
- package/dist/module/wallet/interface.d.ts.map +1 -1
- package/dist/module/wallet/model.d.ts +15 -19
- package/dist/module/wallet/model.d.ts.map +1 -1
- package/dist/module/wallet/model.js +5 -25
- package/dist/module/wallet/model.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/cache/MemoryCache.ts +5 -5
- package/src/cache/index.ts +1 -0
- package/src/cache/walletCache.ts +239 -0
- package/src/chain.ts +1 -1
- package/src/constant.ts +1 -1
- package/src/enum.ts +0 -6
- package/src/history/{electrumTransformer.test.ts → getHistory.test.ts} +26 -53
- package/src/history/{electrumTransformer.ts → getHistory.ts} +31 -15
- package/src/index.ts +3 -1
- package/src/interface.ts +8 -2
- package/src/message/interface.ts +2 -28
- package/src/message/signed.test.ts +36 -48
- package/src/message/signed.ts +9 -12
- package/src/network/Connection.test.ts +3 -3
- package/src/network/ElectrumNetworkProvider.ts +5 -5
- package/src/network/NetworkProvider.ts +2 -2
- package/src/network/Rpc.test.ts +3 -4
- package/src/network/constant.ts +4 -4
- package/src/network/getRelayFeeCache.ts +2 -2
- package/src/rate/ExchangeRate.test.ts +2 -44
- package/src/rate/ExchangeRate.ts +5 -2
- package/src/transaction/Wif.ts +59 -52
- package/src/transaction/allocateFee.test.ts +110 -131
- package/src/transaction/allocateFee.ts +14 -15
- package/src/util/amountInSatoshi.test.ts +1 -9
- package/src/util/amountInSatoshi.ts +6 -10
- package/src/util/asSendRequestObject.ts +12 -7
- package/src/util/checkUtxos.ts +21 -26
- package/src/util/convert.ts +18 -0
- package/src/util/deriveCashaddr.ts +8 -0
- package/src/util/deriveNetwork.ts +1 -1
- package/src/util/derivePublicKeyHash.test.ts +0 -13
- package/src/util/hd.ts +16 -0
- package/src/util/index.ts +3 -7
- package/src/util/satoshiToAmount.test.ts +1 -1
- package/src/util/satoshiToAmount.ts +4 -10
- package/src/util/sumSendRequestAmounts.ts +3 -4
- package/src/util/sumUtxoValue.ts +7 -7
- package/src/wallet/Base.ts +147 -420
- package/src/wallet/Cashtokens.test.headless.js +11 -11
- package/src/wallet/Cashtokens.test.ts +36 -37
- package/src/wallet/HDWallet.test.ts +515 -0
- package/src/wallet/HDWallet.ts +764 -0
- package/src/wallet/Util.ts +1 -1
- package/src/wallet/Watch.ts +447 -0
- package/src/wallet/Wif.bip39.test.ts +1 -1
- package/src/wallet/Wif.test.ts +108 -133
- package/src/wallet/Wif.ts +258 -283
- package/src/wallet/createWallet.ts +28 -18
- package/src/wallet/interface.ts +5 -6
- package/src/wallet/model.test.ts +4 -7
- package/src/wallet/model.ts +19 -51
- package/dist/module/history/electrumTransformer.d.ts.map +0 -1
- package/dist/module/history/electrumTransformer.js.map +0 -1
- package/dist/module/util/balanceObjectFromSatoshi.d.ts +0 -8
- package/dist/module/util/balanceObjectFromSatoshi.d.ts.map +0 -1
- package/dist/module/util/balanceObjectFromSatoshi.js +0 -35
- package/dist/module/util/balanceObjectFromSatoshi.js.map +0 -1
- package/src/util/balanceObjectFromSatoshi.test.ts +0 -58
- package/src/util/balanceObjectFromSatoshi.ts +0 -52
package/src/wallet/Wif.ts
CHANGED
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
//#region Imports
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
encodeHdPublicKey,
|
|
5
|
-
generateBip39Mnemonic,
|
|
6
|
-
HdKeyNetwork,
|
|
7
|
-
hexToBin,
|
|
8
|
-
secp256k1,
|
|
9
|
-
} from "@bitauth/libauth";
|
|
10
|
-
|
|
11
|
-
import {
|
|
3
|
+
assertSuccess,
|
|
12
4
|
binToHex,
|
|
13
5
|
CashAddressNetworkPrefix,
|
|
14
6
|
decodePrivateKeyWif,
|
|
15
7
|
deriveHdPath,
|
|
16
8
|
deriveHdPrivateNodeFromSeed,
|
|
17
9
|
deriveHdPublicNode,
|
|
10
|
+
deriveSeedFromBip39Mnemonic,
|
|
11
|
+
encodeHdPublicKey,
|
|
18
12
|
encodePrivateKeyWif,
|
|
13
|
+
generateBip39Mnemonic,
|
|
19
14
|
generatePrivateKey,
|
|
15
|
+
HdKeyNetwork,
|
|
16
|
+
hexToBin,
|
|
17
|
+
secp256k1,
|
|
20
18
|
} from "@bitauth/libauth";
|
|
21
19
|
|
|
22
20
|
import { NetworkType } from "../enum.js";
|
|
23
21
|
|
|
24
|
-
import { PrivateKeyI } from "../interface.js";
|
|
25
|
-
|
|
26
22
|
import { WalletTypeEnum } from "./enum.js";
|
|
27
23
|
import { MnemonicI, SendRequestOptionsI, WalletInfoI } from "./interface.js";
|
|
28
24
|
|
|
@@ -39,41 +35,195 @@ import {
|
|
|
39
35
|
import { signUnsignedTransaction } from "../transaction/Wif.js";
|
|
40
36
|
|
|
41
37
|
import { DERIVATION_PATHS } from "../constant.js";
|
|
42
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
SignedMessage,
|
|
40
|
+
SignedMessageI,
|
|
41
|
+
SignedMessageResponseI,
|
|
42
|
+
} from "../message/index.js";
|
|
43
43
|
import ElectrumNetworkProvider from "../network/ElectrumNetworkProvider.js";
|
|
44
44
|
import { checkForEmptySeed } from "../util/checkForEmptySeed.js";
|
|
45
45
|
import { checkWifNetwork } from "../util/checkWifNetwork.js";
|
|
46
|
-
import { deriveCashaddr, deriveTokenaddr } from "../util/deriveCashaddr.js";
|
|
47
|
-
import { derivePublicKeyHash } from "../util/derivePublicKeyHash.js";
|
|
48
|
-
import { getXPubKey } from "../util/getXPubKey.js";
|
|
49
46
|
import { generateRandomBytes } from "../util/randomBytes.js";
|
|
50
47
|
|
|
51
48
|
import { Config } from "../config.js";
|
|
52
|
-
import {
|
|
53
|
-
BalanceResponse,
|
|
54
|
-
balanceResponseFromSatoshi,
|
|
55
|
-
} from "../util/balanceObjectFromSatoshi.js";
|
|
56
|
-
import { BaseWallet } from "./Base.js";
|
|
49
|
+
import { WatchWallet } from "./Watch.js";
|
|
57
50
|
//#endregion Imports
|
|
58
51
|
|
|
52
|
+
export interface WalletOptions {
|
|
53
|
+
name?: string;
|
|
54
|
+
mnemonic?: string;
|
|
55
|
+
derivationPath?: string;
|
|
56
|
+
privateKey?: Uint8Array;
|
|
57
|
+
privateKeyWif?: string;
|
|
58
|
+
publicKey?: Uint8Array;
|
|
59
|
+
publicKeyCompressed?: Uint8Array;
|
|
60
|
+
publicKeyHash?: Uint8Array;
|
|
61
|
+
address?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
59
64
|
/**
|
|
60
65
|
* Class to manage a bitcoin cash wallet.
|
|
61
66
|
*/
|
|
62
|
-
export class Wallet extends
|
|
67
|
+
export class Wallet extends WatchWallet {
|
|
63
68
|
declare readonly provider: ElectrumNetworkProvider;
|
|
64
|
-
|
|
65
|
-
declare readonly tokenaddr: string;
|
|
69
|
+
|
|
66
70
|
readonly derivationPath: string = Config.DefaultParentDerivationPath + "/0/0";
|
|
67
71
|
readonly parentDerivationPath: string = Config.DefaultParentDerivationPath;
|
|
68
72
|
readonly mnemonic!: string;
|
|
69
73
|
readonly parentXPubKey!: string;
|
|
70
74
|
readonly privateKey!: Uint8Array;
|
|
71
|
-
readonly publicKeyCompressed!: Uint8Array;
|
|
72
75
|
readonly privateKeyWif!: string;
|
|
73
|
-
|
|
74
|
-
declare readonly publicKeyHash: Uint8Array;
|
|
76
|
+
|
|
75
77
|
declare name: string;
|
|
76
|
-
|
|
78
|
+
|
|
79
|
+
//#region Constructors and Statics
|
|
80
|
+
constructor(
|
|
81
|
+
name = "",
|
|
82
|
+
network = NetworkType.Mainnet,
|
|
83
|
+
walletType = WalletTypeEnum.Seed
|
|
84
|
+
) {
|
|
85
|
+
super(name, network);
|
|
86
|
+
|
|
87
|
+
this.name = name;
|
|
88
|
+
// @ts-ignore
|
|
89
|
+
this.walletType = walletType;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// Initialize the wallet given the options mnemonic, privateKey or publicKey variations
|
|
93
|
+
/// If none provided, a new random mnemonic will be generated
|
|
94
|
+
/// If mnemonic or private key provided, the wallet will be able to sign transactions
|
|
95
|
+
/// Otherwise, the wallet will be watch-only
|
|
96
|
+
/// This internal method is called by the various static constructors
|
|
97
|
+
protected async initialize({
|
|
98
|
+
name = "",
|
|
99
|
+
mnemonic = undefined,
|
|
100
|
+
derivationPath = undefined,
|
|
101
|
+
privateKey = undefined,
|
|
102
|
+
privateKeyWif = undefined,
|
|
103
|
+
publicKey = undefined,
|
|
104
|
+
publicKeyCompressed = undefined,
|
|
105
|
+
publicKeyHash = undefined,
|
|
106
|
+
address = undefined,
|
|
107
|
+
}: WalletOptions = {}) {
|
|
108
|
+
// seed wallet
|
|
109
|
+
if (this.walletType === WalletTypeEnum.Seed && !mnemonic) {
|
|
110
|
+
mnemonic = generateBip39Mnemonic();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (mnemonic?.length) {
|
|
114
|
+
mnemonic = mnemonic.trim().toLowerCase();
|
|
115
|
+
if (mnemonic.split(" ").length !== 12) {
|
|
116
|
+
throw Error("Invalid mnemonic");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (derivationPath) {
|
|
120
|
+
// @ts-ignore
|
|
121
|
+
this.derivationPath = derivationPath;
|
|
122
|
+
|
|
123
|
+
// If the derivation path is for the first account child, set the parent derivation path
|
|
124
|
+
const path = derivationPath.split("/");
|
|
125
|
+
if (path.slice(-2).join("/") == "0/0") {
|
|
126
|
+
// @ts-ignore
|
|
127
|
+
this.parentDerivationPath = path.slice(0, -2).join("/");
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
derivationPath = Config.DefaultParentDerivationPath + "/0/0";
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
this.parentDerivationPath = Config.DefaultParentDerivationPath;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// @ts-ignore
|
|
136
|
+
this.mnemonic = mnemonic;
|
|
137
|
+
// @ts-ignore
|
|
138
|
+
this.derivationPath = derivationPath;
|
|
139
|
+
|
|
140
|
+
const seed = deriveSeedFromBip39Mnemonic(this.mnemonic);
|
|
141
|
+
checkForEmptySeed(seed);
|
|
142
|
+
|
|
143
|
+
const rootNode = deriveHdPrivateNodeFromSeed(seed, {
|
|
144
|
+
assumeValidity: true,
|
|
145
|
+
throwErrors: true,
|
|
146
|
+
});
|
|
147
|
+
const parentNode = deriveHdPath(rootNode, this.parentDerivationPath);
|
|
148
|
+
|
|
149
|
+
// @ts-ignore
|
|
150
|
+
this.parentXPubKey = assertSuccess(
|
|
151
|
+
encodeHdPublicKey({
|
|
152
|
+
node: deriveHdPublicNode(parentNode),
|
|
153
|
+
network: this.network === NetworkType.Mainnet ? "mainnet" : "testnet",
|
|
154
|
+
})
|
|
155
|
+
).hdPublicKey;
|
|
156
|
+
|
|
157
|
+
const childNode = deriveHdPath(rootNode, this.derivationPath);
|
|
158
|
+
privateKey = childNode.privateKey;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// privkey wallet
|
|
162
|
+
if (this.walletType === WalletTypeEnum.PrivateKey && !privateKey) {
|
|
163
|
+
// @ts-ignore
|
|
164
|
+
this.privateKey = generatePrivateKey(
|
|
165
|
+
() => generateRandomBytes(32) as Uint8Array
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (privateKey?.length) {
|
|
170
|
+
// @ts-ignore
|
|
171
|
+
this.privateKey = privateKey;
|
|
172
|
+
|
|
173
|
+
privateKeyWif = encodePrivateKeyWif(
|
|
174
|
+
privateKey,
|
|
175
|
+
this.network === NetworkType.Regtest
|
|
176
|
+
? NetworkType.Testnet
|
|
177
|
+
: this.network
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// wif wallet
|
|
182
|
+
if (this.walletType === WalletTypeEnum.Wif && !privateKeyWif) {
|
|
183
|
+
// @ts-ignore
|
|
184
|
+
this.privateKey = generatePrivateKey(
|
|
185
|
+
() => generateRandomBytes(32) as Uint8Array
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
privateKeyWif = encodePrivateKeyWif(
|
|
189
|
+
this.privateKey,
|
|
190
|
+
this.network === NetworkType.Regtest
|
|
191
|
+
? NetworkType.Testnet
|
|
192
|
+
: this.network
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (privateKeyWif?.length) {
|
|
197
|
+
checkWifNetwork(privateKeyWif, this.network);
|
|
198
|
+
|
|
199
|
+
// @ts-ignore
|
|
200
|
+
this.privateKeyWif = privateKeyWif;
|
|
201
|
+
|
|
202
|
+
if (!this.privateKey) {
|
|
203
|
+
// @ts-ignore
|
|
204
|
+
this.privateKey = assertSuccess(
|
|
205
|
+
decodePrivateKeyWif(privateKeyWif)
|
|
206
|
+
).privateKey;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
publicKey = assertSuccess(
|
|
210
|
+
secp256k1.derivePublicKeyUncompressed(this.privateKey)
|
|
211
|
+
);
|
|
212
|
+
publicKeyCompressed = assertSuccess(
|
|
213
|
+
secp256k1.compressPublicKey(publicKey!)
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// rest cases are for watch wallets
|
|
218
|
+
return super.initialize({
|
|
219
|
+
name,
|
|
220
|
+
publicKey,
|
|
221
|
+
publicKeyCompressed,
|
|
222
|
+
publicKeyHash,
|
|
223
|
+
address,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
//#endregion Constructors and Statics
|
|
77
227
|
|
|
78
228
|
//#region Accessors
|
|
79
229
|
// Get mnemonic and derivation path for wallet
|
|
@@ -114,43 +264,68 @@ export class Wallet extends BaseWallet {
|
|
|
114
264
|
};
|
|
115
265
|
}
|
|
116
266
|
|
|
117
|
-
//
|
|
118
|
-
public
|
|
119
|
-
if (this.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
267
|
+
// Get common xpub paths from zerothChild privateKey
|
|
268
|
+
public async deriveHdPaths(hdPaths: string[]): Promise<any[]> {
|
|
269
|
+
if (!this.mnemonic)
|
|
270
|
+
throw Error("refusing to create wallet from empty mnemonic");
|
|
271
|
+
const seed = deriveSeedFromBip39Mnemonic(this.mnemonic);
|
|
272
|
+
checkForEmptySeed(seed);
|
|
273
|
+
const hdNode = deriveHdPrivateNodeFromSeed(seed, {
|
|
274
|
+
assumeValidity: true, // TODO: we should switch to libauth's BIP39 implementation and set this to false
|
|
275
|
+
throwErrors: true,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
const result: any[] = [];
|
|
279
|
+
|
|
280
|
+
for (const path of hdPaths) {
|
|
281
|
+
if (path === "m") {
|
|
282
|
+
throw Error(
|
|
283
|
+
"Storing or sharing of parent public key may lead to loss of funds. Storing or sharing *root* parent public keys is strongly discouraged, although all parent keys have risk. See: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#implications"
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
const childNode = deriveHdPath(hdNode, path);
|
|
287
|
+
if (typeof childNode === "string") {
|
|
288
|
+
throw Error(childNode);
|
|
289
|
+
}
|
|
290
|
+
const node = deriveHdPublicNode(childNode);
|
|
291
|
+
if (typeof node === "string") {
|
|
292
|
+
throw Error(node);
|
|
293
|
+
}
|
|
294
|
+
const xPubKey = encodeHdPublicKey(
|
|
295
|
+
{
|
|
296
|
+
network: this.network as HdKeyNetwork,
|
|
297
|
+
node: node,
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
throwErrors: true,
|
|
301
|
+
}
|
|
302
|
+
).hdPublicKey;
|
|
303
|
+
const key = new XPubKey({
|
|
304
|
+
path: path,
|
|
305
|
+
xPubKey: xPubKey,
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
result.push(await key.ready());
|
|
125
309
|
}
|
|
310
|
+
return await Promise.all(result).then((result) => {
|
|
311
|
+
return result;
|
|
312
|
+
});
|
|
126
313
|
}
|
|
127
314
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
315
|
+
public async getXPubKeys(paths?: string[]) {
|
|
316
|
+
if (this.mnemonic) {
|
|
317
|
+
if (paths) {
|
|
318
|
+
let xPubKeys = await this.deriveHdPaths(paths);
|
|
319
|
+
return [xPubKeys];
|
|
320
|
+
} else {
|
|
321
|
+
return await this.deriveHdPaths(DERIVATION_PATHS);
|
|
322
|
+
}
|
|
134
323
|
} else {
|
|
135
|
-
throw Error(
|
|
136
|
-
"The compressed public key for this wallet is not known, perhaps the wallet was created to watch the *hash* of a public key? i.e. a cashaddress."
|
|
137
|
-
);
|
|
324
|
+
throw Error("xpubkeys can only be derived from seed type wallets.");
|
|
138
325
|
}
|
|
139
326
|
}
|
|
140
327
|
//#endregion
|
|
141
328
|
|
|
142
|
-
//#region Constructors and Statics
|
|
143
|
-
constructor(
|
|
144
|
-
name = "",
|
|
145
|
-
network = NetworkType.Mainnet,
|
|
146
|
-
walletType = WalletTypeEnum.Seed
|
|
147
|
-
) {
|
|
148
|
-
super(network);
|
|
149
|
-
this.name = name;
|
|
150
|
-
// @ts-ignore
|
|
151
|
-
this.walletType = walletType;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
329
|
//#region Statics
|
|
155
330
|
/**
|
|
156
331
|
* fromId - create a wallet from encoded walletId string
|
|
@@ -197,20 +372,19 @@ export class Wallet extends BaseWallet {
|
|
|
197
372
|
/**
|
|
198
373
|
* fromSeed - create a wallet using the seed phrase and derivation path
|
|
199
374
|
*
|
|
200
|
-
* unless specified the derivation path m/44'/
|
|
201
|
-
* this derivation path is standard for Electron Cash SLP and other SLP enabled wallets
|
|
375
|
+
* unless specified the derivation path m/44'/0'/0'/0/0 will be used
|
|
202
376
|
*
|
|
203
|
-
* @param
|
|
377
|
+
* @param mnemonic BIP39 12 word seed phrase
|
|
204
378
|
* @param derivationPath BIP44 HD wallet derivation path to get a single the private key from hierarchy
|
|
205
379
|
*
|
|
206
380
|
* @returns instantiated wallet
|
|
207
381
|
*/
|
|
208
382
|
public static async fromSeed<T extends typeof Wallet>(
|
|
209
383
|
this: T,
|
|
210
|
-
|
|
384
|
+
mnemonic: string,
|
|
211
385
|
derivationPath?: string
|
|
212
386
|
): Promise<InstanceType<T>> {
|
|
213
|
-
return new this().fromSeed(
|
|
387
|
+
return new this().fromSeed(mnemonic, derivationPath) as InstanceType<T>;
|
|
214
388
|
}
|
|
215
389
|
|
|
216
390
|
/**
|
|
@@ -233,59 +407,6 @@ export class Wallet extends BaseWallet {
|
|
|
233
407
|
//#endregion Constructors
|
|
234
408
|
|
|
235
409
|
//#region Protected implementations
|
|
236
|
-
protected async generate(): Promise<this> {
|
|
237
|
-
if (this.walletType === WalletTypeEnum.Wif) {
|
|
238
|
-
return await this._generateWif();
|
|
239
|
-
} else if (this.walletType === WalletTypeEnum.Watch) {
|
|
240
|
-
return this;
|
|
241
|
-
} else if (this.walletType === WalletTypeEnum.Hd) {
|
|
242
|
-
throw Error("Not implemented");
|
|
243
|
-
} else if (this.walletType === WalletTypeEnum.Seed) {
|
|
244
|
-
return await this._generateMnemonic();
|
|
245
|
-
} else {
|
|
246
|
-
console.log(this.walletType);
|
|
247
|
-
throw Error(`Could not determine walletType: ${this.walletType}`);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
private async _generateWif() {
|
|
252
|
-
if (!this.privateKey) {
|
|
253
|
-
// @ts-ignore
|
|
254
|
-
this.privateKey = generatePrivateKey(
|
|
255
|
-
() => generateRandomBytes(32) as Uint8Array
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
return this.deriveInfo();
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
private async _generateMnemonic() {
|
|
262
|
-
// @ts-ignore
|
|
263
|
-
this.mnemonic = generateBip39Mnemonic();
|
|
264
|
-
if (this.mnemonic.length == 0)
|
|
265
|
-
throw Error("refusing to create wallet from empty mnemonic");
|
|
266
|
-
const seed = deriveSeedFromBip39Mnemonic(this.mnemonic);
|
|
267
|
-
checkForEmptySeed(seed);
|
|
268
|
-
const network = this.isTestnet ? "testnet" : "mainnet";
|
|
269
|
-
// @ts-ignore
|
|
270
|
-
this.parentXPubKey = getXPubKey(seed, this.parentDerivationPath, network);
|
|
271
|
-
|
|
272
|
-
const hdNode = deriveHdPrivateNodeFromSeed(seed, {
|
|
273
|
-
assumeValidity: true, // TODO: we should switch to libauth's BIP39 implementation and set this to false
|
|
274
|
-
throwErrors: true,
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
const zerothChild = deriveHdPath(hdNode, this.derivationPath);
|
|
278
|
-
if (typeof zerothChild === "string") {
|
|
279
|
-
throw Error(zerothChild);
|
|
280
|
-
}
|
|
281
|
-
// @ts-ignore
|
|
282
|
-
this.privateKey = zerothChild.privateKey;
|
|
283
|
-
|
|
284
|
-
// @ts-ignore
|
|
285
|
-
this.walletType = WalletTypeEnum.Seed;
|
|
286
|
-
return await this.deriveInfo();
|
|
287
|
-
}
|
|
288
|
-
|
|
289
410
|
protected fromId = async (walletId: string): Promise<this> => {
|
|
290
411
|
const [walletType, networkGiven, arg1, arg2]: string[] =
|
|
291
412
|
walletId.split(":");
|
|
@@ -332,116 +453,21 @@ export class Wallet extends BaseWallet {
|
|
|
332
453
|
}
|
|
333
454
|
};
|
|
334
455
|
|
|
335
|
-
public async getXPubKeys(paths?) {
|
|
336
|
-
if (this.mnemonic) {
|
|
337
|
-
if (paths) {
|
|
338
|
-
let xPubKeys = await this.deriveHdPaths(paths);
|
|
339
|
-
return [xPubKeys];
|
|
340
|
-
} else {
|
|
341
|
-
return await this.deriveHdPaths(DERIVATION_PATHS);
|
|
342
|
-
}
|
|
343
|
-
} else {
|
|
344
|
-
throw Error("xpubkeys can only be derived from seed type wallets.");
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
456
|
// Initialize wallet from a mnemonic phrase
|
|
348
457
|
protected async fromSeed(
|
|
349
458
|
mnemonic: string,
|
|
350
459
|
derivationPath?: string
|
|
351
460
|
): Promise<this> {
|
|
352
|
-
|
|
353
|
-
this.mnemonic = mnemonic.trim().toLowerCase();
|
|
354
|
-
|
|
355
|
-
if (this.mnemonic.length == 0)
|
|
461
|
+
if (!mnemonic.length) {
|
|
356
462
|
throw Error("refusing to create wallet from empty mnemonic");
|
|
357
|
-
const seed = deriveSeedFromBip39Mnemonic(this.mnemonic);
|
|
358
|
-
checkForEmptySeed(seed);
|
|
359
|
-
if (![12, 24].includes(this.mnemonic.split(" ").length)) {
|
|
360
|
-
throw Error("Invalid mnemonic, must be 12 or 24 words");
|
|
361
463
|
}
|
|
362
|
-
const hdNode = deriveHdPrivateNodeFromSeed(seed, {
|
|
363
|
-
assumeValidity: true, // TODO: we should switch to libauth's BIP39 implementation and set this to false
|
|
364
|
-
throwErrors: true,
|
|
365
|
-
});
|
|
366
|
-
if (derivationPath) {
|
|
367
|
-
// @ts-ignore
|
|
368
|
-
this.derivationPath = derivationPath;
|
|
369
|
-
|
|
370
|
-
// If the derivation path is for the first account child, set the parent derivation path
|
|
371
|
-
const path = derivationPath.split("/");
|
|
372
|
-
if (path.slice(-2).join("/") == "0/0") {
|
|
373
|
-
// @ts-ignore
|
|
374
|
-
this.parentDerivationPath = path.slice(0, -2).join("/");
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
const zerothChild = deriveHdPath(hdNode, this.derivationPath);
|
|
379
|
-
if (typeof zerothChild === "string") {
|
|
380
|
-
throw Error(zerothChild);
|
|
381
|
-
}
|
|
382
|
-
// @ts-ignore
|
|
383
|
-
this.privateKey = zerothChild.privateKey;
|
|
384
|
-
|
|
385
|
-
const network = this.isTestnet ? "testnet" : "mainnet";
|
|
386
|
-
// @ts-ignore
|
|
387
|
-
this.parentXPubKey = await getXPubKey(
|
|
388
|
-
seed,
|
|
389
|
-
this.parentDerivationPath,
|
|
390
|
-
network
|
|
391
|
-
);
|
|
392
464
|
|
|
393
465
|
// @ts-ignore
|
|
394
466
|
this.walletType = WalletTypeEnum.Seed;
|
|
395
|
-
await this.deriveInfo();
|
|
396
|
-
return this;
|
|
397
|
-
}
|
|
398
467
|
|
|
399
|
-
|
|
400
|
-
public async deriveHdPaths(hdPaths: string[]): Promise<any[]> {
|
|
401
|
-
if (!this.mnemonic)
|
|
402
|
-
throw Error("refusing to create wallet from empty mnemonic");
|
|
403
|
-
const seed = deriveSeedFromBip39Mnemonic(this.mnemonic);
|
|
404
|
-
checkForEmptySeed(seed);
|
|
405
|
-
const hdNode = deriveHdPrivateNodeFromSeed(seed, {
|
|
406
|
-
assumeValidity: true, // TODO: we should switch to libauth's BIP39 implementation and set this to false
|
|
407
|
-
throwErrors: true,
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
const result: any[] = [];
|
|
411
|
-
|
|
412
|
-
for (const path of hdPaths) {
|
|
413
|
-
if (path === "m") {
|
|
414
|
-
throw Error(
|
|
415
|
-
"Storing or sharing of parent public key may lead to loss of funds. Storing or sharing *root* parent public keys is strongly discouraged, although all parent keys have risk. See: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#implications"
|
|
416
|
-
);
|
|
417
|
-
}
|
|
418
|
-
const childNode = deriveHdPath(hdNode, path);
|
|
419
|
-
if (typeof childNode === "string") {
|
|
420
|
-
throw Error(childNode);
|
|
421
|
-
}
|
|
422
|
-
const node = deriveHdPublicNode(childNode);
|
|
423
|
-
if (typeof node === "string") {
|
|
424
|
-
throw Error(node);
|
|
425
|
-
}
|
|
426
|
-
const xPubKey = encodeHdPublicKey(
|
|
427
|
-
{
|
|
428
|
-
network: this.network as HdKeyNetwork,
|
|
429
|
-
node: node,
|
|
430
|
-
},
|
|
431
|
-
{
|
|
432
|
-
throwErrors: true,
|
|
433
|
-
}
|
|
434
|
-
).hdPublicKey;
|
|
435
|
-
const key = new XPubKey({
|
|
436
|
-
path: path,
|
|
437
|
-
xPubKey: xPubKey,
|
|
438
|
-
});
|
|
468
|
+
await this.initialize({ mnemonic, derivationPath });
|
|
439
469
|
|
|
440
|
-
|
|
441
|
-
}
|
|
442
|
-
return await Promise.all(result).then((result) => {
|
|
443
|
-
return result;
|
|
444
|
-
});
|
|
470
|
+
return this;
|
|
445
471
|
}
|
|
446
472
|
|
|
447
473
|
// Initialize wallet from private key in hex or Uint8Array
|
|
@@ -452,31 +478,21 @@ export class Wallet extends BaseWallet {
|
|
|
452
478
|
privateKey = hexToBin(privateKey);
|
|
453
479
|
}
|
|
454
480
|
|
|
455
|
-
// @ts-ignore
|
|
456
|
-
this.privateKey = privateKey;
|
|
457
481
|
// @ts-ignore
|
|
458
482
|
this.walletType = WalletTypeEnum.PrivateKey;
|
|
459
|
-
|
|
483
|
+
|
|
484
|
+
await this.initialize({ privateKey });
|
|
485
|
+
|
|
460
486
|
return this;
|
|
461
487
|
}
|
|
462
488
|
|
|
463
489
|
// Initialize wallet from Wallet Import Format
|
|
464
|
-
protected async fromWIF(
|
|
465
|
-
checkWifNetwork(secret, this.network);
|
|
466
|
-
|
|
467
|
-
let wifResult = decodePrivateKeyWif(secret);
|
|
468
|
-
|
|
469
|
-
if (typeof wifResult === "string") {
|
|
470
|
-
throw Error(wifResult as string);
|
|
471
|
-
}
|
|
472
|
-
let resultData: PrivateKeyI = wifResult as PrivateKeyI;
|
|
473
|
-
// @ts-ignore
|
|
474
|
-
this.privateKey = resultData.privateKey;
|
|
475
|
-
// @ts-ignore
|
|
476
|
-
this.privateKeyWif = secret;
|
|
490
|
+
protected async fromWIF(privateKeyWif: string): Promise<this> {
|
|
477
491
|
// @ts-ignore
|
|
478
492
|
this.walletType = WalletTypeEnum.Wif;
|
|
479
|
-
|
|
493
|
+
|
|
494
|
+
await this.initialize({ privateKeyWif });
|
|
495
|
+
|
|
480
496
|
return this;
|
|
481
497
|
}
|
|
482
498
|
|
|
@@ -491,7 +507,7 @@ export class Wallet extends BaseWallet {
|
|
|
491
507
|
if (name.length > 0) {
|
|
492
508
|
return this.named(name, dbName);
|
|
493
509
|
} else {
|
|
494
|
-
return this.
|
|
510
|
+
return this.initialize();
|
|
495
511
|
}
|
|
496
512
|
}
|
|
497
513
|
//#endregion Protected Implementations
|
|
@@ -538,24 +554,6 @@ export class Wallet extends BaseWallet {
|
|
|
538
554
|
//#endregion Serialization
|
|
539
555
|
|
|
540
556
|
//#region Funds
|
|
541
|
-
public async getMaxAmountToSend(
|
|
542
|
-
params: {
|
|
543
|
-
outputCount?: number;
|
|
544
|
-
options?: SendRequestOptionsI;
|
|
545
|
-
} = {
|
|
546
|
-
outputCount: 1,
|
|
547
|
-
options: {},
|
|
548
|
-
}
|
|
549
|
-
): Promise<BalanceResponse> {
|
|
550
|
-
const { value: result } = await this._getMaxAmountToSend({
|
|
551
|
-
options: params.options,
|
|
552
|
-
outputCount: params.outputCount,
|
|
553
|
-
privateKey: this.privateKey,
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
return await balanceResponseFromSatoshi(result);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
557
|
/**
|
|
560
558
|
* sendMax Send all available funds to a destination cash address
|
|
561
559
|
*
|
|
@@ -588,11 +586,17 @@ export class Wallet extends BaseWallet {
|
|
|
588
586
|
options?: SendRequestOptionsI,
|
|
589
587
|
privateKey?: Uint8Array
|
|
590
588
|
) {
|
|
589
|
+
privateKey = privateKey ?? this.privateKey;
|
|
590
|
+
|
|
591
|
+
if (!privateKey && options?.buildUnsigned !== true) {
|
|
592
|
+
throw new Error(`Missing private key`);
|
|
593
|
+
}
|
|
594
|
+
|
|
591
595
|
return super.encodeTransaction(
|
|
592
596
|
requests,
|
|
593
597
|
discardChange,
|
|
594
598
|
options,
|
|
595
|
-
|
|
599
|
+
privateKey
|
|
596
600
|
);
|
|
597
601
|
}
|
|
598
602
|
|
|
@@ -608,42 +612,13 @@ export class Wallet extends BaseWallet {
|
|
|
608
612
|
}
|
|
609
613
|
//#endregion Funds
|
|
610
614
|
|
|
611
|
-
//#region Private implementation details
|
|
612
|
-
private async deriveInfo() {
|
|
613
|
-
const publicKey = secp256k1.derivePublicKeyUncompressed(this.privateKey);
|
|
614
|
-
if (typeof publicKey === "string") {
|
|
615
|
-
throw new Error(publicKey);
|
|
616
|
-
}
|
|
617
|
-
// @ts-ignore
|
|
618
|
-
this.publicKey = publicKey;
|
|
619
|
-
const publicKeyCompressed = secp256k1.derivePublicKeyCompressed(
|
|
620
|
-
this.privateKey
|
|
621
|
-
);
|
|
622
|
-
if (typeof publicKeyCompressed === "string") {
|
|
623
|
-
throw new Error(publicKeyCompressed);
|
|
624
|
-
}
|
|
625
|
-
// @ts-ignore
|
|
626
|
-
this.publicKeyCompressed = publicKeyCompressed;
|
|
627
|
-
const networkType =
|
|
628
|
-
this.network === NetworkType.Regtest ? NetworkType.Testnet : this.network;
|
|
629
|
-
// @ts-ignore
|
|
630
|
-
this.privateKeyWif = encodePrivateKeyWif(this.privateKey, networkType);
|
|
631
|
-
checkWifNetwork(this.privateKeyWif, this.network);
|
|
632
|
-
|
|
633
|
-
// @ts-ignore
|
|
634
|
-
this.cashaddr = deriveCashaddr(this.privateKey, this.networkPrefix);
|
|
635
|
-
// @ts-ignore
|
|
636
|
-
this.tokenaddr = deriveTokenaddr(this.privateKey, this.networkPrefix);
|
|
637
|
-
// @ts-ignore
|
|
638
|
-
this.publicKeyHash = derivePublicKeyHash(this.cashaddr);
|
|
639
|
-
return this;
|
|
640
|
-
}
|
|
641
|
-
//#endregion Private implementation details
|
|
642
|
-
|
|
643
615
|
//#region Signing
|
|
644
616
|
// Convenience wrapper to sign interface
|
|
645
|
-
public
|
|
646
|
-
|
|
617
|
+
public sign(
|
|
618
|
+
message: string,
|
|
619
|
+
privateKey: Uint8Array | undefined = undefined
|
|
620
|
+
): SignedMessageResponseI {
|
|
621
|
+
return super.sign(message, privateKey ?? this.privateKey);
|
|
647
622
|
}
|
|
648
623
|
}
|
|
649
624
|
|