@anywalletkit/wallet-zcash 0.3.1 → 0.5.0
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 +23 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -5
- package/dist/index.d.ts +3 -5
- package/dist/index.js +23 -15
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -368,14 +368,15 @@ interface Built {
|
|
|
368
368
|
* ownership) before signing AND before broadcast — also for caller-supplied raw hex.
|
|
369
369
|
*/
|
|
370
370
|
declare class WalletAccountZcash extends WalletAccountReadOnlyZcash implements IWalletAccount {
|
|
371
|
+
#private;
|
|
371
372
|
/** UTXOs and the tip height come from the network before signing. */
|
|
372
373
|
readonly needsNetwork = true;
|
|
373
374
|
/** Derivation path, or `external` for an external signer. */
|
|
374
375
|
readonly path: string;
|
|
375
376
|
/** Compressed secp256k1 public key. */
|
|
376
377
|
readonly publicKey: Uint8Array;
|
|
377
|
-
/**
|
|
378
|
-
readonly
|
|
378
|
+
/** What holds the key: `seed`, `key` (one imported key) or `external`. */
|
|
379
|
+
readonly signerKind: Signer['kind'];
|
|
379
380
|
private _disposed;
|
|
380
381
|
private _readOnly;
|
|
381
382
|
/** `publicKey` is the signer's compressed secp256k1 key (33 bytes); it is needed synchronously for the address. */
|
|
@@ -396,9 +397,6 @@ declare class WalletAccountZcash extends WalletAccountReadOnlyZcash implements I
|
|
|
396
397
|
* transaction signed with expiry 0 never expires.
|
|
397
398
|
*/
|
|
398
399
|
private chainParams;
|
|
399
|
-
/** Sign every input through the signer; the scriptSig is `<DER ‖ 0x01> <pubkey>`. */
|
|
400
|
-
private signInputs;
|
|
401
|
-
protected signSpend(spend: ZcashSpend): Promise<Built>;
|
|
402
400
|
private checkMax;
|
|
403
401
|
/** The outputs a raw transaction spends, fetched through the client (the wire format carries no values). */
|
|
404
402
|
private spentOutputs;
|
package/dist/index.d.ts
CHANGED
|
@@ -368,14 +368,15 @@ interface Built {
|
|
|
368
368
|
* ownership) before signing AND before broadcast — also for caller-supplied raw hex.
|
|
369
369
|
*/
|
|
370
370
|
declare class WalletAccountZcash extends WalletAccountReadOnlyZcash implements IWalletAccount {
|
|
371
|
+
#private;
|
|
371
372
|
/** UTXOs and the tip height come from the network before signing. */
|
|
372
373
|
readonly needsNetwork = true;
|
|
373
374
|
/** Derivation path, or `external` for an external signer. */
|
|
374
375
|
readonly path: string;
|
|
375
376
|
/** Compressed secp256k1 public key. */
|
|
376
377
|
readonly publicKey: Uint8Array;
|
|
377
|
-
/**
|
|
378
|
-
readonly
|
|
378
|
+
/** What holds the key: `seed`, `key` (one imported key) or `external`. */
|
|
379
|
+
readonly signerKind: Signer['kind'];
|
|
379
380
|
private _disposed;
|
|
380
381
|
private _readOnly;
|
|
381
382
|
/** `publicKey` is the signer's compressed secp256k1 key (33 bytes); it is needed synchronously for the address. */
|
|
@@ -396,9 +397,6 @@ declare class WalletAccountZcash extends WalletAccountReadOnlyZcash implements I
|
|
|
396
397
|
* transaction signed with expiry 0 never expires.
|
|
397
398
|
*/
|
|
398
399
|
private chainParams;
|
|
399
|
-
/** Sign every input through the signer; the scriptSig is `<DER ‖ 0x01> <pubkey>`. */
|
|
400
|
-
private signInputs;
|
|
401
|
-
protected signSpend(spend: ZcashSpend): Promise<Built>;
|
|
402
400
|
private checkMax;
|
|
403
401
|
/** The outputs a raw transaction spends, fetched through the client (the wire format carries no values). */
|
|
404
402
|
private spentOutputs;
|
package/dist/index.js
CHANGED
|
@@ -59,7 +59,8 @@ function encodeAddress(kind, hash, network) {
|
|
|
59
59
|
return b58.encode(Uint8Array.of(a, b, ...hash));
|
|
60
60
|
}
|
|
61
61
|
function decodeAddress(address, network) {
|
|
62
|
-
|
|
62
|
+
if (typeof address !== "string" || /\s/.test(address)) throw new Error(`Invalid Zcash address: it carries whitespace or an invisible character (${JSON.stringify(address)}).`);
|
|
63
|
+
const a = address;
|
|
63
64
|
if (/^u1|^utest/i.test(a)) throw new Error(`Unified address (${a.slice(0, 6)}\u2026) \u2014 shielded receivers are not supported; use a transparent t-address.`);
|
|
64
65
|
if (/^zs1|^ztestsapling/i.test(a)) throw new Error("Sapling shielded address (zs1\u2026) \u2014 this wallet sends to transparent t-addresses only.");
|
|
65
66
|
if (/^zc/i.test(a) && a.length > 90) throw new Error("Sprout address (zc\u2026) \u2014 the Sprout pool is deprecated; use a transparent t-address.");
|
|
@@ -732,15 +733,22 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
732
733
|
path;
|
|
733
734
|
/** Compressed secp256k1 public key. */
|
|
734
735
|
publicKey;
|
|
735
|
-
/**
|
|
736
|
-
|
|
736
|
+
/**
|
|
737
|
+
* The signer that holds the key, in a private field: not a property of the account, so no code
|
|
738
|
+
* the account is handed to (a protocol module, a logger) can reach it and sign around the
|
|
739
|
+
* account's checks (audit 2026-10-29 A1).
|
|
740
|
+
*/
|
|
741
|
+
#signer;
|
|
742
|
+
/** What holds the key: `seed`, `key` (one imported key) or `external`. */
|
|
743
|
+
signerKind;
|
|
737
744
|
_disposed = false;
|
|
738
745
|
_readOnly;
|
|
739
746
|
/** `publicKey` is the signer's compressed secp256k1 key (33 bytes); it is needed synchronously for the address. */
|
|
740
747
|
constructor(signer, publicKey, path, config = {}) {
|
|
741
748
|
super(addressFromPublicKey(publicKey, config.network ?? "mainnet"), config);
|
|
742
|
-
this
|
|
743
|
-
|
|
749
|
+
this.#signer = requireCurve(signer, "secp256k1");
|
|
750
|
+
this.signerKind = this.#signer.kind;
|
|
751
|
+
if (!this.#signer.schemes.includes("ecdsa")) throw new SignerError(`A Zcash account needs a signer with the 'ecdsa' scheme (has: ${this.#signer.schemes.join(", ")}).`);
|
|
744
752
|
this.publicKey = publicKey;
|
|
745
753
|
this.path = path;
|
|
746
754
|
}
|
|
@@ -759,7 +767,7 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
759
767
|
/** Zcash message signature (zcashd `signmessage` encoding), base64. */
|
|
760
768
|
async sign(message) {
|
|
761
769
|
this.live();
|
|
762
|
-
return signMessageWith(message, this
|
|
770
|
+
return signMessageWith(message, this.#signer);
|
|
763
771
|
}
|
|
764
772
|
ctx(intended) {
|
|
765
773
|
return { network: this._network, ownAddress: this.address, intended, maxFee: this.maxFee };
|
|
@@ -788,15 +796,15 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
788
796
|
return { lockTime, expiryHeight, consensusBranchId };
|
|
789
797
|
}
|
|
790
798
|
/** Sign every input through the signer; the scriptSig is `<DER ‖ 0x01> <pubkey>`. */
|
|
791
|
-
async signInputs(tx, spent) {
|
|
799
|
+
async #signInputs(tx, spent) {
|
|
792
800
|
for (let i = 0; i < tx.inputs.length; i++) {
|
|
793
801
|
const digest = sighashAll(tx, i, spent);
|
|
794
|
-
const rs = await this
|
|
802
|
+
const rs = await this.#signer.sign(digest, { scheme: "ecdsa", context: "zcash-sighash" });
|
|
795
803
|
const der = secp256k12.Signature.fromBytes(rs, "compact").toBytes("der");
|
|
796
804
|
tx.inputs[i].scriptSig = p2pkhScriptSig(der, this.publicKey);
|
|
797
805
|
}
|
|
798
806
|
}
|
|
799
|
-
async signSpend(spend) {
|
|
807
|
+
async #signSpend(spend) {
|
|
800
808
|
this.live();
|
|
801
809
|
const plan = await this.planSpend(spend);
|
|
802
810
|
const params = await this.chainParams();
|
|
@@ -808,7 +816,7 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
808
816
|
const spent = plan.utxos.map((u) => ({ value: u.value, script: this.scriptPubKey }));
|
|
809
817
|
const have = plan.utxos.reduce((s, u) => s + u.value, 0n);
|
|
810
818
|
if (have < plan.amount + plan.fee) throw new InsufficientFundsError3(plan.amount + plan.fee, have, "ZEC");
|
|
811
|
-
await this
|
|
819
|
+
await this.#signInputs(tx, spent);
|
|
812
820
|
const ctx = this.ctx({ to: spend.to, value: plan.amount });
|
|
813
821
|
const desc = describeTransaction(tx, spent, ctx);
|
|
814
822
|
assertSafe(desc, ctx);
|
|
@@ -840,7 +848,7 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
840
848
|
/** "What you sign": the fully resolved spend (signed, NOT broadcast) or a caller's raw hex. */
|
|
841
849
|
async describeTransaction(tx) {
|
|
842
850
|
if (typeof tx === "string") return (await this.describeRaw(tx)).desc;
|
|
843
|
-
return (await this
|
|
851
|
+
return (await this.#signSpend(tx)).desc;
|
|
844
852
|
}
|
|
845
853
|
/** 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. */
|
|
846
854
|
async signTransaction(tx, options = {}) {
|
|
@@ -850,7 +858,7 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
850
858
|
this.checkMax(desc.fee, feeLimit(this._config.transactionMaxFee, options), "transaction");
|
|
851
859
|
return tx;
|
|
852
860
|
}
|
|
853
|
-
const built = await this
|
|
861
|
+
const built = await this.#signSpend(tx);
|
|
854
862
|
this.checkMax(built.fee, feeLimit(this._config.transactionMaxFee, options), "transaction");
|
|
855
863
|
return built.hex;
|
|
856
864
|
}
|
|
@@ -868,7 +876,7 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
868
876
|
hash = txid(parsed);
|
|
869
877
|
fee = desc.fee;
|
|
870
878
|
} else {
|
|
871
|
-
const built = await this
|
|
879
|
+
const built = await this.#signSpend(tx);
|
|
872
880
|
rawHex = built.hex;
|
|
873
881
|
hash = built.txid;
|
|
874
882
|
fee = built.fee;
|
|
@@ -881,7 +889,7 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
881
889
|
if (o.token) throw new Error("Tokens are not supported on the zcash blockchain.");
|
|
882
890
|
this.live();
|
|
883
891
|
const client = this.requireClient("transfer");
|
|
884
|
-
const built = await this
|
|
892
|
+
const built = await this.#signSpend({ to: o.recipient, value: o.amount });
|
|
885
893
|
this.checkMax(built.fee, feeLimit(this._config.transferMaxFee, writeOptions), "transfer");
|
|
886
894
|
return { hash: await this.broadcast(client, built.hex, built.txid), fee: built.fee };
|
|
887
895
|
}
|
|
@@ -906,7 +914,7 @@ var WalletAccountZcash = class _WalletAccountZcash extends WalletAccountReadOnly
|
|
|
906
914
|
}
|
|
907
915
|
dispose() {
|
|
908
916
|
this._disposed = true;
|
|
909
|
-
this
|
|
917
|
+
this.#signer.dispose();
|
|
910
918
|
}
|
|
911
919
|
};
|
|
912
920
|
|