@dynamic-labs-wallet/btc 0.0.235 → 0.0.236
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/index.cjs.js +272 -6
- package/index.esm.js +273 -7
- package/package.json +2 -2
- package/src/client/client.d.ts +26 -0
- package/src/client/client.d.ts.map +1 -1
- package/src/utils/calculateBip322Hash/calculateBip322Hash.d.ts.map +1 -1
- package/src/utils/doesInputBelongToAddress/doesInputBelongToAddress.d.ts +11 -0
- package/src/utils/doesInputBelongToAddress/doesInputBelongToAddress.d.ts.map +1 -0
- package/src/utils/doesInputBelongToAddress/index.d.ts +2 -0
- package/src/utils/doesInputBelongToAddress/index.d.ts.map +1 -0
- package/src/utils/encodeBip322Signature/encodeBip322Signature.d.ts.map +1 -1
- package/src/utils/getAddressTypeFromDerivationPath/getAddressTypeFromDerivationPath.d.ts.map +1 -1
- package/src/utils/getPublicKeyFromPrivateKey/getPublicKeyFromPrivateKey.d.ts +16 -0
- package/src/utils/getPublicKeyFromPrivateKey/getPublicKeyFromPrivateKey.d.ts.map +1 -0
- package/src/utils/getPublicKeyFromPrivateKey/index.d.ts +2 -0
- package/src/utils/getPublicKeyFromPrivateKey/index.d.ts.map +1 -0
- package/src/utils/index.d.ts +3 -0
- package/src/utils/index.d.ts.map +1 -1
- package/src/utils/normalizePublicKey/normalizePublicKey.d.ts +1 -2
- package/src/utils/normalizePublicKey/normalizePublicKey.d.ts.map +1 -1
- package/src/utils/publicKeyToBitcoinAddress/publicKeyToBitcoinAddress.d.ts.map +1 -1
- package/src/utils/wifToPrivateKey/index.d.ts +2 -0
- package/src/utils/wifToPrivateKey/index.d.ts.map +1 -0
- package/src/utils/wifToPrivateKey/wifToPrivateKey.d.ts +19 -0
- package/src/utils/wifToPrivateKey/wifToPrivateKey.d.ts.map +1 -0
package/index.cjs.js
CHANGED
|
@@ -122,6 +122,7 @@ let isInitialized = false;
|
|
|
122
122
|
return address;
|
|
123
123
|
};
|
|
124
124
|
|
|
125
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
125
126
|
/**
|
|
126
127
|
* Converts a public key to a Bitcoin address
|
|
127
128
|
*
|
|
@@ -231,6 +232,7 @@ const compressPublicKey = (x, yLastByte)=>{
|
|
|
231
232
|
]);
|
|
232
233
|
};
|
|
233
234
|
|
|
235
|
+
// eslint-disable @nx/enforce-module-boundaries
|
|
234
236
|
/**
|
|
235
237
|
* Normalizes a public key to a standard Buffer format
|
|
236
238
|
* Handles various input types (Uint8Array, Buffer, object with pubKeyAsHex, etc.)
|
|
@@ -248,6 +250,7 @@ const compressPublicKey = (x, yLastByte)=>{
|
|
|
248
250
|
return normalizeForCompressed(buffer);
|
|
249
251
|
};
|
|
250
252
|
|
|
253
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
251
254
|
/**
|
|
252
255
|
* Infers the Bitcoin address type from a BIP-44 derivation path
|
|
253
256
|
*
|
|
@@ -447,6 +450,101 @@ initEccLib();
|
|
|
447
450
|
}
|
|
448
451
|
};
|
|
449
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Converts a Bitcoin WIF (Wallet Import Format) private key to hex format
|
|
455
|
+
* This is the reverse operation of `privateKeyToWIF`
|
|
456
|
+
*
|
|
457
|
+
* WIF decoding steps:
|
|
458
|
+
* 1. Base58 decode the WIF string
|
|
459
|
+
* 2. Validate network prefix
|
|
460
|
+
* 3. Validate checksum (double SHA-256, first 4 bytes)
|
|
461
|
+
* 4. Extract private key bytes (skip prefix, compression flag, and checksum)
|
|
462
|
+
* 5. Convert to hex string
|
|
463
|
+
*
|
|
464
|
+
* @param wif - Private key in WIF format (Base58 encoded)
|
|
465
|
+
* @param network - Bitcoin network (mainnet, testnet)
|
|
466
|
+
* @returns Private key as hex string (64 characters, 32 bytes)
|
|
467
|
+
* @throws Error if WIF format is invalid
|
|
468
|
+
*/ const wifToPrivateKey = (wif, network = 'mainnet')=>{
|
|
469
|
+
try {
|
|
470
|
+
// 1. Decode Base58
|
|
471
|
+
const decoded = bs58.decode(wif);
|
|
472
|
+
// 2. Validate length (should be 37 bytes: 1 prefix + 32 key + 1 compression + 4 checksum)
|
|
473
|
+
// or 38 bytes (with compression flag)
|
|
474
|
+
if (decoded.length !== 37 && decoded.length !== 38) {
|
|
475
|
+
throw new Error(`Invalid WIF length: ${decoded.length}, expected 37 or 38 bytes`);
|
|
476
|
+
}
|
|
477
|
+
// 3. Get network config to validate prefix
|
|
478
|
+
const networkConfig = getBitcoinNetwork(network);
|
|
479
|
+
const expectedPrefix = networkConfig.wif;
|
|
480
|
+
// 4. Validate network prefix
|
|
481
|
+
if (decoded[0] !== expectedPrefix) {
|
|
482
|
+
throw new Error(`Invalid WIF network prefix: expected ${expectedPrefix}, got ${decoded[0]}`);
|
|
483
|
+
}
|
|
484
|
+
// 5. Validate checksum
|
|
485
|
+
const payload = decoded.slice(0, -4);
|
|
486
|
+
const checksum = decoded.slice(-4);
|
|
487
|
+
const firstHash = sha256.sha256(payload);
|
|
488
|
+
const secondHash = sha256.sha256(firstHash);
|
|
489
|
+
const calculatedChecksum = secondHash.slice(0, 4);
|
|
490
|
+
if (!calculatedChecksum.every((byte, index)=>byte === checksum[index])) {
|
|
491
|
+
throw new Error('Invalid WIF checksum');
|
|
492
|
+
}
|
|
493
|
+
// 6. Extract private key bytes (skip prefix, skip compression flag if present, skip checksum)
|
|
494
|
+
// Private key is always 32 bytes, starting at index 1
|
|
495
|
+
const privateKeyStart = 1;
|
|
496
|
+
const privateKeyEnd = 33; // 32 bytes of private key
|
|
497
|
+
const privateKeyBytes = decoded.slice(privateKeyStart, privateKeyEnd);
|
|
498
|
+
// 7. Convert to hex string
|
|
499
|
+
return Buffer.from(privateKeyBytes).toString('hex');
|
|
500
|
+
} catch (error) {
|
|
501
|
+
throw new Error(`Invalid WIF format: ${error instanceof Error ? error.message : String(error)}. Only WIF format is supported.`);
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Derives a public key from a private key (WIF format) based on address type
|
|
507
|
+
*
|
|
508
|
+
* - For NATIVE_SEGWIT (ECDSA): Returns compressed public key (33 bytes)
|
|
509
|
+
* - For TAPROOT (BIP340): Returns x-only public key (32 bytes)
|
|
510
|
+
*
|
|
511
|
+
* @param privateKey - Private key in WIF format (Base58 encoded)
|
|
512
|
+
* @param addressType - Bitcoin address type (NATIVE_SEGWIT or TAPROOT)
|
|
513
|
+
* @param network - Bitcoin network (mainnet, testnet)
|
|
514
|
+
* @returns Public key as Buffer (33 bytes for NATIVE_SEGWIT, 32 bytes for TAPROOT)
|
|
515
|
+
* @throws Error if private key is invalid or derivation fails
|
|
516
|
+
*/ const getPublicKeyFromPrivateKey = async (privateKey, addressType, network = 'mainnet')=>{
|
|
517
|
+
initEccLib();
|
|
518
|
+
try {
|
|
519
|
+
// 1. Decode WIF to hex
|
|
520
|
+
const privateKeyHex = wifToPrivateKey(privateKey, network);
|
|
521
|
+
const privateKeyBytes = new Uint8Array(Buffer.from(privateKeyHex, 'hex'));
|
|
522
|
+
// 2. Import secp256k1 library
|
|
523
|
+
const ecc = await import('@bitcoinerlab/secp256k1');
|
|
524
|
+
// 3. Derive public key based on address type
|
|
525
|
+
if (addressType === 'taproot') {
|
|
526
|
+
// BIP340/Taproot: Derive x-only public key (32 bytes)
|
|
527
|
+
// Get the public key point
|
|
528
|
+
const publicKeyPoint = ecc.pointFromScalar(privateKeyBytes);
|
|
529
|
+
if (!publicKeyPoint) {
|
|
530
|
+
throw new Error('Failed to derive public key from private key');
|
|
531
|
+
}
|
|
532
|
+
// For Taproot, we need the 32-byte x-only public key
|
|
533
|
+
// publicKeyPoint is 33 bytes (0x02/0x03 + 32 bytes x), we take the last 32 bytes
|
|
534
|
+
return Buffer.from(publicKeyPoint.subarray(1)); // Skip prefix, get x-coordinate
|
|
535
|
+
} else {
|
|
536
|
+
// NATIVE_SEGWIT (ECDSA): Derive compressed public key (33 bytes)
|
|
537
|
+
const publicKeyPoint = ecc.pointFromScalar(privateKeyBytes, true); // compressed = true
|
|
538
|
+
if (!publicKeyPoint) {
|
|
539
|
+
throw new Error('Failed to derive public key from private key');
|
|
540
|
+
}
|
|
541
|
+
return Buffer.from(publicKeyPoint); // 33 bytes compressed
|
|
542
|
+
}
|
|
543
|
+
} catch (error) {
|
|
544
|
+
throw new Error(`Failed to derive public key from private key: ${error instanceof Error ? error.message : String(error)}`);
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
|
|
450
548
|
/**
|
|
451
549
|
* Converts an ECDSA signature to DER format
|
|
452
550
|
*
|
|
@@ -614,6 +712,48 @@ initEccLib();
|
|
|
614
712
|
};
|
|
615
713
|
};
|
|
616
714
|
|
|
715
|
+
/**
|
|
716
|
+
* Checks if a PSBT input belongs to a specific address
|
|
717
|
+
* @param input - The PSBT input (from psbt.data.inputs)
|
|
718
|
+
* @param address - The address to check against
|
|
719
|
+
* @param network - The Bitcoin network
|
|
720
|
+
* @returns True if the input belongs to the address, false otherwise
|
|
721
|
+
*/ const doesInputBelongToAddress = (input, address, network)=>{
|
|
722
|
+
if (!input.witnessUtxo) {
|
|
723
|
+
return false;
|
|
724
|
+
}
|
|
725
|
+
const script = Buffer.isBuffer(input.witnessUtxo.script) ? input.witnessUtxo.script : Buffer.from(input.witnessUtxo.script);
|
|
726
|
+
const bitcoinNetwork = getBitcoinNetwork(network);
|
|
727
|
+
try {
|
|
728
|
+
// Try P2WPKH (Native SegWit) - script is OP_0 <20-byte hash>
|
|
729
|
+
if (script.length === 22 && script[0] === 0x00 && script[1] === 0x14) {
|
|
730
|
+
const p2wpkh = bitcoin__namespace.payments.p2wpkh({
|
|
731
|
+
output: script,
|
|
732
|
+
network: bitcoinNetwork
|
|
733
|
+
});
|
|
734
|
+
return p2wpkh.address === address;
|
|
735
|
+
}
|
|
736
|
+
// Try P2TR (Taproot) - script is OP_1 <32-byte x-only pubkey>
|
|
737
|
+
if (script.length === 34 && script[0] === 0x51 && script[1] === 0x20) {
|
|
738
|
+
const p2tr = bitcoin__namespace.payments.p2tr({
|
|
739
|
+
output: script,
|
|
740
|
+
network: bitcoinNetwork
|
|
741
|
+
});
|
|
742
|
+
return p2tr.address === address;
|
|
743
|
+
}
|
|
744
|
+
return false;
|
|
745
|
+
} catch (error) {
|
|
746
|
+
// eslint-disable-next-line no-console
|
|
747
|
+
console.log('[doesInputBelongToAddress] Error checking input', {
|
|
748
|
+
address,
|
|
749
|
+
network,
|
|
750
|
+
error: error instanceof Error ? error.message : String(error)
|
|
751
|
+
});
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
617
757
|
class DynamicBtcWalletClient extends browser.DynamicWalletClient {
|
|
618
758
|
/**
|
|
619
759
|
* Creates a Bitcoin wallet account
|
|
@@ -914,6 +1054,117 @@ class DynamicBtcWalletClient extends browser.DynamicWalletClient {
|
|
|
914
1054
|
return this.convertPrivateKeyToBitcoinFormat(derivedPrivateKey, browser.BitcoinNetwork.MAINNET);
|
|
915
1055
|
}
|
|
916
1056
|
/**
|
|
1057
|
+
* Imports a private key and creates a Bitcoin wallet account
|
|
1058
|
+
* @param privateKey - Private key in WIF format (Base58 encoded)
|
|
1059
|
+
* @param chainName - Chain name ('BTC')
|
|
1060
|
+
* @param thresholdSignatureScheme - The threshold signature scheme to use
|
|
1061
|
+
* @param password - Optional password for encrypted backup
|
|
1062
|
+
* @param onError - Optional error callback
|
|
1063
|
+
* @param signedSessionId - The signed session ID
|
|
1064
|
+
* @param publicAddressCheck - Optional address to validate against
|
|
1065
|
+
* @param addressType - Bitcoin address type (NATIVE_SEGWIT or TAPROOT)
|
|
1066
|
+
* @returns The account address, public key hex, and raw public key
|
|
1067
|
+
*/ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError, signedSessionId, publicAddressCheck, addressType }) {
|
|
1068
|
+
try {
|
|
1069
|
+
const network = browser.BitcoinNetwork.MAINNET;
|
|
1070
|
+
if (!addressType) {
|
|
1071
|
+
throw new Error('addressType is required for BTC importPrivateKey');
|
|
1072
|
+
}
|
|
1073
|
+
const bitcoinAddressType = addressType;
|
|
1074
|
+
if (bitcoinAddressType !== browser.BitcoinAddressType.NATIVE_SEGWIT && bitcoinAddressType !== browser.BitcoinAddressType.TAPROOT) {
|
|
1075
|
+
throw new Error(`Invalid addressType: ${addressType}. Must be one of: ${browser.BitcoinAddressType.NATIVE_SEGWIT}, ${browser.BitcoinAddressType.TAPROOT}`);
|
|
1076
|
+
}
|
|
1077
|
+
const addressTypeEnum = bitcoinAddressType;
|
|
1078
|
+
let ceremonyCeremonyCompleteResolver;
|
|
1079
|
+
let ceremonyAccountAddress;
|
|
1080
|
+
const ceremonyCompletePromise = new Promise((resolve)=>{
|
|
1081
|
+
ceremonyCeremonyCompleteResolver = resolve;
|
|
1082
|
+
});
|
|
1083
|
+
const formattedPrivateKey = wifToPrivateKey(privateKey, network);
|
|
1084
|
+
if (publicAddressCheck) {
|
|
1085
|
+
const derivedPublicKey = await getPublicKeyFromPrivateKey(privateKey, addressTypeEnum, network);
|
|
1086
|
+
const { accountAddress } = this.deriveAccountAddress({
|
|
1087
|
+
rawPublicKey: derivedPublicKey,
|
|
1088
|
+
addressType: addressTypeEnum,
|
|
1089
|
+
network
|
|
1090
|
+
});
|
|
1091
|
+
if (accountAddress !== publicAddressCheck) {
|
|
1092
|
+
throw new Error(`Public address mismatch: derived address ${accountAddress} !== public address ${publicAddressCheck}`);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
|
|
1096
|
+
chainName,
|
|
1097
|
+
privateKey: formattedPrivateKey,
|
|
1098
|
+
thresholdSignatureScheme,
|
|
1099
|
+
bitcoinConfig: {
|
|
1100
|
+
addressType: addressTypeEnum,
|
|
1101
|
+
network
|
|
1102
|
+
},
|
|
1103
|
+
onCeremonyComplete: (accountAddress, walletId)=>{
|
|
1104
|
+
ceremonyAccountAddress = accountAddress;
|
|
1105
|
+
const chainConfig = browser.getMPCChainConfig(this.chainName, {
|
|
1106
|
+
addressType: addressTypeEnum,
|
|
1107
|
+
network
|
|
1108
|
+
});
|
|
1109
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
|
|
1110
|
+
accountAddress,
|
|
1111
|
+
walletId,
|
|
1112
|
+
chainName: this.chainName,
|
|
1113
|
+
thresholdSignatureScheme,
|
|
1114
|
+
derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map((value, index)=>[
|
|
1115
|
+
index,
|
|
1116
|
+
value
|
|
1117
|
+
]))),
|
|
1118
|
+
addressType: addressTypeEnum,
|
|
1119
|
+
clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
|
|
1120
|
+
});
|
|
1121
|
+
this.logger.debug('walletMap updated for wallet', {
|
|
1122
|
+
context: {
|
|
1123
|
+
accountAddress,
|
|
1124
|
+
walletId,
|
|
1125
|
+
walletMap: this.walletMap
|
|
1126
|
+
}
|
|
1127
|
+
});
|
|
1128
|
+
ceremonyCeremonyCompleteResolver(undefined);
|
|
1129
|
+
},
|
|
1130
|
+
onError
|
|
1131
|
+
});
|
|
1132
|
+
await ceremonyCompletePromise;
|
|
1133
|
+
if (!rawPublicKey || !clientKeyShares) {
|
|
1134
|
+
throw new Error(browser.ERROR_IMPORT_PRIVATE_KEY);
|
|
1135
|
+
}
|
|
1136
|
+
const accountAddress = ceremonyAccountAddress || this.deriveAccountAddress({
|
|
1137
|
+
rawPublicKey,
|
|
1138
|
+
addressType: addressTypeEnum,
|
|
1139
|
+
network
|
|
1140
|
+
}).accountAddress;
|
|
1141
|
+
if (publicAddressCheck && accountAddress !== publicAddressCheck) {
|
|
1142
|
+
throw new Error(`Public address mismatch: derived address ${accountAddress} !== public address ${publicAddressCheck}`);
|
|
1143
|
+
}
|
|
1144
|
+
await this.setClientKeySharesToLocalStorage({
|
|
1145
|
+
accountAddress,
|
|
1146
|
+
clientKeyShares,
|
|
1147
|
+
overwriteOrMerge: 'overwrite'
|
|
1148
|
+
});
|
|
1149
|
+
await this.storeEncryptedBackupByWalletWithRetry({
|
|
1150
|
+
accountAddress,
|
|
1151
|
+
clientKeyShares,
|
|
1152
|
+
password,
|
|
1153
|
+
signedSessionId
|
|
1154
|
+
});
|
|
1155
|
+
const publicKeyHex = this.extractPublicKeyHex(rawPublicKey);
|
|
1156
|
+
return {
|
|
1157
|
+
accountAddress,
|
|
1158
|
+
publicKeyHex,
|
|
1159
|
+
rawPublicKey
|
|
1160
|
+
};
|
|
1161
|
+
} catch (error) {
|
|
1162
|
+
this.logger.error(browser.ERROR_IMPORT_PRIVATE_KEY, error);
|
|
1163
|
+
onError == null ? void 0 : onError(error);
|
|
1164
|
+
throw new Error(browser.ERROR_IMPORT_PRIVATE_KEY);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
917
1168
|
* Converts MPC private key to Bitcoin WIF (Wallet Import Format)
|
|
918
1169
|
* Uses the utility function from utils.ts for the core conversion logic
|
|
919
1170
|
* @param privateKey - The private key to convert to a Bitcoin WIF format
|
|
@@ -1000,6 +1251,22 @@ class DynamicBtcWalletClient extends browser.DynamicWalletClient {
|
|
|
1000
1251
|
}
|
|
1001
1252
|
const pubKey = normalizePublicKey(derivedPublicKey, addressType);
|
|
1002
1253
|
const tx = psbt.__CACHE.__TX;
|
|
1254
|
+
// Filter inputs to only sign those that belong to the current address
|
|
1255
|
+
const inputsToSign = psbt.data.inputs.map((input, i)=>({
|
|
1256
|
+
input,
|
|
1257
|
+
index: i
|
|
1258
|
+
})).filter(({ input })=>doesInputBelongToAddress(input, senderAddress, network));
|
|
1259
|
+
this.logger.debug('[BTC Client] signTransaction - Filtering inputs', {
|
|
1260
|
+
totalInputs: psbt.data.inputs.length,
|
|
1261
|
+
inputsToSign: inputsToSign.length,
|
|
1262
|
+
senderAddress
|
|
1263
|
+
});
|
|
1264
|
+
if (inputsToSign.length === 0) {
|
|
1265
|
+
this.logger.warn('[BTC Client] signTransaction - No inputs found for address', {
|
|
1266
|
+
senderAddress,
|
|
1267
|
+
totalInputs: psbt.data.inputs.length
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1003
1270
|
if (addressType === browser.BitcoinAddressType.TAPROOT) {
|
|
1004
1271
|
const tweak = calculateTaprootTweak(pubKey);
|
|
1005
1272
|
const completeBitcoinConfig = _extends({}, bitcoinConfig, {
|
|
@@ -1007,7 +1274,7 @@ class DynamicBtcWalletClient extends browser.DynamicWalletClient {
|
|
|
1007
1274
|
tweak
|
|
1008
1275
|
});
|
|
1009
1276
|
const { prevOutScripts, values } = collectPSBTInputData(psbt);
|
|
1010
|
-
await Promise.all(
|
|
1277
|
+
await Promise.all(inputsToSign.map(async ({ input, index: i })=>{
|
|
1011
1278
|
if (!input.witnessUtxo) {
|
|
1012
1279
|
throw new Error(`Input ${i} missing witnessUtxo`);
|
|
1013
1280
|
}
|
|
@@ -1036,17 +1303,16 @@ class DynamicBtcWalletClient extends browser.DynamicWalletClient {
|
|
|
1036
1303
|
addressType: addressType
|
|
1037
1304
|
});
|
|
1038
1305
|
// Iterate and sign inputs in parallel for better performance
|
|
1039
|
-
await Promise.all(
|
|
1306
|
+
await Promise.all(inputsToSign.map(async ({ input, index: i })=>{
|
|
1040
1307
|
if (!input.witnessUtxo) {
|
|
1041
1308
|
throw new Error(`Input ${i} missing witnessUtxo`);
|
|
1042
1309
|
}
|
|
1043
1310
|
const { script, value } = input.witnessUtxo;
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
output: script,
|
|
1311
|
+
const p2pkh = bitcoin__namespace.payments.p2pkh({
|
|
1312
|
+
hash: script.slice(2),
|
|
1047
1313
|
network: getBitcoinNetwork(network)
|
|
1048
1314
|
});
|
|
1049
|
-
const scriptCode =
|
|
1315
|
+
const scriptCode = p2pkh.output;
|
|
1050
1316
|
if (!scriptCode) throw new Error('Failed to generate scriptCode');
|
|
1051
1317
|
const hash = tx.hashForWitnessV0(i, scriptCode, value, bitcoin__namespace.Transaction.SIGHASH_ALL);
|
|
1052
1318
|
const signature = await this.sign({
|
package/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BitcoinAddressType, DynamicWalletClient, BitcoinNetwork, getMPCChainConfig, getClientKeyShareBackupInfo, ERROR_CREATE_WALLET_ACCOUNT, WalletOperation, ERROR_ACCOUNT_ADDRESS_REQUIRED, ERROR_SIGN_MESSAGE, AuthMode } from '@dynamic-labs-wallet/browser';
|
|
1
|
+
import { BitcoinAddressType, DynamicWalletClient, BitcoinNetwork, getMPCChainConfig, getClientKeyShareBackupInfo, ERROR_CREATE_WALLET_ACCOUNT, WalletOperation, ERROR_ACCOUNT_ADDRESS_REQUIRED, ERROR_SIGN_MESSAGE, ERROR_IMPORT_PRIVATE_KEY, AuthMode } from '@dynamic-labs-wallet/browser';
|
|
2
2
|
import * as bitcoin from 'bitcoinjs-lib';
|
|
3
3
|
import { payments, initEccLib as initEccLib$1 } from 'bitcoinjs-lib';
|
|
4
4
|
import ecc from '@bitcoinerlab/secp256k1';
|
|
@@ -102,6 +102,7 @@ let isInitialized = false;
|
|
|
102
102
|
return address;
|
|
103
103
|
};
|
|
104
104
|
|
|
105
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
105
106
|
/**
|
|
106
107
|
* Converts a public key to a Bitcoin address
|
|
107
108
|
*
|
|
@@ -211,6 +212,7 @@ const compressPublicKey = (x, yLastByte)=>{
|
|
|
211
212
|
]);
|
|
212
213
|
};
|
|
213
214
|
|
|
215
|
+
// eslint-disable @nx/enforce-module-boundaries
|
|
214
216
|
/**
|
|
215
217
|
* Normalizes a public key to a standard Buffer format
|
|
216
218
|
* Handles various input types (Uint8Array, Buffer, object with pubKeyAsHex, etc.)
|
|
@@ -228,6 +230,7 @@ const compressPublicKey = (x, yLastByte)=>{
|
|
|
228
230
|
return normalizeForCompressed(buffer);
|
|
229
231
|
};
|
|
230
232
|
|
|
233
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
231
234
|
/**
|
|
232
235
|
* Infers the Bitcoin address type from a BIP-44 derivation path
|
|
233
236
|
*
|
|
@@ -427,6 +430,101 @@ initEccLib();
|
|
|
427
430
|
}
|
|
428
431
|
};
|
|
429
432
|
|
|
433
|
+
/**
|
|
434
|
+
* Converts a Bitcoin WIF (Wallet Import Format) private key to hex format
|
|
435
|
+
* This is the reverse operation of `privateKeyToWIF`
|
|
436
|
+
*
|
|
437
|
+
* WIF decoding steps:
|
|
438
|
+
* 1. Base58 decode the WIF string
|
|
439
|
+
* 2. Validate network prefix
|
|
440
|
+
* 3. Validate checksum (double SHA-256, first 4 bytes)
|
|
441
|
+
* 4. Extract private key bytes (skip prefix, compression flag, and checksum)
|
|
442
|
+
* 5. Convert to hex string
|
|
443
|
+
*
|
|
444
|
+
* @param wif - Private key in WIF format (Base58 encoded)
|
|
445
|
+
* @param network - Bitcoin network (mainnet, testnet)
|
|
446
|
+
* @returns Private key as hex string (64 characters, 32 bytes)
|
|
447
|
+
* @throws Error if WIF format is invalid
|
|
448
|
+
*/ const wifToPrivateKey = (wif, network = 'mainnet')=>{
|
|
449
|
+
try {
|
|
450
|
+
// 1. Decode Base58
|
|
451
|
+
const decoded = bs58.decode(wif);
|
|
452
|
+
// 2. Validate length (should be 37 bytes: 1 prefix + 32 key + 1 compression + 4 checksum)
|
|
453
|
+
// or 38 bytes (with compression flag)
|
|
454
|
+
if (decoded.length !== 37 && decoded.length !== 38) {
|
|
455
|
+
throw new Error(`Invalid WIF length: ${decoded.length}, expected 37 or 38 bytes`);
|
|
456
|
+
}
|
|
457
|
+
// 3. Get network config to validate prefix
|
|
458
|
+
const networkConfig = getBitcoinNetwork(network);
|
|
459
|
+
const expectedPrefix = networkConfig.wif;
|
|
460
|
+
// 4. Validate network prefix
|
|
461
|
+
if (decoded[0] !== expectedPrefix) {
|
|
462
|
+
throw new Error(`Invalid WIF network prefix: expected ${expectedPrefix}, got ${decoded[0]}`);
|
|
463
|
+
}
|
|
464
|
+
// 5. Validate checksum
|
|
465
|
+
const payload = decoded.slice(0, -4);
|
|
466
|
+
const checksum = decoded.slice(-4);
|
|
467
|
+
const firstHash = sha256(payload);
|
|
468
|
+
const secondHash = sha256(firstHash);
|
|
469
|
+
const calculatedChecksum = secondHash.slice(0, 4);
|
|
470
|
+
if (!calculatedChecksum.every((byte, index)=>byte === checksum[index])) {
|
|
471
|
+
throw new Error('Invalid WIF checksum');
|
|
472
|
+
}
|
|
473
|
+
// 6. Extract private key bytes (skip prefix, skip compression flag if present, skip checksum)
|
|
474
|
+
// Private key is always 32 bytes, starting at index 1
|
|
475
|
+
const privateKeyStart = 1;
|
|
476
|
+
const privateKeyEnd = 33; // 32 bytes of private key
|
|
477
|
+
const privateKeyBytes = decoded.slice(privateKeyStart, privateKeyEnd);
|
|
478
|
+
// 7. Convert to hex string
|
|
479
|
+
return Buffer.from(privateKeyBytes).toString('hex');
|
|
480
|
+
} catch (error) {
|
|
481
|
+
throw new Error(`Invalid WIF format: ${error instanceof Error ? error.message : String(error)}. Only WIF format is supported.`);
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Derives a public key from a private key (WIF format) based on address type
|
|
487
|
+
*
|
|
488
|
+
* - For NATIVE_SEGWIT (ECDSA): Returns compressed public key (33 bytes)
|
|
489
|
+
* - For TAPROOT (BIP340): Returns x-only public key (32 bytes)
|
|
490
|
+
*
|
|
491
|
+
* @param privateKey - Private key in WIF format (Base58 encoded)
|
|
492
|
+
* @param addressType - Bitcoin address type (NATIVE_SEGWIT or TAPROOT)
|
|
493
|
+
* @param network - Bitcoin network (mainnet, testnet)
|
|
494
|
+
* @returns Public key as Buffer (33 bytes for NATIVE_SEGWIT, 32 bytes for TAPROOT)
|
|
495
|
+
* @throws Error if private key is invalid or derivation fails
|
|
496
|
+
*/ const getPublicKeyFromPrivateKey = async (privateKey, addressType, network = 'mainnet')=>{
|
|
497
|
+
initEccLib();
|
|
498
|
+
try {
|
|
499
|
+
// 1. Decode WIF to hex
|
|
500
|
+
const privateKeyHex = wifToPrivateKey(privateKey, network);
|
|
501
|
+
const privateKeyBytes = new Uint8Array(Buffer.from(privateKeyHex, 'hex'));
|
|
502
|
+
// 2. Import secp256k1 library
|
|
503
|
+
const ecc = await import('@bitcoinerlab/secp256k1');
|
|
504
|
+
// 3. Derive public key based on address type
|
|
505
|
+
if (addressType === 'taproot') {
|
|
506
|
+
// BIP340/Taproot: Derive x-only public key (32 bytes)
|
|
507
|
+
// Get the public key point
|
|
508
|
+
const publicKeyPoint = ecc.pointFromScalar(privateKeyBytes);
|
|
509
|
+
if (!publicKeyPoint) {
|
|
510
|
+
throw new Error('Failed to derive public key from private key');
|
|
511
|
+
}
|
|
512
|
+
// For Taproot, we need the 32-byte x-only public key
|
|
513
|
+
// publicKeyPoint is 33 bytes (0x02/0x03 + 32 bytes x), we take the last 32 bytes
|
|
514
|
+
return Buffer.from(publicKeyPoint.subarray(1)); // Skip prefix, get x-coordinate
|
|
515
|
+
} else {
|
|
516
|
+
// NATIVE_SEGWIT (ECDSA): Derive compressed public key (33 bytes)
|
|
517
|
+
const publicKeyPoint = ecc.pointFromScalar(privateKeyBytes, true); // compressed = true
|
|
518
|
+
if (!publicKeyPoint) {
|
|
519
|
+
throw new Error('Failed to derive public key from private key');
|
|
520
|
+
}
|
|
521
|
+
return Buffer.from(publicKeyPoint); // 33 bytes compressed
|
|
522
|
+
}
|
|
523
|
+
} catch (error) {
|
|
524
|
+
throw new Error(`Failed to derive public key from private key: ${error instanceof Error ? error.message : String(error)}`);
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
|
|
430
528
|
/**
|
|
431
529
|
* Converts an ECDSA signature to DER format
|
|
432
530
|
*
|
|
@@ -594,6 +692,48 @@ initEccLib();
|
|
|
594
692
|
};
|
|
595
693
|
};
|
|
596
694
|
|
|
695
|
+
/**
|
|
696
|
+
* Checks if a PSBT input belongs to a specific address
|
|
697
|
+
* @param input - The PSBT input (from psbt.data.inputs)
|
|
698
|
+
* @param address - The address to check against
|
|
699
|
+
* @param network - The Bitcoin network
|
|
700
|
+
* @returns True if the input belongs to the address, false otherwise
|
|
701
|
+
*/ const doesInputBelongToAddress = (input, address, network)=>{
|
|
702
|
+
if (!input.witnessUtxo) {
|
|
703
|
+
return false;
|
|
704
|
+
}
|
|
705
|
+
const script = Buffer.isBuffer(input.witnessUtxo.script) ? input.witnessUtxo.script : Buffer.from(input.witnessUtxo.script);
|
|
706
|
+
const bitcoinNetwork = getBitcoinNetwork(network);
|
|
707
|
+
try {
|
|
708
|
+
// Try P2WPKH (Native SegWit) - script is OP_0 <20-byte hash>
|
|
709
|
+
if (script.length === 22 && script[0] === 0x00 && script[1] === 0x14) {
|
|
710
|
+
const p2wpkh = bitcoin.payments.p2wpkh({
|
|
711
|
+
output: script,
|
|
712
|
+
network: bitcoinNetwork
|
|
713
|
+
});
|
|
714
|
+
return p2wpkh.address === address;
|
|
715
|
+
}
|
|
716
|
+
// Try P2TR (Taproot) - script is OP_1 <32-byte x-only pubkey>
|
|
717
|
+
if (script.length === 34 && script[0] === 0x51 && script[1] === 0x20) {
|
|
718
|
+
const p2tr = bitcoin.payments.p2tr({
|
|
719
|
+
output: script,
|
|
720
|
+
network: bitcoinNetwork
|
|
721
|
+
});
|
|
722
|
+
return p2tr.address === address;
|
|
723
|
+
}
|
|
724
|
+
return false;
|
|
725
|
+
} catch (error) {
|
|
726
|
+
// eslint-disable-next-line no-console
|
|
727
|
+
console.log('[doesInputBelongToAddress] Error checking input', {
|
|
728
|
+
address,
|
|
729
|
+
network,
|
|
730
|
+
error: error instanceof Error ? error.message : String(error)
|
|
731
|
+
});
|
|
732
|
+
return false;
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
597
737
|
class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
598
738
|
/**
|
|
599
739
|
* Creates a Bitcoin wallet account
|
|
@@ -894,6 +1034,117 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
894
1034
|
return this.convertPrivateKeyToBitcoinFormat(derivedPrivateKey, BitcoinNetwork.MAINNET);
|
|
895
1035
|
}
|
|
896
1036
|
/**
|
|
1037
|
+
* Imports a private key and creates a Bitcoin wallet account
|
|
1038
|
+
* @param privateKey - Private key in WIF format (Base58 encoded)
|
|
1039
|
+
* @param chainName - Chain name ('BTC')
|
|
1040
|
+
* @param thresholdSignatureScheme - The threshold signature scheme to use
|
|
1041
|
+
* @param password - Optional password for encrypted backup
|
|
1042
|
+
* @param onError - Optional error callback
|
|
1043
|
+
* @param signedSessionId - The signed session ID
|
|
1044
|
+
* @param publicAddressCheck - Optional address to validate against
|
|
1045
|
+
* @param addressType - Bitcoin address type (NATIVE_SEGWIT or TAPROOT)
|
|
1046
|
+
* @returns The account address, public key hex, and raw public key
|
|
1047
|
+
*/ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError, signedSessionId, publicAddressCheck, addressType }) {
|
|
1048
|
+
try {
|
|
1049
|
+
const network = BitcoinNetwork.MAINNET;
|
|
1050
|
+
if (!addressType) {
|
|
1051
|
+
throw new Error('addressType is required for BTC importPrivateKey');
|
|
1052
|
+
}
|
|
1053
|
+
const bitcoinAddressType = addressType;
|
|
1054
|
+
if (bitcoinAddressType !== BitcoinAddressType.NATIVE_SEGWIT && bitcoinAddressType !== BitcoinAddressType.TAPROOT) {
|
|
1055
|
+
throw new Error(`Invalid addressType: ${addressType}. Must be one of: ${BitcoinAddressType.NATIVE_SEGWIT}, ${BitcoinAddressType.TAPROOT}`);
|
|
1056
|
+
}
|
|
1057
|
+
const addressTypeEnum = bitcoinAddressType;
|
|
1058
|
+
let ceremonyCeremonyCompleteResolver;
|
|
1059
|
+
let ceremonyAccountAddress;
|
|
1060
|
+
const ceremonyCompletePromise = new Promise((resolve)=>{
|
|
1061
|
+
ceremonyCeremonyCompleteResolver = resolve;
|
|
1062
|
+
});
|
|
1063
|
+
const formattedPrivateKey = wifToPrivateKey(privateKey, network);
|
|
1064
|
+
if (publicAddressCheck) {
|
|
1065
|
+
const derivedPublicKey = await getPublicKeyFromPrivateKey(privateKey, addressTypeEnum, network);
|
|
1066
|
+
const { accountAddress } = this.deriveAccountAddress({
|
|
1067
|
+
rawPublicKey: derivedPublicKey,
|
|
1068
|
+
addressType: addressTypeEnum,
|
|
1069
|
+
network
|
|
1070
|
+
});
|
|
1071
|
+
if (accountAddress !== publicAddressCheck) {
|
|
1072
|
+
throw new Error(`Public address mismatch: derived address ${accountAddress} !== public address ${publicAddressCheck}`);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
|
|
1076
|
+
chainName,
|
|
1077
|
+
privateKey: formattedPrivateKey,
|
|
1078
|
+
thresholdSignatureScheme,
|
|
1079
|
+
bitcoinConfig: {
|
|
1080
|
+
addressType: addressTypeEnum,
|
|
1081
|
+
network
|
|
1082
|
+
},
|
|
1083
|
+
onCeremonyComplete: (accountAddress, walletId)=>{
|
|
1084
|
+
ceremonyAccountAddress = accountAddress;
|
|
1085
|
+
const chainConfig = getMPCChainConfig(this.chainName, {
|
|
1086
|
+
addressType: addressTypeEnum,
|
|
1087
|
+
network
|
|
1088
|
+
});
|
|
1089
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
|
|
1090
|
+
accountAddress,
|
|
1091
|
+
walletId,
|
|
1092
|
+
chainName: this.chainName,
|
|
1093
|
+
thresholdSignatureScheme,
|
|
1094
|
+
derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map((value, index)=>[
|
|
1095
|
+
index,
|
|
1096
|
+
value
|
|
1097
|
+
]))),
|
|
1098
|
+
addressType: addressTypeEnum,
|
|
1099
|
+
clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
|
|
1100
|
+
});
|
|
1101
|
+
this.logger.debug('walletMap updated for wallet', {
|
|
1102
|
+
context: {
|
|
1103
|
+
accountAddress,
|
|
1104
|
+
walletId,
|
|
1105
|
+
walletMap: this.walletMap
|
|
1106
|
+
}
|
|
1107
|
+
});
|
|
1108
|
+
ceremonyCeremonyCompleteResolver(undefined);
|
|
1109
|
+
},
|
|
1110
|
+
onError
|
|
1111
|
+
});
|
|
1112
|
+
await ceremonyCompletePromise;
|
|
1113
|
+
if (!rawPublicKey || !clientKeyShares) {
|
|
1114
|
+
throw new Error(ERROR_IMPORT_PRIVATE_KEY);
|
|
1115
|
+
}
|
|
1116
|
+
const accountAddress = ceremonyAccountAddress || this.deriveAccountAddress({
|
|
1117
|
+
rawPublicKey,
|
|
1118
|
+
addressType: addressTypeEnum,
|
|
1119
|
+
network
|
|
1120
|
+
}).accountAddress;
|
|
1121
|
+
if (publicAddressCheck && accountAddress !== publicAddressCheck) {
|
|
1122
|
+
throw new Error(`Public address mismatch: derived address ${accountAddress} !== public address ${publicAddressCheck}`);
|
|
1123
|
+
}
|
|
1124
|
+
await this.setClientKeySharesToLocalStorage({
|
|
1125
|
+
accountAddress,
|
|
1126
|
+
clientKeyShares,
|
|
1127
|
+
overwriteOrMerge: 'overwrite'
|
|
1128
|
+
});
|
|
1129
|
+
await this.storeEncryptedBackupByWalletWithRetry({
|
|
1130
|
+
accountAddress,
|
|
1131
|
+
clientKeyShares,
|
|
1132
|
+
password,
|
|
1133
|
+
signedSessionId
|
|
1134
|
+
});
|
|
1135
|
+
const publicKeyHex = this.extractPublicKeyHex(rawPublicKey);
|
|
1136
|
+
return {
|
|
1137
|
+
accountAddress,
|
|
1138
|
+
publicKeyHex,
|
|
1139
|
+
rawPublicKey
|
|
1140
|
+
};
|
|
1141
|
+
} catch (error) {
|
|
1142
|
+
this.logger.error(ERROR_IMPORT_PRIVATE_KEY, error);
|
|
1143
|
+
onError == null ? void 0 : onError(error);
|
|
1144
|
+
throw new Error(ERROR_IMPORT_PRIVATE_KEY);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
897
1148
|
* Converts MPC private key to Bitcoin WIF (Wallet Import Format)
|
|
898
1149
|
* Uses the utility function from utils.ts for the core conversion logic
|
|
899
1150
|
* @param privateKey - The private key to convert to a Bitcoin WIF format
|
|
@@ -980,6 +1231,22 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
980
1231
|
}
|
|
981
1232
|
const pubKey = normalizePublicKey(derivedPublicKey, addressType);
|
|
982
1233
|
const tx = psbt.__CACHE.__TX;
|
|
1234
|
+
// Filter inputs to only sign those that belong to the current address
|
|
1235
|
+
const inputsToSign = psbt.data.inputs.map((input, i)=>({
|
|
1236
|
+
input,
|
|
1237
|
+
index: i
|
|
1238
|
+
})).filter(({ input })=>doesInputBelongToAddress(input, senderAddress, network));
|
|
1239
|
+
this.logger.debug('[BTC Client] signTransaction - Filtering inputs', {
|
|
1240
|
+
totalInputs: psbt.data.inputs.length,
|
|
1241
|
+
inputsToSign: inputsToSign.length,
|
|
1242
|
+
senderAddress
|
|
1243
|
+
});
|
|
1244
|
+
if (inputsToSign.length === 0) {
|
|
1245
|
+
this.logger.warn('[BTC Client] signTransaction - No inputs found for address', {
|
|
1246
|
+
senderAddress,
|
|
1247
|
+
totalInputs: psbt.data.inputs.length
|
|
1248
|
+
});
|
|
1249
|
+
}
|
|
983
1250
|
if (addressType === BitcoinAddressType.TAPROOT) {
|
|
984
1251
|
const tweak = calculateTaprootTweak(pubKey);
|
|
985
1252
|
const completeBitcoinConfig = _extends({}, bitcoinConfig, {
|
|
@@ -987,7 +1254,7 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
987
1254
|
tweak
|
|
988
1255
|
});
|
|
989
1256
|
const { prevOutScripts, values } = collectPSBTInputData(psbt);
|
|
990
|
-
await Promise.all(
|
|
1257
|
+
await Promise.all(inputsToSign.map(async ({ input, index: i })=>{
|
|
991
1258
|
if (!input.witnessUtxo) {
|
|
992
1259
|
throw new Error(`Input ${i} missing witnessUtxo`);
|
|
993
1260
|
}
|
|
@@ -1016,17 +1283,16 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
1016
1283
|
addressType: addressType
|
|
1017
1284
|
});
|
|
1018
1285
|
// Iterate and sign inputs in parallel for better performance
|
|
1019
|
-
await Promise.all(
|
|
1286
|
+
await Promise.all(inputsToSign.map(async ({ input, index: i })=>{
|
|
1020
1287
|
if (!input.witnessUtxo) {
|
|
1021
1288
|
throw new Error(`Input ${i} missing witnessUtxo`);
|
|
1022
1289
|
}
|
|
1023
1290
|
const { script, value } = input.witnessUtxo;
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
output: script,
|
|
1291
|
+
const p2pkh = bitcoin.payments.p2pkh({
|
|
1292
|
+
hash: script.slice(2),
|
|
1027
1293
|
network: getBitcoinNetwork(network)
|
|
1028
1294
|
});
|
|
1029
|
-
const scriptCode =
|
|
1295
|
+
const scriptCode = p2pkh.output;
|
|
1030
1296
|
if (!scriptCode) throw new Error('Failed to generate scriptCode');
|
|
1031
1297
|
const hash = tx.hashForWitnessV0(i, scriptCode, value, bitcoin.Transaction.SIGHASH_ALL);
|
|
1032
1298
|
const signature = await this.sign({
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs-wallet/btc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.236",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@dynamic-labs/sdk-api-core": "^0.0.828",
|
|
9
|
-
"@dynamic-labs-wallet/browser": "0.0.
|
|
9
|
+
"@dynamic-labs-wallet/browser": "0.0.236",
|
|
10
10
|
"@bitcoinerlab/secp256k1": "^1.2.0",
|
|
11
11
|
"bitcoinjs-lib": "^7.0.0",
|
|
12
12
|
"bip322-js": "^3.0.0",
|
package/src/client/client.d.ts
CHANGED
|
@@ -95,6 +95,32 @@ export declare class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
95
95
|
signedSessionId: string;
|
|
96
96
|
mfaToken?: string;
|
|
97
97
|
}): Promise<string>;
|
|
98
|
+
/**
|
|
99
|
+
* Imports a private key and creates a Bitcoin wallet account
|
|
100
|
+
* @param privateKey - Private key in WIF format (Base58 encoded)
|
|
101
|
+
* @param chainName - Chain name ('BTC')
|
|
102
|
+
* @param thresholdSignatureScheme - The threshold signature scheme to use
|
|
103
|
+
* @param password - Optional password for encrypted backup
|
|
104
|
+
* @param onError - Optional error callback
|
|
105
|
+
* @param signedSessionId - The signed session ID
|
|
106
|
+
* @param publicAddressCheck - Optional address to validate against
|
|
107
|
+
* @param addressType - Bitcoin address type (NATIVE_SEGWIT or TAPROOT)
|
|
108
|
+
* @returns The account address, public key hex, and raw public key
|
|
109
|
+
*/
|
|
110
|
+
importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password, onError, signedSessionId, publicAddressCheck, addressType, }: {
|
|
111
|
+
privateKey: string;
|
|
112
|
+
chainName: string;
|
|
113
|
+
thresholdSignatureScheme: ThresholdSignatureScheme;
|
|
114
|
+
password?: string;
|
|
115
|
+
onError?: (error: Error) => void;
|
|
116
|
+
signedSessionId: string;
|
|
117
|
+
publicAddressCheck?: string;
|
|
118
|
+
addressType?: string;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
accountAddress: string;
|
|
121
|
+
publicKeyHex: string;
|
|
122
|
+
rawPublicKey: EcdsaPublicKey | BIP340KeygenResult | Uint8Array | string | undefined;
|
|
123
|
+
}>;
|
|
98
124
|
/**
|
|
99
125
|
* Converts MPC private key to Bitcoin WIF (Wallet Import Format)
|
|
100
126
|
* Uses the utility function from utils.ts for the core conversion logic
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calculateBip322Hash.d.ts","sourceRoot":"","sources":["../../../src/utils/calculateBip322Hash/calculateBip322Hash.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"calculateBip322Hash.d.ts","sourceRoot":"","sources":["../../../src/utils/calculateBip322Hash/calculateBip322Hash.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGlE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,YACrB,MAAM,UACP,GAAG,eACE,kBAAkB,WACtB,cAAc,KACtB;IAAE,gBAAgB,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,GAAG,CAAA;CAoEjD,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Psbt } from 'bitcoinjs-lib';
|
|
2
|
+
import type { BitcoinNetwork } from '../../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Checks if a PSBT input belongs to a specific address
|
|
5
|
+
* @param input - The PSBT input (from psbt.data.inputs)
|
|
6
|
+
* @param address - The address to check against
|
|
7
|
+
* @param network - The Bitcoin network
|
|
8
|
+
* @returns True if the input belongs to the address, false otherwise
|
|
9
|
+
*/
|
|
10
|
+
export declare const doesInputBelongToAddress: (input: Psbt["data"]["inputs"][number], address: string, network: BitcoinNetwork) => boolean;
|
|
11
|
+
//# sourceMappingURL=doesInputBelongToAddress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doesInputBelongToAddress.d.ts","sourceRoot":"","sources":["../../../src/utils/doesInputBelongToAddress/doesInputBelongToAddress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,UAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAC5B,MAAM,WACN,cAAc,KACtB,OAwCF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/doesInputBelongToAddress/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encodeBip322Signature.d.ts","sourceRoot":"","sources":["../../../src/utils/encodeBip322Signature/encodeBip322Signature.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"encodeBip322Signature.d.ts","sourceRoot":"","sources":["../../../src/utils/encodeBip322Signature/encodeBip322Signature.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,eACpB,GAAG,UACP,GAAG,aACA,cAAc,GAAG,UAAU,eACzB,kBAAkB,KAC9B,MAgDF,CAAC"}
|
package/src/utils/getAddressTypeFromDerivationPath/getAddressTypeFromDerivationPath.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getAddressTypeFromDerivationPath.d.ts","sourceRoot":"","sources":["../../../src/utils/getAddressTypeFromDerivationPath/getAddressTypeFromDerivationPath.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getAddressTypeFromDerivationPath.d.ts","sourceRoot":"","sources":["../../../src/utils/getAddressTypeFromDerivationPath/getAddressTypeFromDerivationPath.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,sBACxB,MAAM,KACxB,kBAyBF,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BitcoinAddressType } from '@dynamic-labs-wallet/browser';
|
|
2
|
+
import type { BitcoinNetwork } from '../../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Derives a public key from a private key (WIF format) based on address type
|
|
5
|
+
*
|
|
6
|
+
* - For NATIVE_SEGWIT (ECDSA): Returns compressed public key (33 bytes)
|
|
7
|
+
* - For TAPROOT (BIP340): Returns x-only public key (32 bytes)
|
|
8
|
+
*
|
|
9
|
+
* @param privateKey - Private key in WIF format (Base58 encoded)
|
|
10
|
+
* @param addressType - Bitcoin address type (NATIVE_SEGWIT or TAPROOT)
|
|
11
|
+
* @param network - Bitcoin network (mainnet, testnet)
|
|
12
|
+
* @returns Public key as Buffer (33 bytes for NATIVE_SEGWIT, 32 bytes for TAPROOT)
|
|
13
|
+
* @throws Error if private key is invalid or derivation fails
|
|
14
|
+
*/
|
|
15
|
+
export declare const getPublicKeyFromPrivateKey: (privateKey: string, addressType: BitcoinAddressType, network?: BitcoinNetwork) => Promise<Buffer>;
|
|
16
|
+
//# sourceMappingURL=getPublicKeyFromPrivateKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getPublicKeyFromPrivateKey.d.ts","sourceRoot":"","sources":["../../../src/utils/getPublicKeyFromPrivateKey/getPublicKeyFromPrivateKey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B,eACzB,MAAM,eACL,kBAAkB,YACtB,cAAc,KACtB,OAAO,CAAC,MAAM,CAsChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/getPublicKeyFromPrivateKey/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC"}
|
package/src/utils/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export { getAddressTypeFromDerivationPath } from './getAddressTypeFromDerivation
|
|
|
4
4
|
export { calculateBip322Hash } from './calculateBip322Hash/index.js';
|
|
5
5
|
export { encodeBip322Signature } from './encodeBip322Signature/index.js';
|
|
6
6
|
export { privateKeyToWIF } from './privateKeyToWIF/index.js';
|
|
7
|
+
export { wifToPrivateKey } from './wifToPrivateKey/index.js';
|
|
8
|
+
export { getPublicKeyFromPrivateKey } from './getPublicKeyFromPrivateKey/index.js';
|
|
7
9
|
export { convertSignatureToDER } from './convertSignatureToDER/index.js';
|
|
8
10
|
export { getUTXOs } from './getUTXOs/index.js';
|
|
9
11
|
export { selectUTXOs } from './selectUTXOs/index.js';
|
|
@@ -12,4 +14,5 @@ export { getDefaultRpcUrl } from './getDefaultRpcUrl/index.js';
|
|
|
12
14
|
export { calculateTaprootTweak } from './calculateTaprootTweak/index.js';
|
|
13
15
|
export { convertSignatureToTaprootBuffer } from './convertSignatureToTaprootBuffer/index.js';
|
|
14
16
|
export { collectPSBTInputData } from './collectPSBTInputData/index.js';
|
|
17
|
+
export { doesInputBelongToAddress } from './doesInputBelongToAddress/index.js';
|
|
15
18
|
//# sourceMappingURL=index.d.ts.map
|
package/src/utils/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,+BAA+B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,+BAA+B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { BitcoinAddressType } from '@dynamic-labs-wallet/browser';
|
|
1
|
+
import { type EcdsaPublicKey, BitcoinAddressType } from '@dynamic-labs-wallet/browser';
|
|
3
2
|
/**
|
|
4
3
|
* Normalizes a public key to a standard Buffer format
|
|
5
4
|
* Handles various input types (Uint8Array, Buffer, object with pubKeyAsHex, etc.)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizePublicKey.d.ts","sourceRoot":"","sources":["../../../src/utils/normalizePublicKey/normalizePublicKey.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"normalizePublicKey.d.ts","sourceRoot":"","sources":["../../../src/utils/normalizePublicKey/normalizePublicKey.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,cAAc,EACnB,kBAAkB,EACnB,MAAM,8BAA8B,CAAC;AAMtC;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,WACrB,cAAc,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,gBACvC,kBAAkB,KAC/B,MAQF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publicKeyToBitcoinAddress.d.ts","sourceRoot":"","sources":["../../../src/utils/publicKeyToBitcoinAddress/publicKeyToBitcoinAddress.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"publicKeyToBitcoinAddress.d.ts","sourceRoot":"","sources":["../../../src/utils/publicKeyToBitcoinAddress/publicKeyToBitcoinAddress.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM3D;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,cACzB,MAAM,GAAG,UAAU,gBACjB,kBAAkB,YACtB,cAAc,KACtB,MAeF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/wifToPrivateKey/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BitcoinNetwork } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Converts a Bitcoin WIF (Wallet Import Format) private key to hex format
|
|
4
|
+
* This is the reverse operation of `privateKeyToWIF`
|
|
5
|
+
*
|
|
6
|
+
* WIF decoding steps:
|
|
7
|
+
* 1. Base58 decode the WIF string
|
|
8
|
+
* 2. Validate network prefix
|
|
9
|
+
* 3. Validate checksum (double SHA-256, first 4 bytes)
|
|
10
|
+
* 4. Extract private key bytes (skip prefix, compression flag, and checksum)
|
|
11
|
+
* 5. Convert to hex string
|
|
12
|
+
*
|
|
13
|
+
* @param wif - Private key in WIF format (Base58 encoded)
|
|
14
|
+
* @param network - Bitcoin network (mainnet, testnet)
|
|
15
|
+
* @returns Private key as hex string (64 characters, 32 bytes)
|
|
16
|
+
* @throws Error if WIF format is invalid
|
|
17
|
+
*/
|
|
18
|
+
export declare const wifToPrivateKey: (wif: string, network?: BitcoinNetwork) => string;
|
|
19
|
+
//# sourceMappingURL=wifToPrivateKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wifToPrivateKey.d.ts","sourceRoot":"","sources":["../../../src/utils/wifToPrivateKey/wifToPrivateKey.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,QACrB,MAAM,YACF,cAAc,KACtB,MAkDF,CAAC"}
|