@anywalletkit/wallet-btc 0.2.2 → 0.2.4
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/{chunk-KAAQYL5X.js → chunk-4WUAN3DC.js} +2 -2
- package/dist/{chunk-KAAQYL5X.js.map → chunk-4WUAN3DC.js.map} +1 -1
- package/dist/history.cjs +1 -1
- package/dist/history.cjs.map +1 -1
- package/dist/history.js +1 -1
- package/dist/index.cjs +36 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +23 -22
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
package/dist/index.cjs
CHANGED
|
@@ -588,6 +588,7 @@ var DUST_LIMIT_P2TR = dustLimit("tr");
|
|
|
588
588
|
var kindOfType = (type) => type === "p2tr" ? "tr" : "wpkh";
|
|
589
589
|
|
|
590
590
|
// src/describe.ts
|
|
591
|
+
var import_core7 = require("@anywalletkit/core");
|
|
591
592
|
var DEFAULT_MAX_FEE_RATE = 500;
|
|
592
593
|
var RBF_SEQUENCE = 4294967293;
|
|
593
594
|
var FINAL_SEQUENCE = 4294967294;
|
|
@@ -622,7 +623,7 @@ function describeTransaction(tx, inputValues, ctx) {
|
|
|
622
623
|
const fee = inputSum - outputSum;
|
|
623
624
|
const amount = outputs.filter((o) => o.role !== "change").reduce((s, o) => s + o.value, 0n);
|
|
624
625
|
const vsize = vsizeOf(tx);
|
|
625
|
-
const feeRate = vsize > 0 ? Math.round(
|
|
626
|
+
const feeRate = vsize > 0 ? Math.round((0, import_core7.bigintToNumber)(fee) / vsize * 100) / 100 : 0;
|
|
626
627
|
if (feeRate > (ctx.maxFeeRate ?? DEFAULT_MAX_FEE_RATE)) warnings.add("high-fee-rate");
|
|
627
628
|
if (amount > 0n && fee * 10n > amount) warnings.add("fee-over-10pct-of-amount");
|
|
628
629
|
if (!outputs.some((o) => o.role === "change")) warnings.add("no-change");
|
|
@@ -668,7 +669,7 @@ var coinType = (network) => network === "bitcoin" ? 0 : 1;
|
|
|
668
669
|
var purposeFor = (type) => type === "p2tr" ? 86 : 84;
|
|
669
670
|
|
|
670
671
|
// src/read-only-account.ts
|
|
671
|
-
var
|
|
672
|
+
var import_core8 = require("@anywalletkit/core");
|
|
672
673
|
var toBig = (v) => typeof v === "bigint" ? v : BigInt(Math.round(Number(v)));
|
|
673
674
|
var WalletAccountReadOnlyBtc = class {
|
|
674
675
|
/** The address. */
|
|
@@ -700,7 +701,7 @@ var WalletAccountReadOnlyBtc = class {
|
|
|
700
701
|
this._client = createClient(config);
|
|
701
702
|
}
|
|
702
703
|
requireClient(what) {
|
|
703
|
-
if (!this._client) throw new
|
|
704
|
+
if (!this._client) throw new import_core8.NetworkError(`The wallet must be connected to a client to ${what}.`);
|
|
704
705
|
return this._client;
|
|
705
706
|
}
|
|
706
707
|
/** Fee-rate ceiling in sat/vB: `BtcConfig.maxFeeRate` or {@link DEFAULT_MAX_FEE_RATE}. */
|
|
@@ -742,7 +743,7 @@ var WalletAccountReadOnlyBtc = class {
|
|
|
742
743
|
const inputWeight = this.inputWeight();
|
|
743
744
|
const feeRate = await this.resolveFeeRate(spend);
|
|
744
745
|
const utxos = await this.requireClient("plan a spend").listUnspent(this.address);
|
|
745
|
-
if (utxos.length === 0) throw new
|
|
746
|
+
if (utxos.length === 0) throw new import_core8.InsufficientFundsError(amount, 0n, "BTC");
|
|
746
747
|
const own = kindOfType(this.addressType);
|
|
747
748
|
const selection = selectCoins({
|
|
748
749
|
utxos,
|
|
@@ -817,7 +818,7 @@ var WalletAccountReadOnlyBtc = class {
|
|
|
817
818
|
};
|
|
818
819
|
|
|
819
820
|
// src/account.ts
|
|
820
|
-
var
|
|
821
|
+
var import_core9 = require("@anywalletkit/core");
|
|
821
822
|
var import_btc_signer4 = require("@scure/btc-signer");
|
|
822
823
|
var import_secp256k12 = require("@noble/curves/secp256k1.js");
|
|
823
824
|
var import_base3 = require("@scure/base");
|
|
@@ -841,15 +842,15 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
841
842
|
const type = config.addressType ?? "p2wpkh";
|
|
842
843
|
super(addressFromPublicKey(publicKey, networkParams(config.network ?? "bitcoin"), type), config);
|
|
843
844
|
this.addressType = type;
|
|
844
|
-
this.signer = (0,
|
|
845
|
+
this.signer = (0, import_core9.requireCurve)(signer, "secp256k1");
|
|
845
846
|
const needed = type === "p2tr" ? "schnorr" : "ecdsa";
|
|
846
|
-
if (!this.signer.schemes.includes(needed)) throw new
|
|
847
|
+
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(", ")}).`);
|
|
847
848
|
this.publicKey = publicKey;
|
|
848
849
|
this.path = path;
|
|
849
850
|
}
|
|
850
851
|
/** Back-compat: wrap a raw derived key in a {@link LocalSigner} (the account takes ownership; it cannot derive). */
|
|
851
852
|
static fromPrivateKey(privateKey, publicKey, path, config = {}) {
|
|
852
|
-
return new _WalletAccountBtc(
|
|
853
|
+
return new _WalletAccountBtc(import_core9.LocalSigner.fromPrivateKey("secp256k1", privateKey, publicKey, path), publicKey, path, config);
|
|
853
854
|
}
|
|
854
855
|
/** Account index for the standard m/{84|86}'/{0|1}'/0'/0/i path. */
|
|
855
856
|
get index() {
|
|
@@ -857,7 +858,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
857
858
|
return m ? Number(m[1]) : void 0;
|
|
858
859
|
}
|
|
859
860
|
live() {
|
|
860
|
-
if (this._disposed) throw new
|
|
861
|
+
if (this._disposed) throw new import_core9.SignerError("This account has been disposed.");
|
|
861
862
|
}
|
|
862
863
|
/** BIP-137 p2wpkh signature, base64 (Electrum / Bitcoin Core encoding). Not available for taproot accounts. */
|
|
863
864
|
async sign(message) {
|
|
@@ -932,7 +933,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
932
933
|
const delta = required - fee;
|
|
933
934
|
if (change === 0n) {
|
|
934
935
|
const have = plan.utxos.reduce((s, u) => s + u.value, 0n);
|
|
935
|
-
throw new
|
|
936
|
+
throw new import_core9.InsufficientFundsError(plan.amount + required, have, "BTC");
|
|
936
937
|
}
|
|
937
938
|
change = change - delta;
|
|
938
939
|
if (change < this.dustLimit) {
|
|
@@ -1012,19 +1013,23 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
1012
1013
|
if (typeof tx === "string") return (await this.describeRaw(tx)).desc;
|
|
1013
1014
|
return (await this.buildSignedTransaction(tx)).desc;
|
|
1014
1015
|
}
|
|
1015
|
-
/** Sign without broadcasting. Returns the raw transaction hex. Raw hex input is returned unchanged. */
|
|
1016
|
-
async signTransaction(tx) {
|
|
1016
|
+
/** Sign without broadcasting. Returns the raw transaction hex. Raw hex input gets the checks `sendTransaction` runs (prevouts through the client) and is returned unchanged, never re-signed. */
|
|
1017
|
+
async signTransaction(tx, options = {}) {
|
|
1017
1018
|
this.live();
|
|
1018
|
-
if (typeof tx === "string")
|
|
1019
|
+
if (typeof tx === "string") {
|
|
1020
|
+
const { desc } = await this.describeRaw(tx);
|
|
1021
|
+
this.checkMax(desc.fee, (0, import_core9.feeLimit)(this._config.transactionMaxFee, options), "transaction");
|
|
1022
|
+
return tx;
|
|
1023
|
+
}
|
|
1019
1024
|
const { tx: built, fee } = await this.buildSignedTransaction(tx);
|
|
1020
|
-
this.checkMax(fee, this._config.transactionMaxFee, "transaction");
|
|
1025
|
+
this.checkMax(fee, (0, import_core9.feeLimit)(this._config.transactionMaxFee, options), "transaction");
|
|
1021
1026
|
return built.hex;
|
|
1022
1027
|
}
|
|
1023
1028
|
async quoteSendTransaction(tx) {
|
|
1024
1029
|
if (typeof tx === "string") return { fee: (await this.describeRaw(tx)).desc.fee };
|
|
1025
1030
|
return super.quoteSendTransaction(tx);
|
|
1026
1031
|
}
|
|
1027
|
-
async sendTransaction(tx) {
|
|
1032
|
+
async sendTransaction(tx, options = {}) {
|
|
1028
1033
|
this.live();
|
|
1029
1034
|
const client = this.requireClient("send transactions");
|
|
1030
1035
|
let rawHex, hash, fee;
|
|
@@ -1039,17 +1044,17 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
1039
1044
|
hash = built.tx.id;
|
|
1040
1045
|
fee = built.fee;
|
|
1041
1046
|
}
|
|
1042
|
-
this.checkMax(fee, this._config.transactionMaxFee, "transaction");
|
|
1047
|
+
this.checkMax(fee, (0, import_core9.feeLimit)(this._config.transactionMaxFee, options), "transaction");
|
|
1043
1048
|
const txid = await client.broadcast(rawHex);
|
|
1044
1049
|
return { hash: txid || hash, fee };
|
|
1045
1050
|
}
|
|
1046
1051
|
/** Native BTC only (`token` is rejected). Subject to `transferMaxFee`. */
|
|
1047
|
-
async transfer(o) {
|
|
1052
|
+
async transfer(o, writeOptions = {}) {
|
|
1048
1053
|
if (o.token) throw new Error("Tokens are not supported on the bitcoin blockchain.");
|
|
1049
1054
|
this.live();
|
|
1050
1055
|
const client = this.requireClient("transfer");
|
|
1051
1056
|
const built = await this.buildSignedTransaction({ to: o.recipient, value: o.amount });
|
|
1052
|
-
this.checkMax(built.fee, this._config.transferMaxFee, "transfer");
|
|
1057
|
+
this.checkMax(built.fee, (0, import_core9.feeLimit)(this._config.transferMaxFee, writeOptions), "transfer");
|
|
1053
1058
|
const txid = await client.broadcast(built.tx.hex);
|
|
1054
1059
|
return { hash: txid || built.tx.id, fee: built.fee };
|
|
1055
1060
|
}
|
|
@@ -1065,8 +1070,8 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
|
|
|
1065
1070
|
};
|
|
1066
1071
|
|
|
1067
1072
|
// src/manager.ts
|
|
1068
|
-
var
|
|
1069
|
-
var WalletManagerBtc = class extends
|
|
1073
|
+
var import_core10 = require("@anywalletkit/core");
|
|
1074
|
+
var WalletManagerBtc = class extends import_core10.WalletManager {
|
|
1070
1075
|
constructor(seedOrSigner, config = {}) {
|
|
1071
1076
|
super(seedOrSigner, config);
|
|
1072
1077
|
}
|
|
@@ -1086,30 +1091,26 @@ var WalletManagerBtc = class extends import_core9.WalletManager {
|
|
|
1086
1091
|
if (cached) return cached;
|
|
1087
1092
|
const external = this.externalSigner();
|
|
1088
1093
|
if (external) return this.fromSigner(external, full);
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1094
|
+
return this.cachedAccount(full, () => {
|
|
1095
|
+
const signer = import_core10.LocalSigner.leafFromSeed(this.seedBytes(), "secp256k1", full);
|
|
1096
|
+
return new WalletAccountBtc(signer, signer.publicKey, full, this._config);
|
|
1097
|
+
});
|
|
1093
1098
|
}
|
|
1094
1099
|
/** Resolve `path` against an injected signer: the signer itself, or a child when it can derive there. */
|
|
1095
1100
|
async fromSigner(signer, path) {
|
|
1096
1101
|
this.requireSigner("secp256k1");
|
|
1097
|
-
let
|
|
1102
|
+
let rel;
|
|
1098
1103
|
let key = "external";
|
|
1099
|
-
if ((0,
|
|
1104
|
+
if ((0, import_core10.isSeedSigner)(signer)) {
|
|
1100
1105
|
if (path === signer.path) key = path;
|
|
1101
1106
|
else if (path.startsWith(`${signer.path}/`)) {
|
|
1102
|
-
|
|
1107
|
+
rel = path.slice(signer.path.length + 1);
|
|
1103
1108
|
key = path;
|
|
1104
|
-
} else throw new
|
|
1109
|
+
} else throw new import_core10.SignerError(`The injected signer sits at ${signer.path}; it cannot provide ${path}.`);
|
|
1105
1110
|
} else if (path !== `${this.basePath}/0'/0/0` && path !== "external") {
|
|
1106
|
-
throw new
|
|
1111
|
+
throw new import_core10.SignerError(`An external signer has one account; ${path} is not derivable from it.`);
|
|
1107
1112
|
}
|
|
1108
|
-
|
|
1109
|
-
if (cached) return cached;
|
|
1110
|
-
const account = new WalletAccountBtc(leaf, await leaf.getPublicKey(), key, this._config);
|
|
1111
|
-
this._accounts.set(key, account);
|
|
1112
|
-
return account;
|
|
1113
|
+
return this.signerAccount(key, signer, rel, (leaf, publicKey) => new WalletAccountBtc(leaf, publicKey, key, this._config));
|
|
1113
1114
|
}
|
|
1114
1115
|
/** A read-only account for any address, with this manager's config. */
|
|
1115
1116
|
getReadOnlyAccount(address) {
|
|
@@ -1251,7 +1252,7 @@ function createBtcHistory(options = {}) {
|
|
|
1251
1252
|
const pageNo = cursor?.p ?? 1;
|
|
1252
1253
|
const data = await failover((c) => c.getAddressPage(address, pageNo, pageSize));
|
|
1253
1254
|
let items = (data.transactions ?? []).map((tx) => mapBlockbookTx(chain, address, tx));
|
|
1254
|
-
items.sort((a, b) => (b.block === void 0 ? 1 : a.block === void 0 ? -1 :
|
|
1255
|
+
items.sort((a, b) => (b.block === void 0 ? 1 : a.block === void 0 ? -1 : b.block > a.block ? 1 : b.block < a.block ? -1 : 0) || b.time - a.time);
|
|
1255
1256
|
const totalPages = data.totalPages ?? 1;
|
|
1256
1257
|
let more = pageNo < totalPages;
|
|
1257
1258
|
if (query.since !== void 0) {
|