@anywalletkit/wallet-btc 0.3.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +34 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +34 -9
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -722,7 +722,24 @@ var purposeFor = (type) => type === "p2tr" ? 86 : 84;
|
|
|
722
722
|
|
|
723
723
|
// src/read-only-account.ts
|
|
724
724
|
var import_core8 = require("@anywalletkit/core");
|
|
725
|
+
function assertSpendShape(spend) {
|
|
726
|
+
const proto = typeof spend === "object" && spend !== null && !Array.isArray(spend) ? Object.getPrototypeOf(spend) : void 0;
|
|
727
|
+
if (proto === void 0 || proto !== null && Object.getPrototypeOf(proto) !== null) {
|
|
728
|
+
throw new UnsafeTransactionError("malformed-spend", "A spend must be one plain object ({ to, value, \u2026 }); a list or another kind of object is not signed.");
|
|
729
|
+
}
|
|
730
|
+
}
|
|
725
731
|
var toBig = (v) => typeof v === "bigint" ? v : BigInt(Math.round(Number(v)));
|
|
732
|
+
function spendValue(v) {
|
|
733
|
+
if (typeof v === "bigint") return v;
|
|
734
|
+
if (typeof v === "number" && Number.isInteger(v)) return BigInt(v);
|
|
735
|
+
if (typeof v === "string" && v.length <= 300 && !/\s/.test(v)) {
|
|
736
|
+
try {
|
|
737
|
+
return BigInt(v);
|
|
738
|
+
} catch {
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
throw new UnsafeTransactionError("malformed-spend", "A spend value must be a bigint, a whole number or an integer string of at most 300 characters (sats).");
|
|
742
|
+
}
|
|
726
743
|
var WalletAccountReadOnlyBtc = class {
|
|
727
744
|
/** The address. */
|
|
728
745
|
address;
|
|
@@ -788,7 +805,8 @@ var WalletAccountReadOnlyBtc = class {
|
|
|
788
805
|
}
|
|
789
806
|
/** Coin selection for a spend (see coinselect.ts). Validates the recipient and the dust floor first. */
|
|
790
807
|
async planSpend(spend) {
|
|
791
|
-
|
|
808
|
+
assertSpendShape(spend);
|
|
809
|
+
const amount = spendValue(spend.value);
|
|
792
810
|
const recipient = decodeAddress(spend.to, this._network);
|
|
793
811
|
const floor = dustLimit(recipient.kind);
|
|
794
812
|
if (amount < floor) throw new Error(`The amount must be at least the dust limit of the recipient's address type (${floor} sat).`);
|
|
@@ -885,8 +903,14 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
885
903
|
/** Compressed secp256k1 public key. */
|
|
886
904
|
publicKey;
|
|
887
905
|
addressType;
|
|
888
|
-
/**
|
|
889
|
-
|
|
906
|
+
/**
|
|
907
|
+
* The signer that holds the key, in a private field: not a property of the account, so no code
|
|
908
|
+
* the account is handed to (a protocol module, a logger) can reach it and sign around the
|
|
909
|
+
* account's checks (audit 2026-10-29 A1).
|
|
910
|
+
*/
|
|
911
|
+
#signer;
|
|
912
|
+
/** What holds the key: `seed`, `key` (one imported key) or `external`. */
|
|
913
|
+
signerKind;
|
|
890
914
|
_disposed = false;
|
|
891
915
|
_readOnly;
|
|
892
916
|
/** `publicKey` is the signer's compressed secp256k1 key (33 bytes); it is needed synchronously for the address. */
|
|
@@ -894,9 +918,10 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
894
918
|
const type = config.addressType ?? "p2wpkh";
|
|
895
919
|
super(addressFromPublicKey(publicKey, networkParams(config.network ?? "bitcoin"), type), config);
|
|
896
920
|
this.addressType = type;
|
|
897
|
-
this
|
|
921
|
+
this.#signer = (0, import_core9.requireCurve)(signer, "secp256k1");
|
|
922
|
+
this.signerKind = this.#signer.kind;
|
|
898
923
|
const needed = type === "p2tr" ? "schnorr" : "ecdsa";
|
|
899
|
-
if (!this
|
|
924
|
+
if (!this.#signer.schemes.includes(needed)) throw new import_core9.SignerError(`A ${type} account needs a signer with the '${needed}' scheme (has: ${this.#signer.schemes.join(", ")}).`);
|
|
900
925
|
this.publicKey = publicKey;
|
|
901
926
|
this.path = path;
|
|
902
927
|
}
|
|
@@ -916,7 +941,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
916
941
|
async sign(message) {
|
|
917
942
|
this.live();
|
|
918
943
|
if (this.addressType === "p2tr") throw new UnsupportedAddressTypeError("BIP-137 message signatures do not exist for taproot accounts (BIP-322 is not implemented).");
|
|
919
|
-
return signMessageWith(message, this
|
|
944
|
+
return signMessageWith(message, this.#signer, "p2wpkh");
|
|
920
945
|
}
|
|
921
946
|
/** The x-only internal key and its BIP-86 tweak (no script tree) for taproot key-path spends. */
|
|
922
947
|
taprootKeys() {
|
|
@@ -934,7 +959,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
934
959
|
const scripts = Array.from({ length: tx.inputsLength }, () => this.scriptPubKey);
|
|
935
960
|
for (let i = 0; i < tx.inputsLength; i++) {
|
|
936
961
|
const sighash = tx.preimageWitnessV1(i, scripts, import_btc_signer4.SigHash.DEFAULT, values);
|
|
937
|
-
const sig = await this
|
|
962
|
+
const sig = await this.#signer.sign(sighash, { scheme: "schnorr", context: "btc-taproot-keypath", tweak });
|
|
938
963
|
tx.updateInput(i, { tapKeySig: sig }, true);
|
|
939
964
|
}
|
|
940
965
|
return;
|
|
@@ -942,7 +967,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
942
967
|
const scriptCode = (0, import_btc_signer4.p2pkh)(this.publicKey).script;
|
|
943
968
|
for (let i = 0; i < tx.inputsLength; i++) {
|
|
944
969
|
const sighash = tx.preimageWitnessV0(i, scriptCode, import_btc_signer4.SigHash.ALL, values[i]);
|
|
945
|
-
const rs = await this
|
|
970
|
+
const rs = await this.#signer.sign(sighash, { scheme: "ecdsa", context: "btc-sighash" });
|
|
946
971
|
const der = import_secp256k12.secp256k1.Signature.fromBytes(rs, "compact").toBytes("der");
|
|
947
972
|
const sig = new Uint8Array(der.length + 1);
|
|
948
973
|
sig.set(der, 0);
|
|
@@ -1129,7 +1154,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
1129
1154
|
}
|
|
1130
1155
|
dispose() {
|
|
1131
1156
|
this._disposed = true;
|
|
1132
|
-
this
|
|
1157
|
+
this.#signer.dispose();
|
|
1133
1158
|
}
|
|
1134
1159
|
};
|
|
1135
1160
|
|