@leather.io/bitcoin 0.12.2 → 0.13.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/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +35 -0
- package/dist/index.d.ts +122 -20
- package/dist/index.js +130 -23
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
- package/src/bitcoin-signer.spec.ts +11 -0
- package/src/bitcoin-signer.ts +196 -3
- package/src/bitcoin.utils.ts +23 -9
- package/src/p2tr-address-gen.ts +8 -8
- package/src/p2wpkh-address-gen.spec.ts +7 -4
- package/src/p2wpkh-address-gen.ts +10 -10
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @leather.io/bitcoin@0.
|
|
2
|
+
> @leather.io/bitcoin@0.13.1 build /home/runner/work/mono/mono/packages/bitcoin
|
|
3
3
|
> tsup
|
|
4
4
|
|
|
5
5
|
CLI Building entry: src/index.ts
|
|
@@ -8,9 +8,9 @@ CLI tsup v8.1.0
|
|
|
8
8
|
CLI Using tsup config: /home/runner/work/mono/mono/packages/bitcoin/tsup.config.ts
|
|
9
9
|
CLI Target: es2022
|
|
10
10
|
ESM Build start
|
|
11
|
-
ESM dist/index.js
|
|
12
|
-
ESM dist/index.js.map
|
|
13
|
-
ESM ⚡️ Build success in
|
|
11
|
+
ESM dist/index.js 21.92 KB
|
|
12
|
+
ESM dist/index.js.map 43.05 KB
|
|
13
|
+
ESM ⚡️ Build success in 73ms
|
|
14
14
|
DTS Build start
|
|
15
|
-
DTS ⚡️ Build success in
|
|
16
|
-
DTS dist/index.d.ts
|
|
15
|
+
DTS ⚡️ Build success in 4398ms
|
|
16
|
+
DTS dist/index.d.ts 15.09 KB
|
package/CHANGELOG.md
CHANGED
|
@@ -196,6 +196,41 @@
|
|
|
196
196
|
* devDependencies
|
|
197
197
|
* @leather.io/rpc bumped to 2.1.7
|
|
198
198
|
|
|
199
|
+
### Dependencies
|
|
200
|
+
|
|
201
|
+
* The following workspace dependencies were updated
|
|
202
|
+
* dependencies
|
|
203
|
+
* @leather.io/constants bumped to 0.12.0
|
|
204
|
+
* @leather.io/crypto bumped to 1.6.1
|
|
205
|
+
* @leather.io/models bumped to 0.16.0
|
|
206
|
+
* @leather.io/utils bumped to 0.16.1
|
|
207
|
+
* devDependencies
|
|
208
|
+
* @leather.io/rpc bumped to 2.1.9
|
|
209
|
+
|
|
210
|
+
## [0.13.0](https://github.com/leather-io/mono/compare/@leather.io/bitcoin-v0.12.2...@leather.io/bitcoin-v0.13.0) (2024-09-20)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
### Features
|
|
214
|
+
|
|
215
|
+
* **bitcoin:** signer logic ([811c15c](https://github.com/leather-io/mono/commit/811c15cd6d4105b07dd89595f136703fd3defd4d))
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
### Bug Fixes
|
|
219
|
+
|
|
220
|
+
* update btc-signer ([714fff0](https://github.com/leather-io/mono/commit/714fff083a581726feceab291d442997aabc9859))
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
### Dependencies
|
|
224
|
+
|
|
225
|
+
* The following workspace dependencies were updated
|
|
226
|
+
* dependencies
|
|
227
|
+
* @leather.io/constants bumped to 0.11.0
|
|
228
|
+
* @leather.io/crypto bumped to 1.6.0
|
|
229
|
+
* @leather.io/models bumped to 0.15.0
|
|
230
|
+
* @leather.io/utils bumped to 0.16.0
|
|
231
|
+
* devDependencies
|
|
232
|
+
* @leather.io/rpc bumped to 2.1.8
|
|
233
|
+
|
|
199
234
|
## [0.12.0](https://github.com/leather-io/mono/compare/@leather.io/bitcoin-v0.11.3...@leather.io/bitcoin-v0.12.0) (2024-09-06)
|
|
200
235
|
|
|
201
236
|
|
package/dist/index.d.ts
CHANGED
|
@@ -3,10 +3,11 @@ import * as bitcoin from 'bitcoinjs-lib';
|
|
|
3
3
|
import * as btc from '@scure/btc-signer';
|
|
4
4
|
import { BitcoinNetworkModes, NetworkModes } from '@leather.io/models';
|
|
5
5
|
import { HDKey, Versions } from '@scure/bip32';
|
|
6
|
+
import * as _scure_btc_signer_payment from '@scure/btc-signer/payment';
|
|
7
|
+
import { P2Ret, P2TROut } from '@scure/btc-signer/payment';
|
|
6
8
|
import { SigHash } from '@scure/btc-signer/transaction';
|
|
7
|
-
import {
|
|
9
|
+
import { PaymentTypes, SignatureHash } from '@leather.io/rpc';
|
|
8
10
|
import { TransactionInput, TransactionOutput } from '@scure/btc-signer/psbt';
|
|
9
|
-
import * as _scure_btc_signer_payment from '@scure/btc-signer/payment';
|
|
10
11
|
import { deriveBip39SeedFromMnemonic, deriveRootBip32Keychain } from '@leather.io/crypto';
|
|
11
12
|
|
|
12
13
|
declare function ecPairFromPrivateKey(key: Uint8Array): ecpair.ECPairInterface;
|
|
@@ -43,18 +44,6 @@ declare function signBip322MessageSimple(args: SignBip322MessageSimple): Promise
|
|
|
43
44
|
signature: string;
|
|
44
45
|
}>;
|
|
45
46
|
|
|
46
|
-
type AllowedSighashTypes = SignatureHash | SigHash;
|
|
47
|
-
interface Signer<Payment> {
|
|
48
|
-
network: BitcoinNetworkModes;
|
|
49
|
-
payment: Payment;
|
|
50
|
-
keychain: HDKey;
|
|
51
|
-
derivationPath: string;
|
|
52
|
-
address: string;
|
|
53
|
-
publicKey: Uint8Array;
|
|
54
|
-
sign(tx: btc.Transaction): void;
|
|
55
|
-
signIndex(tx: btc.Transaction, index: number, allowedSighash?: AllowedSighashTypes[]): void;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
47
|
interface BtcSignerNetwork {
|
|
59
48
|
bech32: string;
|
|
60
49
|
pubKeyHash: number;
|
|
@@ -104,6 +93,9 @@ declare function isBtcSignerLibPaymentType(payment: string): payment is BtcSigne
|
|
|
104
93
|
declare function parseKnownPaymentType(payment: BtcSignerLibPaymentTypeIdentifers | PaymentTypes): PaymentTypes;
|
|
105
94
|
type PaymentTypeMap<T> = Record<PaymentTypes, T>;
|
|
106
95
|
declare function whenPaymentType(mode: PaymentTypes | BtcSignerLibPaymentTypeIdentifers): <T extends unknown>(paymentMap: PaymentTypeMap<T>) => T;
|
|
96
|
+
type SupportedPaymentType = 'p2wpkh' | 'p2tr';
|
|
97
|
+
type SupportedPaymentTypeMap<T> = Record<SupportedPaymentType, T>;
|
|
98
|
+
declare function whenSupportedPaymentType(mode: SupportedPaymentType): <T>(paymentMap: SupportedPaymentTypeMap<T>) => T;
|
|
107
99
|
/**
|
|
108
100
|
* Infers the Bitcoin payment type from the derivation path.
|
|
109
101
|
* Below we see path has 86 in it, per convention, this refers to taproot payments
|
|
@@ -134,6 +126,110 @@ declare function mnemonicToRootNode(secretKey: string): HDKey;
|
|
|
134
126
|
declare function getPsbtTxInputs(psbtTx: btc.Transaction): TransactionInput[];
|
|
135
127
|
declare function getPsbtTxOutputs(psbtTx: btc.Transaction): TransactionOutput[];
|
|
136
128
|
|
|
129
|
+
type AllowedSighashTypes = SignatureHash | SigHash;
|
|
130
|
+
interface BitcoinAccountKeychain {
|
|
131
|
+
descriptor: string;
|
|
132
|
+
masterKeyFingerprint: string;
|
|
133
|
+
keyOrigin: string;
|
|
134
|
+
keychain: HDKey;
|
|
135
|
+
xpub: string;
|
|
136
|
+
}
|
|
137
|
+
type WithDerivePayer<T, P> = T & {
|
|
138
|
+
derivePayer: (args: BitcoinPayerInfo) => P;
|
|
139
|
+
};
|
|
140
|
+
interface BitcoinSigner<Payment> {
|
|
141
|
+
network: BitcoinNetworkModes;
|
|
142
|
+
payment: Payment;
|
|
143
|
+
keychain: HDKey;
|
|
144
|
+
derivationPath: string;
|
|
145
|
+
address: string;
|
|
146
|
+
publicKey: Uint8Array;
|
|
147
|
+
sign(tx: btc.Transaction): void;
|
|
148
|
+
signIndex(tx: btc.Transaction, index: number, allowedSighash?: AllowedSighashTypes[]): void;
|
|
149
|
+
}
|
|
150
|
+
interface BitcoinPayerBase {
|
|
151
|
+
paymentType: PaymentTypes;
|
|
152
|
+
network: BitcoinNetworkModes;
|
|
153
|
+
address: string;
|
|
154
|
+
keyOrigin: string;
|
|
155
|
+
masterKeyFingerprint: string;
|
|
156
|
+
publicKey: Uint8Array;
|
|
157
|
+
}
|
|
158
|
+
interface BitcoinNativeSegwitPayer extends BitcoinPayerBase {
|
|
159
|
+
paymentType: 'p2wpkh';
|
|
160
|
+
payment: P2Ret;
|
|
161
|
+
}
|
|
162
|
+
interface BitcoinTaprootPayer extends BitcoinPayerBase {
|
|
163
|
+
paymentType: 'p2tr';
|
|
164
|
+
payment: P2TROut;
|
|
165
|
+
}
|
|
166
|
+
type BitcoinPayer = BitcoinNativeSegwitPayer | BitcoinTaprootPayer;
|
|
167
|
+
declare function initializeBitcoinAccountKeychainFromDescriptor(descriptor: string): BitcoinAccountKeychain;
|
|
168
|
+
interface BitcoinPayerInfo {
|
|
169
|
+
receive?: number;
|
|
170
|
+
addressIndex: number;
|
|
171
|
+
}
|
|
172
|
+
declare function deriveBitcoinPayerFromAccount(descriptor: string, network: BitcoinNetworkModes): ({ receive, addressIndex }: BitcoinPayerInfo) => {
|
|
173
|
+
keyOrigin: string;
|
|
174
|
+
masterKeyFingerprint: string;
|
|
175
|
+
paymentType: SupportedPaymentType;
|
|
176
|
+
network: BitcoinNetworkModes;
|
|
177
|
+
payment: P2Ret;
|
|
178
|
+
readonly address: string;
|
|
179
|
+
readonly publicKey: Uint8Array;
|
|
180
|
+
};
|
|
181
|
+
interface BtcSignerDerivationPath {
|
|
182
|
+
fingerprint: number;
|
|
183
|
+
path: number[];
|
|
184
|
+
}
|
|
185
|
+
type BtcSignerDefaultBip32Derivation = [Uint8Array, BtcSignerDerivationPath];
|
|
186
|
+
type BtcSignerTapBip32Derivation = [
|
|
187
|
+
Uint8Array,
|
|
188
|
+
{
|
|
189
|
+
hashes: Uint8Array[];
|
|
190
|
+
der: BtcSignerDerivationPath;
|
|
191
|
+
}
|
|
192
|
+
];
|
|
193
|
+
type BtcSignerBip32Derivation = BtcSignerDefaultBip32Derivation | BtcSignerTapBip32Derivation;
|
|
194
|
+
type PayerToBip32DerivationArgs = Pick<BitcoinPayer, 'masterKeyFingerprint' | 'keyOrigin' | 'publicKey'>;
|
|
195
|
+
/**
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* tx.addInput({
|
|
199
|
+
* ...input,
|
|
200
|
+
* bip32Derivation: [payerToBip32Derivation(payer)],
|
|
201
|
+
* })
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
declare function payerToBip32Derivation(args: PayerToBip32DerivationArgs): BtcSignerDefaultBip32Derivation;
|
|
205
|
+
/**
|
|
206
|
+
* @example
|
|
207
|
+
* ```ts
|
|
208
|
+
* tx.addInput({
|
|
209
|
+
* ...input,
|
|
210
|
+
* tapBip32Derivation: [payerToTapBip32Derivation(payer)],
|
|
211
|
+
* })
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
declare function payerToTapBip32Derivation(args: PayerToBip32DerivationArgs): BtcSignerTapBip32Derivation;
|
|
215
|
+
/**
|
|
216
|
+
* @description
|
|
217
|
+
* Turns key format from @scure/btc-signer lib back into key origin string
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* const [inputOne] = getPsbtTxInputs(tx);
|
|
221
|
+
* const keyOrigin = serializeKeyOrigin(inputOne.bip32Derivation[0][1]);
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
declare function serializeKeyOrigin({ fingerprint, path }: BtcSignerDerivationPath): string;
|
|
225
|
+
/**
|
|
226
|
+
* @description
|
|
227
|
+
* Of a given set of a `tx.input`s bip32 derivation paths from
|
|
228
|
+
* `@scure/btc-signer`, serialize the paths back to the string format used
|
|
229
|
+
* internally
|
|
230
|
+
*/
|
|
231
|
+
declare function extractRequiredKeyOrigins(derivation: BtcSignerBip32Derivation[]): string[];
|
|
232
|
+
|
|
137
233
|
declare function makeTaprootAccountDerivationPath(network: BitcoinNetworkModes, accountIndex: number): string;
|
|
138
234
|
/** @deprecated Use makeTaprootAccountDerivationPath */
|
|
139
235
|
declare const getTaprootAccountDerivationPath: typeof makeTaprootAccountDerivationPath;
|
|
@@ -144,10 +240,13 @@ declare function deriveTaprootAccount(keychain: HDKey, network: BitcoinNetworkMo
|
|
|
144
240
|
declare function getTaprootPayment(publicKey: Uint8Array, network: BitcoinNetworkModes): _scure_btc_signer_payment.P2TROut;
|
|
145
241
|
declare function getTaprootPaymentFromAddressIndex(keychain: HDKey, network: BitcoinNetworkModes): _scure_btc_signer_payment.P2TROut;
|
|
146
242
|
interface DeriveTaprootReceiveAddressIndexArgs {
|
|
147
|
-
|
|
243
|
+
keychain: HDKey;
|
|
148
244
|
network: BitcoinNetworkModes;
|
|
149
245
|
}
|
|
150
|
-
declare function
|
|
246
|
+
declare function deriveTaprootReceiveAddressIndexZero({ keychain, network, }: DeriveTaprootReceiveAddressIndexArgs): {
|
|
247
|
+
keychain: HDKey;
|
|
248
|
+
payment: _scure_btc_signer_payment.P2TROut;
|
|
249
|
+
};
|
|
151
250
|
|
|
152
251
|
declare function makeNativeSegwitAccountDerivationPath(network: BitcoinNetworkModes, accountIndex: number): string;
|
|
153
252
|
/** @deprecated Use makeNativeSegwitAccountDerivationPath */
|
|
@@ -157,11 +256,14 @@ declare function makeNativeSegwitAddressIndexDerivationPath(network: BitcoinNetw
|
|
|
157
256
|
declare const getNativeSegwitAddressIndexDerivationPath: typeof makeNativeSegwitAddressIndexDerivationPath;
|
|
158
257
|
declare function deriveNativeSegwitAccountFromRootKeychain(keychain: HDKey, network: BitcoinNetworkModes): (accountIndex: number) => BitcoinAccount;
|
|
159
258
|
declare function getNativeSegWitPaymentFromAddressIndex(keychain: HDKey, network: BitcoinNetworkModes): _scure_btc_signer_payment.P2Ret;
|
|
160
|
-
interface
|
|
161
|
-
|
|
259
|
+
interface DeriveNativeSegwitReceiveAddressIndexArgs {
|
|
260
|
+
keychain: HDKey;
|
|
162
261
|
network: BitcoinNetworkModes;
|
|
163
262
|
}
|
|
164
|
-
declare function
|
|
263
|
+
declare function deriveNativeSegwitReceiveAddressIndexZero({ keychain, network, }: DeriveNativeSegwitReceiveAddressIndexArgs): {
|
|
264
|
+
keychain: HDKey;
|
|
265
|
+
payment: _scure_btc_signer_payment.P2Ret;
|
|
266
|
+
};
|
|
165
267
|
|
|
166
268
|
/**
|
|
167
269
|
* @deprecated
|
|
@@ -180,4 +282,4 @@ declare function makePayToScriptHashAddressBytes(keyHash: Uint8Array): Uint8Arra
|
|
|
180
282
|
declare function makePayToScriptHashAddress(addressBytes: Uint8Array, network: NetworkModes): string;
|
|
181
283
|
declare function publicKeyToPayToScriptHashAddress(publicKey: Uint8Array, network: NetworkModes): string;
|
|
182
284
|
|
|
183
|
-
export { type AllowedSighashTypes, type BitcoinAccount, type BtcSignerLibPaymentTypeIdentifers, type BtcSignerNetwork, type GetTaprootAddressArgs, type PaymentTypeMap, type
|
|
285
|
+
export { type AllowedSighashTypes, type BitcoinAccount, type BitcoinAccountKeychain, type BitcoinNativeSegwitPayer, type BitcoinPayer, type BitcoinPayerBase, type BitcoinPayerInfo, type BitcoinSigner, type BitcoinTaprootPayer, type BtcSignerDefaultBip32Derivation, type BtcSignerLibPaymentTypeIdentifers, type BtcSignerNetwork, type BtcSignerTapBip32Derivation, type GetTaprootAddressArgs, type PaymentTypeMap, type SupportedPaymentType, type SupportedPaymentTypeMap, type WithDerivePayer, bip322TransactionToSignValues, bitcoinNetworkModeToCoreNetworkMode, bitcoinNetworkToCoreNetworkMap, btcSignerLibPaymentTypeToPaymentTypeMap, coinTypeMap, createNativeSegwitBitcoinJsSigner, createTaprootBitcoinJsSigner, createToSpendTx, createWalletIdDecoratedPath, decodeBitcoinTx, decodeCompressedWifPrivateKey, deriveAddressIndexKeychainFromAccount, deriveAddressIndexZeroFromAccount, deriveBitcoinPayerFromAccount, deriveBtcBip49SeedFromMnemonic, deriveNativeSegwitAccountFromRootKeychain, deriveNativeSegwitReceiveAddressIndexZero, deriveRootBtcKeychain, deriveTaprootAccount, deriveTaprootReceiveAddressIndexZero, ecPairFromPrivateKey, ecdsaPublicKeyLength, ecdsaPublicKeyToSchnorr, encodeMessageWitnessData, extractExtendedPublicKeyFromPolicy, extractRequiredKeyOrigins, getAddressFromOutScript, getBitcoinCoinTypeIndexByNetwork, getBitcoinInputAddress, getBitcoinJsLibNetworkConfigByMode, getBtcSignerLibNetworkConfigByMode, getHdKeyVersionsFromNetwork, getInputPaymentType, getNativeSegWitPaymentFromAddressIndex, getNativeSegwitAccountDerivationPath, getNativeSegwitAddressIndexDerivationPath, getPsbtTxInputs, getPsbtTxOutputs, getTaprootAccountDerivationPath, getTaprootAddress, getTaprootAddressIndexDerivationPath, getTaprootPayment, getTaprootPaymentFromAddressIndex, hashBip322Message, inferNetworkFromPath, inferPaymentTypeFromPath, initBitcoinAccount, initializeBitcoinAccountKeychainFromDescriptor, isBtcSignerLibPaymentType, isSupportedMessageSigningPaymentType, lookUpLedgerKeysByPath, makeNativeSegwitAccountDerivationPath, makeNativeSegwitAddressIndexDerivationPath, makePayToScriptHashAddress, makePayToScriptHashAddressBytes, makePayToScriptHashKeyHash, makeTaprootAccountDerivationPath, makeTaprootAddressIndexDerivationPath, mnemonicToRootNode, parseKnownPaymentType, payToScriptHashTestnetPrefix, payerToBip32Derivation, payerToTapBip32Derivation, paymentTypeMap, publicKeyToPayToScriptHashAddress, serializeKeyOrigin, signBip322MessageSimple, toXOnly, tweakSigner, whenPaymentType, whenSupportedPaymentType };
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,11 @@ import { hexToBytes } from "@noble/hashes/utils";
|
|
|
12
12
|
import { HDKey } from "@scure/bip32";
|
|
13
13
|
import { mnemonicToSeedSync } from "@scure/bip39";
|
|
14
14
|
import * as btc2 from "@scure/btc-signer";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
DerivationPathDepth as DerivationPathDepth2,
|
|
17
|
+
extractAccountIndexFromPath,
|
|
18
|
+
extractPurposeFromPath
|
|
19
|
+
} from "@leather.io/crypto";
|
|
16
20
|
import { defaultWalletKeyId, isDefined, whenNetwork } from "@leather.io/utils";
|
|
17
21
|
|
|
18
22
|
// src/bitcoin.network.ts
|
|
@@ -58,7 +62,7 @@ function getBitcoinJsLibNetworkConfigByMode(network) {
|
|
|
58
62
|
|
|
59
63
|
// src/p2tr-address-gen.ts
|
|
60
64
|
import * as btc from "@scure/btc-signer";
|
|
61
|
-
import { DerivationPathDepth
|
|
65
|
+
import { DerivationPathDepth } from "@leather.io/crypto";
|
|
62
66
|
function makeTaprootAccountDerivationPath(network, accountIndex) {
|
|
63
67
|
return `m/86'/${getBitcoinCoinTypeIndexByNetwork(network)}'/${accountIndex}'`;
|
|
64
68
|
}
|
|
@@ -91,13 +95,15 @@ function getTaprootPaymentFromAddressIndex(keychain, network) {
|
|
|
91
95
|
if (!keychain.publicKey) throw new Error("Keychain has no public key");
|
|
92
96
|
return getTaprootPayment(keychain.publicKey, network);
|
|
93
97
|
}
|
|
94
|
-
function
|
|
95
|
-
|
|
98
|
+
function deriveTaprootReceiveAddressIndexZero({
|
|
99
|
+
keychain,
|
|
96
100
|
network
|
|
97
101
|
}) {
|
|
98
|
-
const keychain = deriveKeychainFromXpub(xpub);
|
|
99
102
|
const zeroAddressIndex = deriveAddressIndexZeroFromAccount(keychain);
|
|
100
|
-
return
|
|
103
|
+
return {
|
|
104
|
+
keychain: zeroAddressIndex,
|
|
105
|
+
payment: getTaprootPaymentFromAddressIndex(zeroAddressIndex, network)
|
|
106
|
+
};
|
|
101
107
|
}
|
|
102
108
|
|
|
103
109
|
// src/bitcoin.utils.ts
|
|
@@ -192,11 +198,21 @@ function parseKnownPaymentType(payment) {
|
|
|
192
198
|
function whenPaymentType(mode) {
|
|
193
199
|
return (paymentMap) => paymentMap[parseKnownPaymentType(mode)];
|
|
194
200
|
}
|
|
201
|
+
function whenSupportedPaymentType(mode) {
|
|
202
|
+
return (paymentMap) => paymentMap[mode];
|
|
203
|
+
}
|
|
195
204
|
function inferPaymentTypeFromPath(path) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
205
|
+
const purpose = extractPurposeFromPath(path);
|
|
206
|
+
switch (purpose) {
|
|
207
|
+
case 84:
|
|
208
|
+
return "p2wpkh";
|
|
209
|
+
case 86:
|
|
210
|
+
return "p2tr";
|
|
211
|
+
case 44:
|
|
212
|
+
return "p2pkh";
|
|
213
|
+
default:
|
|
214
|
+
throw new Error(`Unable to infer payment type from purpose=${purpose}`);
|
|
215
|
+
}
|
|
200
216
|
}
|
|
201
217
|
function inferNetworkFromPath(path) {
|
|
202
218
|
return path.split("/")[2].startsWith("0") ? "mainnet" : "testnet";
|
|
@@ -248,9 +264,7 @@ function getTaprootAddress({ index, keychain, network }) {
|
|
|
248
264
|
if (keychain.depth !== DerivationPathDepth2.Account)
|
|
249
265
|
throw new Error("Expects keychain to be on the account index");
|
|
250
266
|
const addressIndex = deriveAddressIndexKeychainFromAccount(keychain)(index);
|
|
251
|
-
if (!addressIndex.publicKey)
|
|
252
|
-
throw new Error("Expected publicKey to be defined");
|
|
253
|
-
}
|
|
267
|
+
if (!addressIndex.publicKey) throw new Error("Expected publicKey to be defined");
|
|
254
268
|
const payment = getTaprootPayment(addressIndex.publicKey, network);
|
|
255
269
|
if (!payment.address) throw new Error("Expected address to be defined");
|
|
256
270
|
return payment.address;
|
|
@@ -383,9 +397,21 @@ async function signBip322MessageSimple(args) {
|
|
|
383
397
|
};
|
|
384
398
|
}
|
|
385
399
|
|
|
400
|
+
// src/bitcoin-signer.ts
|
|
401
|
+
import { HARDENED_OFFSET } from "@scure/bip32";
|
|
402
|
+
import * as btc4 from "@scure/btc-signer";
|
|
403
|
+
import {
|
|
404
|
+
DerivationPathDepth as DerivationPathDepth4,
|
|
405
|
+
appendAddressIndexToPath,
|
|
406
|
+
decomposeDescriptor,
|
|
407
|
+
deriveKeychainFromXpub,
|
|
408
|
+
keyOriginToDerivationPath
|
|
409
|
+
} from "@leather.io/crypto";
|
|
410
|
+
import { hexToNumber, toHexString } from "@leather.io/utils";
|
|
411
|
+
|
|
386
412
|
// src/p2wpkh-address-gen.ts
|
|
387
413
|
import * as btc3 from "@scure/btc-signer";
|
|
388
|
-
import { DerivationPathDepth as DerivationPathDepth3
|
|
414
|
+
import { DerivationPathDepth as DerivationPathDepth3 } from "@leather.io/crypto";
|
|
389
415
|
function makeNativeSegwitAccountDerivationPath(network, accountIndex) {
|
|
390
416
|
return `m/84'/${getBitcoinCoinTypeIndexByNetwork(network)}'/${accountIndex}'`;
|
|
391
417
|
}
|
|
@@ -410,15 +436,89 @@ function getNativeSegWitPaymentFromAddressIndex(keychain, network) {
|
|
|
410
436
|
if (!keychain.publicKey) throw new Error("Keychain does not have a public key");
|
|
411
437
|
return btc3.p2wpkh(keychain.publicKey, getBtcSignerLibNetworkConfigByMode(network));
|
|
412
438
|
}
|
|
413
|
-
function
|
|
414
|
-
|
|
439
|
+
function deriveNativeSegwitReceiveAddressIndexZero({
|
|
440
|
+
keychain,
|
|
415
441
|
network
|
|
416
442
|
}) {
|
|
417
|
-
if (!xpub) return;
|
|
418
|
-
const keychain = deriveKeychainFromXpub2(xpub);
|
|
419
|
-
if (!keychain) return;
|
|
420
443
|
const zeroAddressIndex = deriveAddressIndexZeroFromAccount(keychain);
|
|
421
|
-
return
|
|
444
|
+
return {
|
|
445
|
+
keychain: zeroAddressIndex,
|
|
446
|
+
payment: getNativeSegWitPaymentFromAddressIndex(zeroAddressIndex, network)
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// src/bitcoin-signer.ts
|
|
451
|
+
function initializeBitcoinAccountKeychainFromDescriptor(descriptor) {
|
|
452
|
+
const { fingerprint, keyOrigin } = decomposeDescriptor(descriptor);
|
|
453
|
+
return {
|
|
454
|
+
descriptor,
|
|
455
|
+
xpub: extractExtendedPublicKeyFromPolicy(descriptor),
|
|
456
|
+
keyOrigin,
|
|
457
|
+
masterKeyFingerprint: fingerprint,
|
|
458
|
+
keychain: deriveKeychainFromXpub(extractExtendedPublicKeyFromPolicy(descriptor))
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
function deriveBitcoinPayerFromAccount(descriptor, network) {
|
|
462
|
+
const { fingerprint, keyOrigin } = decomposeDescriptor(descriptor);
|
|
463
|
+
const accountKeychain = deriveKeychainFromXpub(extractExtendedPublicKeyFromPolicy(descriptor));
|
|
464
|
+
const paymentType = inferPaymentTypeFromPath(keyOrigin);
|
|
465
|
+
if (accountKeychain.depth !== DerivationPathDepth4.Account)
|
|
466
|
+
throw new Error("Keychain passed is not an account");
|
|
467
|
+
return ({ receive = 0, addressIndex }) => {
|
|
468
|
+
const childKeychain = accountKeychain.deriveChild(receive).deriveChild(addressIndex);
|
|
469
|
+
const derivePayerFromAccount = whenSupportedPaymentType(paymentType)({
|
|
470
|
+
p2tr: getTaprootPaymentFromAddressIndex,
|
|
471
|
+
p2wpkh: getNativeSegWitPaymentFromAddressIndex
|
|
472
|
+
});
|
|
473
|
+
const payment = derivePayerFromAccount(childKeychain, network);
|
|
474
|
+
return {
|
|
475
|
+
keyOrigin: appendAddressIndexToPath(keyOrigin, 0),
|
|
476
|
+
masterKeyFingerprint: fingerprint,
|
|
477
|
+
paymentType,
|
|
478
|
+
network,
|
|
479
|
+
payment,
|
|
480
|
+
get address() {
|
|
481
|
+
if (!payment.address) throw new Error("Payment address could not be derived");
|
|
482
|
+
return payment.address;
|
|
483
|
+
},
|
|
484
|
+
get publicKey() {
|
|
485
|
+
if (!childKeychain.publicKey) throw new Error("Public key could not be derived");
|
|
486
|
+
return childKeychain.publicKey;
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
function payerToBip32Derivation(args) {
|
|
492
|
+
return [
|
|
493
|
+
args.publicKey,
|
|
494
|
+
{
|
|
495
|
+
fingerprint: hexToNumber(args.masterKeyFingerprint),
|
|
496
|
+
path: btc4.bip32Path(keyOriginToDerivationPath(args.keyOrigin))
|
|
497
|
+
}
|
|
498
|
+
];
|
|
499
|
+
}
|
|
500
|
+
function payerToTapBip32Derivation(args) {
|
|
501
|
+
return [
|
|
502
|
+
// TODO: @kyranjamie to default to schnoor when TR so conversion isn't
|
|
503
|
+
// necessary here?
|
|
504
|
+
ecdsaPublicKeyToSchnorr(args.publicKey),
|
|
505
|
+
{
|
|
506
|
+
hashes: [],
|
|
507
|
+
der: {
|
|
508
|
+
fingerprint: hexToNumber(args.masterKeyFingerprint),
|
|
509
|
+
path: btc4.bip32Path(keyOriginToDerivationPath(args.keyOrigin))
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
function serializeKeyOrigin({ fingerprint, path }) {
|
|
515
|
+
const values = path.map((num) => num >= HARDENED_OFFSET ? num - HARDENED_OFFSET + "'" : num);
|
|
516
|
+
return `${toHexString(fingerprint)}/${values.join("/")}`;
|
|
517
|
+
}
|
|
518
|
+
function extractRequiredKeyOrigins(derivation) {
|
|
519
|
+
return derivation.map(
|
|
520
|
+
([_pubkey, path]) => serializeKeyOrigin("hashes" in path ? path.der : path)
|
|
521
|
+
);
|
|
422
522
|
}
|
|
423
523
|
|
|
424
524
|
// src/p2wsh-p2sh-address-gen.ts
|
|
@@ -476,17 +576,19 @@ export {
|
|
|
476
576
|
decodeCompressedWifPrivateKey,
|
|
477
577
|
deriveAddressIndexKeychainFromAccount,
|
|
478
578
|
deriveAddressIndexZeroFromAccount,
|
|
579
|
+
deriveBitcoinPayerFromAccount,
|
|
479
580
|
deriveBtcBip49SeedFromMnemonic,
|
|
480
|
-
deriveNativeSegWitReceiveAddressIndex,
|
|
481
581
|
deriveNativeSegwitAccountFromRootKeychain,
|
|
582
|
+
deriveNativeSegwitReceiveAddressIndexZero,
|
|
482
583
|
deriveRootBtcKeychain,
|
|
483
584
|
deriveTaprootAccount,
|
|
484
|
-
|
|
585
|
+
deriveTaprootReceiveAddressIndexZero,
|
|
485
586
|
ecPairFromPrivateKey,
|
|
486
587
|
ecdsaPublicKeyLength,
|
|
487
588
|
ecdsaPublicKeyToSchnorr,
|
|
488
589
|
encodeMessageWitnessData,
|
|
489
590
|
extractExtendedPublicKeyFromPolicy,
|
|
591
|
+
extractRequiredKeyOrigins,
|
|
490
592
|
getAddressFromOutScript,
|
|
491
593
|
getBitcoinCoinTypeIndexByNetwork,
|
|
492
594
|
getBitcoinInputAddress,
|
|
@@ -508,6 +610,7 @@ export {
|
|
|
508
610
|
inferNetworkFromPath,
|
|
509
611
|
inferPaymentTypeFromPath,
|
|
510
612
|
initBitcoinAccount,
|
|
613
|
+
initializeBitcoinAccountKeychainFromDescriptor,
|
|
511
614
|
isBtcSignerLibPaymentType,
|
|
512
615
|
isSupportedMessageSigningPaymentType,
|
|
513
616
|
lookUpLedgerKeysByPath,
|
|
@@ -521,11 +624,15 @@ export {
|
|
|
521
624
|
mnemonicToRootNode,
|
|
522
625
|
parseKnownPaymentType,
|
|
523
626
|
payToScriptHashTestnetPrefix,
|
|
627
|
+
payerToBip32Derivation,
|
|
628
|
+
payerToTapBip32Derivation,
|
|
524
629
|
paymentTypeMap,
|
|
525
630
|
publicKeyToPayToScriptHashAddress,
|
|
631
|
+
serializeKeyOrigin,
|
|
526
632
|
signBip322MessageSimple,
|
|
527
633
|
toXOnly,
|
|
528
634
|
tweakSigner,
|
|
529
|
-
whenPaymentType
|
|
635
|
+
whenPaymentType,
|
|
636
|
+
whenSupportedPaymentType
|
|
530
637
|
};
|
|
531
638
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bip322/bip322-utils.ts","../src/bitcoin.utils.ts","../src/bitcoin.network.ts","../src/p2tr-address-gen.ts","../src/bip322/sign-message-bip322-bitcoinjs.ts","../src/p2wpkh-address-gen.ts","../src/p2wsh-p2sh-address-gen.ts"],"sourcesContent":["import ecc from '@bitcoinerlab/secp256k1';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { hexToBytes, utf8ToBytes } from '@stacks/common';\nimport * as bitcoin from 'bitcoinjs-lib';\nimport { ECPairFactory } from 'ecpair';\nimport { encode } from 'varuint-bitcoin';\n\nimport { PaymentTypes } from '@leather.io/rpc';\nimport { isString } from '@leather.io/utils';\n\nimport { toXOnly } from '../bitcoin.utils';\n\nconst bip322MessageTag = 'BIP0322-signed-message';\n\nconst ECPair = ECPairFactory(ecc);\nbitcoin.initEccLib(ecc);\n\nexport function ecPairFromPrivateKey(key: Uint8Array) {\n return ECPair.fromPrivateKey(Buffer.from(key));\n}\n\n// See tagged hashes section of BIP-340\n// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki#design\nconst messageTagHash = Uint8Array.from([\n ...sha256(utf8ToBytes(bip322MessageTag)),\n ...sha256(utf8ToBytes(bip322MessageTag)),\n]);\n\nexport function hashBip322Message(message: Uint8Array | string) {\n return sha256(\n Uint8Array.from([...messageTagHash, ...(isString(message) ? utf8ToBytes(message) : message)])\n );\n}\n\nexport const bip322TransactionToSignValues = {\n prevoutHash: hexToBytes('0000000000000000000000000000000000000000000000000000000000000000'),\n prevoutIndex: 0xffffffff,\n sequence: 0,\n};\n\nfunction encodeVarString(b: Buffer) {\n return Buffer.concat([encode(b.byteLength), b]);\n}\n\nconst supportedMessageSigningPaymentTypes: PaymentTypes[] = ['p2wpkh', 'p2tr'];\n\nexport function isSupportedMessageSigningPaymentType(paymentType: string) {\n return supportedMessageSigningPaymentTypes.includes(paymentType as PaymentTypes);\n}\n\n/**\n * Encode witness data for a BIP322 message\n * TODO: Refactor to remove `Buffer` use\n */\nexport function encodeMessageWitnessData(witnessArray: Buffer[]) {\n const len = encode(witnessArray.length);\n return Buffer.concat([len, ...witnessArray.map(witness => encodeVarString(witness))]);\n}\n\nfunction tapTweakHash(pubKey: Buffer, h: Buffer | undefined): Buffer {\n return bitcoin.crypto.taggedHash('TapTweak', Buffer.concat(h ? [pubKey, h] : [pubKey]));\n}\n\nexport function tweakSigner(signer: bitcoin.Signer, opts: any = {}): bitcoin.Signer {\n // @ts-expect-error privateKey exists on signer\n let privateKey: Uint8Array | undefined = signer.privateKey!;\n if (!privateKey) {\n throw new Error('Private key is required for tweaking signer!');\n }\n if (signer.publicKey[0] === 3) {\n privateKey = ecc.privateNegate(privateKey);\n }\n\n const tweakedPrivateKey = ecc.privateAdd(\n privateKey,\n tapTweakHash(toXOnly(signer.publicKey), opts.tweakHash)\n );\n if (!tweakedPrivateKey) {\n throw new Error('Invalid tweaked private key!');\n }\n\n return ECPair.fromPrivateKey(Buffer.from(tweakedPrivateKey), {\n network: opts.network,\n });\n}\n","import { hexToBytes } from '@noble/hashes/utils';\nimport { HDKey, Versions } from '@scure/bip32';\nimport { mnemonicToSeedSync } from '@scure/bip39';\nimport * as btc from '@scure/btc-signer';\nimport { TransactionInput, TransactionOutput } from '@scure/btc-signer/psbt';\n\nimport { DerivationPathDepth, extractAccountIndexFromPath } from '@leather.io/crypto';\nimport { BitcoinNetworkModes, NetworkModes } from '@leather.io/models';\nimport type { PaymentTypes } from '@leather.io/rpc';\nimport { defaultWalletKeyId, isDefined, whenNetwork } from '@leather.io/utils';\n\nimport { BtcSignerNetwork, getBtcSignerLibNetworkConfigByMode } from './bitcoin.network';\nimport { getTaprootPayment } from './p2tr-address-gen';\n\nexport interface BitcoinAccount {\n type: PaymentTypes;\n derivationPath: string;\n keychain: HDKey;\n accountIndex: number;\n network: BitcoinNetworkModes;\n}\nexport function initBitcoinAccount(derivationPath: string, policy: string): BitcoinAccount {\n const xpub = extractExtendedPublicKeyFromPolicy(policy);\n const network = inferNetworkFromPath(derivationPath);\n return {\n keychain: HDKey.fromExtendedKey(xpub, getHdKeyVersionsFromNetwork(network)),\n network,\n derivationPath,\n type: inferPaymentTypeFromPath(derivationPath),\n accountIndex: extractAccountIndexFromPath(derivationPath),\n };\n}\n\n/**\n * Represents a map of `BitcoinNetworkModes` to `NetworkModes`. While Bitcoin\n * has a number of networks, its often only necessary to consider the higher\n * level concept of mainnet and testnet\n */\nexport const bitcoinNetworkToCoreNetworkMap: Record<BitcoinNetworkModes, NetworkModes> = {\n mainnet: 'mainnet',\n testnet: 'testnet',\n regtest: 'testnet',\n signet: 'testnet',\n};\nexport function bitcoinNetworkModeToCoreNetworkMode(mode: BitcoinNetworkModes) {\n return bitcoinNetworkToCoreNetworkMap[mode];\n}\n\n/**\n * Map representing the \"Coin Type\" section of a derivation path.\n * Consider example below, Coin type is one, thus testnet\n * @example\n * `m/86'/1'/0'/0/0`\n */\nexport const coinTypeMap: Record<NetworkModes, 0 | 1> = {\n mainnet: 0,\n testnet: 1,\n};\n\nexport function getBitcoinCoinTypeIndexByNetwork(network: BitcoinNetworkModes) {\n return coinTypeMap[bitcoinNetworkModeToCoreNetworkMode(network)];\n}\n\nexport function deriveAddressIndexKeychainFromAccount(keychain: HDKey) {\n if (keychain.depth !== DerivationPathDepth.Account)\n throw new Error('Keychain passed is not an account');\n\n return (index: number) => keychain.deriveChild(0).deriveChild(index);\n}\n\nexport function deriveAddressIndexZeroFromAccount(keychain: HDKey) {\n return deriveAddressIndexKeychainFromAccount(keychain)(0);\n}\n\nexport const ecdsaPublicKeyLength = 33;\n\nexport function ecdsaPublicKeyToSchnorr(pubKey: Uint8Array) {\n if (pubKey.byteLength !== ecdsaPublicKeyLength) throw new Error('Invalid public key length');\n return pubKey.slice(1);\n}\n\n// Basically same as above, to remove\nexport const toXOnly = (pubKey: Buffer) => (pubKey.length === 32 ? pubKey : pubKey.subarray(1, 33));\n\nexport function decodeBitcoinTx(tx: string): ReturnType<typeof btc.RawTx.decode> {\n return btc.RawTx.decode(hexToBytes(tx));\n}\n\nexport function getAddressFromOutScript(script: Uint8Array, bitcoinNetwork: BtcSignerNetwork) {\n const outputScript = btc.OutScript.decode(script);\n\n switch (outputScript.type) {\n case 'pkh':\n case 'sh':\n case 'wpkh':\n case 'wsh':\n return btc.Address(bitcoinNetwork).encode({\n type: outputScript.type,\n hash: outputScript.hash,\n });\n case 'tr':\n return btc.Address(bitcoinNetwork).encode({\n type: outputScript.type,\n pubkey: outputScript.pubkey,\n });\n case 'ms':\n return btc.p2ms(outputScript.m, outputScript.pubkeys).address ?? '';\n case 'pk':\n return btc.p2pk(outputScript.pubkey, bitcoinNetwork).address ?? '';\n case 'unknown':\n return 'unknown';\n case 'tr_ms':\n case 'tr_ns':\n default:\n return '';\n }\n}\n\n/**\n * Payment type identifiers, as described by `@scure/btc-signer` library\n */\nexport type BtcSignerLibPaymentTypeIdentifers = 'wpkh' | 'wsh' | 'tr' | 'pkh' | 'sh';\n\nexport const paymentTypeMap: Record<BtcSignerLibPaymentTypeIdentifers, PaymentTypes> = {\n wpkh: 'p2wpkh',\n wsh: 'p2wpkh-p2sh',\n tr: 'p2tr',\n pkh: 'p2pkh',\n sh: 'p2sh',\n};\n\nexport function btcSignerLibPaymentTypeToPaymentTypeMap(\n payment: BtcSignerLibPaymentTypeIdentifers\n) {\n return paymentTypeMap[payment];\n}\n\nexport function isBtcSignerLibPaymentType(\n payment: string\n): payment is BtcSignerLibPaymentTypeIdentifers {\n return payment in paymentTypeMap;\n}\n\nexport function parseKnownPaymentType(payment: BtcSignerLibPaymentTypeIdentifers | PaymentTypes) {\n return isBtcSignerLibPaymentType(payment)\n ? btcSignerLibPaymentTypeToPaymentTypeMap(payment)\n : payment;\n}\n\nexport type PaymentTypeMap<T> = Record<PaymentTypes, T>;\nexport function whenPaymentType(mode: PaymentTypes | BtcSignerLibPaymentTypeIdentifers) {\n return <T extends unknown>(paymentMap: PaymentTypeMap<T>): T =>\n paymentMap[parseKnownPaymentType(mode)];\n}\n\n/**\n * Infers the Bitcoin payment type from the derivation path.\n * Below we see path has 86 in it, per convention, this refers to taproot payments\n * @example\n * `m/86'/1'/0'/0/0`\n */\nexport function inferPaymentTypeFromPath(path: string): PaymentTypes {\n if (path.startsWith('m/84')) return 'p2wpkh';\n if (path.startsWith('m/86')) return 'p2tr';\n if (path.startsWith('m/44')) return 'p2pkh';\n throw new Error(`Unable to infer payment type from path=${path}`);\n}\n\nexport function inferNetworkFromPath(path: string): NetworkModes {\n return path.split('/')[2].startsWith('0') ? 'mainnet' : 'testnet';\n}\n\nexport function extractExtendedPublicKeyFromPolicy(policy: string) {\n return policy.split(']')[1];\n}\n\nexport function createWalletIdDecoratedPath(policy: string, walletId: string) {\n return policy.split(']')[0].replace('[', '').replace('m', walletId);\n}\n\n// Primarily used to get the correct `Version` when passing Ledger Bitcoin\n// extended public keys to the HDKey constructor\nexport function getHdKeyVersionsFromNetwork(network: NetworkModes) {\n return whenNetwork(network)({\n mainnet: undefined,\n testnet: {\n private: 0x00000000,\n public: 0x043587cf,\n } as Versions,\n });\n}\n\nexport function getBitcoinInputAddress(input: TransactionInput, bitcoinNetwork: BtcSignerNetwork) {\n if (isDefined(input.witnessUtxo))\n return getAddressFromOutScript(input.witnessUtxo.script, bitcoinNetwork);\n if (isDefined(input.nonWitnessUtxo) && isDefined(input.index))\n return getAddressFromOutScript(\n input.nonWitnessUtxo.outputs[input.index]?.script,\n bitcoinNetwork\n );\n return '';\n}\n\nexport function getInputPaymentType(\n input: TransactionInput,\n network: BitcoinNetworkModes\n): PaymentTypes {\n const address = getBitcoinInputAddress(input, getBtcSignerLibNetworkConfigByMode(network));\n if (address === '') throw new Error('Input address cannot be empty');\n if (address.startsWith('bc1p') || address.startsWith('tb1p') || address.startsWith('bcrt1p'))\n return 'p2tr';\n if (address.startsWith('bc1q') || address.startsWith('tb1q') || address.startsWith('bcrt1q'))\n return 'p2wpkh';\n throw new Error('Unable to infer payment type from input address');\n}\n\n// Ledger wallets are keyed by their derivation path. To reuse the look up logic\n// between payment types, this factory fn accepts a fn that generates the path\nexport function lookUpLedgerKeysByPath(\n getDerivationPath: (network: BitcoinNetworkModes, accountIndex: number) => string\n) {\n return (\n ledgerKeyMap: Record<string, { policy: string } | undefined>,\n network: BitcoinNetworkModes\n ) =>\n (accountIndex: number) => {\n const path = getDerivationPath(network, accountIndex);\n // Single wallet mode, hardcoded default walletId\n const account = ledgerKeyMap[path.replace('m', defaultWalletKeyId)];\n if (!account) return;\n return initBitcoinAccount(path, account.policy);\n };\n}\n\nexport interface GetTaprootAddressArgs {\n index: number;\n keychain?: HDKey;\n network: BitcoinNetworkModes;\n}\nexport function getTaprootAddress({ index, keychain, network }: GetTaprootAddressArgs) {\n if (!keychain) throw new Error('Expected keychain to be provided');\n\n if (keychain.depth !== DerivationPathDepth.Account)\n throw new Error('Expects keychain to be on the account index');\n\n const addressIndex = deriveAddressIndexKeychainFromAccount(keychain)(index);\n\n if (!addressIndex.publicKey) {\n throw new Error('Expected publicKey to be defined');\n }\n\n const payment = getTaprootPayment(addressIndex.publicKey, network);\n\n if (!payment.address) throw new Error('Expected address to be defined');\n\n return payment.address;\n}\n\n/**\n * @deprecated\n * Use `deriveRootBip32Keychain` in `@leather.io/crypto` instead\n */\nexport function mnemonicToRootNode(secretKey: string) {\n const seed = mnemonicToSeedSync(secretKey);\n return HDKey.fromMasterSeed(seed);\n}\n\nexport function getPsbtTxInputs(psbtTx: btc.Transaction): TransactionInput[] {\n const inputsLength = psbtTx.inputsLength;\n const inputs: TransactionInput[] = [];\n for (let i = 0; i < inputsLength; i++) inputs.push(psbtTx.getInput(i));\n return inputs;\n}\n\nexport function getPsbtTxOutputs(psbtTx: btc.Transaction): TransactionOutput[] {\n const outputsLength = psbtTx.outputsLength;\n const outputs: TransactionOutput[] = [];\n for (let i = 0; i < outputsLength; i++) outputs.push(psbtTx.getOutput(i));\n return outputs;\n}\n","import * as bitcoinJs from 'bitcoinjs-lib';\n\nimport { BitcoinNetworkModes } from '@leather.io/models';\n\n// See this PR https://github.com/paulmillr/@scure/btc-signer/pull/15\n// Atttempting to add these directly to the library\nexport interface BtcSignerNetwork {\n bech32: string;\n pubKeyHash: number;\n scriptHash: number;\n wif: number;\n}\n\nconst bitcoinMainnet: BtcSignerNetwork = {\n bech32: 'bc',\n pubKeyHash: 0x00,\n scriptHash: 0x05,\n wif: 0x80,\n};\n\nconst bitcoinTestnet: BtcSignerNetwork = {\n bech32: 'tb',\n pubKeyHash: 0x6f,\n scriptHash: 0xc4,\n wif: 0xef,\n};\n\nconst bitcoinRegtest: BtcSignerNetwork = {\n bech32: 'bcrt',\n pubKeyHash: 0x6f,\n scriptHash: 0xc4,\n wif: 0xef,\n};\n\nconst btcSignerLibNetworks: Record<BitcoinNetworkModes, BtcSignerNetwork> = {\n mainnet: bitcoinMainnet,\n testnet: bitcoinTestnet,\n regtest: bitcoinRegtest,\n // Signet originally was going to have its own prefix but authors decided to\n // copy testnet\n signet: bitcoinTestnet,\n};\n\nexport function getBtcSignerLibNetworkConfigByMode(network: BitcoinNetworkModes) {\n return btcSignerLibNetworks[network];\n}\n\nconst bitcoinJsLibNetworks: Record<BitcoinNetworkModes, bitcoinJs.Network> = {\n mainnet: bitcoinJs.networks.bitcoin,\n testnet: bitcoinJs.networks.testnet,\n regtest: bitcoinJs.networks.regtest,\n signet: bitcoinJs.networks.testnet,\n};\n\nexport function getBitcoinJsLibNetworkConfigByMode(network: BitcoinNetworkModes) {\n return bitcoinJsLibNetworks[network];\n}\n","import { HDKey } from '@scure/bip32';\nimport * as btc from '@scure/btc-signer';\n\nimport { DerivationPathDepth, deriveKeychainFromXpub } from '@leather.io/crypto';\nimport { BitcoinNetworkModes } from '@leather.io/models';\n\nimport { getBtcSignerLibNetworkConfigByMode } from './bitcoin.network';\nimport {\n BitcoinAccount,\n deriveAddressIndexZeroFromAccount,\n ecdsaPublicKeyToSchnorr,\n getBitcoinCoinTypeIndexByNetwork,\n} from './bitcoin.utils';\n\nexport function makeTaprootAccountDerivationPath(\n network: BitcoinNetworkModes,\n accountIndex: number\n) {\n return `m/86'/${getBitcoinCoinTypeIndexByNetwork(network)}'/${accountIndex}'`;\n}\n/** @deprecated Use makeTaprootAccountDerivationPath */\nexport const getTaprootAccountDerivationPath = makeTaprootAccountDerivationPath;\n\nexport function makeTaprootAddressIndexDerivationPath(\n network: BitcoinNetworkModes,\n accountIndex: number,\n addressIndex: number\n) {\n return makeTaprootAccountDerivationPath(network, accountIndex) + `/0/${addressIndex}`;\n}\n/** @deprecated Use makeTaprootAddressIndexDerivationPath */\nexport const getTaprootAddressIndexDerivationPath = makeTaprootAddressIndexDerivationPath;\n\nexport function deriveTaprootAccount(keychain: HDKey, network: BitcoinNetworkModes) {\n if (keychain.depth !== DerivationPathDepth.Root)\n throw new Error('Keychain passed is not an account');\n\n return (accountIndex: number): BitcoinAccount => ({\n type: 'p2tr',\n network,\n accountIndex,\n derivationPath: makeTaprootAccountDerivationPath(network, accountIndex),\n keychain: keychain.derive(makeTaprootAccountDerivationPath(network, accountIndex)),\n });\n}\n\nexport function getTaprootPayment(publicKey: Uint8Array, network: BitcoinNetworkModes) {\n return btc.p2tr(\n ecdsaPublicKeyToSchnorr(publicKey),\n undefined,\n getBtcSignerLibNetworkConfigByMode(network)\n );\n}\n\nexport function getTaprootPaymentFromAddressIndex(keychain: HDKey, network: BitcoinNetworkModes) {\n if (keychain.depth !== DerivationPathDepth.AddressIndex)\n throw new Error('Keychain passed is not an address index');\n\n if (!keychain.publicKey) throw new Error('Keychain has no public key');\n\n return getTaprootPayment(keychain.publicKey, network);\n}\n\ninterface DeriveTaprootReceiveAddressIndexArgs {\n xpub: string;\n network: BitcoinNetworkModes;\n}\nexport function deriveTaprootReceiveAddressIndex({\n xpub,\n network,\n}: DeriveTaprootReceiveAddressIndexArgs) {\n const keychain = deriveKeychainFromXpub(xpub);\n\n const zeroAddressIndex = deriveAddressIndexZeroFromAccount(keychain);\n\n return getTaprootPaymentFromAddressIndex(zeroAddressIndex, network);\n}\n","import { base64 } from '@scure/base';\nimport * as btc from '@scure/btc-signer';\nimport * as bitcoin from 'bitcoinjs-lib';\n\nimport { BitcoinNetworkModes } from '@leather.io/models';\n\nimport { getBitcoinJsLibNetworkConfigByMode } from '../bitcoin.network';\nimport {\n bip322TransactionToSignValues,\n ecPairFromPrivateKey,\n encodeMessageWitnessData,\n hashBip322Message,\n tweakSigner,\n} from './bip322-utils';\n\nexport function createNativeSegwitBitcoinJsSigner(privateKey: Buffer) {\n return ecPairFromPrivateKey(privateKey);\n}\n\nexport function createTaprootBitcoinJsSigner(privateKey: Buffer) {\n return tweakSigner(ecPairFromPrivateKey(privateKey));\n}\n\nexport function createToSpendTx(address: string, message: string, network: BitcoinNetworkModes) {\n const { prevoutHash, prevoutIndex, sequence } = bip322TransactionToSignValues;\n\n const script = bitcoin.address.toOutputScript(\n address,\n getBitcoinJsLibNetworkConfigByMode(network)\n );\n\n const hash = hashBip322Message(message);\n const commands = [0, Buffer.from(hash)];\n const scriptSig = bitcoin.script.compile(commands);\n\n const virtualToSpend = new bitcoin.Transaction();\n virtualToSpend.version = 0;\n virtualToSpend.addInput(Buffer.from(prevoutHash), prevoutIndex, sequence, scriptSig);\n virtualToSpend.addOutput(script, 0);\n return { virtualToSpend, script };\n}\n\nfunction createToSignTx(toSpendTxHex: Buffer, script: Buffer, network: BitcoinNetworkModes) {\n const virtualToSign = new bitcoin.Psbt({ network: getBitcoinJsLibNetworkConfigByMode(network) });\n virtualToSign.setVersion(0);\n const prevTxHash = toSpendTxHex;\n const prevOutIndex = 0;\n const toSignScriptSig = bitcoin.script.compile([bitcoin.script.OPS.OP_RETURN]);\n\n virtualToSign.addInput({\n hash: prevTxHash,\n index: prevOutIndex,\n sequence: 0,\n witnessUtxo: { script, value: 0 },\n });\n\n virtualToSign.addOutput({ script: toSignScriptSig, value: 0 });\n return virtualToSign;\n}\n\ninterface SignBip322MessageSimple {\n address: string;\n message: string;\n network: BitcoinNetworkModes;\n signPsbt(psbt: bitcoin.Psbt): Promise<btc.Transaction>;\n}\nexport async function signBip322MessageSimple(args: SignBip322MessageSimple) {\n const { address, message, network, signPsbt } = args;\n\n const { virtualToSpend, script } = createToSpendTx(address, message, network);\n\n const virtualToSign = createToSignTx(virtualToSpend.getHash(), script, network);\n\n const signedTx = await signPsbt(virtualToSign);\n\n const asBitcoinJsTransaction = bitcoin.Psbt.fromBuffer(Buffer.from(signedTx.toPSBT()));\n\n asBitcoinJsTransaction.finalizeInput(0);\n\n // sign the tx\n // section 5.1\n // github.com/LegReq/bip0322-signatures/blob/master/BIP0322_signing.ipynb\n const toSignTx = asBitcoinJsTransaction.extractTransaction();\n\n const result = encodeMessageWitnessData(toSignTx.ins[0].witness);\n\n return {\n virtualToSpend,\n virtualToSign: toSignTx,\n unencodedSig: result,\n signature: base64.encode(result),\n };\n}\n","import { HDKey } from '@scure/bip32';\nimport * as btc from '@scure/btc-signer';\n\nimport { DerivationPathDepth, deriveKeychainFromXpub } from '@leather.io/crypto';\nimport { BitcoinNetworkModes } from '@leather.io/models';\n\nimport { getBtcSignerLibNetworkConfigByMode } from './bitcoin.network';\nimport {\n BitcoinAccount,\n deriveAddressIndexZeroFromAccount,\n getBitcoinCoinTypeIndexByNetwork,\n} from './bitcoin.utils';\n\nexport function makeNativeSegwitAccountDerivationPath(\n network: BitcoinNetworkModes,\n accountIndex: number\n) {\n return `m/84'/${getBitcoinCoinTypeIndexByNetwork(network)}'/${accountIndex}'`;\n}\n/** @deprecated Use makeNativeSegwitAccountDerivationPath */\nexport const getNativeSegwitAccountDerivationPath = makeNativeSegwitAccountDerivationPath;\n\nexport function makeNativeSegwitAddressIndexDerivationPath(\n network: BitcoinNetworkModes,\n accountIndex: number,\n addressIndex: number\n) {\n return makeNativeSegwitAccountDerivationPath(network, accountIndex) + `/0/${addressIndex}`;\n}\n/** @deprecated Use makeNativeSegwitAddressIndexDerivationPath */\nexport const getNativeSegwitAddressIndexDerivationPath = makeNativeSegwitAddressIndexDerivationPath;\n\nexport function deriveNativeSegwitAccountFromRootKeychain(\n keychain: HDKey,\n network: BitcoinNetworkModes\n) {\n if (keychain.depth !== DerivationPathDepth.Root) throw new Error('Keychain passed is not a root');\n return (accountIndex: number): BitcoinAccount => ({\n type: 'p2wpkh',\n network,\n accountIndex,\n derivationPath: makeNativeSegwitAccountDerivationPath(network, accountIndex),\n keychain: keychain.derive(makeNativeSegwitAccountDerivationPath(network, accountIndex)),\n });\n}\n\nexport function getNativeSegWitPaymentFromAddressIndex(\n keychain: HDKey,\n network: BitcoinNetworkModes\n) {\n if (keychain.depth !== DerivationPathDepth.AddressIndex)\n throw new Error('Keychain passed is not an address index');\n\n if (!keychain.publicKey) throw new Error('Keychain does not have a public key');\n\n return btc.p2wpkh(keychain.publicKey, getBtcSignerLibNetworkConfigByMode(network));\n}\n\ninterface DeriveNativeSegWitReceiveAddressIndexArgs {\n xpub: string;\n network: BitcoinNetworkModes;\n}\nexport function deriveNativeSegWitReceiveAddressIndex({\n xpub,\n network,\n}: DeriveNativeSegWitReceiveAddressIndexArgs) {\n if (!xpub) return;\n const keychain = deriveKeychainFromXpub(xpub);\n if (!keychain) return;\n const zeroAddressIndex = deriveAddressIndexZeroFromAccount(keychain);\n return getNativeSegWitPaymentFromAddressIndex(zeroAddressIndex, network);\n}\n","import { ripemd160 } from '@noble/hashes/ripemd160';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { base58check } from '@scure/base';\n\nimport { deriveBip39SeedFromMnemonic, deriveRootBip32Keychain } from '@leather.io/crypto';\nimport { NetworkModes } from '@leather.io/models';\n\n/**\n * @deprecated\n * Use `deriveBip39MnemonicFromSeed` from `@leather.io/crypto`\n */\nexport const deriveBtcBip49SeedFromMnemonic = deriveBip39SeedFromMnemonic;\n\n/**\n * @deprecated\n * Use `deriveRootBip32Keychain` from `@leather.io/crypto`\n */\nexport const deriveRootBtcKeychain = deriveRootBip32Keychain;\n\nexport function decodeCompressedWifPrivateKey(key: string) {\n // https://en.bitcoinwiki.org/wiki/Wallet_import_format\n // Decode Compressed WIF format private key\n const compressedWifFormatPrivateKey = base58check(sha256).decode(key);\n // Drop leading network byte, trailing public key SEC format byte\n return compressedWifFormatPrivateKey.slice(1, compressedWifFormatPrivateKey.length - 1);\n}\n\n// https://en.bitcoin.it/wiki/List_of_address_prefixes\nconst payToScriptHashMainnetPrefix = 0x05;\nexport const payToScriptHashTestnetPrefix = 0xc4;\n\nconst payToScriptHashPrefixMap: Record<NetworkModes, number> = {\n mainnet: payToScriptHashMainnetPrefix,\n testnet: payToScriptHashTestnetPrefix,\n};\n\nfunction hash160(input: Uint8Array) {\n return ripemd160(sha256(input));\n}\n\nexport function makePayToScriptHashKeyHash(publicKey: Uint8Array) {\n return hash160(publicKey);\n}\n\nexport function makePayToScriptHashAddressBytes(keyHash: Uint8Array) {\n const redeemScript = Uint8Array.from([\n ...Uint8Array.of(0x00),\n ...Uint8Array.of(keyHash.length),\n ...keyHash,\n ]);\n return hash160(redeemScript);\n}\n\nexport function makePayToScriptHashAddress(addressBytes: Uint8Array, network: NetworkModes) {\n const networkByte = payToScriptHashPrefixMap[network];\n const addressWithPrefix = Uint8Array.from([networkByte, ...addressBytes]);\n return base58check(sha256).encode(addressWithPrefix);\n}\n\nexport function publicKeyToPayToScriptHashAddress(publicKey: Uint8Array, network: NetworkModes) {\n const hash = makePayToScriptHashKeyHash(publicKey);\n const addrBytes = makePayToScriptHashAddressBytes(hash);\n return makePayToScriptHashAddress(addrBytes, network);\n}\n"],"mappings":"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","names":["hexToBytes","btc","DerivationPathDepth","DerivationPathDepth","script","address","hexToBytes","bitcoin","address","script","btc","DerivationPathDepth","deriveKeychainFromXpub","DerivationPathDepth","deriveKeychainFromXpub","sha256"]}
|
|
1
|
+
{"version":3,"sources":["../src/bip322/bip322-utils.ts","../src/bitcoin.utils.ts","../src/bitcoin.network.ts","../src/p2tr-address-gen.ts","../src/bip322/sign-message-bip322-bitcoinjs.ts","../src/bitcoin-signer.ts","../src/p2wpkh-address-gen.ts","../src/p2wsh-p2sh-address-gen.ts"],"sourcesContent":["import ecc from '@bitcoinerlab/secp256k1';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { hexToBytes, utf8ToBytes } from '@stacks/common';\nimport * as bitcoin from 'bitcoinjs-lib';\nimport { ECPairFactory } from 'ecpair';\nimport { encode } from 'varuint-bitcoin';\n\nimport { PaymentTypes } from '@leather.io/rpc';\nimport { isString } from '@leather.io/utils';\n\nimport { toXOnly } from '../bitcoin.utils';\n\nconst bip322MessageTag = 'BIP0322-signed-message';\n\nconst ECPair = ECPairFactory(ecc);\nbitcoin.initEccLib(ecc);\n\nexport function ecPairFromPrivateKey(key: Uint8Array) {\n return ECPair.fromPrivateKey(Buffer.from(key));\n}\n\n// See tagged hashes section of BIP-340\n// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki#design\nconst messageTagHash = Uint8Array.from([\n ...sha256(utf8ToBytes(bip322MessageTag)),\n ...sha256(utf8ToBytes(bip322MessageTag)),\n]);\n\nexport function hashBip322Message(message: Uint8Array | string) {\n return sha256(\n Uint8Array.from([...messageTagHash, ...(isString(message) ? utf8ToBytes(message) : message)])\n );\n}\n\nexport const bip322TransactionToSignValues = {\n prevoutHash: hexToBytes('0000000000000000000000000000000000000000000000000000000000000000'),\n prevoutIndex: 0xffffffff,\n sequence: 0,\n};\n\nfunction encodeVarString(b: Buffer) {\n return Buffer.concat([encode(b.byteLength), b]);\n}\n\nconst supportedMessageSigningPaymentTypes: PaymentTypes[] = ['p2wpkh', 'p2tr'];\n\nexport function isSupportedMessageSigningPaymentType(paymentType: string) {\n return supportedMessageSigningPaymentTypes.includes(paymentType as PaymentTypes);\n}\n\n/**\n * Encode witness data for a BIP322 message\n * TODO: Refactor to remove `Buffer` use\n */\nexport function encodeMessageWitnessData(witnessArray: Buffer[]) {\n const len = encode(witnessArray.length);\n return Buffer.concat([len, ...witnessArray.map(witness => encodeVarString(witness))]);\n}\n\nfunction tapTweakHash(pubKey: Buffer, h: Buffer | undefined): Buffer {\n return bitcoin.crypto.taggedHash('TapTweak', Buffer.concat(h ? [pubKey, h] : [pubKey]));\n}\n\nexport function tweakSigner(signer: bitcoin.Signer, opts: any = {}): bitcoin.Signer {\n // @ts-expect-error privateKey exists on signer\n let privateKey: Uint8Array | undefined = signer.privateKey!;\n if (!privateKey) {\n throw new Error('Private key is required for tweaking signer!');\n }\n if (signer.publicKey[0] === 3) {\n privateKey = ecc.privateNegate(privateKey);\n }\n\n const tweakedPrivateKey = ecc.privateAdd(\n privateKey,\n tapTweakHash(toXOnly(signer.publicKey), opts.tweakHash)\n );\n if (!tweakedPrivateKey) {\n throw new Error('Invalid tweaked private key!');\n }\n\n return ECPair.fromPrivateKey(Buffer.from(tweakedPrivateKey), {\n network: opts.network,\n });\n}\n","import { hexToBytes } from '@noble/hashes/utils';\nimport { HDKey, Versions } from '@scure/bip32';\nimport { mnemonicToSeedSync } from '@scure/bip39';\nimport * as btc from '@scure/btc-signer';\nimport { TransactionInput, TransactionOutput } from '@scure/btc-signer/psbt';\n\nimport {\n DerivationPathDepth,\n extractAccountIndexFromPath,\n extractPurposeFromPath,\n} from '@leather.io/crypto';\nimport { BitcoinNetworkModes, NetworkModes } from '@leather.io/models';\nimport type { PaymentTypes } from '@leather.io/rpc';\nimport { defaultWalletKeyId, isDefined, whenNetwork } from '@leather.io/utils';\n\nimport { BtcSignerNetwork, getBtcSignerLibNetworkConfigByMode } from './bitcoin.network';\nimport { getTaprootPayment } from './p2tr-address-gen';\n\nexport interface BitcoinAccount {\n type: PaymentTypes;\n derivationPath: string;\n keychain: HDKey;\n accountIndex: number;\n network: BitcoinNetworkModes;\n}\nexport function initBitcoinAccount(derivationPath: string, policy: string): BitcoinAccount {\n const xpub = extractExtendedPublicKeyFromPolicy(policy);\n const network = inferNetworkFromPath(derivationPath);\n return {\n keychain: HDKey.fromExtendedKey(xpub, getHdKeyVersionsFromNetwork(network)),\n network,\n derivationPath,\n type: inferPaymentTypeFromPath(derivationPath),\n accountIndex: extractAccountIndexFromPath(derivationPath),\n };\n}\n\n/**\n * Represents a map of `BitcoinNetworkModes` to `NetworkModes`. While Bitcoin\n * has a number of networks, its often only necessary to consider the higher\n * level concept of mainnet and testnet\n */\nexport const bitcoinNetworkToCoreNetworkMap: Record<BitcoinNetworkModes, NetworkModes> = {\n mainnet: 'mainnet',\n testnet: 'testnet',\n regtest: 'testnet',\n signet: 'testnet',\n};\nexport function bitcoinNetworkModeToCoreNetworkMode(mode: BitcoinNetworkModes) {\n return bitcoinNetworkToCoreNetworkMap[mode];\n}\n\n/**\n * Map representing the \"Coin Type\" section of a derivation path.\n * Consider example below, Coin type is one, thus testnet\n * @example\n * `m/86'/1'/0'/0/0`\n */\nexport const coinTypeMap: Record<NetworkModes, 0 | 1> = {\n mainnet: 0,\n testnet: 1,\n};\n\nexport function getBitcoinCoinTypeIndexByNetwork(network: BitcoinNetworkModes) {\n return coinTypeMap[bitcoinNetworkModeToCoreNetworkMode(network)];\n}\n\nexport function deriveAddressIndexKeychainFromAccount(keychain: HDKey) {\n if (keychain.depth !== DerivationPathDepth.Account)\n throw new Error('Keychain passed is not an account');\n\n return (index: number) => keychain.deriveChild(0).deriveChild(index);\n}\n\nexport function deriveAddressIndexZeroFromAccount(keychain: HDKey) {\n return deriveAddressIndexKeychainFromAccount(keychain)(0);\n}\n\nexport const ecdsaPublicKeyLength = 33;\n\nexport function ecdsaPublicKeyToSchnorr(pubKey: Uint8Array) {\n if (pubKey.byteLength !== ecdsaPublicKeyLength) throw new Error('Invalid public key length');\n return pubKey.slice(1);\n}\n\n// Basically same as above, to remove\nexport const toXOnly = (pubKey: Buffer) => (pubKey.length === 32 ? pubKey : pubKey.subarray(1, 33));\n\nexport function decodeBitcoinTx(tx: string): ReturnType<typeof btc.RawTx.decode> {\n return btc.RawTx.decode(hexToBytes(tx));\n}\n\nexport function getAddressFromOutScript(script: Uint8Array, bitcoinNetwork: BtcSignerNetwork) {\n const outputScript = btc.OutScript.decode(script);\n\n switch (outputScript.type) {\n case 'pkh':\n case 'sh':\n case 'wpkh':\n case 'wsh':\n return btc.Address(bitcoinNetwork).encode({\n type: outputScript.type,\n hash: outputScript.hash,\n });\n case 'tr':\n return btc.Address(bitcoinNetwork).encode({\n type: outputScript.type,\n pubkey: outputScript.pubkey,\n });\n case 'ms':\n return btc.p2ms(outputScript.m, outputScript.pubkeys).address ?? '';\n case 'pk':\n return btc.p2pk(outputScript.pubkey, bitcoinNetwork).address ?? '';\n case 'unknown':\n return 'unknown';\n case 'tr_ms':\n case 'tr_ns':\n default:\n return '';\n }\n}\n\n/**\n * Payment type identifiers, as described by `@scure/btc-signer` library\n */\nexport type BtcSignerLibPaymentTypeIdentifers = 'wpkh' | 'wsh' | 'tr' | 'pkh' | 'sh';\n\nexport const paymentTypeMap: Record<BtcSignerLibPaymentTypeIdentifers, PaymentTypes> = {\n wpkh: 'p2wpkh',\n wsh: 'p2wpkh-p2sh',\n tr: 'p2tr',\n pkh: 'p2pkh',\n sh: 'p2sh',\n};\n\nexport function btcSignerLibPaymentTypeToPaymentTypeMap(\n payment: BtcSignerLibPaymentTypeIdentifers\n) {\n return paymentTypeMap[payment];\n}\n\nexport function isBtcSignerLibPaymentType(\n payment: string\n): payment is BtcSignerLibPaymentTypeIdentifers {\n return payment in paymentTypeMap;\n}\n\nexport function parseKnownPaymentType(payment: BtcSignerLibPaymentTypeIdentifers | PaymentTypes) {\n return isBtcSignerLibPaymentType(payment)\n ? btcSignerLibPaymentTypeToPaymentTypeMap(payment)\n : payment;\n}\n\nexport type PaymentTypeMap<T> = Record<PaymentTypes, T>;\nexport function whenPaymentType(mode: PaymentTypes | BtcSignerLibPaymentTypeIdentifers) {\n return <T extends unknown>(paymentMap: PaymentTypeMap<T>): T =>\n paymentMap[parseKnownPaymentType(mode)];\n}\n\nexport type SupportedPaymentType = 'p2wpkh' | 'p2tr';\nexport type SupportedPaymentTypeMap<T> = Record<SupportedPaymentType, T>;\nexport function whenSupportedPaymentType(mode: SupportedPaymentType) {\n return <T>(paymentMap: SupportedPaymentTypeMap<T>): T => paymentMap[mode];\n}\n\n/**\n * Infers the Bitcoin payment type from the derivation path.\n * Below we see path has 86 in it, per convention, this refers to taproot payments\n * @example\n * `m/86'/1'/0'/0/0`\n */\nexport function inferPaymentTypeFromPath(path: string): PaymentTypes {\n const purpose = extractPurposeFromPath(path);\n switch (purpose) {\n case 84:\n return 'p2wpkh';\n case 86:\n return 'p2tr';\n case 44:\n return 'p2pkh';\n default:\n throw new Error(`Unable to infer payment type from purpose=${purpose}`);\n }\n}\n\nexport function inferNetworkFromPath(path: string): NetworkModes {\n return path.split('/')[2].startsWith('0') ? 'mainnet' : 'testnet';\n}\n\nexport function extractExtendedPublicKeyFromPolicy(policy: string) {\n return policy.split(']')[1];\n}\n\nexport function createWalletIdDecoratedPath(policy: string, walletId: string) {\n return policy.split(']')[0].replace('[', '').replace('m', walletId);\n}\n\n// Primarily used to get the correct `Version` when passing Ledger Bitcoin\n// extended public keys to the HDKey constructor\nexport function getHdKeyVersionsFromNetwork(network: NetworkModes) {\n return whenNetwork(network)({\n mainnet: undefined,\n testnet: {\n private: 0x00000000,\n public: 0x043587cf,\n } as Versions,\n });\n}\n\nexport function getBitcoinInputAddress(input: TransactionInput, bitcoinNetwork: BtcSignerNetwork) {\n if (isDefined(input.witnessUtxo))\n return getAddressFromOutScript(input.witnessUtxo.script, bitcoinNetwork);\n if (isDefined(input.nonWitnessUtxo) && isDefined(input.index))\n return getAddressFromOutScript(\n input.nonWitnessUtxo.outputs[input.index]?.script,\n bitcoinNetwork\n );\n return '';\n}\n\nexport function getInputPaymentType(\n input: TransactionInput,\n network: BitcoinNetworkModes\n): PaymentTypes {\n const address = getBitcoinInputAddress(input, getBtcSignerLibNetworkConfigByMode(network));\n if (address === '') throw new Error('Input address cannot be empty');\n if (address.startsWith('bc1p') || address.startsWith('tb1p') || address.startsWith('bcrt1p'))\n return 'p2tr';\n if (address.startsWith('bc1q') || address.startsWith('tb1q') || address.startsWith('bcrt1q'))\n return 'p2wpkh';\n throw new Error('Unable to infer payment type from input address');\n}\n\n// Ledger wallets are keyed by their derivation path. To reuse the look up logic\n// between payment types, this factory fn accepts a fn that generates the path\nexport function lookUpLedgerKeysByPath(\n getDerivationPath: (network: BitcoinNetworkModes, accountIndex: number) => string\n) {\n return (\n ledgerKeyMap: Record<string, { policy: string } | undefined>,\n network: BitcoinNetworkModes\n ) =>\n (accountIndex: number) => {\n const path = getDerivationPath(network, accountIndex);\n // Single wallet mode, hardcoded default walletId\n const account = ledgerKeyMap[path.replace('m', defaultWalletKeyId)];\n if (!account) return;\n return initBitcoinAccount(path, account.policy);\n };\n}\n\nexport interface GetTaprootAddressArgs {\n index: number;\n keychain?: HDKey;\n network: BitcoinNetworkModes;\n}\nexport function getTaprootAddress({ index, keychain, network }: GetTaprootAddressArgs) {\n if (!keychain) throw new Error('Expected keychain to be provided');\n\n if (keychain.depth !== DerivationPathDepth.Account)\n throw new Error('Expects keychain to be on the account index');\n\n const addressIndex = deriveAddressIndexKeychainFromAccount(keychain)(index);\n\n if (!addressIndex.publicKey) throw new Error('Expected publicKey to be defined');\n\n const payment = getTaprootPayment(addressIndex.publicKey, network);\n\n if (!payment.address) throw new Error('Expected address to be defined');\n return payment.address;\n}\n\n/**\n * @deprecated\n * Use `deriveRootBip32Keychain` in `@leather.io/crypto` instead\n */\nexport function mnemonicToRootNode(secretKey: string) {\n const seed = mnemonicToSeedSync(secretKey);\n return HDKey.fromMasterSeed(seed);\n}\n\nexport function getPsbtTxInputs(psbtTx: btc.Transaction): TransactionInput[] {\n const inputsLength = psbtTx.inputsLength;\n const inputs: TransactionInput[] = [];\n for (let i = 0; i < inputsLength; i++) inputs.push(psbtTx.getInput(i));\n return inputs;\n}\n\nexport function getPsbtTxOutputs(psbtTx: btc.Transaction): TransactionOutput[] {\n const outputsLength = psbtTx.outputsLength;\n const outputs: TransactionOutput[] = [];\n for (let i = 0; i < outputsLength; i++) outputs.push(psbtTx.getOutput(i));\n return outputs;\n}\n","import * as bitcoinJs from 'bitcoinjs-lib';\n\nimport { BitcoinNetworkModes } from '@leather.io/models';\n\n// See this PR https://github.com/paulmillr/@scure/btc-signer/pull/15\n// Atttempting to add these directly to the library\nexport interface BtcSignerNetwork {\n bech32: string;\n pubKeyHash: number;\n scriptHash: number;\n wif: number;\n}\n\nconst bitcoinMainnet: BtcSignerNetwork = {\n bech32: 'bc',\n pubKeyHash: 0x00,\n scriptHash: 0x05,\n wif: 0x80,\n};\n\nconst bitcoinTestnet: BtcSignerNetwork = {\n bech32: 'tb',\n pubKeyHash: 0x6f,\n scriptHash: 0xc4,\n wif: 0xef,\n};\n\nconst bitcoinRegtest: BtcSignerNetwork = {\n bech32: 'bcrt',\n pubKeyHash: 0x6f,\n scriptHash: 0xc4,\n wif: 0xef,\n};\n\nconst btcSignerLibNetworks: Record<BitcoinNetworkModes, BtcSignerNetwork> = {\n mainnet: bitcoinMainnet,\n testnet: bitcoinTestnet,\n regtest: bitcoinRegtest,\n // Signet originally was going to have its own prefix but authors decided to\n // copy testnet\n signet: bitcoinTestnet,\n};\n\nexport function getBtcSignerLibNetworkConfigByMode(network: BitcoinNetworkModes) {\n return btcSignerLibNetworks[network];\n}\n\nconst bitcoinJsLibNetworks: Record<BitcoinNetworkModes, bitcoinJs.Network> = {\n mainnet: bitcoinJs.networks.bitcoin,\n testnet: bitcoinJs.networks.testnet,\n regtest: bitcoinJs.networks.regtest,\n signet: bitcoinJs.networks.testnet,\n};\n\nexport function getBitcoinJsLibNetworkConfigByMode(network: BitcoinNetworkModes) {\n return bitcoinJsLibNetworks[network];\n}\n","import { HDKey } from '@scure/bip32';\nimport * as btc from '@scure/btc-signer';\n\nimport { DerivationPathDepth } from '@leather.io/crypto';\nimport { BitcoinNetworkModes } from '@leather.io/models';\n\nimport { getBtcSignerLibNetworkConfigByMode } from './bitcoin.network';\nimport {\n BitcoinAccount,\n deriveAddressIndexZeroFromAccount,\n ecdsaPublicKeyToSchnorr,\n getBitcoinCoinTypeIndexByNetwork,\n} from './bitcoin.utils';\n\nexport function makeTaprootAccountDerivationPath(\n network: BitcoinNetworkModes,\n accountIndex: number\n) {\n return `m/86'/${getBitcoinCoinTypeIndexByNetwork(network)}'/${accountIndex}'`;\n}\n/** @deprecated Use makeTaprootAccountDerivationPath */\nexport const getTaprootAccountDerivationPath = makeTaprootAccountDerivationPath;\n\nexport function makeTaprootAddressIndexDerivationPath(\n network: BitcoinNetworkModes,\n accountIndex: number,\n addressIndex: number\n) {\n return makeTaprootAccountDerivationPath(network, accountIndex) + `/0/${addressIndex}`;\n}\n/** @deprecated Use makeTaprootAddressIndexDerivationPath */\nexport const getTaprootAddressIndexDerivationPath = makeTaprootAddressIndexDerivationPath;\n\nexport function deriveTaprootAccount(keychain: HDKey, network: BitcoinNetworkModes) {\n if (keychain.depth !== DerivationPathDepth.Root)\n throw new Error('Keychain passed is not an account');\n\n return (accountIndex: number): BitcoinAccount => ({\n type: 'p2tr',\n network,\n accountIndex,\n derivationPath: makeTaprootAccountDerivationPath(network, accountIndex),\n keychain: keychain.derive(makeTaprootAccountDerivationPath(network, accountIndex)),\n });\n}\n\nexport function getTaprootPayment(publicKey: Uint8Array, network: BitcoinNetworkModes) {\n return btc.p2tr(\n ecdsaPublicKeyToSchnorr(publicKey),\n undefined,\n getBtcSignerLibNetworkConfigByMode(network)\n );\n}\n\nexport function getTaprootPaymentFromAddressIndex(keychain: HDKey, network: BitcoinNetworkModes) {\n if (keychain.depth !== DerivationPathDepth.AddressIndex)\n throw new Error('Keychain passed is not an address index');\n\n if (!keychain.publicKey) throw new Error('Keychain has no public key');\n\n return getTaprootPayment(keychain.publicKey, network);\n}\n\ninterface DeriveTaprootReceiveAddressIndexArgs {\n keychain: HDKey;\n network: BitcoinNetworkModes;\n}\nexport function deriveTaprootReceiveAddressIndexZero({\n keychain,\n network,\n}: DeriveTaprootReceiveAddressIndexArgs) {\n const zeroAddressIndex = deriveAddressIndexZeroFromAccount(keychain);\n return {\n keychain: zeroAddressIndex,\n payment: getTaprootPaymentFromAddressIndex(zeroAddressIndex, network),\n };\n}\n","import { base64 } from '@scure/base';\nimport * as btc from '@scure/btc-signer';\nimport * as bitcoin from 'bitcoinjs-lib';\n\nimport { BitcoinNetworkModes } from '@leather.io/models';\n\nimport { getBitcoinJsLibNetworkConfigByMode } from '../bitcoin.network';\nimport {\n bip322TransactionToSignValues,\n ecPairFromPrivateKey,\n encodeMessageWitnessData,\n hashBip322Message,\n tweakSigner,\n} from './bip322-utils';\n\nexport function createNativeSegwitBitcoinJsSigner(privateKey: Buffer) {\n return ecPairFromPrivateKey(privateKey);\n}\n\nexport function createTaprootBitcoinJsSigner(privateKey: Buffer) {\n return tweakSigner(ecPairFromPrivateKey(privateKey));\n}\n\nexport function createToSpendTx(address: string, message: string, network: BitcoinNetworkModes) {\n const { prevoutHash, prevoutIndex, sequence } = bip322TransactionToSignValues;\n\n const script = bitcoin.address.toOutputScript(\n address,\n getBitcoinJsLibNetworkConfigByMode(network)\n );\n\n const hash = hashBip322Message(message);\n const commands = [0, Buffer.from(hash)];\n const scriptSig = bitcoin.script.compile(commands);\n\n const virtualToSpend = new bitcoin.Transaction();\n virtualToSpend.version = 0;\n virtualToSpend.addInput(Buffer.from(prevoutHash), prevoutIndex, sequence, scriptSig);\n virtualToSpend.addOutput(script, 0);\n return { virtualToSpend, script };\n}\n\nfunction createToSignTx(toSpendTxHex: Buffer, script: Buffer, network: BitcoinNetworkModes) {\n const virtualToSign = new bitcoin.Psbt({ network: getBitcoinJsLibNetworkConfigByMode(network) });\n virtualToSign.setVersion(0);\n const prevTxHash = toSpendTxHex;\n const prevOutIndex = 0;\n const toSignScriptSig = bitcoin.script.compile([bitcoin.script.OPS.OP_RETURN]);\n\n virtualToSign.addInput({\n hash: prevTxHash,\n index: prevOutIndex,\n sequence: 0,\n witnessUtxo: { script, value: 0 },\n });\n\n virtualToSign.addOutput({ script: toSignScriptSig, value: 0 });\n return virtualToSign;\n}\n\ninterface SignBip322MessageSimple {\n address: string;\n message: string;\n network: BitcoinNetworkModes;\n signPsbt(psbt: bitcoin.Psbt): Promise<btc.Transaction>;\n}\nexport async function signBip322MessageSimple(args: SignBip322MessageSimple) {\n const { address, message, network, signPsbt } = args;\n\n const { virtualToSpend, script } = createToSpendTx(address, message, network);\n\n const virtualToSign = createToSignTx(virtualToSpend.getHash(), script, network);\n\n const signedTx = await signPsbt(virtualToSign);\n\n const asBitcoinJsTransaction = bitcoin.Psbt.fromBuffer(Buffer.from(signedTx.toPSBT()));\n\n asBitcoinJsTransaction.finalizeInput(0);\n\n // sign the tx\n // section 5.1\n // github.com/LegReq/bip0322-signatures/blob/master/BIP0322_signing.ipynb\n const toSignTx = asBitcoinJsTransaction.extractTransaction();\n\n const result = encodeMessageWitnessData(toSignTx.ins[0].witness);\n\n return {\n virtualToSpend,\n virtualToSign: toSignTx,\n unencodedSig: result,\n signature: base64.encode(result),\n };\n}\n","import { HARDENED_OFFSET, HDKey } from '@scure/bip32';\nimport * as btc from '@scure/btc-signer';\nimport { P2Ret, P2TROut } from '@scure/btc-signer/payment';\nimport { SigHash } from '@scure/btc-signer/transaction';\n\nimport {\n DerivationPathDepth,\n appendAddressIndexToPath,\n decomposeDescriptor,\n deriveKeychainFromXpub,\n keyOriginToDerivationPath,\n} from '@leather.io/crypto';\nimport type { BitcoinNetworkModes } from '@leather.io/models';\nimport { PaymentTypes, SignatureHash } from '@leather.io/rpc';\nimport { hexToNumber, toHexString } from '@leather.io/utils';\n\nimport {\n SupportedPaymentType,\n ecdsaPublicKeyToSchnorr,\n extractExtendedPublicKeyFromPolicy,\n inferPaymentTypeFromPath,\n whenSupportedPaymentType,\n} from './bitcoin.utils';\nimport { getTaprootPaymentFromAddressIndex } from './p2tr-address-gen';\nimport { getNativeSegWitPaymentFromAddressIndex } from './p2wpkh-address-gen';\n\nexport type AllowedSighashTypes = SignatureHash | SigHash;\n\nexport interface BitcoinAccountKeychain {\n descriptor: string;\n masterKeyFingerprint: string;\n keyOrigin: string;\n keychain: HDKey;\n xpub: string;\n}\n\nexport type WithDerivePayer<T, P> = T & { derivePayer: (args: BitcoinPayerInfo) => P };\n\nexport interface BitcoinSigner<Payment> {\n network: BitcoinNetworkModes;\n payment: Payment;\n keychain: HDKey;\n derivationPath: string;\n address: string;\n publicKey: Uint8Array;\n sign(tx: btc.Transaction): void;\n signIndex(tx: btc.Transaction, index: number, allowedSighash?: AllowedSighashTypes[]): void;\n}\n\nexport interface BitcoinPayerBase {\n paymentType: PaymentTypes;\n network: BitcoinNetworkModes;\n address: string;\n keyOrigin: string;\n masterKeyFingerprint: string;\n publicKey: Uint8Array;\n}\n\nexport interface BitcoinNativeSegwitPayer extends BitcoinPayerBase {\n paymentType: 'p2wpkh';\n payment: P2Ret;\n}\n\nexport interface BitcoinTaprootPayer extends BitcoinPayerBase {\n paymentType: 'p2tr';\n payment: P2TROut;\n}\n\nexport type BitcoinPayer = BitcoinNativeSegwitPayer | BitcoinTaprootPayer;\n\nexport function initializeBitcoinAccountKeychainFromDescriptor(\n descriptor: string\n): BitcoinAccountKeychain {\n const { fingerprint, keyOrigin } = decomposeDescriptor(descriptor);\n return {\n descriptor,\n xpub: extractExtendedPublicKeyFromPolicy(descriptor),\n keyOrigin,\n masterKeyFingerprint: fingerprint,\n keychain: deriveKeychainFromXpub(extractExtendedPublicKeyFromPolicy(descriptor)),\n };\n}\n\nexport interface BitcoinPayerInfo {\n receive?: number;\n addressIndex: number;\n}\nexport function deriveBitcoinPayerFromAccount(descriptor: string, network: BitcoinNetworkModes) {\n const { fingerprint, keyOrigin } = decomposeDescriptor(descriptor);\n const accountKeychain = deriveKeychainFromXpub(extractExtendedPublicKeyFromPolicy(descriptor));\n const paymentType = inferPaymentTypeFromPath(keyOrigin) as SupportedPaymentType;\n\n if (accountKeychain.depth !== DerivationPathDepth.Account)\n throw new Error('Keychain passed is not an account');\n\n return ({ receive = 0, addressIndex }: BitcoinPayerInfo) => {\n const childKeychain = accountKeychain.deriveChild(receive).deriveChild(addressIndex);\n\n const derivePayerFromAccount = whenSupportedPaymentType(paymentType)({\n p2tr: getTaprootPaymentFromAddressIndex,\n p2wpkh: getNativeSegWitPaymentFromAddressIndex,\n });\n\n const payment = derivePayerFromAccount(childKeychain, network);\n\n return {\n keyOrigin: appendAddressIndexToPath(keyOrigin, 0),\n masterKeyFingerprint: fingerprint,\n paymentType,\n network,\n payment,\n get address() {\n if (!payment.address) throw new Error('Payment address could not be derived');\n return payment.address;\n },\n get publicKey() {\n if (!childKeychain.publicKey) throw new Error('Public key could not be derived');\n return childKeychain.publicKey;\n },\n };\n };\n}\n\ninterface BtcSignerDerivationPath {\n fingerprint: number;\n path: number[];\n}\nexport type BtcSignerDefaultBip32Derivation = [Uint8Array, BtcSignerDerivationPath];\nexport type BtcSignerTapBip32Derivation = [\n Uint8Array,\n { hashes: Uint8Array[]; der: BtcSignerDerivationPath },\n];\n\ntype BtcSignerBip32Derivation = BtcSignerDefaultBip32Derivation | BtcSignerTapBip32Derivation;\n\ntype PayerToBip32DerivationArgs = Pick<\n BitcoinPayer,\n 'masterKeyFingerprint' | 'keyOrigin' | 'publicKey'\n>;\n\n/**\n * @example\n * ```ts\n * tx.addInput({\n * ...input,\n * bip32Derivation: [payerToBip32Derivation(payer)],\n * })\n * ```\n */\nexport function payerToBip32Derivation(\n args: PayerToBip32DerivationArgs\n): BtcSignerDefaultBip32Derivation {\n return [\n args.publicKey,\n {\n fingerprint: hexToNumber(args.masterKeyFingerprint),\n path: btc.bip32Path(keyOriginToDerivationPath(args.keyOrigin)),\n },\n ];\n}\n\n/**\n * @example\n * ```ts\n * tx.addInput({\n * ...input,\n * tapBip32Derivation: [payerToTapBip32Derivation(payer)],\n * })\n * ```\n */\nexport function payerToTapBip32Derivation(\n args: PayerToBip32DerivationArgs\n): BtcSignerTapBip32Derivation {\n return [\n // TODO: @kyranjamie to default to schnoor when TR so conversion isn't\n // necessary here?\n ecdsaPublicKeyToSchnorr(args.publicKey),\n {\n hashes: [],\n der: {\n fingerprint: hexToNumber(args.masterKeyFingerprint),\n path: btc.bip32Path(keyOriginToDerivationPath(args.keyOrigin)),\n },\n },\n ];\n}\n\n/**\n * @description\n * Turns key format from @scure/btc-signer lib back into key origin string\n * @example\n * ```ts\n * const [inputOne] = getPsbtTxInputs(tx);\n * const keyOrigin = serializeKeyOrigin(inputOne.bip32Derivation[0][1]);\n * ```\n */\nexport function serializeKeyOrigin({ fingerprint, path }: BtcSignerDerivationPath) {\n const values = path.map(num => (num >= HARDENED_OFFSET ? num - HARDENED_OFFSET + \"'\" : num));\n return `${toHexString(fingerprint)}/${values.join('/')}`;\n}\n\n/**\n * @description\n * Of a given set of a `tx.input`s bip32 derivation paths from\n * `@scure/btc-signer`, serialize the paths back to the string format used\n * internally\n */\nexport function extractRequiredKeyOrigins(derivation: BtcSignerBip32Derivation[]) {\n return derivation.map(([_pubkey, path]) =>\n serializeKeyOrigin('hashes' in path ? path.der : path)\n );\n}\n","import { HDKey } from '@scure/bip32';\nimport * as btc from '@scure/btc-signer';\n\nimport { DerivationPathDepth } from '@leather.io/crypto';\nimport { BitcoinNetworkModes } from '@leather.io/models';\n\nimport { getBtcSignerLibNetworkConfigByMode } from './bitcoin.network';\nimport {\n BitcoinAccount,\n deriveAddressIndexZeroFromAccount,\n getBitcoinCoinTypeIndexByNetwork,\n} from './bitcoin.utils';\n\nexport function makeNativeSegwitAccountDerivationPath(\n network: BitcoinNetworkModes,\n accountIndex: number\n) {\n return `m/84'/${getBitcoinCoinTypeIndexByNetwork(network)}'/${accountIndex}'`;\n}\n/** @deprecated Use makeNativeSegwitAccountDerivationPath */\nexport const getNativeSegwitAccountDerivationPath = makeNativeSegwitAccountDerivationPath;\n\nexport function makeNativeSegwitAddressIndexDerivationPath(\n network: BitcoinNetworkModes,\n accountIndex: number,\n addressIndex: number\n) {\n return makeNativeSegwitAccountDerivationPath(network, accountIndex) + `/0/${addressIndex}`;\n}\n/** @deprecated Use makeNativeSegwitAddressIndexDerivationPath */\nexport const getNativeSegwitAddressIndexDerivationPath = makeNativeSegwitAddressIndexDerivationPath;\n\nexport function deriveNativeSegwitAccountFromRootKeychain(\n keychain: HDKey,\n network: BitcoinNetworkModes\n) {\n if (keychain.depth !== DerivationPathDepth.Root) throw new Error('Keychain passed is not a root');\n return (accountIndex: number): BitcoinAccount => ({\n type: 'p2wpkh',\n network,\n accountIndex,\n derivationPath: makeNativeSegwitAccountDerivationPath(network, accountIndex),\n keychain: keychain.derive(makeNativeSegwitAccountDerivationPath(network, accountIndex)),\n });\n}\n\nexport function getNativeSegWitPaymentFromAddressIndex(\n keychain: HDKey,\n network: BitcoinNetworkModes\n) {\n if (keychain.depth !== DerivationPathDepth.AddressIndex)\n throw new Error('Keychain passed is not an address index');\n\n if (!keychain.publicKey) throw new Error('Keychain does not have a public key');\n\n return btc.p2wpkh(keychain.publicKey, getBtcSignerLibNetworkConfigByMode(network));\n}\n\ninterface DeriveNativeSegwitReceiveAddressIndexArgs {\n keychain: HDKey;\n network: BitcoinNetworkModes;\n}\nexport function deriveNativeSegwitReceiveAddressIndexZero({\n keychain,\n network,\n}: DeriveNativeSegwitReceiveAddressIndexArgs) {\n const zeroAddressIndex = deriveAddressIndexZeroFromAccount(keychain);\n return {\n keychain: zeroAddressIndex,\n payment: getNativeSegWitPaymentFromAddressIndex(zeroAddressIndex, network),\n };\n}\n","import { ripemd160 } from '@noble/hashes/ripemd160';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { base58check } from '@scure/base';\n\nimport { deriveBip39SeedFromMnemonic, deriveRootBip32Keychain } from '@leather.io/crypto';\nimport { NetworkModes } from '@leather.io/models';\n\n/**\n * @deprecated\n * Use `deriveBip39MnemonicFromSeed` from `@leather.io/crypto`\n */\nexport const deriveBtcBip49SeedFromMnemonic = deriveBip39SeedFromMnemonic;\n\n/**\n * @deprecated\n * Use `deriveRootBip32Keychain` from `@leather.io/crypto`\n */\nexport const deriveRootBtcKeychain = deriveRootBip32Keychain;\n\nexport function decodeCompressedWifPrivateKey(key: string) {\n // https://en.bitcoinwiki.org/wiki/Wallet_import_format\n // Decode Compressed WIF format private key\n const compressedWifFormatPrivateKey = base58check(sha256).decode(key);\n // Drop leading network byte, trailing public key SEC format byte\n return compressedWifFormatPrivateKey.slice(1, compressedWifFormatPrivateKey.length - 1);\n}\n\n// https://en.bitcoin.it/wiki/List_of_address_prefixes\nconst payToScriptHashMainnetPrefix = 0x05;\nexport const payToScriptHashTestnetPrefix = 0xc4;\n\nconst payToScriptHashPrefixMap: Record<NetworkModes, number> = {\n mainnet: payToScriptHashMainnetPrefix,\n testnet: payToScriptHashTestnetPrefix,\n};\n\nfunction hash160(input: Uint8Array) {\n return ripemd160(sha256(input));\n}\n\nexport function makePayToScriptHashKeyHash(publicKey: Uint8Array) {\n return hash160(publicKey);\n}\n\nexport function makePayToScriptHashAddressBytes(keyHash: Uint8Array) {\n const redeemScript = Uint8Array.from([\n ...Uint8Array.of(0x00),\n ...Uint8Array.of(keyHash.length),\n ...keyHash,\n ]);\n return hash160(redeemScript);\n}\n\nexport function makePayToScriptHashAddress(addressBytes: Uint8Array, network: NetworkModes) {\n const networkByte = payToScriptHashPrefixMap[network];\n const addressWithPrefix = Uint8Array.from([networkByte, ...addressBytes]);\n return base58check(sha256).encode(addressWithPrefix);\n}\n\nexport function publicKeyToPayToScriptHashAddress(publicKey: Uint8Array, network: NetworkModes) {\n const hash = makePayToScriptHashKeyHash(publicKey);\n const addrBytes = makePayToScriptHashAddressBytes(hash);\n return makePayToScriptHashAddress(addrBytes, network);\n}\n"],"mappings":"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","names":["hexToBytes","btc","DerivationPathDepth","DerivationPathDepth","script","address","hexToBytes","bitcoin","address","script","btc","DerivationPathDepth","btc","DerivationPathDepth","DerivationPathDepth","DerivationPathDepth","sha256"]}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@leather.io/bitcoin",
|
|
3
3
|
"author": "Leather.io contact@leather.io",
|
|
4
4
|
"description": "Shared bitcoin utilities",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.13.1",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/leather.io/mono/tree/dev/packages/bitcoin",
|
|
8
8
|
"repository": {
|
|
@@ -17,25 +17,25 @@
|
|
|
17
17
|
"bugs": "https://github.com/leather-io/mono/issues",
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@bitcoinerlab/secp256k1": "1.0.2",
|
|
20
|
-
"@noble/hashes": "1.
|
|
20
|
+
"@noble/hashes": "1.5.0",
|
|
21
21
|
"@noble/secp256k1": "2.1.0",
|
|
22
|
-
"@scure/base": "1.1.
|
|
23
|
-
"@scure/bip32": "1.
|
|
24
|
-
"@scure/bip39": "1.
|
|
25
|
-
"@scure/btc-signer": "1.
|
|
22
|
+
"@scure/base": "1.1.9",
|
|
23
|
+
"@scure/bip32": "1.5.0",
|
|
24
|
+
"@scure/bip39": "1.4.0",
|
|
25
|
+
"@scure/btc-signer": "1.4.0",
|
|
26
26
|
"@stacks/common": "6.13.0",
|
|
27
27
|
"@stacks/transactions": "6.15.0",
|
|
28
28
|
"bip32": "4.0.0",
|
|
29
29
|
"bitcoinjs-lib": "6.1.5",
|
|
30
30
|
"ecpair": "2.1.0",
|
|
31
|
+
"just-memoize": "2.2.0",
|
|
31
32
|
"varuint-bitcoin": "1.1.2",
|
|
32
|
-
"@leather.io/constants": "0.
|
|
33
|
-
"@leather.io/
|
|
34
|
-
"@leather.io/
|
|
35
|
-
"@leather.io/
|
|
33
|
+
"@leather.io/constants": "0.12.0",
|
|
34
|
+
"@leather.io/crypto": "1.6.1",
|
|
35
|
+
"@leather.io/utils": "0.16.1",
|
|
36
|
+
"@leather.io/models": "0.16.0"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
|
-
"@vitest/coverage-istanbul": "0.34.6",
|
|
39
39
|
"eslint": "8.53.0",
|
|
40
40
|
"prettier": "3.3.3",
|
|
41
41
|
"tslib": "2.6.2",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"typescript": "5.5.4",
|
|
44
44
|
"vitest": "2.0.5",
|
|
45
45
|
"@leather.io/eslint-config": "0.7.0",
|
|
46
|
-
"@leather.io/rpc": "2.1.7",
|
|
47
46
|
"@leather.io/prettier-config": "0.6.0",
|
|
47
|
+
"@leather.io/rpc": "2.1.9",
|
|
48
48
|
"@leather.io/tsconfig-config": "0.6.0"
|
|
49
49
|
},
|
|
50
50
|
"keywords": [
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { serializeKeyOrigin } from './bitcoin-signer';
|
|
2
|
+
|
|
3
|
+
describe(serializeKeyOrigin.name, () => {
|
|
4
|
+
test('that is turns @scure/btc-signer format derivation path into key origin', () => {
|
|
5
|
+
const test = {
|
|
6
|
+
fingerprint: 3621349508,
|
|
7
|
+
path: [2147483732, 2147483648, 2147483648, 0, 0],
|
|
8
|
+
};
|
|
9
|
+
expect(serializeKeyOrigin(test)).toEqual("d7d96884/84'/0'/0'/0/0");
|
|
10
|
+
});
|
|
11
|
+
});
|
package/src/bitcoin-signer.ts
CHANGED
|
@@ -1,13 +1,42 @@
|
|
|
1
|
-
import { HDKey } from '@scure/bip32';
|
|
1
|
+
import { HARDENED_OFFSET, HDKey } from '@scure/bip32';
|
|
2
2
|
import * as btc from '@scure/btc-signer';
|
|
3
|
+
import { P2Ret, P2TROut } from '@scure/btc-signer/payment';
|
|
3
4
|
import { SigHash } from '@scure/btc-signer/transaction';
|
|
4
5
|
|
|
6
|
+
import {
|
|
7
|
+
DerivationPathDepth,
|
|
8
|
+
appendAddressIndexToPath,
|
|
9
|
+
decomposeDescriptor,
|
|
10
|
+
deriveKeychainFromXpub,
|
|
11
|
+
keyOriginToDerivationPath,
|
|
12
|
+
} from '@leather.io/crypto';
|
|
5
13
|
import type { BitcoinNetworkModes } from '@leather.io/models';
|
|
6
|
-
import { SignatureHash } from '@leather.io/rpc';
|
|
14
|
+
import { PaymentTypes, SignatureHash } from '@leather.io/rpc';
|
|
15
|
+
import { hexToNumber, toHexString } from '@leather.io/utils';
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
SupportedPaymentType,
|
|
19
|
+
ecdsaPublicKeyToSchnorr,
|
|
20
|
+
extractExtendedPublicKeyFromPolicy,
|
|
21
|
+
inferPaymentTypeFromPath,
|
|
22
|
+
whenSupportedPaymentType,
|
|
23
|
+
} from './bitcoin.utils';
|
|
24
|
+
import { getTaprootPaymentFromAddressIndex } from './p2tr-address-gen';
|
|
25
|
+
import { getNativeSegWitPaymentFromAddressIndex } from './p2wpkh-address-gen';
|
|
7
26
|
|
|
8
27
|
export type AllowedSighashTypes = SignatureHash | SigHash;
|
|
9
28
|
|
|
10
|
-
export interface
|
|
29
|
+
export interface BitcoinAccountKeychain {
|
|
30
|
+
descriptor: string;
|
|
31
|
+
masterKeyFingerprint: string;
|
|
32
|
+
keyOrigin: string;
|
|
33
|
+
keychain: HDKey;
|
|
34
|
+
xpub: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type WithDerivePayer<T, P> = T & { derivePayer: (args: BitcoinPayerInfo) => P };
|
|
38
|
+
|
|
39
|
+
export interface BitcoinSigner<Payment> {
|
|
11
40
|
network: BitcoinNetworkModes;
|
|
12
41
|
payment: Payment;
|
|
13
42
|
keychain: HDKey;
|
|
@@ -17,3 +46,167 @@ export interface Signer<Payment> {
|
|
|
17
46
|
sign(tx: btc.Transaction): void;
|
|
18
47
|
signIndex(tx: btc.Transaction, index: number, allowedSighash?: AllowedSighashTypes[]): void;
|
|
19
48
|
}
|
|
49
|
+
|
|
50
|
+
export interface BitcoinPayerBase {
|
|
51
|
+
paymentType: PaymentTypes;
|
|
52
|
+
network: BitcoinNetworkModes;
|
|
53
|
+
address: string;
|
|
54
|
+
keyOrigin: string;
|
|
55
|
+
masterKeyFingerprint: string;
|
|
56
|
+
publicKey: Uint8Array;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface BitcoinNativeSegwitPayer extends BitcoinPayerBase {
|
|
60
|
+
paymentType: 'p2wpkh';
|
|
61
|
+
payment: P2Ret;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface BitcoinTaprootPayer extends BitcoinPayerBase {
|
|
65
|
+
paymentType: 'p2tr';
|
|
66
|
+
payment: P2TROut;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type BitcoinPayer = BitcoinNativeSegwitPayer | BitcoinTaprootPayer;
|
|
70
|
+
|
|
71
|
+
export function initializeBitcoinAccountKeychainFromDescriptor(
|
|
72
|
+
descriptor: string
|
|
73
|
+
): BitcoinAccountKeychain {
|
|
74
|
+
const { fingerprint, keyOrigin } = decomposeDescriptor(descriptor);
|
|
75
|
+
return {
|
|
76
|
+
descriptor,
|
|
77
|
+
xpub: extractExtendedPublicKeyFromPolicy(descriptor),
|
|
78
|
+
keyOrigin,
|
|
79
|
+
masterKeyFingerprint: fingerprint,
|
|
80
|
+
keychain: deriveKeychainFromXpub(extractExtendedPublicKeyFromPolicy(descriptor)),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface BitcoinPayerInfo {
|
|
85
|
+
receive?: number;
|
|
86
|
+
addressIndex: number;
|
|
87
|
+
}
|
|
88
|
+
export function deriveBitcoinPayerFromAccount(descriptor: string, network: BitcoinNetworkModes) {
|
|
89
|
+
const { fingerprint, keyOrigin } = decomposeDescriptor(descriptor);
|
|
90
|
+
const accountKeychain = deriveKeychainFromXpub(extractExtendedPublicKeyFromPolicy(descriptor));
|
|
91
|
+
const paymentType = inferPaymentTypeFromPath(keyOrigin) as SupportedPaymentType;
|
|
92
|
+
|
|
93
|
+
if (accountKeychain.depth !== DerivationPathDepth.Account)
|
|
94
|
+
throw new Error('Keychain passed is not an account');
|
|
95
|
+
|
|
96
|
+
return ({ receive = 0, addressIndex }: BitcoinPayerInfo) => {
|
|
97
|
+
const childKeychain = accountKeychain.deriveChild(receive).deriveChild(addressIndex);
|
|
98
|
+
|
|
99
|
+
const derivePayerFromAccount = whenSupportedPaymentType(paymentType)({
|
|
100
|
+
p2tr: getTaprootPaymentFromAddressIndex,
|
|
101
|
+
p2wpkh: getNativeSegWitPaymentFromAddressIndex,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const payment = derivePayerFromAccount(childKeychain, network);
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
keyOrigin: appendAddressIndexToPath(keyOrigin, 0),
|
|
108
|
+
masterKeyFingerprint: fingerprint,
|
|
109
|
+
paymentType,
|
|
110
|
+
network,
|
|
111
|
+
payment,
|
|
112
|
+
get address() {
|
|
113
|
+
if (!payment.address) throw new Error('Payment address could not be derived');
|
|
114
|
+
return payment.address;
|
|
115
|
+
},
|
|
116
|
+
get publicKey() {
|
|
117
|
+
if (!childKeychain.publicKey) throw new Error('Public key could not be derived');
|
|
118
|
+
return childKeychain.publicKey;
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface BtcSignerDerivationPath {
|
|
125
|
+
fingerprint: number;
|
|
126
|
+
path: number[];
|
|
127
|
+
}
|
|
128
|
+
export type BtcSignerDefaultBip32Derivation = [Uint8Array, BtcSignerDerivationPath];
|
|
129
|
+
export type BtcSignerTapBip32Derivation = [
|
|
130
|
+
Uint8Array,
|
|
131
|
+
{ hashes: Uint8Array[]; der: BtcSignerDerivationPath },
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
type BtcSignerBip32Derivation = BtcSignerDefaultBip32Derivation | BtcSignerTapBip32Derivation;
|
|
135
|
+
|
|
136
|
+
type PayerToBip32DerivationArgs = Pick<
|
|
137
|
+
BitcoinPayer,
|
|
138
|
+
'masterKeyFingerprint' | 'keyOrigin' | 'publicKey'
|
|
139
|
+
>;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* tx.addInput({
|
|
145
|
+
* ...input,
|
|
146
|
+
* bip32Derivation: [payerToBip32Derivation(payer)],
|
|
147
|
+
* })
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export function payerToBip32Derivation(
|
|
151
|
+
args: PayerToBip32DerivationArgs
|
|
152
|
+
): BtcSignerDefaultBip32Derivation {
|
|
153
|
+
return [
|
|
154
|
+
args.publicKey,
|
|
155
|
+
{
|
|
156
|
+
fingerprint: hexToNumber(args.masterKeyFingerprint),
|
|
157
|
+
path: btc.bip32Path(keyOriginToDerivationPath(args.keyOrigin)),
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @example
|
|
164
|
+
* ```ts
|
|
165
|
+
* tx.addInput({
|
|
166
|
+
* ...input,
|
|
167
|
+
* tapBip32Derivation: [payerToTapBip32Derivation(payer)],
|
|
168
|
+
* })
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
export function payerToTapBip32Derivation(
|
|
172
|
+
args: PayerToBip32DerivationArgs
|
|
173
|
+
): BtcSignerTapBip32Derivation {
|
|
174
|
+
return [
|
|
175
|
+
// TODO: @kyranjamie to default to schnoor when TR so conversion isn't
|
|
176
|
+
// necessary here?
|
|
177
|
+
ecdsaPublicKeyToSchnorr(args.publicKey),
|
|
178
|
+
{
|
|
179
|
+
hashes: [],
|
|
180
|
+
der: {
|
|
181
|
+
fingerprint: hexToNumber(args.masterKeyFingerprint),
|
|
182
|
+
path: btc.bip32Path(keyOriginToDerivationPath(args.keyOrigin)),
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @description
|
|
190
|
+
* Turns key format from @scure/btc-signer lib back into key origin string
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts
|
|
193
|
+
* const [inputOne] = getPsbtTxInputs(tx);
|
|
194
|
+
* const keyOrigin = serializeKeyOrigin(inputOne.bip32Derivation[0][1]);
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
export function serializeKeyOrigin({ fingerprint, path }: BtcSignerDerivationPath) {
|
|
198
|
+
const values = path.map(num => (num >= HARDENED_OFFSET ? num - HARDENED_OFFSET + "'" : num));
|
|
199
|
+
return `${toHexString(fingerprint)}/${values.join('/')}`;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* @description
|
|
204
|
+
* Of a given set of a `tx.input`s bip32 derivation paths from
|
|
205
|
+
* `@scure/btc-signer`, serialize the paths back to the string format used
|
|
206
|
+
* internally
|
|
207
|
+
*/
|
|
208
|
+
export function extractRequiredKeyOrigins(derivation: BtcSignerBip32Derivation[]) {
|
|
209
|
+
return derivation.map(([_pubkey, path]) =>
|
|
210
|
+
serializeKeyOrigin('hashes' in path ? path.der : path)
|
|
211
|
+
);
|
|
212
|
+
}
|
package/src/bitcoin.utils.ts
CHANGED
|
@@ -4,7 +4,11 @@ import { mnemonicToSeedSync } from '@scure/bip39';
|
|
|
4
4
|
import * as btc from '@scure/btc-signer';
|
|
5
5
|
import { TransactionInput, TransactionOutput } from '@scure/btc-signer/psbt';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
DerivationPathDepth,
|
|
9
|
+
extractAccountIndexFromPath,
|
|
10
|
+
extractPurposeFromPath,
|
|
11
|
+
} from '@leather.io/crypto';
|
|
8
12
|
import { BitcoinNetworkModes, NetworkModes } from '@leather.io/models';
|
|
9
13
|
import type { PaymentTypes } from '@leather.io/rpc';
|
|
10
14
|
import { defaultWalletKeyId, isDefined, whenNetwork } from '@leather.io/utils';
|
|
@@ -153,6 +157,12 @@ export function whenPaymentType(mode: PaymentTypes | BtcSignerLibPaymentTypeIden
|
|
|
153
157
|
paymentMap[parseKnownPaymentType(mode)];
|
|
154
158
|
}
|
|
155
159
|
|
|
160
|
+
export type SupportedPaymentType = 'p2wpkh' | 'p2tr';
|
|
161
|
+
export type SupportedPaymentTypeMap<T> = Record<SupportedPaymentType, T>;
|
|
162
|
+
export function whenSupportedPaymentType(mode: SupportedPaymentType) {
|
|
163
|
+
return <T>(paymentMap: SupportedPaymentTypeMap<T>): T => paymentMap[mode];
|
|
164
|
+
}
|
|
165
|
+
|
|
156
166
|
/**
|
|
157
167
|
* Infers the Bitcoin payment type from the derivation path.
|
|
158
168
|
* Below we see path has 86 in it, per convention, this refers to taproot payments
|
|
@@ -160,10 +170,17 @@ export function whenPaymentType(mode: PaymentTypes | BtcSignerLibPaymentTypeIden
|
|
|
160
170
|
* `m/86'/1'/0'/0/0`
|
|
161
171
|
*/
|
|
162
172
|
export function inferPaymentTypeFromPath(path: string): PaymentTypes {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
173
|
+
const purpose = extractPurposeFromPath(path);
|
|
174
|
+
switch (purpose) {
|
|
175
|
+
case 84:
|
|
176
|
+
return 'p2wpkh';
|
|
177
|
+
case 86:
|
|
178
|
+
return 'p2tr';
|
|
179
|
+
case 44:
|
|
180
|
+
return 'p2pkh';
|
|
181
|
+
default:
|
|
182
|
+
throw new Error(`Unable to infer payment type from purpose=${purpose}`);
|
|
183
|
+
}
|
|
167
184
|
}
|
|
168
185
|
|
|
169
186
|
export function inferNetworkFromPath(path: string): NetworkModes {
|
|
@@ -245,14 +262,11 @@ export function getTaprootAddress({ index, keychain, network }: GetTaprootAddres
|
|
|
245
262
|
|
|
246
263
|
const addressIndex = deriveAddressIndexKeychainFromAccount(keychain)(index);
|
|
247
264
|
|
|
248
|
-
if (!addressIndex.publicKey)
|
|
249
|
-
throw new Error('Expected publicKey to be defined');
|
|
250
|
-
}
|
|
265
|
+
if (!addressIndex.publicKey) throw new Error('Expected publicKey to be defined');
|
|
251
266
|
|
|
252
267
|
const payment = getTaprootPayment(addressIndex.publicKey, network);
|
|
253
268
|
|
|
254
269
|
if (!payment.address) throw new Error('Expected address to be defined');
|
|
255
|
-
|
|
256
270
|
return payment.address;
|
|
257
271
|
}
|
|
258
272
|
|
package/src/p2tr-address-gen.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HDKey } from '@scure/bip32';
|
|
2
2
|
import * as btc from '@scure/btc-signer';
|
|
3
3
|
|
|
4
|
-
import { DerivationPathDepth
|
|
4
|
+
import { DerivationPathDepth } from '@leather.io/crypto';
|
|
5
5
|
import { BitcoinNetworkModes } from '@leather.io/models';
|
|
6
6
|
|
|
7
7
|
import { getBtcSignerLibNetworkConfigByMode } from './bitcoin.network';
|
|
@@ -62,16 +62,16 @@ export function getTaprootPaymentFromAddressIndex(keychain: HDKey, network: Bitc
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
interface DeriveTaprootReceiveAddressIndexArgs {
|
|
65
|
-
|
|
65
|
+
keychain: HDKey;
|
|
66
66
|
network: BitcoinNetworkModes;
|
|
67
67
|
}
|
|
68
|
-
export function
|
|
69
|
-
|
|
68
|
+
export function deriveTaprootReceiveAddressIndexZero({
|
|
69
|
+
keychain,
|
|
70
70
|
network,
|
|
71
71
|
}: DeriveTaprootReceiveAddressIndexArgs) {
|
|
72
|
-
const keychain = deriveKeychainFromXpub(xpub);
|
|
73
|
-
|
|
74
72
|
const zeroAddressIndex = deriveAddressIndexZeroFromAccount(keychain);
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
return {
|
|
74
|
+
keychain: zeroAddressIndex,
|
|
75
|
+
payment: getTaprootPaymentFromAddressIndex(zeroAddressIndex, network),
|
|
76
|
+
};
|
|
77
77
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { deriveKeychainFromXpub } from '@leather.io/crypto';
|
|
2
|
+
|
|
3
|
+
import { deriveNativeSegwitReceiveAddressIndexZero } from './p2wpkh-address-gen';
|
|
2
4
|
|
|
3
5
|
describe('Bitcoin bech32 (P2WPKH address derivation', () => {
|
|
4
6
|
describe('from extended public key', () => {
|
|
@@ -34,12 +36,13 @@ describe('Bitcoin bech32 (P2WPKH address derivation', () => {
|
|
|
34
36
|
];
|
|
35
37
|
|
|
36
38
|
describe.each(accounts)('Account', account => {
|
|
37
|
-
const keychain =
|
|
38
|
-
|
|
39
|
+
const keychain = deriveKeychainFromXpub(account.extended_public_key);
|
|
40
|
+
const { payment } = deriveNativeSegwitReceiveAddressIndexZero({
|
|
41
|
+
keychain,
|
|
39
42
|
network: 'mainnet',
|
|
40
43
|
});
|
|
41
44
|
test('bech 32 address', () =>
|
|
42
|
-
expect(
|
|
45
|
+
expect(payment?.address).toEqual(account.zeroIndexChildAddress));
|
|
43
46
|
});
|
|
44
47
|
});
|
|
45
48
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HDKey } from '@scure/bip32';
|
|
2
2
|
import * as btc from '@scure/btc-signer';
|
|
3
3
|
|
|
4
|
-
import { DerivationPathDepth
|
|
4
|
+
import { DerivationPathDepth } from '@leather.io/crypto';
|
|
5
5
|
import { BitcoinNetworkModes } from '@leather.io/models';
|
|
6
6
|
|
|
7
7
|
import { getBtcSignerLibNetworkConfigByMode } from './bitcoin.network';
|
|
@@ -56,17 +56,17 @@ export function getNativeSegWitPaymentFromAddressIndex(
|
|
|
56
56
|
return btc.p2wpkh(keychain.publicKey, getBtcSignerLibNetworkConfigByMode(network));
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
interface
|
|
60
|
-
|
|
59
|
+
interface DeriveNativeSegwitReceiveAddressIndexArgs {
|
|
60
|
+
keychain: HDKey;
|
|
61
61
|
network: BitcoinNetworkModes;
|
|
62
62
|
}
|
|
63
|
-
export function
|
|
64
|
-
|
|
63
|
+
export function deriveNativeSegwitReceiveAddressIndexZero({
|
|
64
|
+
keychain,
|
|
65
65
|
network,
|
|
66
|
-
}:
|
|
67
|
-
if (!xpub) return;
|
|
68
|
-
const keychain = deriveKeychainFromXpub(xpub);
|
|
69
|
-
if (!keychain) return;
|
|
66
|
+
}: DeriveNativeSegwitReceiveAddressIndexArgs) {
|
|
70
67
|
const zeroAddressIndex = deriveAddressIndexZeroFromAccount(keychain);
|
|
71
|
-
return
|
|
68
|
+
return {
|
|
69
|
+
keychain: zeroAddressIndex,
|
|
70
|
+
payment: getNativeSegWitPaymentFromAddressIndex(zeroAddressIndex, network),
|
|
71
|
+
};
|
|
72
72
|
}
|