@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.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
- /** The signer that holds the key. */
378
- readonly signer: Signer;
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
- /** The signer that holds the key. */
378
- readonly signer: Signer;
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
- const a = address.trim();
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
- /** The signer that holds the key. */
736
- signer;
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.signer = requireCurve(signer, "secp256k1");
743
- if (!this.signer.schemes.includes("ecdsa")) throw new SignerError(`A Zcash account needs a signer with the 'ecdsa' scheme (has: ${this.signer.schemes.join(", ")}).`);
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.signer);
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.signer.sign(digest, { scheme: "ecdsa", context: "zcash-sighash" });
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.signInputs(tx, spent);
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.signSpend(tx)).desc;
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.signSpend(tx);
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.signSpend(tx);
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.signSpend({ to: o.recipient, value: o.amount });
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.signer.dispose();
917
+ this.#signer.dispose();
910
918
  }
911
919
  };
912
920