@winbit32/wallet-kit 0.1.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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +117 -0
  3. package/dist/cosign/bytes.d.ts +10 -0
  4. package/dist/cosign/bytes.d.ts.map +1 -0
  5. package/dist/cosign/bytes.js +37 -0
  6. package/dist/cosign/bytes.js.map +1 -0
  7. package/dist/cosign/config.d.ts +58 -0
  8. package/dist/cosign/config.d.ts.map +1 -0
  9. package/dist/cosign/config.js +54 -0
  10. package/dist/cosign/config.js.map +1 -0
  11. package/dist/cosign/cosignSend.d.ts +104 -0
  12. package/dist/cosign/cosignSend.d.ts.map +1 -0
  13. package/dist/cosign/cosignSend.js +157 -0
  14. package/dist/cosign/cosignSend.js.map +1 -0
  15. package/dist/cosign/index.d.ts +33 -0
  16. package/dist/cosign/index.d.ts.map +1 -0
  17. package/dist/cosign/index.js +49 -0
  18. package/dist/cosign/index.js.map +1 -0
  19. package/dist/cosign/initiator.d.ts +121 -0
  20. package/dist/cosign/initiator.d.ts.map +1 -0
  21. package/dist/cosign/initiator.js +270 -0
  22. package/dist/cosign/initiator.js.map +1 -0
  23. package/dist/cosign/orchardFrost.d.ts +140 -0
  24. package/dist/cosign/orchardFrost.d.ts.map +1 -0
  25. package/dist/cosign/orchardFrost.js +227 -0
  26. package/dist/cosign/orchardFrost.js.map +1 -0
  27. package/dist/cosign/relay.d.ts +100 -0
  28. package/dist/cosign/relay.d.ts.map +1 -0
  29. package/dist/cosign/relay.js +359 -0
  30. package/dist/cosign/relay.js.map +1 -0
  31. package/dist/cosign/seed.d.ts +32 -0
  32. package/dist/cosign/seed.d.ts.map +1 -0
  33. package/dist/cosign/seed.js +69 -0
  34. package/dist/cosign/seed.js.map +1 -0
  35. package/dist/cosign/transports.d.ts +127 -0
  36. package/dist/cosign/transports.d.ts.map +1 -0
  37. package/dist/cosign/transports.js +426 -0
  38. package/dist/cosign/transports.js.map +1 -0
  39. package/dist/cosign/vaultShare.d.ts +65 -0
  40. package/dist/cosign/vaultShare.d.ts.map +1 -0
  41. package/dist/cosign/vaultShare.js +157 -0
  42. package/dist/cosign/vaultShare.js.map +1 -0
  43. package/dist/index.d.ts +16 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +43 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/monero/types.d.ts +75 -0
  48. package/dist/monero/types.d.ts.map +1 -0
  49. package/dist/monero/types.js +9 -0
  50. package/dist/monero/types.js.map +1 -0
  51. package/dist/scanner/baseUrl.d.ts +24 -0
  52. package/dist/scanner/baseUrl.d.ts.map +1 -0
  53. package/dist/scanner/baseUrl.js +35 -0
  54. package/dist/scanner/baseUrl.js.map +1 -0
  55. package/dist/scanner/moneroScannerClient.d.ts +97 -0
  56. package/dist/scanner/moneroScannerClient.d.ts.map +1 -0
  57. package/dist/scanner/moneroScannerClient.js +125 -0
  58. package/dist/scanner/moneroScannerClient.js.map +1 -0
  59. package/dist/scanner/zcashScannerClient.d.ts +116 -0
  60. package/dist/scanner/zcashScannerClient.d.ts.map +1 -0
  61. package/dist/scanner/zcashScannerClient.js +150 -0
  62. package/dist/scanner/zcashScannerClient.js.map +1 -0
  63. package/package.json +37 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FungeLLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # @winbit32/wallet-kit
2
+
3
+ Embeddable Zcash + Monero wallet primitives extracted from
4
+ [Winbit32](https://winbit32.com). The goal: anyone who wants to add a
5
+ Zcash/Monero wallet (scanning, shielded sends, FROST co-signing) to their
6
+ site installs this package and calls functions — no Winbit32 UI required.
7
+
8
+ ## Status / roadmap
9
+
10
+ Extraction happens in slices (each slice moves source here and leaves a
11
+ re-export shim at the old Winbit32 path, so the app keeps working):
12
+
13
+ | Slice | Contents | Status |
14
+ | --- | --- | --- |
15
+ | Scanner clients | Zcash Orchard scan-job/UTXO/broadcast client, Monero LWS scan-job client, base-URL resolution | **Done** |
16
+ | Cosign client | WB32COSIGN relay transports, `.wult` share handling, FROST/Orchard ceremony, headless initiator pipeline | **Done** |
17
+ | MCP payment tools | `make_payment` tools ship in the seneschal.space payments-gateway, which consumes this kit; `request_payment` was already there | **Done** (lives in payments-gateway) |
18
+ | Shielded send/scan core | `shielded-transaction-client` (PCZT build/sign/broadcast via WebZjs), note cache | Planned |
19
+
20
+ ## What's in the box today
21
+
22
+ ```ts
23
+ import {
24
+ resolveWalletScannerBaseUrl,
25
+ createWalletScannerClient, // Zcash: Orchard scan jobs, UTXOs, tx broadcast
26
+ createMoneroWalletScannerClient, // Monero: LWS scan jobs
27
+ mapScannerBalanceToSnapshot, // wire → bigint balance snapshot
28
+ } from '@winbit32/wallet-kit';
29
+
30
+ const zec = createWalletScannerClient({ baseUrl: 'https://api.zcash.winbit32.com/api' });
31
+ const { data } = await zec.startOrchardScanJob({ ufvk, autoDetect: true });
32
+
33
+ const xmr = createMoneroWalletScannerClient();
34
+ const job = await xmr.startMoneroScanJob({ address, viewKey });
35
+ ```
36
+
37
+ - All clients take an optional `baseUrl`/`apiKey`; without them the
38
+ public `api.zcash.winbit32.com` host is used (its nginx injects the
39
+ upstream API key, so browsers need none).
40
+ - `resolveWalletScannerBaseUrl()` honours `REACT_APP_WALLET_SCANNER_URL`
41
+ and falls back to a same-origin `/api` proxy in development and the
42
+ public host in production. Non-CRA embedders should pass `baseUrl`
43
+ explicitly.
44
+ - No runtime dependencies; browser-first (uses `fetch`); works in Node ≥ 18.
45
+
46
+ ## Co-signing (FROST/Orchard, 2-of-2)
47
+
48
+ The canonical WB32COSIGN client lives here (`src/cosign/`). It powers both
49
+ browser initiators (Secresea-style "send from a `.wult` share" flows) and
50
+ fully headless Node hosts such as the seneschal.space payments-gateway:
51
+
52
+ ```ts
53
+ import {
54
+ unwrapVaultShare, toOrchardBundle, // .wult → key bundle
55
+ deriveOrchardAddressFromBundle, // bundle → UFVK + u1… address
56
+ runHeadlessCosignSend, // scan → build → ceremony → broadcast
57
+ resolveCosignConfig,
58
+ } from '@winbit32/wallet-kit';
59
+
60
+ const share = await unwrapVaultShare(wultBytes, password);
61
+ const bundle = toOrchardBundle(share);
62
+ const { txid } = await runHeadlessCosignSend({
63
+ config: resolveCosignConfig({ relayBaseUrl, pcztApiBaseUrl, fetchImpl: fetch }),
64
+ wasm, bundle, ufvk, unifiedAddress, scanner,
65
+ toAddress: 'u1…', amountZat: 25_000, // zatoshis
66
+ onQrReady: (qr) => showToHuman(qr), // WB32COSIGN:1:… pairing payload
67
+ });
68
+ ```
69
+
70
+ - The host holds **one** share; the human's cosigner (winbit32.com `#cosign`)
71
+ holds the other. Neither side ever has the full spending key.
72
+ - Transports are pluggable (`BroadcastChannel` same-device, HTTPS relay
73
+ cross-device); messages are AES-GCM encrypted with the QR session key.
74
+ - The `orchard-frost` WASM is loaded by the host: browsers fetch it from
75
+ `public/orchard-frost/`, Node hosts read the same artefacts from disk
76
+ (see `loadOrchardFrostWasmNode` in the payments-gateway for the pattern).
77
+
78
+ ## Building
79
+
80
+ ```sh
81
+ cd packages/wallet-kit
82
+ npm run build # tsc → dist/ (CommonJS + .d.ts; ESM hosts use src/ via bundler)
83
+ ```
84
+
85
+ The compiled `dist/` is CommonJS so plain Node hosts (e.g. the
86
+ payments-gateway via a `file:` dependency) can `require`/`import` it without
87
+ a bundler. Browser consumers (Winbit32 itself) compile `src/` directly
88
+ through their own bundler via the alias seam described below.
89
+
90
+ ## Tests
91
+
92
+ Kit tests run under the host repo's jest (CRA 27) in a Node environment:
93
+
94
+ ```sh
95
+ CI=true npx react-app-rewired test --watchAll=false --testPathPattern='packages/wallet-kit'
96
+ ```
97
+
98
+ `src/cosign/__tests__/ceremony.integration.test.ts` runs a **real**
99
+ FROST/Orchard ceremony against the staged WASM — initiator and an
100
+ independently-implemented cosigner stand-in — plus the whole
101
+ `runHeadlessCosignSend` pipeline against fake PCZT/scanner endpoints. It
102
+ skips (not fails) if `public/orchard-frost/` artefacts are missing.
103
+
104
+ ## How Winbit32 consumes it
105
+
106
+ The app imports `@winbit32/wallet-kit` directly from `packages/wallet-kit/src`
107
+ via a webpack alias + jest `moduleNameMapper` + tsconfig `paths` (see
108
+ `config-overrides.js`). npm workspaces are deliberately NOT used yet: the
109
+ CRA + WASM webpack setup is sensitive to `node_modules` hoisting, so the
110
+ alias seam gives us the package boundary without the install churn. When
111
+ the kit is published, the alias is simply dropped and the app depends on
112
+ the npm package like everyone else.
113
+
114
+ Old Winbit32 paths (`src/components/toolbox/walletScannerBaseUrl.ts`,
115
+ `.../zcash-extensions/api/walletScannerClient.ts`,
116
+ `.../monero-extensions/api/moneroWalletScannerClient.ts`) remain as
117
+ re-export shims; new code should import from `@winbit32/wallet-kit`.
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Small hex / base64 helpers shared across the cosign module.
3
+ * Browser-safe (uses `btoa`/`atob`); no Node Buffer dependency so the module
4
+ * stays portable when extracted into a standalone package.
5
+ */
6
+ export declare const hexToBytes: (hex: string) => Uint8Array;
7
+ export declare const bytesToHex: (bytes: Uint8Array) => string;
8
+ export declare const toBase64: (bytes: Uint8Array) => string;
9
+ export declare const fromBase64: (b64: string) => Uint8Array;
10
+ //# sourceMappingURL=bytes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../src/cosign/bytes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,UAAU,QAAS,MAAM,KAAG,UAQxC,CAAC;AAEF,eAAO,MAAM,UAAU,UAAW,UAAU,KAAG,MACoB,CAAC;AAEpE,eAAO,MAAM,QAAQ,UAAW,UAAU,KAAG,MAI5C,CAAC;AAEF,eAAO,MAAM,UAAU,QAAS,MAAM,KAAG,UAKxC,CAAC"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Small hex / base64 helpers shared across the cosign module.
4
+ * Browser-safe (uses `btoa`/`atob`); no Node Buffer dependency so the module
5
+ * stays portable when extracted into a standalone package.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.fromBase64 = exports.toBase64 = exports.bytesToHex = exports.hexToBytes = void 0;
9
+ const hexToBytes = (hex) => {
10
+ const clean = hex.startsWith('0x') ? hex.slice(2) : hex;
11
+ if (clean.length % 2 !== 0)
12
+ throw new Error('hex string must have an even length');
13
+ const bytes = new Uint8Array(clean.length / 2);
14
+ for (let i = 0; i < bytes.length; i++) {
15
+ bytes[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
16
+ }
17
+ return bytes;
18
+ };
19
+ exports.hexToBytes = hexToBytes;
20
+ const bytesToHex = (bytes) => Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
21
+ exports.bytesToHex = bytesToHex;
22
+ const toBase64 = (bytes) => {
23
+ let s = '';
24
+ for (let i = 0; i < bytes.length; i++)
25
+ s += String.fromCharCode(bytes[i]);
26
+ return btoa(s);
27
+ };
28
+ exports.toBase64 = toBase64;
29
+ const fromBase64 = (b64) => {
30
+ const binary = atob(b64);
31
+ const bytes = new Uint8Array(binary.length);
32
+ for (let i = 0; i < binary.length; i++)
33
+ bytes[i] = binary.charCodeAt(i);
34
+ return bytes;
35
+ };
36
+ exports.fromBase64 = fromBase64;
37
+ //# sourceMappingURL=bytes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/cosign/bytes.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEI,MAAM,UAAU,GAAG,CAAC,GAAW,EAAc,EAAE;IACrD,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACxD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACnF,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACtC,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;KACvD;IACD,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AARW,QAAA,UAAU,cAQrB;AAEK,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAU,EAAE,CACvD,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AADvD,QAAA,UAAU,cAC6C;AAE7D,MAAM,QAAQ,GAAG,CAAC,KAAiB,EAAU,EAAE;IACrD,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;AAChB,CAAC,CAAC;AAJW,QAAA,QAAQ,YAInB;AAEK,MAAM,UAAU,GAAG,CAAC,GAAW,EAAc,EAAE;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACxE,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AALW,QAAA,UAAU,cAKrB"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @fileoverview Configuration boundary for the wallet-kit co-signing module.
3
+ *
4
+ * Everything host-specific (API base, relay base, where the WASM is served,
5
+ * which `fetch` to use, network) is injected here rather than hardcoded —
6
+ * this package IS the standalone "add MPC co-signing to your Zcash site"
7
+ * module (canonical home; ported from Secresea's `services/cosign/`, which
8
+ * migrates onto this package once it consumes npm deps). Per project
9
+ * conventions we never export mutable objects/arrays or `let` bindings —
10
+ * config is passed by value through function parameters;
11
+ * `resolveCosignConfig()` returns a fresh frozen object.
12
+ *
13
+ * The defaults assume the common single-origin deployment (frontend + NFPT
14
+ * API on one origin), so a host that mounts the NFPT API at `/api` and
15
+ * serves the WASM from `/orchard-frost` needs to pass nothing. Node hosts
16
+ * (e.g. payments-gateway) pass absolute URLs + a WASM loader instead.
17
+ */
18
+ import type { OrchardFrostWasmModule } from './orchardFrost';
19
+ /** Zcash network selector understood by the PCZT endpoints. */
20
+ export type ZcashNetwork = 'main' | 'test';
21
+ export interface CosignConfig {
22
+ /**
23
+ * Base path/URL for the PCZT endpoints
24
+ * (`/build`, `/orchard-sighash`, `/apply-orchard-frost`, `/broadcast`).
25
+ */
26
+ pcztApiBaseUrl: string;
27
+ /**
28
+ * Base path/URL for the WB32COSIGN relay
29
+ * (`POST /:sessionId`, `POST /message/:sessionId`, `GET /message/:sessionId/:partyId`).
30
+ */
31
+ relayBaseUrl: string;
32
+ /** Base path/URL under which the orchard-frost WASM assets are served. */
33
+ wasmBaseUrl: string;
34
+ /** Zcash network for builds/proofs. */
35
+ network: ZcashNetwork;
36
+ /** `fetch` implementation (injectable for tests / non-browser hosts). */
37
+ fetchImpl: typeof fetch;
38
+ /**
39
+ * Optional override for loading the Orchard FROST WASM. Hosts that bundle
40
+ * the WASM with their own toolchain provide this; otherwise the default
41
+ * loader fetches the artefacts from `wasmBaseUrl`.
42
+ */
43
+ loadOrchardFrostWasm?: () => Promise<OrchardFrostWasmModule>;
44
+ /** Optional cache-bust token appended to WASM asset URLs (e.g. a build id). */
45
+ assetCacheBustToken?: string;
46
+ }
47
+ export declare const DEFAULT_PCZT_API_BASE_URL = "/api/pczt";
48
+ export declare const DEFAULT_RELAY_BASE_URL = "/api/cosign";
49
+ export declare const DEFAULT_WASM_BASE_URL = "/orchard-frost";
50
+ export declare const DEFAULT_NETWORK: ZcashNetwork;
51
+ /**
52
+ * Merge caller overrides with the defaults and return a fresh, frozen config.
53
+ *
54
+ * @param partial Any subset of {@link CosignConfig}; omitted fields fall back
55
+ * to the module defaults.
56
+ */
57
+ export declare const resolveCosignConfig: (partial?: Partial<CosignConfig>) => Readonly<CosignConfig>;
58
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/cosign/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE7D,+DAA+D;AAC/D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC5B;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,OAAO,EAAE,YAAY,CAAC;IACtB,yEAAyE;IACzE,SAAS,EAAE,OAAO,KAAK,CAAC;IACxB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC7D,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAID,eAAO,MAAM,yBAAyB,cAAc,CAAC;AACrD,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AACpD,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AACtD,eAAO,MAAM,eAAe,EAAE,YAAqB,CAAC;AAYpD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,aAAa,QAAQ,YAAY,CAAC,KAAQ,SAAS,YAAY,CAW9F,CAAC"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Configuration boundary for the wallet-kit co-signing module.
4
+ *
5
+ * Everything host-specific (API base, relay base, where the WASM is served,
6
+ * which `fetch` to use, network) is injected here rather than hardcoded —
7
+ * this package IS the standalone "add MPC co-signing to your Zcash site"
8
+ * module (canonical home; ported from Secresea's `services/cosign/`, which
9
+ * migrates onto this package once it consumes npm deps). Per project
10
+ * conventions we never export mutable objects/arrays or `let` bindings —
11
+ * config is passed by value through function parameters;
12
+ * `resolveCosignConfig()` returns a fresh frozen object.
13
+ *
14
+ * The defaults assume the common single-origin deployment (frontend + NFPT
15
+ * API on one origin), so a host that mounts the NFPT API at `/api` and
16
+ * serves the WASM from `/orchard-frost` needs to pass nothing. Node hosts
17
+ * (e.g. payments-gateway) pass absolute URLs + a WASM loader instead.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.resolveCosignConfig = exports.DEFAULT_NETWORK = exports.DEFAULT_WASM_BASE_URL = exports.DEFAULT_RELAY_BASE_URL = exports.DEFAULT_PCZT_API_BASE_URL = void 0;
21
+ // Named defaults — single source of truth, easy to retune without hunting
22
+ // through call sites.
23
+ exports.DEFAULT_PCZT_API_BASE_URL = '/api/pczt';
24
+ exports.DEFAULT_RELAY_BASE_URL = '/api/cosign';
25
+ exports.DEFAULT_WASM_BASE_URL = '/orchard-frost';
26
+ exports.DEFAULT_NETWORK = 'main';
27
+ const stripTrailingSlash = (s) => s.replace(/\/+$/, '');
28
+ const defaultFetch = () => {
29
+ const f = (typeof globalThis !== 'undefined' ? globalThis.fetch : undefined);
30
+ if (typeof f !== 'function') {
31
+ throw new Error('No fetch implementation available; pass `fetchImpl` in the cosign config.');
32
+ }
33
+ return f.bind(globalThis);
34
+ };
35
+ /**
36
+ * Merge caller overrides with the defaults and return a fresh, frozen config.
37
+ *
38
+ * @param partial Any subset of {@link CosignConfig}; omitted fields fall back
39
+ * to the module defaults.
40
+ */
41
+ const resolveCosignConfig = (partial = {}) => {
42
+ const config = {
43
+ pcztApiBaseUrl: stripTrailingSlash(partial.pcztApiBaseUrl ?? exports.DEFAULT_PCZT_API_BASE_URL),
44
+ relayBaseUrl: stripTrailingSlash(partial.relayBaseUrl ?? exports.DEFAULT_RELAY_BASE_URL),
45
+ wasmBaseUrl: stripTrailingSlash(partial.wasmBaseUrl ?? exports.DEFAULT_WASM_BASE_URL),
46
+ network: partial.network ?? exports.DEFAULT_NETWORK,
47
+ fetchImpl: partial.fetchImpl ?? defaultFetch(),
48
+ loadOrchardFrostWasm: partial.loadOrchardFrostWasm,
49
+ assetCacheBustToken: partial.assetCacheBustToken,
50
+ };
51
+ return Object.freeze(config);
52
+ };
53
+ exports.resolveCosignConfig = resolveCosignConfig;
54
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/cosign/config.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;;;AAkCH,0EAA0E;AAC1E,sBAAsB;AACT,QAAA,yBAAyB,GAAG,WAAW,CAAC;AACxC,QAAA,sBAAsB,GAAG,aAAa,CAAC;AACvC,QAAA,qBAAqB,GAAG,gBAAgB,CAAC;AACzC,QAAA,eAAe,GAAiB,MAAM,CAAC;AAEpD,MAAM,kBAAkB,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAExE,MAAM,YAAY,GAAG,GAAiB,EAAE;IACvC,MAAM,CAAC,GAAG,CAAC,OAAO,UAAU,KAAK,WAAW,CAAC,CAAC,CAAE,UAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAA6B,CAAC;IAClH,IAAI,OAAO,CAAC,KAAK,UAAU,EAAE;QAC5B,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;KAC7F;IACD,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC3B,CAAC,CAAC;AAEF;;;;;GAKG;AACI,MAAM,mBAAmB,GAAG,CAAC,UAAiC,EAAE,EAA0B,EAAE;IAClG,MAAM,MAAM,GAAiB;QAC5B,cAAc,EAAE,kBAAkB,CAAC,OAAO,CAAC,cAAc,IAAI,iCAAyB,CAAC;QACvF,YAAY,EAAE,kBAAkB,CAAC,OAAO,CAAC,YAAY,IAAI,8BAAsB,CAAC;QAChF,WAAW,EAAE,kBAAkB,CAAC,OAAO,CAAC,WAAW,IAAI,6BAAqB,CAAC;QAC7E,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,uBAAe;QAC3C,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,YAAY,EAAE;QAC9C,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;QAClD,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;KAChD,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC,CAAC;AAXW,QAAA,mBAAmB,uBAW9B"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * @fileoverview Orchard FROST send orchestration — ties the co-signing
3
+ * ceremony to the chain via the PCZT endpoints.
4
+ *
5
+ * Pipeline (mirrors WINBIT32's shielded-transaction-client FROST path):
6
+ * 1. POST /pczt/orchard-sighash → sighash + per-action `alpha`s + action
7
+ * indices + (optional) per-action fvk.ak + an IO-finalised PCZT.
8
+ * 2. For each Orchard action: run the two-round FROST ceremony with that
9
+ * action's `alpha` as the randomiser (`runOrchardInitiatorAction`).
10
+ * 3. POST /pczt/apply-orchard-frost → inject sigs, prove, finalise.
11
+ * 4. POST /pczt/broadcast → txid.
12
+ *
13
+ * Everything host-specific is injected via {@link CosignConfig} (API base,
14
+ * network, fetch), and the WASM engine + loaded share are passed in — no
15
+ * globals. This file is the canonical standalone copy (ported from
16
+ * Secresea's `services/cosign/cosignSend.ts`).
17
+ *
18
+ * The PCZT *build* (gathering spendable notes for the FROST UFVK) belongs to
19
+ * the wallet/scan layer; this module starts from an already-built unsigned
20
+ * PCZT. `buildPczt` is provided as a thin typed wrapper for callers that want
21
+ * the server to build it from explicit spends/outputs.
22
+ */
23
+ import type { CosignConfig } from './config';
24
+ import type { CosignTransport } from './transports';
25
+ import { type OrchardKeyShareForCosign, type SigningDisplay, type CosignCallbacks } from './relay';
26
+ import type { OrchardFrostWasmModule } from './orchardFrost';
27
+ export type PcztFormat = 'base64' | 'hex';
28
+ export interface OrchardSighashResult {
29
+ success?: boolean;
30
+ /** ZIP-244 Orchard sighash (64 hex / 32 bytes), shared across all actions. */
31
+ orchardSighash: string;
32
+ /** Number of Orchard actions that need a FROST signature. */
33
+ orchardActionCount: number;
34
+ /** Per-action `alpha` randomisers the PCZT pre-committed to (64 hex each). */
35
+ orchardAlphas: string[];
36
+ /** PCZT action index for each entry in `orchardAlphas`. */
37
+ orchardFrostActionIndices: number[];
38
+ /** Total Orchard actions (incl. dummies that don't need signing). */
39
+ orchardActionTotal?: number;
40
+ /** Per-action fvk.ak, for verifying the PCZT was built with our group key. */
41
+ orchardFvkAks?: string[];
42
+ /** IO-finalised PCZT to feed back into apply (dummies pre-signed). */
43
+ pczt?: string;
44
+ pcztFormat?: PcztFormat;
45
+ }
46
+ export declare const extractOrchardSighash: (config: CosignConfig, pczt: string, pcztFormat?: PcztFormat) => Promise<OrchardSighashResult>;
47
+ export interface ApplyOrchardFrostParams {
48
+ pczt: string;
49
+ pcztFormat?: PcztFormat;
50
+ orchardSignatures: string[];
51
+ orchardFrostActionIndices?: number[];
52
+ orchardGroupPublic?: string;
53
+ network?: CosignConfig['network'];
54
+ }
55
+ export declare const applyOrchardFrostSignatures: (config: CosignConfig, params: ApplyOrchardFrostParams) => Promise<{
56
+ pczt: string;
57
+ }>;
58
+ export interface BroadcastResult {
59
+ success?: boolean;
60
+ txid: string;
61
+ broadcastedAt?: string;
62
+ }
63
+ export declare const broadcastPczt: (config: CosignConfig, signedPczt: string, format?: PcztFormat) => Promise<BroadcastResult>;
64
+ /** Thin pass-through to /pczt/build; the caller assembles spends/outputs. */
65
+ export declare const buildPczt: <T = {
66
+ pczt: string;
67
+ }>(config: CosignConfig, buildRequest: Record<string, unknown>) => Promise<T>;
68
+ export interface CosignSendParams {
69
+ config: CosignConfig;
70
+ wasm: OrchardFrostWasmModule;
71
+ /** WB32COSIGN session AES key (hex). */
72
+ encKeyHex: string;
73
+ transport: CosignTransport;
74
+ /** This device's Vultisig localPartyId. */
75
+ myPartyId: string;
76
+ /** Our loaded Orchard FROST share (from the .wult). */
77
+ share: OrchardKeyShareForCosign;
78
+ publicKeyPackage: {
79
+ signerPubkeys: Record<string, string>;
80
+ groupPublic: string;
81
+ };
82
+ /** Unsigned PCZT (base64 by default) to co-sign. */
83
+ unsignedPczt: string;
84
+ pcztFormat?: PcztFormat;
85
+ display: SigningDisplay;
86
+ /**
87
+ * When provided, wait for a cosigner with one of these Vultisig
88
+ * localPartyIds to join before signing (the QR-pairing handshake).
89
+ * Omit if the caller already performed the join.
90
+ */
91
+ validSignerIds?: string[];
92
+ callbacks?: CosignCallbacks;
93
+ }
94
+ export interface CosignSendResult {
95
+ txid: string;
96
+ signedPczt: string;
97
+ signatures: string[];
98
+ }
99
+ /**
100
+ * Drive an unsigned PCZT through the Orchard FROST co-signing pipeline to a
101
+ * broadcast txid. The cosigner (WINBIT32) co-signs each action over the relay.
102
+ */
103
+ export declare const cosignSendPczt: (p: CosignSendParams) => Promise<CosignSendResult>;
104
+ //# sourceMappingURL=cosignSend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cosignSend.d.ts","sourceRoot":"","sources":["../../src/cosign/cosignSend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Orchard FROST send orchestration — ties the co-signing
4
+ * ceremony to the chain via the PCZT endpoints.
5
+ *
6
+ * Pipeline (mirrors WINBIT32's shielded-transaction-client FROST path):
7
+ * 1. POST /pczt/orchard-sighash → sighash + per-action `alpha`s + action
8
+ * indices + (optional) per-action fvk.ak + an IO-finalised PCZT.
9
+ * 2. For each Orchard action: run the two-round FROST ceremony with that
10
+ * action's `alpha` as the randomiser (`runOrchardInitiatorAction`).
11
+ * 3. POST /pczt/apply-orchard-frost → inject sigs, prove, finalise.
12
+ * 4. POST /pczt/broadcast → txid.
13
+ *
14
+ * Everything host-specific is injected via {@link CosignConfig} (API base,
15
+ * network, fetch), and the WASM engine + loaded share are passed in — no
16
+ * globals. This file is the canonical standalone copy (ported from
17
+ * Secresea's `services/cosign/cosignSend.ts`).
18
+ *
19
+ * The PCZT *build* (gathering spendable notes for the FROST UFVK) belongs to
20
+ * the wallet/scan layer; this module starts from an already-built unsigned
21
+ * PCZT. `buildPczt` is provided as a thin typed wrapper for callers that want
22
+ * the server to build it from explicit spends/outputs.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.cosignSendPczt = exports.buildPczt = exports.broadcastPczt = exports.applyOrchardFrostSignatures = exports.extractOrchardSighash = void 0;
26
+ const relay_1 = require("./relay");
27
+ const HEX64 = /^[0-9a-fA-F]{64}$/;
28
+ // ── PCZT API client (config-injected fetch) ─────────────────────────
29
+ const postJson = async (config, pathSuffix, body) => {
30
+ const resp = await config.fetchImpl(`${config.pcztApiBaseUrl}${pathSuffix}`, {
31
+ method: 'POST',
32
+ headers: { 'Content-Type': 'application/json' },
33
+ body: JSON.stringify(body),
34
+ });
35
+ const text = await resp.text();
36
+ let parsed = null;
37
+ try {
38
+ parsed = text ? JSON.parse(text) : null;
39
+ }
40
+ catch { /* non-JSON error body */ }
41
+ if (!resp.ok || (parsed && parsed.success === false)) {
42
+ const msg = (parsed && typeof parsed.error === 'string') ? parsed.error : (text || `HTTP ${resp.status}`);
43
+ throw new Error(`pczt${pathSuffix} failed: ${msg}`);
44
+ }
45
+ return parsed;
46
+ };
47
+ const extractOrchardSighash = (config, pczt, pcztFormat = 'base64') => postJson(config, '/orchard-sighash', { pczt, pcztFormat });
48
+ exports.extractOrchardSighash = extractOrchardSighash;
49
+ const applyOrchardFrostSignatures = (config, params) => postJson(config, '/apply-orchard-frost', {
50
+ pczt: params.pczt,
51
+ pcztFormat: params.pcztFormat ?? 'base64',
52
+ orchardSignatures: params.orchardSignatures,
53
+ ...(params.orchardFrostActionIndices ? { orchardFrostActionIndices: params.orchardFrostActionIndices } : {}),
54
+ ...(params.orchardGroupPublic ? { orchardGroupPublic: params.orchardGroupPublic } : {}),
55
+ network: params.network ?? config.network,
56
+ });
57
+ exports.applyOrchardFrostSignatures = applyOrchardFrostSignatures;
58
+ const broadcastPczt = (config, signedPczt, format = 'base64') => postJson(config, '/broadcast', { signedPczt, format });
59
+ exports.broadcastPczt = broadcastPczt;
60
+ /** Thin pass-through to /pczt/build; the caller assembles spends/outputs. */
61
+ const buildPczt = (config, buildRequest) => postJson(config, '/build', buildRequest);
62
+ exports.buildPczt = buildPczt;
63
+ /**
64
+ * Drive an unsigned PCZT through the Orchard FROST co-signing pipeline to a
65
+ * broadcast txid. The cosigner (WINBIT32) co-signs each action over the relay.
66
+ */
67
+ const cosignSendPczt = async (p) => {
68
+ const { config, wasm, transport, share, publicKeyPackage, callbacks } = p;
69
+ const pcztFormat = p.pcztFormat ?? 'base64';
70
+ const groupPublicHex = (publicKeyPackage.groupPublic || '').toLowerCase();
71
+ if (p.validSignerIds && p.validSignerIds.length > 0) {
72
+ await (0, relay_1.waitForCosignerJoin)({ encKeyHex: p.encKeyHex, transport, validSignerIds: p.validSignerIds, callbacks });
73
+ }
74
+ callbacks?.onProgress?.('Requesting Orchard sighash from server...');
75
+ const sh = await (0, exports.extractOrchardSighash)(config, p.unsignedPczt, pcztFormat);
76
+ if (!sh.orchardSighash || !HEX64.test(sh.orchardSighash)) {
77
+ throw new Error('Server returned an invalid Orchard sighash (expected 64 hex chars).');
78
+ }
79
+ const actionCount = sh.orchardActionCount || 0;
80
+ const alphas = Array.isArray(sh.orchardAlphas) ? sh.orchardAlphas : [];
81
+ const indices = Array.isArray(sh.orchardFrostActionIndices) ? sh.orchardFrostActionIndices : [];
82
+ if (actionCount > 0) {
83
+ if (alphas.length !== actionCount) {
84
+ throw new Error(`Server returned ${alphas.length} Orchard alphas but ${actionCount} actions need signing — ` +
85
+ 'upgrade the orchard-scanner so extract-orchard-sighash returns per-action alphas.');
86
+ }
87
+ alphas.forEach((a, i) => {
88
+ if (!HEX64.test(a || ''))
89
+ throw new Error(`Invalid Orchard alpha at index ${i} (expected 64 hex chars).`);
90
+ });
91
+ assertFvkMatchesGroup(sh, actionCount, groupPublicHex, indices);
92
+ }
93
+ const signatures = [];
94
+ for (let i = 0; i < actionCount; i++) {
95
+ callbacks?.onProgress?.(`Orchard FROST signing action ${i + 1} of ${actionCount}...`);
96
+ const frostOrchardData = {
97
+ sighash: sh.orchardSighash,
98
+ randomizer: alphas[i],
99
+ pubKeyPackage: { signerPubkeys: publicKeyPackage.signerPubkeys, groupPublic: publicKeyPackage.groupPublic },
100
+ };
101
+ const result = await (0, relay_1.runOrchardInitiatorAction)({
102
+ wasm,
103
+ encKeyHex: p.encKeyHex,
104
+ transport,
105
+ myPartyId: p.myPartyId,
106
+ orchardKeyShare: share,
107
+ frostOrchardData,
108
+ display: p.display,
109
+ callbacks,
110
+ keepAlive: i < actionCount - 1,
111
+ });
112
+ signatures.push(result.signature);
113
+ }
114
+ callbacks?.onProgress?.('Submitting signatures to server for proving...');
115
+ const applyPczt = sh.pczt ?? p.unsignedPczt;
116
+ const applyFormat = (sh.pczt ? sh.pcztFormat : pcztFormat) ?? 'base64';
117
+ const applied = await (0, exports.applyOrchardFrostSignatures)(config, {
118
+ pczt: applyPczt,
119
+ pcztFormat: applyFormat,
120
+ orchardSignatures: signatures,
121
+ orchardFrostActionIndices: indices.length === signatures.length ? indices : undefined,
122
+ orchardGroupPublic: HEX64.test(groupPublicHex) ? groupPublicHex : undefined,
123
+ network: config.network,
124
+ });
125
+ if (!applied?.pczt)
126
+ throw new Error('apply-orchard-frost returned no signed PCZT.');
127
+ callbacks?.onProgress?.('Broadcasting transaction...');
128
+ const broadcast = await (0, exports.broadcastPczt)(config, applied.pczt, 'base64');
129
+ if (!broadcast?.txid)
130
+ throw new Error('Broadcast returned no txid.');
131
+ callbacks?.onProgress?.('Transaction broadcast.');
132
+ return { txid: broadcast.txid, signedPczt: applied.pczt, signatures };
133
+ };
134
+ exports.cosignSendPczt = cosignSendPczt;
135
+ /**
136
+ * Refuse to sign if any action's fvk.ak differs from our FROST group_public —
137
+ * no FROST signature can verify against a PCZT built with a different key.
138
+ */
139
+ const assertFvkMatchesGroup = (sh, actionCount, groupPublicHex, indices) => {
140
+ const aks = Array.isArray(sh.orchardFvkAks) ? sh.orchardFvkAks : [];
141
+ if (!groupPublicHex || aks.length !== actionCount)
142
+ return; // nothing to verify against
143
+ const mismatches = [];
144
+ for (let i = 0; i < aks.length; i++) {
145
+ const ak = (aks[i] || '').trim().toLowerCase();
146
+ if (!HEX64.test(ak))
147
+ continue;
148
+ if (ak !== groupPublicHex)
149
+ mismatches.push(`action ${indices[i] ?? i}: ak=${ak.slice(0, 16)}…`);
150
+ }
151
+ if (mismatches.length > 0) {
152
+ throw new Error(`Orchard FROST keys do not match the PCZT's FVK (group_public=${groupPublicHex.slice(0, 16)}…, ` +
153
+ `but ${mismatches.join(', ')}). The PCZT was built with a different Orchard key than your share derives — ` +
154
+ 'no signature can verify until both devices share the same bundle.');
155
+ }
156
+ };
157
+ //# sourceMappingURL=cosignSend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cosignSend.js","sourceRoot":"","sources":["../../src/cosign/cosignSend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @fileoverview Public surface of the WB32COSIGN co-signing client.
3
+ *
4
+ * Self-contained and framework-agnostic: load a WINBIT32 `.wult` share,
5
+ * derive the FROST UFVK / unified address, and drive a co-signed shielded
6
+ * send (QR pairing → two-round Orchard FROST ceremony → prove → broadcast)
7
+ * against any WB32COSIGN relay + NFPT PCZT endpoints. Wire format is
8
+ * byte-compatible with WINBIT32's `cosign.exe` and Secresea.
9
+ *
10
+ * Works in browsers and Node ≥ 18 (WebCrypto / Web Streams /
11
+ * BroadcastChannel are global in both; WebRTC is browser-only and skipped
12
+ * automatically by the transport factory).
13
+ *
14
+ * - `vaultShare` — load a WINBIT32 `.wult` co-signing share.
15
+ * - `config` — injectable host configuration (API/relay/WASM/network).
16
+ * - `orchardFrost` — Orchard FROST WASM engine (load, derive, ceremony ops).
17
+ * - `bytes` — hex/base64 helpers.
18
+ * - `seed` — deterministic vault-identity → Zcash seed (HKDF).
19
+ * - `transports` — WB32COSIGN message transports (BroadcastChannel/HTTP/WebRTC).
20
+ * - `relay` — session/QR, encrypted envelopes, Orchard FROST initiator.
21
+ * - `cosignSend` — PCZT send orchestration + thin PCZT API client.
22
+ * - `initiator` — headless full pipeline (scan → select → build → ceremony).
23
+ */
24
+ export * from './vaultShare';
25
+ export * from './config';
26
+ export * from './orchardFrost';
27
+ export * from './bytes';
28
+ export * from './seed';
29
+ export * from './transports';
30
+ export * from './relay';
31
+ export * from './cosignSend';
32
+ export * from './initiator';
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cosign/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}