@anywalletkit/wallet-zcash 0.4.0 → 0.5.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 +33 -8
- 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 +33 -8
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -985,7 +985,24 @@ var import_secp256k12 = require("@noble/curves/secp256k1.js");
|
|
|
985
985
|
|
|
986
986
|
// src/read-only-account.ts
|
|
987
987
|
var import_core6 = require("@anywalletkit/core");
|
|
988
|
+
function assertSpendShape(spend) {
|
|
989
|
+
const proto = typeof spend === "object" && spend !== null && !Array.isArray(spend) ? Object.getPrototypeOf(spend) : void 0;
|
|
990
|
+
if (proto === void 0 || proto !== null && Object.getPrototypeOf(proto) !== null) {
|
|
991
|
+
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.");
|
|
992
|
+
}
|
|
993
|
+
}
|
|
988
994
|
var toBig = (v) => typeof v === "bigint" ? v : BigInt(typeof v === "string" ? v.trim() : Math.round(v));
|
|
995
|
+
function spendValue(v) {
|
|
996
|
+
if (typeof v === "bigint") return v;
|
|
997
|
+
if (typeof v === "number" && Number.isInteger(v)) return BigInt(v);
|
|
998
|
+
if (typeof v === "string" && v.length <= 300 && !/\s/.test(v)) {
|
|
999
|
+
try {
|
|
1000
|
+
return BigInt(v);
|
|
1001
|
+
} catch {
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
throw new UnsafeTransactionError("malformed-spend", "A spend value must be a bigint, a whole number or an integer string of at most 300 characters (zatoshis).");
|
|
1005
|
+
}
|
|
989
1006
|
var WalletAccountReadOnlyZcash = class {
|
|
990
1007
|
/** The transparent address. */
|
|
991
1008
|
address;
|
|
@@ -1030,8 +1047,9 @@ var WalletAccountReadOnlyZcash = class {
|
|
|
1030
1047
|
}
|
|
1031
1048
|
/** Coin selection for a spend (ZIP-317 fee). Validates the recipient and the dust floor first. */
|
|
1032
1049
|
async planSpend(spend) {
|
|
1050
|
+
assertSpendShape(spend);
|
|
1033
1051
|
if (this.scriptKind !== "p2pkh") throw new Error(`Cannot build spends from a ${this.scriptKind} address; only P2PKH (t1\u2026) accounts spend.`);
|
|
1034
|
-
const amount =
|
|
1052
|
+
const amount = spendValue(spend.value);
|
|
1035
1053
|
const recipient = decodeAddress(spend.to, this._network);
|
|
1036
1054
|
if (amount < DUST_LIMIT) throw new Error(`The amount must be at least the dust limit (${DUST_LIMIT} zatoshis).`);
|
|
1037
1055
|
const utxos = await this.requireClient("plan a spend").listUnspent(this.address);
|
|
@@ -1104,15 +1122,22 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
1104
1122
|
path;
|
|
1105
1123
|
/** Compressed secp256k1 public key. */
|
|
1106
1124
|
publicKey;
|
|
1107
|
-
/**
|
|
1108
|
-
|
|
1125
|
+
/**
|
|
1126
|
+
* The signer that holds the key, in a private field: not a property of the account, so no code
|
|
1127
|
+
* the account is handed to (a protocol module, a logger) can reach it and sign around the
|
|
1128
|
+
* account's checks (audit 2026-10-29 A1).
|
|
1129
|
+
*/
|
|
1130
|
+
#signer;
|
|
1131
|
+
/** What holds the key: `seed`, `key` (one imported key) or `external`. */
|
|
1132
|
+
signerKind;
|
|
1109
1133
|
_disposed = false;
|
|
1110
1134
|
_readOnly;
|
|
1111
1135
|
/** `publicKey` is the signer's compressed secp256k1 key (33 bytes); it is needed synchronously for the address. */
|
|
1112
1136
|
constructor(signer, publicKey, path, config = {}) {
|
|
1113
1137
|
super(addressFromPublicKey(publicKey, config.network ?? "mainnet"), config);
|
|
1114
|
-
this
|
|
1115
|
-
|
|
1138
|
+
this.#signer = (0, import_core7.requireCurve)(signer, "secp256k1");
|
|
1139
|
+
this.signerKind = this.#signer.kind;
|
|
1140
|
+
if (!this.#signer.schemes.includes("ecdsa")) throw new import_core7.SignerError(`A Zcash account needs a signer with the 'ecdsa' scheme (has: ${this.#signer.schemes.join(", ")}).`);
|
|
1116
1141
|
this.publicKey = publicKey;
|
|
1117
1142
|
this.path = path;
|
|
1118
1143
|
}
|
|
@@ -1131,7 +1156,7 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
1131
1156
|
/** Zcash message signature (zcashd `signmessage` encoding), base64. */
|
|
1132
1157
|
async sign(message) {
|
|
1133
1158
|
this.live();
|
|
1134
|
-
return signMessageWith(message, this
|
|
1159
|
+
return signMessageWith(message, this.#signer);
|
|
1135
1160
|
}
|
|
1136
1161
|
ctx(intended) {
|
|
1137
1162
|
return { network: this._network, ownAddress: this.address, intended, maxFee: this.maxFee };
|
|
@@ -1163,7 +1188,7 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
1163
1188
|
async #signInputs(tx, spent) {
|
|
1164
1189
|
for (let i = 0; i < tx.inputs.length; i++) {
|
|
1165
1190
|
const digest = sighashAll(tx, i, spent);
|
|
1166
|
-
const rs = await this
|
|
1191
|
+
const rs = await this.#signer.sign(digest, { scheme: "ecdsa", context: "zcash-sighash" });
|
|
1167
1192
|
const der = import_secp256k12.secp256k1.Signature.fromBytes(rs, "compact").toBytes("der");
|
|
1168
1193
|
tx.inputs[i].scriptSig = p2pkhScriptSig(der, this.publicKey);
|
|
1169
1194
|
}
|
|
@@ -1278,7 +1303,7 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
1278
1303
|
}
|
|
1279
1304
|
dispose() {
|
|
1280
1305
|
this._disposed = true;
|
|
1281
|
-
this
|
|
1306
|
+
this.#signer.dispose();
|
|
1282
1307
|
}
|
|
1283
1308
|
};
|
|
1284
1309
|
|