@ledgerhq/zcash-utils 2.3.0 → 2.4.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/README.md CHANGED
@@ -8,25 +8,24 @@ Spending key material never enters this layer. It reads a Unified Full Viewing K
8
8
 
9
9
  ## Installation
10
10
 
11
- The package is published to Ledger's internal JFrog Artifactory, not to public npm, so the `@ledgerhq` scope must be routed there:
12
-
13
11
  ```sh
14
- # ~/.npmrc
15
- @ledgerhq:registry=https://<artifactory-host>/
12
+ npm install @ledgerhq/zcash-utils
16
13
  ```
17
14
 
18
- ```sh
19
- pnpm add @ledgerhq/zcash-utils
20
- ```
15
+ Published on the public npm registry under the `@ledgerhq` scope; no registry configuration is needed.
21
16
 
22
- Prebuilt `.node` binaries are bundled in the package for six targets: `darwin-arm64`, `darwin-x64`, `linux-x64-gnu`, `linux-arm64-gnu`, `win32-x64-msvc`, `win32-arm64-msvc`. On any other platform, build from source — see [`CONTRIBUTING.md`](CONTRIBUTING.md).
17
+ Prebuilt `.node` binaries are bundled for six targets — `darwin-arm64`, `darwin-x64`, `linux-x64-gnu`, `linux-arm64-gnu`, `win32-x64-msvc`, `win32-arm64-msvc` — so there is no compilation step and no Rust toolchain to install. On any other platform, build from source: see [`CONTRIBUTING.md`](CONTRIBUTING.md).
18
+
19
+ Node.js 20 or later. The addon is a native module, so it runs in Node and in the Electron main process, not in a browser or a renderer without `nodeIntegration`.
23
20
 
24
21
  ## Quick start — scanning
25
22
 
26
23
  ```typescript
27
24
  import { startSync, getChainTip } from "@ledgerhq/zcash-utils";
28
25
 
29
- const grpcUrl = "https://zaino-zec-testnet.nodes.stg.ledger-test.com/";
26
+ // Any lightwalletd or Zaino endpoint. This one is public; Ledger Live points
27
+ // at its own infrastructure.
28
+ const grpcUrl = "https://testnet.zec.rocks:443";
30
29
  const tip = await getChainTip(grpcUrl);
31
30
 
32
31
  const stream = await startSync({
@@ -157,7 +156,7 @@ Full signatures, every field, and its constraints are in [`index.d.ts`](index.d.
157
156
  | Export | Purpose |
158
157
  | --- | --- |
159
158
  | `buildTransaction(params)` | Builds, proves, and serializes a V5 PCZT from Orchard notes, transparent UTXOs, or both. Bears the Halo 2 proving cost inline (~2–5 s cold, ~hundreds of ms after, via a process-global proving-key cache). |
160
- | `buildIronwoodTransaction(params)` | Same, for an Ironwood (NU6.3) source — a redacted V6 PCZT. See the status note below. |
159
+ | `buildIronwoodTransaction(params)` | Same, for an Ironwood (NU6.3) source — a redacted V6 PCZT. See [Ironwood (NU6.3)](#ironwood-nu63) below. |
161
160
  | `parsePczt(pcztHex)` | Decodes canonical PCZT bytes into the `PcztTransaction` the device signer consumes. Fails if a field the device needs to sign is missing. |
162
161
  | `finalizeTransaction(params)` | Injects device signatures, computes the binding signature, extracts the signed transaction and its txid. CPU-bound (proof verification), dispatched to a blocking thread. |
163
162
  | `broadcastTransaction(grpcUrl, txHex)` | Submits a signed transaction to a lightwalletd / Zaino endpoint; returns the txid. |
@@ -186,11 +185,13 @@ The same quantity is not spelled the same way everywhere in this API. Read this
186
185
 
187
186
  **`scriptPubKey`** keeps its canonical Bitcoin/Zcash casing, rather than napi's default camelCasing of the Rust field name (`scriptPubkey`).
188
187
 
189
- ## Ironwood (NU6.3) status
188
+ ## Ironwood (NU6.3)
189
+
190
+ Ironwood is supported on both halves of the wallet, and the crates it rests on are on their stable releases.
190
191
 
191
- `buildIronwoodTransaction` is exposed so the JS side can be wired up in parallel, but Rust-side Ironwood crafting is still a dry run: the wallet-side crates it depends on (`pczt`, `zcash_client_backend`) are release candidates for NU6.3. Those pins are re-confirmed and bumped to the stable releases before the mainnet build cut. See [`docs/architecture.md`](docs/architecture.md).
192
+ Scanning is not gated by `orchardOnly`: `ShieldedTransaction.ironwoodNotes` is populated alongside `orchardNotes`, and `ShieldedNote.pool` tells the two apart. Crafting goes through `buildIronwoodTransaction`, which emits a V6 (ZIP-230) PCZT; `finalizeTransaction` and `broadcastTransaction` accept V6 as they do V5.
192
193
 
193
- Ironwood notes on the scanning path are complete and not gated by `orchardOnly`: `ShieldedTransaction.ironwoodNotes` is populated alongside `orchardNotes`, and `ShieldedNote.pool` distinguishes them.
194
+ What that support is tested against is worth knowing, since the pool is young. Witness computation is checked offline against a real Ironwood anchor captured from a public testnet node, scanning from the NU6.3 testnet activation height. Trial decryption is exercised against a synthetic Ironwood action built from the `orchard` note-encryption API — genuine cryptography, but not a real on-chain transaction, because no Ironwood transaction addressed to a key we hold has been available to capture as a fixture.
194
195
 
195
196
  ## Documentation
196
197
 
@@ -203,4 +204,4 @@ Ironwood notes on the scanning path are complete and not gated by `orchardOnly`:
203
204
 
204
205
  ## License
205
206
 
206
- [Apache-2.0](LICENSE.md), as the rest of the Ledger device stack.
207
+ [Apache-2.0](LICENSE.md)
package/index.d.ts CHANGED
@@ -10,7 +10,10 @@
10
10
  * a seed phrase directly in this layer.
11
11
  */
12
12
  export interface SyncParams {
13
- /** gRPC endpoint URL (e.g. `"https://zaino-zec-testnet.nodes.stg.ledger-test.com/"`). */
13
+ /**
14
+ * gRPC endpoint URL of a lightwalletd or Zaino server (e.g. the public
15
+ * `"https://testnet.zec.rocks:443"`).
16
+ */
14
17
  grpcUrl: string
15
18
  /** Unified Full Viewing Key (UFVK) for the account to scan. */
16
19
  viewingKey: string
@@ -368,10 +371,8 @@ export interface BuildIronwoodTransactionResult {
368
371
  /**
369
372
  * Build, prove, and serialize a redacted V6 PCZT for an Ironwood send.
370
373
  *
371
- * Rust-only crafting is dry-run pending the NU6.3 wallet-side crates
372
- * stabilizing (`pczt`, `zcash_client_backend` are release candidates); this
373
- * NAPI wrapper is exposed now so the JS side can be wired up in parallel and
374
- * re-pinned when those crates stabilize (see `docs/architecture.md`).
374
+ * The Ironwood counterpart of `buildTransaction`, taking Ironwood notes in
375
+ * place of Orchard ones and emitting a V6 (ZIP-230) PCZT.
375
376
  *
376
377
  * Same proving-cost profile as `buildTransaction`: Halo 2 proof generation
377
378
  * happens here for the Ironwood bundle (~2-5 s first call against the
@@ -679,6 +680,57 @@ export declare function parsePczt(pcztHex: string): PcztTransaction
679
680
  * all available receivers and does NOT match the device address.
680
681
  */
681
682
  export declare function orchardAddressFromUfvk(ufvk: string): string
683
+ /** TEST-ONLY. Account UFVK + transparent xpub, as derived from a mnemonic. */
684
+ export interface TestDerivedKeys {
685
+ ufvk: string
686
+ xpub: string
687
+ }
688
+ /**
689
+ * TEST-ONLY. Derives the account UFVK and transparent xpub from a mnemonic.
690
+ * Not named `deriveKeys` — that name is reserved for an anticipated future
691
+ * production export.
692
+ *
693
+ * Exists so the `ledger-live` coin-tester can obtain the same UFVK/xpub a
694
+ * device would report, without a physical Ledger. Never call this from
695
+ * production wallet code: it holds the mnemonic (spending-key material) in
696
+ * process memory, which the production host must never do.
697
+ */
698
+ export declare function testDeriveKeys(mnemonic: string, account: number, network: string): TestDerivedKeys
699
+ /** TEST-ONLY. Result of [`test_sign_pczt`]. */
700
+ export interface TestSignPcztResult {
701
+ /**
702
+ * 128-hex-char RedPallas `spendAuthSig`, one per unsigned Orchard action,
703
+ * in PCZT-action order. Empty when the PCZT carries no Orchard bundle.
704
+ */
705
+ orchardSignatures: Array<string>
706
+ /**
707
+ * 128-hex-char RedPallas `spendAuthSig`, one per unsigned Ironwood
708
+ * action, in PCZT-action order. Empty when the PCZT carries no Ironwood
709
+ * bundle (e.g. a V5/Orchard or transparent-only PCZT).
710
+ */
711
+ ironwoodSignatures: Array<string>
712
+ /**
713
+ * Hex DER secp256k1 signature, one per transparent input, in input order.
714
+ * Empty when the PCZT carries no transparent inputs.
715
+ */
716
+ transparentSignatures: Array<string>
717
+ }
718
+ /**
719
+ * TEST-ONLY. Signs whichever bundles the PCZT carries (Orchard actions,
720
+ * Ironwood actions, transparent inputs) using spending-key material derived
721
+ * from `mnemonic`. An absent bundle yields an empty list for that leg, not
722
+ * an error.
723
+ *
724
+ * Exists so the `ledger-live` coin-tester can act as a device stand-in in
725
+ * CI: `coin-zcash` routes z→z, z→t and t→z through the V6/Ironwood builder
726
+ * (only t→t stays V5), so both spend-auth legs are covered here. Never call
727
+ * this from production wallet code: it derives and holds spending-key
728
+ * material from a seed, which the production host must never do.
729
+ *
730
+ * CPU-bound (Orchard/Ironwood proving-key-adjacent signing work): dispatched
731
+ * to `tokio::task::spawn_blocking`, mirroring `finalize_transaction`.
732
+ */
733
+ export declare function testSignPczt(mnemonic: string, account: number, network: string, pcztHex: string): Promise<TestSignPcztResult>
682
734
  /**
683
735
  * Async iterator over matched shielded transactions.
684
736
  *
Binary file
Binary file
package/index.js CHANGED
@@ -310,7 +310,7 @@ if (!nativeBinding) {
310
310
  throw new Error(`Failed to load native binding`)
311
311
  }
312
312
 
313
- const { TransactionStream, startSync, getChainTip, findBlockHeight, buildTransaction, buildIronwoodTransaction, finalizeTransaction, broadcastTransaction, transactionDetails, parsePczt, orchardAddressFromUfvk } = nativeBinding
313
+ const { TransactionStream, startSync, getChainTip, findBlockHeight, buildTransaction, buildIronwoodTransaction, finalizeTransaction, broadcastTransaction, transactionDetails, parsePczt, orchardAddressFromUfvk, testDeriveKeys, testSignPczt } = nativeBinding
314
314
 
315
315
  module.exports.TransactionStream = TransactionStream
316
316
  module.exports.startSync = startSync
@@ -323,3 +323,5 @@ module.exports.broadcastTransaction = broadcastTransaction
323
323
  module.exports.transactionDetails = transactionDetails
324
324
  module.exports.parsePczt = parsePczt
325
325
  module.exports.orchardAddressFromUfvk = orchardAddressFromUfvk
326
+ module.exports.testDeriveKeys = testDeriveKeys
327
+ module.exports.testSignPczt = testSignPczt
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/zcash-utils",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Native Zcash key derivation and shielded sync — Node.js (NAPI)",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",