@babylonlabs-io/ledger-vault-signer 0.4.0 → 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/THIRD-PARTY-NOTICES.md +18 -4
- package/dist/dmkApduSender.d.ts +9 -1
- package/dist/dmkApduSender.d.ts.map +1 -1
- package/dist/dmkSession.d.ts.map +1 -1
- package/dist/errors.d.ts +102 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/expectedSignatures.d.ts +83 -0
- package/dist/expectedSignatures.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +11 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1746 -278
- package/dist/index.js.map +1 -1
- package/dist/rawApdu.d.ts +59 -0
- package/dist/rawApdu.d.ts.map +1 -0
- package/dist/signPsbt.d.ts +71 -0
- package/dist/signPsbt.d.ts.map +1 -0
- package/dist/signPsbtLoop.d.ts +46 -0
- package/dist/signPsbtLoop.d.ts.map +1 -0
- package/dist/signPsbtMerge.d.ts +9 -0
- package/dist/signPsbtMerge.d.ts.map +1 -0
- package/dist/signPsbtPrepare.d.ts +57 -0
- package/dist/signPsbtPrepare.d.ts.map +1 -0
- package/dist/tapLeafHash.d.ts +4 -0
- package/dist/tapLeafHash.d.ts.map +1 -0
- package/dist/vaultCommands.d.ts +2 -7
- package/dist/vaultCommands.d.ts.map +1 -1
- package/package.json +3 -2
package/THIRD-PARTY-NOTICES.md
CHANGED
|
@@ -12,12 +12,26 @@ their own license files. Vendored source:
|
|
|
12
12
|
- Source: https://github.com/LedgerHQ/app-bitcoin
|
|
13
13
|
- Version: ledger-bitcoin@0.3.0 (commit 0a9e9e141f3340d29e7c6181177d4e5e9483a9f7)
|
|
14
14
|
- Files: vendored under packages/babylon-ledger-vault-signer/src/vendor/ledger-bitcoin/
|
|
15
|
-
|
|
15
|
+
— the source is in-tree and, from #2219 onward, the compiled vendored code is
|
|
16
|
+
also bundled into the published dist/ (build strips the per-file provenance
|
|
17
|
+
headers, so this notice is the redistribution record; see the audit-boundary
|
|
18
|
+
section of that directory's README)
|
|
16
19
|
- License: Apache License 2.0
|
|
17
20
|
- Modifications: see the per-file provenance headers in the vendored source
|
|
18
|
-
(explicit Buffer import, defensive strict-null guards, formatting;
|
|
19
|
-
additionally
|
|
20
|
-
|
|
21
|
+
(explicit Buffer import, defensive strict-null guards, formatting; varint.ts
|
|
22
|
+
additionally makes `parseVarint` reject the non-minimal "overlong" CompactSize
|
|
23
|
+
encodings upstream accepts; psbtv2.ts additionally drops `fromBitcoinJS`,
|
|
24
|
+
unifies the serialization key comparator to byte-lexicographic order, rejects
|
|
25
|
+
repeated keypairs and trailing bytes on deserialize, and adds two BIP-371
|
|
26
|
+
`psbtIn` enum members plus a public `getInputEntriesOfType` reader;
|
|
27
|
+
clientCommands.ts adds an optional `onYield` validator hook to `YieldCommand`
|
|
28
|
+
/ `ClientCommandInterpreter`; buffertools.ts additionally makes
|
|
29
|
+
`unsafeTo64bitLE` reject input that is not a non-negative safe integer, which
|
|
30
|
+
upstream wrapped or encoded as zero; merkelizedPsbt.ts additionally requires
|
|
31
|
+
the input/output map counts to equal the declared `PSBT_GLOBAL_*_COUNT`s in
|
|
32
|
+
both directions, where upstream ignored surplus maps; merkle.ts additionally
|
|
33
|
+
throws a typed `Error` rather than a raw `TypeError` on an out-of-bounds leaf
|
|
34
|
+
index).
|
|
21
35
|
|
|
22
36
|
### Apache License 2.0
|
|
23
37
|
|
package/dist/dmkApduSender.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { DmkSessionHandle } from './dmkSession';
|
|
2
|
+
import { RawApduSender } from './rawApdu';
|
|
2
3
|
import { ApduSender } from './vaultCommands';
|
|
3
4
|
/**
|
|
4
|
-
* Build a sender bound to one device session
|
|
5
|
+
* Build a non-throwing sender bound to one device session: every status word
|
|
6
|
+
* — 0xE000 included — comes back as data. A `sessionId` must never outlive
|
|
5
7
|
* its connection — recreate the sender whenever the session changes.
|
|
6
8
|
*/
|
|
9
|
+
export declare function createDmkRawApduSender(handle: DmkSessionHandle): RawApduSender;
|
|
10
|
+
/**
|
|
11
|
+
* Build the ceremony's throwing sender: the raw sender plus the shared
|
|
12
|
+
* status-word classification (typed error on anything but 0x9000), carrying
|
|
13
|
+
* the connect-time app identity so 0x6E00 names the app that answered.
|
|
14
|
+
*/
|
|
7
15
|
export declare function createDmkApduSender(handle: DmkSessionHandle): ApduSender;
|
|
8
16
|
//# sourceMappingURL=dmkApduSender.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dmkApduSender.d.ts","sourceRoot":"","sources":["../src/dmkApduSender.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dmkApduSender.d.ts","sourceRoot":"","sources":["../src/dmkApduSender.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAmD,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAChG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAkDlD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,CAqB9E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAKxE"}
|
package/dist/dmkSession.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dmkSession.d.ts","sourceRoot":"","sources":["../src/dmkSession.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAoB,MAAM,iCAAiC,CAAC;AAU9G,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,mBAAmB,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;
|
|
1
|
+
{"version":3,"file":"dmkSession.d.ts","sourceRoot":"","sources":["../src/dmkSession.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAoB,MAAM,iCAAiC,CAAC;AAU9G,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,mBAAmB,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAwCD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAkBnE;AAuBD;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAU/E;AAED,sEAAsE;AACtE,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMlF;AAED;;;GAGG;AACH,wBAAgB,QAAQ,IAAI,IAAI,CAI/B"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
export declare const LEDGER_USER_REFUSED_ERROR_NAME = "LedgerUserRefusedError";
|
|
11
11
|
export declare const LEDGER_DEVICE_LOCKED_ERROR_NAME = "LedgerDeviceLockedError";
|
|
12
12
|
export declare const LEDGER_DEVICE_ERROR_NAME = "LedgerDeviceError";
|
|
13
|
+
export declare const LEDGER_YIELD_MISMATCH_ERROR_NAME = "LedgerYieldMismatchError";
|
|
14
|
+
export declare const LEDGER_SIGN_PSBT_INCOMPLETE_ERROR_NAME = "LedgerSignPsbtIncompleteError";
|
|
15
|
+
export declare const LEDGER_SIGN_PSBT_PROTOCOL_ERROR_NAME = "LedgerSignPsbtProtocolError";
|
|
16
|
+
export declare const LEDGER_SIGN_PSBT_ABORTED_ERROR_NAME = "LedgerSignPsbtAbortedError";
|
|
13
17
|
/**
|
|
14
18
|
* The user declined the request on-device. The message keeps the
|
|
15
19
|
* "User rejected" prefix — wallet-connector's `isUserRejectionMessage` and
|
|
@@ -34,7 +38,105 @@ export declare class LedgerDeviceError extends Error {
|
|
|
34
38
|
readonly statusWord: number;
|
|
35
39
|
constructor(statusWord: number, message: string);
|
|
36
40
|
}
|
|
41
|
+
export type LedgerYieldMismatchKind = "unexpected-input" | "wrong-spend-type" | "wrong-signer-key" | "unknown-leaf-hash" | "non-default-sighash" | "duplicate-yield" | "unexpected-encoding";
|
|
42
|
+
/**
|
|
43
|
+
* A SIGN_PSBT YIELD failed the expected-signature table assertion — a
|
|
44
|
+
* misrouted signature caught before it is ever recorded or merged. The loop
|
|
45
|
+
* stops sending CONTINUEs and never retries a YIELD (per-type signature caps
|
|
46
|
+
* and the payout claimer mask make a replayed SIGN_PSBT after partial YIELDs
|
|
47
|
+
* non-idempotent — fw `sign_custom_inputs.c:180-181,348-352`).
|
|
48
|
+
*/
|
|
49
|
+
export declare class LedgerYieldMismatchError extends Error {
|
|
50
|
+
readonly kind: LedgerYieldMismatchKind;
|
|
51
|
+
readonly inputIndex?: number;
|
|
52
|
+
constructor(kind: LedgerYieldMismatchKind, inputIndex?: number);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* SIGN_PSBT ended 0x9000 but the collected yields are not set-equal to the
|
|
56
|
+
* expected table — e.g. the device silently skipped an input. Failing here
|
|
57
|
+
* loudly prevents a half-signed PSBT from reaching the merge.
|
|
58
|
+
*/
|
|
59
|
+
export declare class LedgerSignPsbtIncompleteError extends Error {
|
|
60
|
+
/** Missing (input, leaf) units: `"i:leafHex"` for tapscript, `"i"` for keypath. */
|
|
61
|
+
readonly missing: readonly string[];
|
|
62
|
+
constructor(missing: readonly string[]);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Non-secret identity of one accepted YIELD: which input it signed, and for a
|
|
66
|
+
* tapscript spend which taptree leaf — a public value the input's control
|
|
67
|
+
* block already commits to. It deliberately carries NO signature material:
|
|
68
|
+
* an Error is the object most likely to be `console.error`'d or shipped to
|
|
69
|
+
* telemetry, and both that and `JSON.stringify` serialize own enumerable
|
|
70
|
+
* properties, so anything attached here is effectively logged (CLAUDE.md
|
|
71
|
+
* critical path #7 — never log signatures or payload bytes).
|
|
72
|
+
*/
|
|
73
|
+
export interface CollectedYieldRef {
|
|
74
|
+
readonly inputIndex: number;
|
|
75
|
+
/** Lowercase-hex tapleaf hash; absent on keypath spends. */
|
|
76
|
+
readonly leafHashHex?: string;
|
|
77
|
+
/** Type-level guard: makes a full `CollectedYield` fail to assign here. */
|
|
78
|
+
readonly signature?: never;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Strip accepted yields down to their identity. The parameter is structural so
|
|
82
|
+
* this module imports nothing, and every returned object is fresh — no
|
|
83
|
+
* signature bytes ride along by reference.
|
|
84
|
+
*/
|
|
85
|
+
export declare function toCollectedYieldRefs(yields: readonly {
|
|
86
|
+
readonly inputIndex: number;
|
|
87
|
+
readonly leafHashHex?: string;
|
|
88
|
+
}[]): readonly CollectedYieldRef[];
|
|
89
|
+
/**
|
|
90
|
+
* A host-side SIGN_PSBT protocol failure: a prepare-time rejection, an
|
|
91
|
+
* unparseable YIELD payload, or an interpreter request outside the committed
|
|
92
|
+
* PSBT material. With our commitments seeded up front, these mean host bug or
|
|
93
|
+
* corrupted exchange — never a user action.
|
|
94
|
+
*/
|
|
95
|
+
export declare class LedgerSignPsbtProtocolError extends Error {
|
|
96
|
+
readonly detail: string;
|
|
97
|
+
/**
|
|
98
|
+
* Which yields the device had already delivered when the failure hit, by
|
|
99
|
+
* identity only (see {@link CollectedYieldRef}); empty for prepare-time
|
|
100
|
+
* rejections, which run before any device I/O. Diagnostics only — nothing in
|
|
101
|
+
* this package reads them, and whether a failed ceremony burns the device
|
|
102
|
+
* signatures is unresolved, so there is no retry or resume path here.
|
|
103
|
+
*/
|
|
104
|
+
readonly collectedYields: readonly CollectedYieldRef[];
|
|
105
|
+
constructor(detail: string, collectedYields?: readonly CollectedYieldRef[]);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The host abandoned the SIGN_PSBT loop (abort signal) — the loop stops
|
|
109
|
+
* sending, nothing else. What the device does next (verified at base app rev
|
|
110
|
+
* `e400d8d8` + fw `90cf41f`; the `6fcad4fd`→`90cf41f` delta is payout-validation
|
|
111
|
+
* only and touches neither path below):
|
|
112
|
+
*
|
|
113
|
+
* - Within ~5 s (50 ticks, `base:io_ext.h:28`) the device sits blocked
|
|
114
|
+
* awaiting CONTINUE; the next non-CONTINUE APDU is eaten with 0x6A80 and the
|
|
115
|
+
* interrupted handler unwinds (`base:dispatcher.c:107-111`) — a direct retry
|
|
116
|
+
* uses `resendOnceOnIncorrectData`.
|
|
117
|
+
* - A validation-phase abandonment leaves the intent intact; a Payout/NoPayout
|
|
118
|
+
* SIGNING-phase abandonment invalidates it (`fw:sign_custom_inputs.c:207-344`)
|
|
119
|
+
* — post-abort "intent-loaded" is a HINT only, and the retry path must also
|
|
120
|
+
* absorb 0xB007.
|
|
121
|
+
* - After >5 s of host silence the app exits to the dashboard
|
|
122
|
+
* (`base:io_ext.c:103-111` → SDK `app_exit()`); the host then sees 0x6E00 or
|
|
123
|
+
* a transport failure — full re-ceremony required.
|
|
124
|
+
*/
|
|
125
|
+
export declare class LedgerSignPsbtAbortedError extends Error {
|
|
126
|
+
/** Yields the device had already delivered when the host stopped sending. */
|
|
127
|
+
readonly yieldedCount: number;
|
|
128
|
+
/**
|
|
129
|
+
* True only when the abort left a dispatcher mid-interruption (device
|
|
130
|
+
* awaiting CONTINUE) — the one state the resend-once recovery exists for.
|
|
131
|
+
*/
|
|
132
|
+
readonly dispatcherInterrupted: boolean;
|
|
133
|
+
constructor(yieldedCount: number, dispatcherInterrupted: boolean);
|
|
134
|
+
}
|
|
37
135
|
export declare function isLedgerUserRefusedError(error: unknown): error is LedgerUserRefusedError;
|
|
38
136
|
export declare function isLedgerDeviceError(error: unknown): error is LedgerDeviceError;
|
|
39
137
|
export declare function isLedgerDeviceLockedError(error: unknown): error is LedgerDeviceLockedError;
|
|
138
|
+
export declare function isLedgerYieldMismatchError(error: unknown): error is LedgerYieldMismatchError;
|
|
139
|
+
export declare function isLedgerSignPsbtIncompleteError(error: unknown): error is LedgerSignPsbtIncompleteError;
|
|
140
|
+
export declare function isLedgerSignPsbtProtocolError(error: unknown): error is LedgerSignPsbtProtocolError;
|
|
141
|
+
export declare function isLedgerSignPsbtAbortedError(error: unknown): error is LedgerSignPsbtAbortedError;
|
|
40
142
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,8BAA8B,2BAA2B,CAAC;AACvE,eAAO,MAAM,+BAA+B,4BAA4B,CAAC;AACzE,eAAO,MAAM,wBAAwB,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,8BAA8B,2BAA2B,CAAC;AACvE,eAAO,MAAM,+BAA+B,4BAA4B,CAAC;AACzE,eAAO,MAAM,wBAAwB,sBAAsB,CAAC;AAC5D,eAAO,MAAM,gCAAgC,6BAA6B,CAAC;AAC3E,eAAO,MAAM,sCAAsC,kCAAkC,CAAC;AACtF,eAAO,MAAM,oCAAoC,gCAAgC,CAAC;AAClF,eAAO,MAAM,mCAAmC,+BAA+B,CAAC;AAMhF;;;;;GAKG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,UAAU,EAAE,MAAM;CAK/B;AAED,+DAA+D;AAC/D,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,UAAU,EAAE,MAAM;CAK/B;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAKhD;AAED,MAAM,MAAM,uBAAuB,GAC/B,kBAAkB,GAClB,kBAAkB,GAClB,kBAAkB,GAClB,mBAAmB,GACnB,qBAAqB,GACrB,iBAAiB,GACjB,qBAAqB,CAAC;AAE1B;;;;;;GAMG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAEjB,IAAI,EAAE,uBAAuB,EAAE,UAAU,CAAC,EAAE,MAAM;CAS/D;AAED;;;;GAIG;AACH,qBAAa,6BAA8B,SAAQ,KAAK;IACtD,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;gBAExB,OAAO,EAAE,SAAS,MAAM,EAAE;CAQvC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAChF,SAAS,iBAAiB,EAAE,CAI9B;AAED;;;;;GAKG;AACH,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,QAAQ,CAAC,eAAe,EAAE,SAAS,iBAAiB,EAAE,CAAC;gBAE3C,MAAM,EAAE,MAAM,EAAE,eAAe,GAAE,SAAS,iBAAiB,EAAO;CAM/E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;gBAE5B,YAAY,EAAE,MAAM,EAAE,qBAAqB,EAAE,OAAO;CAMjE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAExF;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,uBAAuB,CAE1F;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,wBAAwB,CAE5F;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,6BAA6B,CAEtG;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,2BAA2B,CAElG;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,0BAA0B,CAEhG"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
|
+
export type InputSigExpectation = {
|
|
3
|
+
readonly kind: "tapscript";
|
|
4
|
+
/** TapLeaf hashes (lowercase hex) of this input's TAP_LEAF_SCRIPT entries. */
|
|
5
|
+
readonly expectedLeafHashHexes: ReadonlySet<string>;
|
|
6
|
+
/** UNTWEAKED depositor x-only key — the tapscript branch leaves `tweak_data` NULL
|
|
7
|
+
* (`base:sign_input.c:430-433`), so no tweak is applied (`base:sign_input.c:159-161`). */
|
|
8
|
+
readonly expectedSignerXOnlyHex: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly kind: "taproot-keypath";
|
|
11
|
+
/** BIP-86 tweaked output key == witness program of the input's P2TR scriptPubKey. */
|
|
12
|
+
readonly expectedOutputKeyHex: string;
|
|
13
|
+
};
|
|
14
|
+
export interface ExpectedSignatureTable {
|
|
15
|
+
/** inputIndex → expectation. Inputs absent here must never appear in a YIELD. */
|
|
16
|
+
readonly byInput: ReadonlyMap<number, InputSigExpectation>;
|
|
17
|
+
/** Σ over inputs: tapscript → |expectedLeafHashHexes|; keypath → 1. */
|
|
18
|
+
readonly expectedYieldCount: number;
|
|
19
|
+
}
|
|
20
|
+
export type CollectedYield = {
|
|
21
|
+
readonly kind: "tapscript";
|
|
22
|
+
readonly inputIndex: number;
|
|
23
|
+
readonly signerXOnlyHex: string;
|
|
24
|
+
readonly leafHashHex: string;
|
|
25
|
+
/** Exactly 64 bytes (SIGHASH_DEFAULT on all vault paths). */
|
|
26
|
+
readonly signature: Uint8Array;
|
|
27
|
+
} | {
|
|
28
|
+
readonly kind: "taproot-keypath";
|
|
29
|
+
readonly inputIndex: number;
|
|
30
|
+
readonly outputKeyHex: string;
|
|
31
|
+
readonly signature: Uint8Array;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The per-input read surface of the vendored `PsbtV2` the table builder
|
|
35
|
+
* consumes — structural, so no vendored symbol reaches the emitted
|
|
36
|
+
* declarations (vendor d.ts is excluded from dist; see `vite.config.ts`).
|
|
37
|
+
*/
|
|
38
|
+
export interface ExpectedSignaturePsbt {
|
|
39
|
+
getGlobalInputCount(): number;
|
|
40
|
+
getInputEntriesOfType(inputIndex: number, keyType: number): readonly {
|
|
41
|
+
readonly keyData: Buffer;
|
|
42
|
+
readonly value: Buffer;
|
|
43
|
+
}[];
|
|
44
|
+
getInputWitnessUtxo(inputIndex: number): {
|
|
45
|
+
readonly amount: number;
|
|
46
|
+
readonly scriptPubKey: Buffer;
|
|
47
|
+
} | undefined;
|
|
48
|
+
}
|
|
49
|
+
export interface BuildExpectedSignatureTableParams {
|
|
50
|
+
/**
|
|
51
|
+
* The exact map model committed to the device — pass the MerkelizedPsbt
|
|
52
|
+
* instance, not a re-parse, so there is no parse/serialize gap.
|
|
53
|
+
*/
|
|
54
|
+
readonly psbt: ExpectedSignaturePsbt;
|
|
55
|
+
/** Connected depositor x-only key (64 lowercase hex) — pins the table. */
|
|
56
|
+
readonly depositorXOnlyHex: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Classify every input of the committed map model (build rules per the B1-c
|
|
60
|
+
* spec §3.1; BIP-371 key types verified against `base:psbt.h:37-42`).
|
|
61
|
+
* Throws `LedgerSignPsbtProtocolError` on any rule violation — all before any
|
|
62
|
+
* device I/O.
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildExpectedSignatureTable(params: BuildExpectedSignatureTableParams): ExpectedSignatureTable;
|
|
65
|
+
export interface YieldCollector {
|
|
66
|
+
/**
|
|
67
|
+
* Interpreter `onYield`: parse + assert + record. Throws
|
|
68
|
+
* `LedgerYieldMismatchError` (semantic) / `LedgerSignPsbtProtocolError`
|
|
69
|
+
* (unparseable). A throw propagates out of `interpreter.execute()` BEFORE
|
|
70
|
+
* the payload is recorded (`clientCommands.ts` onYield seam).
|
|
71
|
+
*/
|
|
72
|
+
assertAndRecord(payload: Buffer): void;
|
|
73
|
+
readonly yields: readonly CollectedYield[];
|
|
74
|
+
/** Drives onProgress in the loop. */
|
|
75
|
+
readonly lastYield: CollectedYield | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* After sw 0x9000, before merge: set equality in BOTH directions.
|
|
78
|
+
* Throws `LedgerSignPsbtIncompleteError`.
|
|
79
|
+
*/
|
|
80
|
+
assertComplete(): void;
|
|
81
|
+
}
|
|
82
|
+
export declare function createYieldCollector(table: ExpectedSignatureTable): YieldCollector;
|
|
83
|
+
//# sourceMappingURL=expectedSignatures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expectedSignatures.d.ts","sourceRoot":"","sources":["../src/expectedSignatures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAuChC,MAAM,MAAM,mBAAmB,GAC3B;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,8EAA8E;IAC9E,QAAQ,CAAC,qBAAqB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpD;8FAC0F;IAC1F,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACzC,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,qFAAqF;IACrF,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;CACvC,CAAC;AAEN,MAAM,WAAW,sBAAsB;IACrC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC3D,uEAAuE;IACvE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,MAAM,cAAc,GACtB;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;CAChC,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;CAChC,CAAC;AAEN;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,mBAAmB,IAAI,MAAM,CAAC;IAC9B,qBAAqB,CACnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,SAAS;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnE,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACjH;AAED,MAAM,WAAW,iCAAiC;IAChD;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,0EAA0E;IAC1E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AAwFD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,iCAAiC,GAAG,sBAAsB,CAqH7G;AAED,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,qCAAqC;IACrC,QAAQ,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IAC/C;;;OAGG;IACH,cAAc,IAAI,IAAI,CAAC;CACxB;AAsBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,sBAAsB,GAAG,cAAc,CAwHlF"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var le=Object.create;var O=Object.defineProperty;var _e=Object.getOwnPropertyDescriptor;var de=Object.getOwnPropertyNames;var he=Object.getPrototypeOf,pe=Object.prototype.hasOwnProperty;var Te=(e,t,n)=>t in e?O(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var fe=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of de(t))!pe.call(e,o)&&o!==n&&O(e,o,{get:()=>t[o],enumerable:!(r=_e(t,o))||r.enumerable});return e};var d=(e,t,n)=>(n=e!=null?le(he(e)):{},fe(t||!e||!e.__esModule?O(n,"default",{value:e,enumerable:!0}):n,e));var w=(e,t,n)=>Te(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ge=require("@scure/bip32"),Ae=1,me=1,Re=1,we=2,Ce=33,Se=256,Pe=257,$e=258,De=39,Ie=259,ve=105,Oe=260,Le=261,Ve=262,ye=271,Ue=265,Ne=266,Me=267,ke=268,be=269,Ge=270,Fe=263,xe=264,D=32,Be=32,S=255,Ke=3+D,b=Math.floor(S/Ke);function _(e,t){if(t.length>S)throw new Error(`TLV value for tag 0x${e.toString(16)} exceeds 255 bytes`);const n=new Uint8Array(3+t.length);return n[0]=e>>8&255,n[1]=e&255,n[2]=t.length,n.set(t,3),n}function v(e,t,n){if(e<0n||e>=1n<<BigInt(8*t))throw new Error(`${n} ${e} does not fit in ${t} bytes`);const r=new Uint8Array(t);let o=e;for(let i=t-1;i>=0;i--)r[i]=Number(o&0xffn),o>>=8n;return r}function T(e,t,n){return _(e,v(BigInt(t),1,n))}function $(e,t,n){return _(e,v(BigInt(t),4,n))}function g(e,t,n){return _(e,v(t,8,n))}function I(e){const t=e.reduce((o,i)=>o+i.length,0),n=new Uint8Array(t);let r=0;for(const o of e)n.set(o,r),r+=o.length;return n}function U(e,t,n){if(e.length!==t)throw new Error(`${n} must be ${t} bytes, got ${e.length}`);return e}const G=5;function te(e){if(e.depositorPath.length!==G)throw new Error(`depositorPath must have exactly ${G} levels, got ${e.depositorPath.length}`);const t=I(e.depositorPath.map(n=>v(BigInt(n>>>0),4,"path level")));return I([T(Re,Ae,"structureType"),T(we,me,"version"),$(Ce,e.coinType,"coinType"),g(Se,e.baseFeeRate,"baseFeeRate"),$(Pe,e.peginCsvTimelock,"peginCsvTimelock"),$($e,e.payoutTimelock,"payoutTimelock"),_(De,U(e.prepeginTxidInternal,Be,"prepeginTxid")),$(Ie,e.htlcRefundTimelock,"htlcRefundTimelock"),_(ve,t),T(Oe,e.keeperCount,"keeperCount"),T(Le,e.challengerCount,"challengerCount"),T(Ve,e.vaultCount,"vaultCount"),g(ye,e.prepeginMaxFee,"prepeginMaxFee")])}function ne(e){return I([T(Ue,e.htlcVout,"htlcVout"),_(Ne,U(e.vaultProviderPubkey,D,"vaultProviderPubkey")),g(Me,e.vaultAmount,"vaultAmount"),g(ke,e.commissionFee,"commissionFee"),g(be,e.depositorClaimValue,"depositorClaimValue"),g(Ge,e.peginMaxFee,"peginMaxFee")])}function oe(e,t){const n=(i,u)=>i.map((s,E)=>U(s,D,`${u}[${E}]`)).sort((s,E)=>{for(let l=0;l<D;l++)if(s[l]!==E[l])return s[l]-E[l];return 0}),r=[...n(e,"keeper").map(i=>_(Fe,i)),...n(t,"challenger").map(i=>_(xe,i))],o=[];for(let i=0;i<r.length;i+=b)o.push(I(r.slice(i,i+b)));return o}const m=225,L=128,F=129,He=0,Ye=1,Xe=0,je=1,We=2,P=0,x=64,B=1024,K=10,H=32;function qe(e){return new Uint8Array([e>>8&255,e&255])}function Je(e){const t=e>>>0;return new Uint8Array([t>>>24&255,t>>>16&255,t>>>8&255,t&255])}function V(e){const t=new Uint8Array(e.reduce((r,o)=>r+o.length,0));let n=0;for(const r of e)t.set(r,n),n+=r.length;return t}const Y=/^[a-z0-9-]+$/;async function ze(e,{appName:t,derivationPath:n,context:r}){const o=new TextEncoder().encode(t);if(o.length<1||o.length>x)throw new Error(`appName must be 1..${x} bytes, got ${o.length}`);if(!Y.test(t))throw new Error(`appName must match ${Y} — the device rejects other characters`);if(n.length<1||n.length>K)throw new Error(`derivationPath must have 1..${K} levels`);if(r.length<1||r.length>B)throw new Error(`context must be 1..${B} bytes, got ${r.length}`);const i=V([new Uint8Array([o.length]),o,new Uint8Array([n.length]),V(n.map(Je)),qe(r.length)]),u=Math.min(r.length,S-i.length);if(u<0)throw new Error("appName and derivationPath leave no room for context in the first APDU");let s=await e({cla:m,ins:F,p1:He,p2:P,data:V([i,r.subarray(0,u)])});for(let E=u;E<r.length;E+=S)s=await e({cla:m,ins:F,p1:Ye,p2:P,data:r.subarray(E,E+S)});if(s.length!==H)throw new Error(`Expected a ${H}-byte context root, got ${s.length} bytes`);return s}async function Qe(e,{scalars:t,groups:n,keeperPubkeys:r,challengerPubkeys:o}){if(n.length!==t.vaultCount)throw new Error(`vaultCount ${t.vaultCount} does not match ${n.length} group(s)`);if(r.length!==t.keeperCount)throw new Error(`keeperCount ${t.keeperCount} does not match ${r.length} key(s)`);if(t.keeperCount<1||t.challengerCount<1)throw new Error(`Both rosters must be non-empty: keeperCount=${t.keeperCount}, challengerCount=${t.challengerCount}`);if(o.length!==t.challengerCount)throw new Error(`challengerCount ${t.challengerCount} does not match ${o.length} key(s)`);await e({cla:m,ins:L,p1:Xe,p2:P,data:te(t)});for(const i of n)await e({cla:m,ins:L,p1:je,p2:P,data:ne(i)});for(const i of oe(r,o))await e({cla:m,ins:L,p1:We,p2:P,data:i})}const Ze=0,et=0,tt=1,nt=0,X=33,j=10;async function ot(e,t,n){if(t.length<1||t.length>j)throw new Error(`BIP-32 path must have 1..${j} levels, got ${t.length}`);const r=await e({cla:m,ins:Ze,p1:et,p2:tt,data:st(t)}),o=new TextDecoder().decode(r),i=ge.HDKey.fromExtendedKey(o,n);if(!i.publicKey||i.publicKey.length!==X)throw new Error(`Ledger returned an extended key without a ${X}-byte public key`);return rt(i.publicKey.subarray(1))}function rt(e){return Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function st(e){const t=new Uint8Array(2+e.length*4);return t[0]=nt,t[1]=e.length,e.forEach((n,r)=>{const o=2+r*4;t[o]=n>>>24&255,t[o+1]=n>>>16&255,t[o+2]=n>>>8&255,t[o+3]=n&255}),t}const N="LedgerUserRefusedError",M="LedgerDeviceLockedError",k="LedgerDeviceError";function re(e){return e.toString(16).padStart(4,"0")}class se extends Error{constructor(n){super(`User rejected the request on the Ledger device (0x${re(n)})`);w(this,"statusWord");this.name=N,this.statusWord=n}}class ie extends Error{constructor(n){super(`The Ledger device is locked — unlock it and retry (0x${re(n)})`);w(this,"statusWord");this.name=M,this.statusWord=n}}class ce extends Error{constructor(n,r){super(r);w(this,"statusWord");this.name=k,this.statusWord=n}}function it(e){return e instanceof Error&&e.name===N}function ct(e){return e instanceof Error&&e.name===k}function at(e){return e instanceof Error&&e.name===M}const ut=36864,Et=new Set([21761,27013]),lt=new Set([21781,27010,21251]),W=2,ae=28160,_t={27264:"The device rejected the data as invalid",27266:"The device does not support this request — check that the app build matches the selected network",27270:"The device rejected the instruction parameters",27271:"The device rejected the payload length",27904:"The running app does not support this instruction",[ae]:"The running app does not handle vault instructions — open the Babylon Vault app",45056:"The device reported a wrong response length",45063:"The device is not in the expected state for this step",45064:"The device rejected a signature or HMAC as invalid",45065:"The device rejected the CPFP anchor",45066:"The device has already signed the maximum number of these transactions",28416:"The device reported an internal error"};function dt(e){if(e.statusCode.length!==W)throw new Error(`The device returned a ${e.statusCode.length}-byte status word; expected ${W}.`);return e.statusCode[0]<<8|e.statusCode[1]}function ht(e){if(e.data.length>255)throw new Error(`APDU data is ${e.data.length} bytes; Lc is a single byte (max 255)`);const t=new Uint8Array(5+e.data.length);return t[0]=e.cla,t[1]=e.ins,t[2]=e.p1,t[3]=e.p2,t[4]=e.data.length,t.set(e.data,5),t}function q(){return globalThis.__LEDGER_VAULT_APDU_TRACE__===!0}function h(e){return e.toString(16).padStart(2,"0")}function J(e){return e.toString(16).padStart(4,"0")}function pt(e){return async t=>{const n=`${h(t.cla)} ${h(t.ins)} ${h(t.p1)} ${h(t.p2)} Lc=${t.data.length}`;let r;try{r=await e.dmk.sendApdu({sessionId:e.sessionId,apdu:ht(t)})}catch(i){throw q()&&console.debug(`[ledger-vault] APDU ${n} -> transport error`,i),i}const o=dt(r);if(q()&&console.debug(`[ledger-vault] APDU ${n} -> sw=0x${J(o)} len=${r.data.length}`),Et.has(o))throw new se(o);if(lt.has(o))throw new ie(o);if(o!==ut){const i=_t[o],u=o===ae&&e.appName?` (app at connect time: "${e.appName}"${e.appVersion?` v${e.appVersion}`:""})`:"";throw new ce(o,`${i??"The device rejected the request"} (ins 0x${h(t.ins)} p1 0x${h(t.p1)}, sw 0x${J(o)})${u}`)}return r.data}}const Tt={isRefresherDisabled:!0};let A,f;function ft(){if(!f){const e=(async()=>{const[{DeviceManagementKitBuilder:t},{webHidTransportFactory:n}]=await Promise.all([import("@ledgerhq/device-management-kit"),import("@ledgerhq/device-transport-kit-web-hid")]);return A=new t().addTransport(n).build(),A})().catch(t=>{throw f===e&&(f=void 0),t});f=e}return f}async function gt(){const e=await ft(),[{firstValueFrom:t},{webHidIdentifier:n}]=await Promise.all([import("rxjs"),import("@ledgerhq/device-transport-kit-web-hid")]),r=await t(e.startDiscovering({transport:n})),o=await e.connect({device:r,sessionRefresherOptions:Tt}),i=await At(e,o);return{dmk:e,sessionId:o,...i}}async function At(e,t){try{const{GetAppAndVersionCommand:n,isSuccessCommandResult:r}=await import("@ledgerhq/device-management-kit"),o=await e.sendCommand({sessionId:t,command:new n});return r(o)?{appName:o.data.name,appVersion:o.data.version}:{}}catch{return{}}}async function mt(e){const{firstValueFrom:t}=await import("rxjs");try{return await t(e.dmk.getDeviceSessionState({sessionId:e.sessionId})),!0}catch(n){if((n==null?void 0:n._tag)==="DeviceSessionNotFound")return!1;throw n}}async function Rt(e){try{await e.dmk.disconnect({sessionId:e.sessionId})}catch{}}function wt(){A==null||A.close(),A=void 0,f=void 0}const z=32,Ct=10,Q=0xffffffffn,Z=72,St=1008,Pt=4320,$t=91,Dt=4031,ue=546n,ee=ue,It=2n,y=2,Ee="DepositTermsRejectedError";class c extends Error{constructor(n,r="device-envelope"){super(n);w(this,"reason");this.name=Ee,this.reason=r}}const a="Deposit terms outside the device-supported range";function p(e,t,n,r){if(!Number.isInteger(t)||t<n||t>r)throw new c(`${a}: ${e} ${t} not in [${n}, ${r}]`)}function vt(e){if(e.vaultCoreVersion!==y)throw new c(`${a}: vaultCoreVersion ${e.vaultCoreVersion} is not ${y}; this device only supports tx-graph v${y} deposits.`);if(e.protocolFeeRate<1n||e.protocolFeeRate>Q)throw new c(`${a}: protocolFeeRate ${e.protocolFeeRate} not in [1, ${Q}]`);if(p("timelockPegin",e.timelockPegin,Z,St),p("timelockAssert",e.timelockAssert,$t,Dt),p("timelockRefund",e.timelockRefund,Z,Pt),p("keeper count",e.vaultKeeperBtcPubkeys.length,1,z),p("challenger count",e.universalChallengerBtcPubkeys.length,1,z),p("vault count",e.vaults.length,1,Ct),C("prepeginMaxFee",e.prepeginMaxFee),e.prepeginMaxFee<1n)throw new c(`${a}: prepeginMaxFee ${e.prepeginMaxFee} must be >= 1`);let t=-1;for(const s of e.vaults){if(!Number.isInteger(s.htlcVout)||s.htlcVout<0||s.htlcVout>255)throw new c(`${a}: htlcVout ${s.htlcVout} not in [0, 255]`);if(s.htlcVout<=t)throw new c(`${a}: vault groups must be in strictly ascending htlcVout order; got ${s.htlcVout} after ${t}`);t=s.htlcVout}const n=s=>s.replace(/^0x/,"").toLowerCase(),r=new Set(e.vaults.map(s=>n(s.vaultProviderBtcPubkey))),o=new Set;for(const[s,E]of[["vaultKeeperBtcPubkeys",e.vaultKeeperBtcPubkeys],["universalChallengerBtcPubkeys",e.universalChallengerBtcPubkeys]])for(const l of E){const R=n(l);if(r.has(R))throw new c(`${a}: ${s} contains the vault provider's own key (${R.slice(0,16)}…)`);if(o.has(R))throw new c(`${a}: duplicate participant key in ${s} (${R.slice(0,16)}…)`);o.add(R)}const i=ue,u=It*i;for(const s of e.vaults){if(C(`vault ${s.htlcVout} peginAmount`,s.peginAmount),C(`vault ${s.htlcVout} commissionFee`,s.commissionFee),C(`vault ${s.htlcVout} depositorClaimValue`,s.depositorClaimValue),C(`vault ${s.htlcVout} peginMaxFee`,s.peginMaxFee),s.commissionFee<i)throw new c(`${a}: vault ${s.htlcVout} commissionFee ${s.commissionFee} below the ${i}-sat dust limit`);if(s.depositorClaimValue<ee)throw new c(`${a}: vault ${s.htlcVout} depositorClaimValue ${s.depositorClaimValue} below the ${ee}-sat device floor`);if(s.peginAmount<=s.commissionFee+u)throw new c(`${a}: vault ${s.htlcVout} peginAmount ${s.peginAmount} must exceed commissionFee + ${u} (${s.commissionFee+u})`)}}const Ot=(1n<<64n)-1n;function C(e,t){if(t<0n||t>Ot)throw new c(`${a}: ${e} ${t} does not fit in an unsigned 64-bit field`)}exports.DEPOSIT_TERMS_REJECTED_ERROR_NAME=Ee;exports.DepositTermsRejectedError=c;exports.LEDGER_DEVICE_ERROR_NAME=k;exports.LEDGER_DEVICE_LOCKED_ERROR_NAME=M;exports.LEDGER_USER_REFUSED_ERROR_NAME=N;exports.LedgerDeviceError=ce;exports.LedgerDeviceLockedError=ie;exports.LedgerUserRefusedError=se;exports.approveVaultIntent=Qe;exports.assertDepositTermsDeviceCompatible=vt;exports.closeDmk=wt;exports.connectDmkSession=gt;exports.createDmkApduSender=pt;exports.deriveContextHash=ze;exports.disconnectDmkSession=Rt;exports.encodeIntentGroup=ne;exports.encodeIntentScalars=te;exports.encodeKeyBatches=oe;exports.getXOnlyPublicKeyHex=ot;exports.isLedgerDeviceError=ct;exports.isLedgerDeviceLockedError=at;exports.isLedgerUserRefusedError=it;exports.isSessionAlive=mt;
|
|
1
|
+
"use strict";var Me=Object.create;var rt=Object.defineProperty;var Le=Object.getOwnPropertyDescriptor;var ve=Object.getOwnPropertyNames;var xe=Object.getPrototypeOf,Ne=Object.prototype.hasOwnProperty;var De=(e,t,n)=>t in e?rt(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var $e=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ve(t))!Ne.call(e,o)&&o!==n&&rt(e,o,{get:()=>t[o],enumerable:!(r=Le(t,o))||r.enumerable});return e};var R=(e,t,n)=>(n=e!=null?Me(xe(e)):{},$e(t||!e||!e.__esModule?rt(n,"default",{value:e,enumerable:!0}):n,e));var h=(e,t,n)=>De(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ke=require("@scure/bip32"),u=require("buffer"),w=require("bitcoinjs-lib"),Ue=require("@bitcoin-js/tiny-secp256k1-asmjs");function Ve(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:()=>e[n]})}}return t.default=e,Object.freeze(t)}const ht=Ve(Ue),Ge=1,Ke=1,He=1,Fe=2,Ye=33,Xe=256,qe=257,We=258,ze=39,je=259,Ze=105,Qe=260,Je=261,tn=262,en=271,nn=265,rn=266,on=267,sn=268,an=269,un=270,cn=263,ln=264,J=32,hn=32,V=255,fn=3+J,Rt=Math.floor(V/fn);function b(e,t){if(t.length>V)throw new Error(`TLV value for tag 0x${e.toString(16)} exceeds 255 bytes`);const n=new Uint8Array(3+t.length);return n[0]=e>>8&255,n[1]=e&255,n[2]=t.length,n.set(t,3),n}function nt(e,t,n){if(e<0n||e>=1n<<BigInt(8*t))throw new Error(`${n} ${e} does not fit in ${t} bytes`);const r=new Uint8Array(t);let o=e;for(let s=t-1;s>=0;s--)r[s]=Number(o&0xffn),o>>=8n;return r}function B(e,t,n){return b(e,nt(BigInt(t),1,n))}function X(e,t,n){return b(e,nt(BigInt(t),4,n))}function L(e,t,n){return b(e,nt(t,8,n))}function tt(e){const t=e.reduce((o,s)=>o+s.length,0),n=new Uint8Array(t);let r=0;for(const o of e)n.set(o,r),r+=o.length;return n}function wt(e,t,n){if(e.length!==t)throw new Error(`${n} must be ${t} bytes, got ${e.length}`);return e}const Ct=5;function ne(e){if(e.depositorPath.length!==Ct)throw new Error(`depositorPath must have exactly ${Ct} levels, got ${e.depositorPath.length}`);const t=tt(e.depositorPath.map(n=>nt(BigInt(n>>>0),4,"path level")));return tt([B(He,Ge,"structureType"),B(Fe,Ke,"version"),X(Ye,e.coinType,"coinType"),L(Xe,e.baseFeeRate,"baseFeeRate"),X(qe,e.peginCsvTimelock,"peginCsvTimelock"),X(We,e.payoutTimelock,"payoutTimelock"),b(ze,wt(e.prepeginTxidInternal,hn,"prepeginTxid")),X(je,e.htlcRefundTimelock,"htlcRefundTimelock"),b(Ze,t),B(Qe,e.keeperCount,"keeperCount"),B(Je,e.challengerCount,"challengerCount"),B(tn,e.vaultCount,"vaultCount"),L(en,e.prepeginMaxFee,"prepeginMaxFee")])}function re(e){return tt([B(nn,e.htlcVout,"htlcVout"),b(rn,wt(e.vaultProviderPubkey,J,"vaultProviderPubkey")),L(on,e.vaultAmount,"vaultAmount"),L(sn,e.commissionFee,"commissionFee"),L(an,e.depositorClaimValue,"depositorClaimValue"),L(un,e.peginMaxFee,"peginMaxFee")])}function oe(e,t){const n=(s,i)=>s.map((a,c)=>wt(a,J,`${i}[${c}]`)).sort((a,c)=>{for(let l=0;l<J;l++)if(a[l]!==c[l])return a[l]-c[l];return 0}),r=[...n(e,"keeper").map(s=>b(cn,s)),...n(t,"challenger").map(s=>b(ln,s))],o=[];for(let s=0;s<r.length;s+=Rt)o.push(tt(r.slice(s,s+Rt)));return o}const A=225,ot=128,Ot=129,pn=0,dn=1,gn=0,En=1,wn=2,G=0,Bt=64,Mt=1024,Lt=10,vt=32;function _n(e){return new Uint8Array([e>>8&255,e&255])}function mn(e){const t=e>>>0;return new Uint8Array([t>>>24&255,t>>>16&255,t>>>8&255,t&255])}function st(e){const t=new Uint8Array(e.reduce((r,o)=>r+o.length,0));let n=0;for(const r of e)t.set(r,n),n+=r.length;return t}const xt=/^[a-z0-9-]+$/;async function Tn(e,{appName:t,derivationPath:n,context:r}){const o=new TextEncoder().encode(t);if(o.length<1||o.length>Bt)throw new Error(`appName must be 1..${Bt} bytes, got ${o.length}`);if(!xt.test(t))throw new Error(`appName must match ${xt} — the device rejects other characters`);if(n.length<1||n.length>Lt)throw new Error(`derivationPath must have 1..${Lt} levels`);if(r.length<1||r.length>Mt)throw new Error(`context must be 1..${Mt} bytes, got ${r.length}`);const s=st([new Uint8Array([o.length]),o,new Uint8Array([n.length]),st(n.map(mn)),_n(r.length)]),i=Math.min(r.length,V-s.length);if(i<0)throw new Error("appName and derivationPath leave no room for context in the first APDU");let a=await e({cla:A,ins:Ot,p1:pn,p2:G,data:st([s,r.subarray(0,i)])});for(let c=i;c<r.length;c+=V)a=await e({cla:A,ins:Ot,p1:dn,p2:G,data:r.subarray(c,c+V)});if(a.length!==vt)throw new Error(`Expected a ${vt}-byte context root, got ${a.length} bytes`);return a}async function Sn(e,{scalars:t,groups:n,keeperPubkeys:r,challengerPubkeys:o}){if(n.length!==t.vaultCount)throw new Error(`vaultCount ${t.vaultCount} does not match ${n.length} group(s)`);if(r.length!==t.keeperCount)throw new Error(`keeperCount ${t.keeperCount} does not match ${r.length} key(s)`);if(t.keeperCount<1||t.challengerCount<1)throw new Error(`Both rosters must be non-empty: keeperCount=${t.keeperCount}, challengerCount=${t.challengerCount}`);if(o.length!==t.challengerCount)throw new Error(`challengerCount ${t.challengerCount} does not match ${o.length} key(s)`);await e({cla:A,ins:ot,p1:gn,p2:G,data:ne(t)});for(const s of n)await e({cla:A,ins:ot,p1:En,p2:G,data:re(s)});for(const s of oe(r,o))await e({cla:A,ins:ot,p1:wn,p2:G,data:s})}const In=0,yn=0,Pn=1,bn=0,Nt=33,Dt=10;async function An(e,t,n){if(t.length<1||t.length>Dt)throw new Error(`BIP-32 path must have 1..${Dt} levels, got ${t.length}`);const r=await e({cla:A,ins:In,p1:yn,p2:Pn,data:Cn(t)}),o=new TextDecoder().decode(r),s=ke.HDKey.fromExtendedKey(o,n);if(!s.publicKey||s.publicKey.length!==Nt)throw new Error(`Ledger returned an extended key without a ${Nt}-byte public key`);return Rn(s.publicKey.subarray(1))}function Rn(e){return Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function Cn(e){const t=new Uint8Array(2+e.length*4);return t[0]=bn,t[1]=e.length,e.forEach((n,r)=>{const o=2+r*4;t[o]=n>>>24&255,t[o+1]=n>>>16&255,t[o+2]=n>>>8&255,t[o+3]=n&255}),t}const _t="LedgerUserRefusedError",mt="LedgerDeviceLockedError",Tt="LedgerDeviceError",St="LedgerYieldMismatchError",It="LedgerSignPsbtIncompleteError",yt="LedgerSignPsbtProtocolError",Pt="LedgerSignPsbtAbortedError";function se(e){return e.toString(16).padStart(4,"0")}class ie extends Error{constructor(n){super(`User rejected the request on the Ledger device (0x${se(n)})`);h(this,"statusWord");this.name=_t,this.statusWord=n}}class ae extends Error{constructor(n){super(`The Ledger device is locked — unlock it and retry (0x${se(n)})`);h(this,"statusWord");this.name=mt,this.statusWord=n}}class ue extends Error{constructor(n,r){super(r);h(this,"statusWord");this.name=Tt,this.statusWord=n}}class I extends Error{constructor(n,r){super(`The device yielded a signature that fails the expected-signature table (${n}${r===void 0?"":` on input ${r}`})`);h(this,"kind");h(this,"inputIndex");this.name=St,this.kind=n,this.inputIndex=r}}class ce extends Error{constructor(n){super(`The device completed SIGN_PSBT without yielding every expected signature (missing ${n.length}: ${n.join(", ")})`);h(this,"missing");this.name=It,this.missing=n}}function Z(e){return e.map(({inputIndex:t,leafHashHex:n})=>n===void 0?{inputIndex:t}:{inputIndex:t,leafHashHex:n})}class p extends Error{constructor(n,r=[]){super(`SIGN_PSBT protocol failure: ${n}`);h(this,"detail");h(this,"collectedYields");this.name=yt,this.detail=n,this.collectedYields=r}}class Q extends Error{constructor(n,r){super("SIGN_PSBT was abandoned host-side before completion");h(this,"yieldedCount");h(this,"dispatcherInterrupted");this.name=Pt,this.yieldedCount=n,this.dispatcherInterrupted=r}}function On(e){return e instanceof Error&&e.name===_t}function Bn(e){return e instanceof Error&&e.name===Tt}function Mn(e){return e instanceof Error&&e.name===mt}function le(e){return e instanceof Error&&e.name===St}function Ln(e){return e instanceof Error&&e.name===It}function he(e){return e instanceof Error&&e.name===yt}function vn(e){return e instanceof Error&&e.name===Pt}const xn=36864,Nn=new Set([21761,27013]),Dn=new Set([21781,27010,21251]),fe=28160,pe=45063,de=45066,$n={27264:"The device rejected the data as invalid",27266:"The device does not support this request — check that the app build matches the selected network",27270:"The device rejected the instruction parameters",27271:"The device rejected the payload length",27904:"The running app does not support this instruction",[fe]:"The running app does not handle vault instructions — open the Babylon Vault app",45056:"The device reported a wrong response length",[pe]:"The device is not in the expected state for this step",45064:"The device rejected a signature or HMAC as invalid",45065:"The device rejected the CPFP anchor",[de]:"The device has already signed the maximum number of these transactions",28416:"The device reported an internal error"};function v(e){return e.toString(16).padStart(2,"0")}function ge(e){return e.toString(16).padStart(4,"0")}function Ee(e,t){if(e===xn)return;if(Nn.has(e))return new ie(e);if(Dn.has(e))return new ae(e);const n=$n[e],r=e===fe&&t.appName?` (app at connect time: "${t.appName}"${t.appVersion?` v${t.appVersion}`:""})`:"";return new ue(e,`${n??"The device rejected the request"} (ins 0x${v(t.ins)} p1 0x${v(t.p1)}, sw 0x${ge(e)})${r}`)}function kn(e,t){return async n=>{const{sw:r,data:o}=await e(n),s=Ee(r,{...t,ins:n.ins,p1:n.p1});if(s)throw s;return o}}const $t=2;function Un(e){if(e.statusCode.length!==$t)throw new Error(`The device returned a ${e.statusCode.length}-byte status word; expected ${$t}.`);return e.statusCode[0]<<8|e.statusCode[1]}function q(e,t){if(!Number.isInteger(e)||e<0||e>255)throw new Error(`APDU ${t} ${e} is not a single byte (0..255)`)}function Vn(e){if(q(e.cla,"cla"),q(e.ins,"ins"),q(e.p1,"p1"),q(e.p2,"p2"),e.data.length>255)throw new Error(`APDU data is ${e.data.length} bytes; Lc is a single byte (max 255)`);const t=new Uint8Array(5+e.data.length);return t[0]=e.cla,t[1]=e.ins,t[2]=e.p1,t[3]=e.p2,t[4]=e.data.length,t.set(e.data,5),t}function kt(){return globalThis.__LEDGER_VAULT_APDU_TRACE__===!0}function we(e){return async t=>{const n=`${v(t.cla)} ${v(t.ins)} ${v(t.p1)} ${v(t.p2)} Lc=${t.data.length}`;let r;try{r=await e.dmk.sendApdu({sessionId:e.sessionId,apdu:Vn(t)})}catch(s){throw kt()&&console.debug(`[ledger-vault] APDU ${n} -> transport error`,s),s}const o=Un(r);return kt()&&console.debug(`[ledger-vault] APDU ${n} -> sw=0x${ge(o)} len=${r.data.length}`),{sw:o,data:r.data}}}function Gn(e){return kn(we(e),{appName:e.appName,appVersion:e.appVersion})}const Kn={isRefresherDisabled:!0};let x,M;function Hn(){if(!M){const e=(async()=>{const[{DeviceManagementKitBuilder:t},{webHidTransportFactory:n}]=await Promise.all([import("@ledgerhq/device-management-kit"),import("@ledgerhq/device-transport-kit-web-hid")]);return x=new t().addTransport(n).build(),x})().catch(t=>{throw M===e&&(M=void 0),t});M=e}return M}async function Fn(){const e=await Hn(),[{firstValueFrom:t},{webHidIdentifier:n}]=await Promise.all([import("rxjs"),import("@ledgerhq/device-transport-kit-web-hid")]),r=await t(e.startDiscovering({transport:n})),o=await e.connect({device:r,sessionRefresherOptions:Kn}),s=await Yn(e,o);return{dmk:e,sessionId:o,...s}}async function Yn(e,t){try{const{GetAppAndVersionCommand:n,isSuccessCommandResult:r}=await import("@ledgerhq/device-management-kit"),o=await e.sendCommand({sessionId:t,command:new n});return r(o)?{appName:o.data.name,appVersion:o.data.version}:{}}catch{return{}}}async function Xn(e){const{firstValueFrom:t}=await import("rxjs");try{return await t(e.dmk.getDeviceSessionState({sessionId:e.sessionId})),!0}catch(n){if((n==null?void 0:n._tag)==="DeviceSessionNotFound")return!1;throw n}}async function qn(e){try{await e.dmk.disconnect({sessionId:e.sessionId})}catch{}}function Wn(){x==null||x.close(),x=void 0,M=void 0}const Ut=32,zn=10,Vt=0xffffffffn,Gt=72,jn=1008,Zn=4320,Qn=91,Jn=4031,_e=546n,Kt=_e,tr=2n,it=2,me="DepositTermsRejectedError";class _ extends Error{constructor(n,r="device-envelope"){super(n);h(this,"reason");this.name=me,this.reason=r}}const T="Deposit terms outside the device-supported range";function C(e,t,n,r){if(!Number.isInteger(t)||t<n||t>r)throw new _(`${T}: ${e} ${t} not in [${n}, ${r}]`)}function er(e){if(e.vaultCoreVersion!==it)throw new _(`${T}: vaultCoreVersion ${e.vaultCoreVersion} is not ${it}; this device only supports tx-graph v${it} deposits.`);if(e.protocolFeeRate<1n||e.protocolFeeRate>Vt)throw new _(`${T}: protocolFeeRate ${e.protocolFeeRate} not in [1, ${Vt}]`);if(C("timelockPegin",e.timelockPegin,Gt,jn),C("timelockAssert",e.timelockAssert,Qn,Jn),C("timelockRefund",e.timelockRefund,Gt,Zn),C("keeper count",e.vaultKeeperBtcPubkeys.length,1,Ut),C("challenger count",e.universalChallengerBtcPubkeys.length,1,Ut),C("vault count",e.vaults.length,1,zn),U("prepeginMaxFee",e.prepeginMaxFee),e.prepeginMaxFee<1n)throw new _(`${T}: prepeginMaxFee ${e.prepeginMaxFee} must be >= 1`);let t=-1;for(const a of e.vaults){if(!Number.isInteger(a.htlcVout)||a.htlcVout<0||a.htlcVout>255)throw new _(`${T}: htlcVout ${a.htlcVout} not in [0, 255]`);if(a.htlcVout<=t)throw new _(`${T}: vault groups must be in strictly ascending htlcVout order; got ${a.htlcVout} after ${t}`);t=a.htlcVout}const n=a=>a.replace(/^0x/,"").toLowerCase(),r=new Set(e.vaults.map(a=>n(a.vaultProviderBtcPubkey))),o=new Set;for(const[a,c]of[["vaultKeeperBtcPubkeys",e.vaultKeeperBtcPubkeys],["universalChallengerBtcPubkeys",e.universalChallengerBtcPubkeys]])for(const l of c){const f=n(l);if(r.has(f))throw new _(`${T}: ${a} contains the vault provider's own key (${f.slice(0,16)}…)`);if(o.has(f))throw new _(`${T}: duplicate participant key in ${a} (${f.slice(0,16)}…)`);o.add(f)}const s=_e,i=tr*s;for(const a of e.vaults){if(U(`vault ${a.htlcVout} peginAmount`,a.peginAmount),U(`vault ${a.htlcVout} commissionFee`,a.commissionFee),U(`vault ${a.htlcVout} depositorClaimValue`,a.depositorClaimValue),U(`vault ${a.htlcVout} peginMaxFee`,a.peginMaxFee),a.commissionFee<s)throw new _(`${T}: vault ${a.htlcVout} commissionFee ${a.commissionFee} below the ${s}-sat dust limit`);if(a.depositorClaimValue<Kt)throw new _(`${T}: vault ${a.htlcVout} depositorClaimValue ${a.depositorClaimValue} below the ${Kt}-sat device floor`);if(a.peginAmount<=a.commissionFee+i)throw new _(`${T}: vault ${a.htlcVout} peginAmount ${a.peginAmount} must exceed commissionFee + ${i} (${a.commissionFee+i})`)}}const nr=(1n<<64n)-1n;function U(e,t){if(t<0n||t>nr)throw new _(`${T}: ${e} ${t} does not fit in an unsigned 64-bit field`)}const Ht=253,rr=254,or=65535,sr=4294967295;function ir(e){if(e<Ht)return u.Buffer.from([e]);if(e<=or){const t=u.Buffer.alloc(2);return t.writeUInt16LE(e),u.Buffer.concat([u.Buffer.from([Ht]),t])}if(e<=sr){const t=u.Buffer.alloc(4);return t.writeUInt32LE(e),u.Buffer.concat([u.Buffer.from([rr]),t])}throw new Error(`Script too large to encode as CompactSize: ${e} bytes`)}const ar="TapLeaf";function ur(e,t){const n=u.Buffer.concat([u.Buffer.from([e]),ir(t.length),u.Buffer.from(t)]);return w.crypto.taggedHash(ar,n)}function cr(e,t,n,r){for(let o=0;o<t;o++){if(n[o+r]===void 0)throw Error("Buffer too small");n[o+r]=Number(e%BigInt(256)),e=e>>BigInt(8)}}function lr(e,t,n){let r=BigInt(0);for(let o=0;o<n;o++){const s=e[o+t];if(s===void 0)throw Error("Buffer too small");r+=BigInt(s)<<BigInt(o*8)}return r}function P(e){if(e<0)throw RangeError("Negative bigint is not a valid varint");if(e>Number.MAX_SAFE_INTEGER)throw RangeError("Too large for a Number");return Number(e)}function hr(e){if(typeof e=="number"&&(e=P(e)),e<BigInt(0))throw new RangeError("Negative numbers are not supported");if(e>=BigInt(1)<<BigInt(64))throw new RangeError("Too large for a Bitcoin-style varint");return e<BigInt(253)?1:e<=BigInt(65535)?3:e<=BigInt(4294967295)?5:9}const fr=BigInt(253),pr=BigInt(65535)+BigInt(1),dr=BigInt(4294967295)+BigInt(1);function Te(e,t){if(t<0)throw RangeError("Negative offset is invalid");const n=e[t];if(n===void 0)throw Error("Buffer too small");if(n<253)return[BigInt(n),1];{let r,o;n===253?(r=2,o=fr):n===254?(r=4,o=pr):(r=8,o=dr);const s=lr(e,t+1,r);if(s<o)throw RangeError(`Non-minimal varint at offset ${t}: a ${r+1}-byte CompactSize must encode a value of at least ${o}; re-encode it in its canonical (shorter) form`);return[s,r+1]}}function $(e){typeof e=="number"&&(e=P(e));const t=hr(e);e=BigInt(e);const n=u.Buffer.alloc(t);return t==1?n[0]=Number(e):(t==3?n[0]=253:t===5?n[0]=254:n[0]=255,cr(e,t-1,n,1)),n}const gr=31;function Se(e){if(!Number.isSafeInteger(e)||e<0)throw new Error("Can't convert a number that is not a non-negative safe integer to 64-bit LE");const t=u.Buffer.alloc(8,0);for(let n=0;n<t.length;n++){const r=e&255;t[n]=r,e=(e-r)/256}return t}function ft(e){let t=0;if(e.length!==8)throw new Error("Expected Buffer of length 8");if(e[7]!==0)throw new Error("Can't encode numbers > MAX_SAFE_INT");const n=e[6];if(n===void 0||n>gr)throw new Error("Can't encode numbers > MAX_SAFE_INT");for(let r=e.length-1;r>=0;r--){const o=e[r];if(o===void 0)throw new Error("Buffer too small");t=t*256+o}return t}class N{constructor(){h(this,"bufs",[])}write(t,n){const r=u.Buffer.alloc(t);n(r),this.bufs.push(r)}writeUInt8(t){this.write(1,n=>n.writeUInt8(t,0))}writeInt32(t){this.write(4,n=>n.writeInt32LE(t,0))}writeUInt32(t){this.write(4,n=>n.writeUInt32LE(t,0))}writeUInt64(t){const n=Se(t);this.writeSlice(n)}writeVarInt(t){this.bufs.push($(t))}writeSlice(t){this.bufs.push(u.Buffer.from(t))}writeVarSlice(t){this.writeVarInt(t.length),this.writeSlice(t)}buffer(){return u.Buffer.concat(this.bufs)}}class D{constructor(t,n=0){this.buffer=t,this.offset=n}available(){return this.buffer.length-this.offset}readUInt8(){const t=this.buffer.readUInt8(this.offset);return this.offset++,t}readInt32(){const t=this.buffer.readInt32LE(this.offset);return this.offset+=4,t}readUInt32(){const t=this.buffer.readUInt32LE(this.offset);return this.offset+=4,t}readUInt64(){const t=this.readSlice(8);return ft(t)}readVarInt(){const[t,n]=Te(this.buffer,this.offset);return this.offset+=n,t}readSlice(t){if(this.buffer.length<this.offset+t)throw new Error("Cannot read slice out of bounds");const n=this.buffer.subarray(this.offset,this.offset+t);return this.offset+=t,n}readVarSlice(){const t=P(this.readVarInt());return this.readSlice(t)}readVector(){const t=this.readVarInt(),n=[];for(let r=0;r<t;r++)n.push(this.readVarSlice());return n}}var pt=(e=>(e[e.NON_WITNESS_UTXO=0]="NON_WITNESS_UTXO",e[e.WITNESS_UTXO=1]="WITNESS_UTXO",e[e.PARTIAL_SIG=2]="PARTIAL_SIG",e[e.SIGHASH_TYPE=3]="SIGHASH_TYPE",e[e.REDEEM_SCRIPT=4]="REDEEM_SCRIPT",e[e.WITNESS_SCRIPT=5]="WITNESS_SCRIPT",e[e.BIP32_DERIVATION=6]="BIP32_DERIVATION",e[e.FINAL_SCRIPTSIG=7]="FINAL_SCRIPTSIG",e[e.FINAL_SCRIPTWITNESS=8]="FINAL_SCRIPTWITNESS",e[e.PREVIOUS_TXID=14]="PREVIOUS_TXID",e[e.OUTPUT_INDEX=15]="OUTPUT_INDEX",e[e.SEQUENCE=16]="SEQUENCE",e[e.TAP_KEY_SIG=19]="TAP_KEY_SIG",e[e.TAP_LEAF_SCRIPT=21]="TAP_LEAF_SCRIPT",e[e.TAP_BIP32_DERIVATION=22]="TAP_BIP32_DERIVATION",e[e.TAP_INTERNAL_KEY=23]="TAP_INTERNAL_KEY",e))(pt||{});const Ft=u.Buffer.from([112,115,98,116,255]),Er=4294967295;class Ie extends Error{}class ye{constructor(){h(this,"globalMap",new Map);h(this,"inputMaps",[]);h(this,"outputMaps",[])}setGlobalTxVersion(t){this.setGlobal(2,O(t))}getGlobalTxVersion(){return this.getGlobal(2).readUInt32LE(0)}setGlobalFallbackLocktime(t){this.setGlobal(3,O(t))}getGlobalFallbackLocktime(){var t;return(t=this.getGlobalOptional(3))==null?void 0:t.readUInt32LE(0)}setGlobalInputCount(t){this.setGlobal(4,qt(t))}getGlobalInputCount(){return Wt(this.getGlobal(4))}setGlobalOutputCount(t){this.setGlobal(5,qt(t))}getGlobalOutputCount(){return Wt(this.getGlobal(5))}setGlobalTxModifiable(t){this.setGlobal(6,t)}getGlobalTxModifiable(){return this.getGlobalOptional(6)}setGlobalPsbtVersion(t){this.setGlobal(251,O(t))}getGlobalPsbtVersion(){return this.getGlobal(251).readUInt32LE(0)}setInputNonWitnessUtxo(t,n){this.setInput(t,0,E(),n)}getInputNonWitnessUtxo(t){return this.getInputOptional(t,0,E())}setInputWitnessUtxo(t,n,r){const o=new N;o.writeSlice(Xt(n)),o.writeVarSlice(r),this.setInput(t,1,E(),o.buffer())}getInputWitnessUtxo(t){const n=this.getInputOptional(t,1,E());if(!n)return;const r=new D(n);return{amount:ft(r.readSlice(8)),scriptPubKey:r.readVarSlice()}}setInputPartialSig(t,n,r){this.setInput(t,2,n,r)}getInputPartialSig(t,n){return this.getInputOptional(t,2,n)}setInputSighashType(t,n){this.setInput(t,3,E(),O(n))}getInputSighashType(t){const n=this.getInputOptional(t,3,E());if(n)return n.readUInt32LE(0)}setInputRedeemScript(t,n){this.setInput(t,4,E(),n)}getInputRedeemScript(t){return this.getInputOptional(t,4,E())}setInputWitnessScript(t,n){this.setInput(t,5,E(),n)}getInputWitnessScript(t){return this.getInputOptional(t,5,E())}setInputBip32Derivation(t,n,r,o){if(n.length!==33)throw new Error("Invalid pubkey length: "+n.length);this.setInput(t,6,n,this.encodeBip32Derivation(r,o))}getInputBip32Derivation(t,n){const r=this.getInputOptional(t,6,n);if(r)return this.decodeBip32Derivation(r)}setInputFinalScriptsig(t,n){this.setInput(t,7,E(),n)}getInputFinalScriptsig(t){return this.getInputOptional(t,7,E())}setInputFinalScriptwitness(t,n){this.setInput(t,8,E(),n)}getInputFinalScriptwitness(t){return this.getInput(t,8,E())}setInputPreviousTxId(t,n){this.setInput(t,14,E(),n)}getInputPreviousTxid(t){return this.getInput(t,14,E())}setInputOutputIndex(t,n){this.setInput(t,15,E(),O(n))}getInputOutputIndex(t){return this.getInput(t,15,E()).readUInt32LE(0)}setInputSequence(t,n){this.setInput(t,16,E(),O(n))}getInputSequence(t){var n;return((n=this.getInputOptional(t,16,E()))==null?void 0:n.readUInt32LE(0))??Er}setInputTapKeySig(t,n){this.setInput(t,19,E(),n)}getInputTapKeySig(t){return this.getInputOptional(t,19,E())}setInputTapBip32Derivation(t,n,r,o,s){if(n.length!==32)throw new Error("Invalid pubkey length: "+n.length);const i=this.encodeTapBip32Derivation(r,o,s);this.setInput(t,22,n,i)}getInputTapBip32Derivation(t,n){const r=this.getInput(t,22,n);return this.decodeTapBip32Derivation(r)}getInputKeyDatas(t,n){return this.getKeyDatas(this.inputMaps[t],n)}getInputEntriesOfType(t,n){const r=this.inputMaps[t];if(!r)throw new Error("No such map");const o=[];return r.forEach((s,i)=>{this.isKeyType(i,[n])&&o.push({keyData:u.Buffer.from(i.substring(2),"hex"),value:u.Buffer.from(s)})}),o}setOutputRedeemScript(t,n){this.setOutput(t,0,E(),n)}getOutputRedeemScript(t){return this.getOutput(t,0,E())}setOutputBip32Derivation(t,n,r,o){this.setOutput(t,2,n,this.encodeBip32Derivation(r,o))}getOutputBip32Derivation(t,n){const r=this.getOutput(t,2,n);return this.decodeBip32Derivation(r)}setOutputAmount(t,n){this.setOutput(t,3,E(),Xt(n))}getOutputAmount(t){const n=this.getOutput(t,3,E());return ft(n)}setOutputScript(t,n){this.setOutput(t,4,E(),n)}getOutputScript(t){return this.getOutput(t,4,E())}setOutputTapBip32Derivation(t,n,r,o,s){const i=this.encodeTapBip32Derivation(r,o,s);this.setOutput(t,7,n,i)}getOutputTapBip32Derivation(t,n){const r=this.getOutput(t,7,n);return this.decodeTapBip32Derivation(r)}deleteInputEntries(t,n){const r=this.inputMaps[t];if(!r)throw new Error("No such map");r.forEach((o,s,i)=>{this.isKeyType(s,n)&&i.delete(s)})}copy(t){this.copyMap(this.globalMap,t.globalMap),this.copyMaps(this.inputMaps,t.inputMaps),this.copyMaps(this.outputMaps,t.outputMaps)}copyMaps(t,n){t.forEach((r,o)=>{const s=new Map;this.copyMap(r,s),n[o]=s})}copyMap(t,n){t.forEach((r,o)=>n.set(o,u.Buffer.from(r)))}serialize(){const t=new N;return t.writeSlice(Ft),ut(t,this.globalMap),this.inputMaps.forEach(n=>{ut(t,n)}),this.outputMaps.forEach(n=>{ut(t,n)}),t.buffer()}deserialize(t){const n=new D(t);if(!n.readSlice(5).equals(Ft))throw new Error("Invalid magic bytes");for(;this.readKeyPair(this.globalMap,n););let r;try{r=this.getGlobalPsbtVersion()}catch(i){if(!(i instanceof Ie))throw i;r=0}if(r!==0&&r!==2)throw new Error("Only PSBTs of version 0 or 2 are supported");let o,s;if(r===0){const i=this.getGlobal(0),a=w.Transaction.fromBuffer(i);o=a.ins.length,s=a.outs.length}else o=this.getGlobalInputCount(),s=this.getGlobalOutputCount();for(let i=0;i<o;i++){const a=new Map;for(this.inputMaps[i]=a;this.readKeyPair(a,n););}for(let i=0;i<s;i++){const a=new Map;for(this.outputMaps[i]=a;this.readKeyPair(a,n););}if(n.available()!==0)throw new Error("Trailing bytes after PSBT output maps");this.normalizeToV2()}normalizeToV2(){var o;const t=(o=this.getGlobalOptional(251))==null?void 0:o.readUInt32LE(0);if(t===2)return;if(t!==void 0)throw new Error("Invalid or unsupported value for PSBT_GLOBAL_VERSION");const n=this.getGlobal(0),r=w.Transaction.fromBuffer(n);this.setGlobalPsbtVersion(2),this.setGlobalTxVersion(r.version),this.setGlobalFallbackLocktime(r.locktime),this.setGlobalInputCount(r.ins.length),this.setGlobalOutputCount(r.outs.length),r.ins.forEach((s,i)=>{this.setInputPreviousTxId(i,s.hash),this.setInputOutputIndex(i,s.index),this.setInputSequence(i,s.sequence)}),r.outs.forEach((s,i)=>{this.setOutputAmount(i,s.value),this.setOutputScript(i,s.script)}),this.globalMap.delete("0".padStart(2,"0"))}readKeyPair(t,n){const r=P(n.readVarInt());if(r===0)return!1;const o=n.readUInt8(),s=n.readSlice(r-1),i=n.readVarSlice(),a=new k(o,s).toString();if(t.has(a))throw new Error("Repeated keypair in PSBT map");return t.set(a,i),!0}getKeyDatas(t,n){if(!t)throw new Error("No such map");const r=[];return t.forEach((o,s)=>{this.isKeyType(s,[n])&&r.push(u.Buffer.from(s.substring(2),"hex"))}),r}isKeyType(t,n){const r=u.Buffer.from(t.substring(0,2),"hex").readUInt8(0);return n.some(o=>o===r)}setGlobal(t,n){const r=new k(t,u.Buffer.from([]));this.globalMap.set(r.toString(),n)}getGlobal(t){return at(this.globalMap,t,E())}getGlobalOptional(t){return dt(this.globalMap,t,E())}setInput(t,n,r,o){Yt(this.getMap(t,this.inputMaps),n,r,o)}getInput(t,n,r){return at(this.inputMaps[t],n,r)}getInputOptional(t,n,r){return dt(this.inputMaps[t],n,r)}setOutput(t,n,r,o){Yt(this.getMap(t,this.outputMaps),n,r,o)}getOutput(t,n,r){return at(this.outputMaps[t],n,r)}getMap(t,n){const r=n[t];if(r)return r;const o=new Map;return n[t]=o,o}encodeBip32Derivation(t,n){const r=new N;return this.writeBip32Derivation(r,t,n),r.buffer()}decodeBip32Derivation(t){const n=new D(t);return this.readBip32Derivation(n)}writeBip32Derivation(t,n,r){t.writeSlice(n),r.forEach(o=>{t.writeUInt32(o)})}readBip32Derivation(t){const n=t.readSlice(4),r=[];for(;t.offset<t.buffer.length;)r.push(t.readUInt32());return{masterFingerprint:n,path:r}}encodeTapBip32Derivation(t,n,r){const o=new N;return o.writeVarInt(t.length),t.forEach(s=>{o.writeSlice(s)}),this.writeBip32Derivation(o,n,r),o.buffer()}decodeTapBip32Derivation(t){const n=new D(t),r=P(n.readVarInt()),o=[];for(let i=0;i<r;i++)o.push(n.readSlice(32));const s=this.readBip32Derivation(n);return{hashes:o,...s}}}function at(e,t,n){const r=dt(e,t,n);if(r===void 0)throw new Ie(new k(t,n).toString());return r}function dt(e,t,n){if(!e)throw new Error("No such map");const r=new k(t,n),o=e.get(r.toString());if(o!==void 0)return u.Buffer.from(o)}class k{constructor(t,n){h(this,"keyType");h(this,"keyData");this.keyType=t,this.keyData=n}toString(){const t=new N;return this.toBuffer(t),t.buffer().toString("hex")}serialize(t){t.writeVarInt(1+this.keyData.length),this.toBuffer(t)}toBuffer(t){t.writeUInt8(this.keyType),t.writeSlice(this.keyData)}}class wr{constructor(t,n){h(this,"key");h(this,"value");this.key=t,this.value=n}serialize(t){this.key.serialize(t),t.writeVarSlice(this.value)}}function _r(e){return new k(e.readUInt8(0),e.subarray(1))}function ut(e,t){const n=[...t].sort(([r],[o])=>r<o?-1:r>o?1:0);for(const[r,o]of n)new wr(_r(u.Buffer.from(r,"hex")),o).serialize(e);e.writeUInt8(0)}function E(){return u.Buffer.from([])}function Yt(e,t,n,r){const o=new k(t,n);e.set(o.toString(),r)}function O(e){const t=u.Buffer.alloc(4);return t.writeUInt32LE(e,0),t}function Xt(e){return Se(e)}function qt(e){const t=new N;return t.writeVarInt(e),t.buffer()}function Wt(e){return P(new D(e).readVarInt())}const zt=192,gt=32,jt=2,W=33,z=32,mr=1,Tr="TapBranch",Sr="TapTweak",Zt=64,Qt=32,ct=64,Ir=34,et=u.Buffer.from([81,32]),yr=u.Buffer.from([0,20]),Pr=2,br=3;function Ar(e){w.initEccLib(ht);const t=w.payments.p2tr({internalPubkey:u.Buffer.from(e,"hex")}).output;if(!t)throw new p("p2tr produced no output script for the depositor key");return t}function Jt(e,t){const n=u.Buffer.concat([u.Buffer.from([t]),u.Buffer.from(e,"hex")]);return u.Buffer.concat([yr,w.crypto.hash160(n)])}function Pe(e){return e.length===Ir&&e.subarray(0,et.length).equals(et)}function Rr(e,t,n,r){if(!Pe(r))throw new p(`input ${e} is tapscript but its witnessUtxo script is not P2TR`);const o=t.length-W;if(o<0||o%z!==0)throw new p(`input ${e} control block length ${t.length} is not ${W} plus a multiple of ${z}`);const s=t.subarray(1,W);if(!ht.isXOnlyPoint(s))throw new p(`input ${e} control block internal key is not an x-only point`);let i=n;for(let f=W;f<t.length;f+=z){const g=t.subarray(f,f+z),d=u.Buffer.compare(i,g)<0?[i,g]:[g,i];i=w.crypto.taggedHash(Tr,u.Buffer.concat(d))}const a=w.crypto.taggedHash(Sr,u.Buffer.concat([s,i])),c=ht.xOnlyPointAddTweak(s,a);if(!c)throw new p(`input ${e} control block internal key has no taproot output key`);if(!r.subarray(et.length).equals(u.Buffer.from(c.xOnlyPubkey)))throw new p(`input ${e} control block does not commit to its TAP_LEAF_SCRIPT (recomputed taproot output key differs from the witnessUtxo witness program)`);if(c.parity!==(t[0]&mr))throw new p(`input ${e} control block parity bit disagrees with the recomputed taproot output key`)}function Cr(e){const{psbt:t,depositorXOnlyHex:n}=e,r=new Map,o=t.getGlobalInputCount(),s=Ar(n),i=[Jt(n,Pr),Jt(n,br)];for(let c=0;c<o;c++){const l=t.getInputEntriesOfType(c,pt.TAP_LEAF_SCRIPT);if(l.length>0){if(l.length>1)throw new p(`input ${c} carries an ambiguous leaf set (${l.length} TAP_LEAF_SCRIPT entries)`);const d=l[0].value;if(d.length<jt)throw new p(`input ${c} TAP_LEAF_SCRIPT value length ${d.length} is below the ${jt}-byte minimum (script byte plus the leaf-version byte)`);const m=d[d.length-1];if(m!==zt)throw new p(`input ${c} leaf version 0x${m.toString(16)} is not tapscript (0xc0)`);const y=t.getInputWitnessUtxo(c);if(!y)throw new p(`input ${c} is tapscript but has no witnessUtxo`);const Be=d.subarray(0,d.length-1),At=ur(zt,Be);Rr(c,l[0].keyData,At,y.scriptPubKey),r.set(c,{kind:"tapscript",expectedLeafHashHexes:new Set([At.toString("hex")]),expectedSignerXOnlyHex:n});continue}const f=t.getInputEntriesOfType(c,pt.TAP_INTERNAL_KEY);if(f.length>0){const d=f[0];if(f.length>1||d.keyData.length!==0||d.value.length!==gt)throw new p(`input ${c} carries a malformed TAP_INTERNAL_KEY entry`);if(d.value.toString("hex")!==n)throw new p(`input ${c} internal key is not the connected depositor key`);const m=t.getInputWitnessUtxo(c);if(!m)throw new p(`input ${c} is keypath but has no witnessUtxo`);const y=m.scriptPubKey;if(!Pe(y))throw new p(`input ${c} witnessUtxo script is not P2TR`);if(!y.equals(s))throw new p(`input ${c} witnessUtxo is not the BIP-86 P2TR of the depositor key`);r.set(c,{kind:"taproot-keypath",expectedOutputKeyHex:y.subarray(et.length).toString("hex")});continue}const g=t.getInputWitnessUtxo(c);if(g&&(g.scriptPubKey.equals(s)||i.some(d=>g.scriptPubKey.equals(d))))throw new p(`input ${c} spends a depositor-owned UTXO but carries no signing metadata`)}if(r.size===0)throw new p("PSBT contains no depositor-signable input");let a=0;for(const c of r.values())a+=c.kind==="tapscript"?c.expectedLeafHashHexes.size:1;return{byInput:r,expectedYieldCount:a}}function j(e){return e.kind==="tapscript"?`${e.inputIndex}:${e.leafHashHex}`:`${e.inputIndex}`}function te(e,t){if(e<ct)throw new p(`YIELD payload truncated inside the signature (${e} of ${ct} bytes on input ${t})`);if(e!==ct)throw new I("non-default-sighash",t)}function Or(e){const t=[],n=new Set;return{assertAndRecord:s=>{let i,a;try{const[f,g]=Te(s,0);i=P(f),a=g}catch(f){throw new p(`unparseable YIELD payload: ${f instanceof Error?f.message:String(f)}`)}const c=s[a];if(c===void 0)throw new p("YIELD payload truncated before the augmented-pubkey length");const l=e.byInput.get(i);if(l===void 0)throw new I("unexpected-input",i);if(c===Zt){if(l.kind!=="tapscript")throw new I("wrong-spend-type",i);const f=a+1+Zt;if(s.length<f)throw new p("YIELD payload truncated inside the augmented pubkey");const g=s.subarray(a+1,a+1+gt).toString("hex"),d=s.subarray(a+1+gt,f).toString("hex"),m=s.subarray(f);if(g!==l.expectedSignerXOnlyHex)throw new I("wrong-signer-key",i);if(!l.expectedLeafHashHexes.has(d))throw new I("unknown-leaf-hash",i);te(m.length,i);const y={kind:"tapscript",inputIndex:i,signerXOnlyHex:g,leafHashHex:d,signature:Uint8Array.from(m)};if(n.has(j(y)))throw new I("duplicate-yield",i);n.add(j(y)),t.push(y);return}if(c===Qt){if(l.kind!=="taproot-keypath")throw new I("wrong-spend-type",i);const f=a+1+Qt;if(s.length<f)throw new p("YIELD payload truncated inside the augmented pubkey");const g=s.subarray(a+1,f).toString("hex"),d=s.subarray(f);if(g!==l.expectedOutputKeyHex)throw new I("wrong-signer-key",i);te(d.length,i);const m={kind:"taproot-keypath",inputIndex:i,outputKeyHex:g,signature:Uint8Array.from(d)};if(n.has(j(m)))throw new I("duplicate-yield",i);n.add(j(m)),t.push(m);return}throw new I("unexpected-encoding",i)},get yields(){return t},get lastYield(){return t[t.length-1]},assertComplete:()=>{const s=new Set;for(const[c,l]of e.byInput)if(l.kind==="tapscript")for(const f of l.expectedLeafHashHexes)s.add(`${c}:${f}`);else s.add(`${c}`);const i=[...s].filter(c=>!n.has(c)),a=[...n].some(c=>!s.has(c));if(i.length>0||a||n.size!==e.expectedYieldCount)throw new ce(i)}}}class H{constructor(t,n=w.crypto.sha256){h(this,"leaves");h(this,"rootNode");h(this,"leafNodes");h(this,"h");this.leaves=t,this.h=n;const r=this.calculateRoot(t);this.rootNode=r.root,this.leafNodes=r.leaves}getRoot(){return this.rootNode.hash}size(){return this.leaves.length}getLeaves(){return this.leaves}getLeafHash(t){const n=this.leafNodes[t];if(n===void 0)throw Error("Index out of bounds");return n.hash}getProof(t){const n=this.leafNodes[t];if(n===void 0)throw Error("Index out of bounds");return Et(n)}calculateRoot(t){const n=t.length;if(n==0)return{root:new lt(void 0,void 0,u.Buffer.alloc(32,0)),leaves:[]};if(n==1){const f=new lt(void 0,void 0,t[0]);return{root:f,leaves:[f]}}const r=Mr(n),o=this.calculateRoot(t.slice(0,r)),s=this.calculateRoot(t.slice(r)),i=o.root,a=s.root,c=this.hashNode(i.hash,a.hash),l=new lt(i,a,c);return i.parent=l,a.parent=l,{root:l,leaves:o.leaves.concat(s.leaves)}}hashNode(t,n){return this.h(u.Buffer.concat([u.Buffer.from([1]),t,n]))}}function F(e,t=w.crypto.sha256){return Br(u.Buffer.from([0]),e,t)}function Br(e,t,n){return n(u.Buffer.concat([e,t]))}class lt{constructor(t,n,r){h(this,"leftChild");h(this,"rightChild");h(this,"parent");h(this,"hash");this.leftChild=t,this.rightChild=n,this.hash=r}isLeaf(){return this.leftChild==null}}function Et(e){if(!e.parent)return[];if(e.parent.leftChild==e){if(!e.parent.rightChild)throw new Error("Expected right child to exist");return[e.parent.rightChild.hash,...Et(e.parent)]}else{if(!e.parent.leftChild)throw new Error("Expected left child to exist");return[e.parent.leftChild.hash,...Et(e.parent)]}}function Mr(e){if(e<2)throw Error("Expected n >= 2");return Lr(e)?e/2:1<<Math.floor(Math.log2(e))}function Lr(e){return(e&e-1)==0}const bt=255,vr=2,S=32;class Y{}class xr extends Y{constructor(n,r,o){super();h(this,"results");h(this,"code",16);this.progressCallback=r,this.onYield=o,this.results=n}execute(n){const r=u.Buffer.from(n.subarray(1));return this.onYield&&this.onYield(u.Buffer.from(r)),this.results.push(r),this.progressCallback&&this.progressCallback(),u.Buffer.from("")}}class Nr extends Y{constructor(n,r){super();h(this,"knownPreimages");h(this,"queue");h(this,"code",64);this.knownPreimages=n,this.queue=r}execute(n){const r=u.Buffer.from(n.subarray(1));if(r.length!==1+S)throw new Error("Invalid request, unexpected trailing data");if(r[0]!==0)throw new Error("Unsupported request, the first byte should be 0");const s=u.Buffer.from(r.subarray(1,1+S)).toString("hex"),i=this.knownPreimages.get(s);if(i!==void 0){const a=$(i.length),c=bt-a.length-1,l=Math.min(c,i.length);if(l<i.length)for(let f=l;f<i.length;f++)this.queue.push(u.Buffer.from(i.subarray(f,f+1)));return u.Buffer.concat([a,u.Buffer.from([l]),u.Buffer.from(i.subarray(0,l))])}throw new Error(`Requested unknown preimage for: ${s}`)}}class Dr extends Y{constructor(n,r){super();h(this,"knownTrees");h(this,"queue");h(this,"code",65);this.knownTrees=n,this.queue=r}execute(n){const r=u.Buffer.from(n.subarray(1));if(r.length<S+1+1)throw new Error("Invalid request, expected at least 34 bytes");const o=new D(r),i=o.readSlice(S).toString("hex");let a,c;try{a=P(o.readVarInt()),c=P(o.readVarInt())}catch{throw new Error("Invalid request, couldn't parse tree_size or leaf_index")}const l=this.knownTrees.get(i);if(!l)throw new Error(`Requested Merkle leaf proof for unknown tree: ${i}`);if(c>=a||l.size()!==a)throw new Error("Invalid index or tree size.");if(this.queue.length!==0)throw new Error("This command should not execute when the queue is not empty.");const f=l.getProof(c),g=Math.min(Math.floor((bt-S-1-1)/S),f.length),d=f.length-g;return d>0&&this.queue.push(...f.slice(-d)),u.Buffer.concat([l.getLeafHash(c),u.Buffer.from([f.length]),u.Buffer.from([g]),...f.slice(0,g)])}}class $r extends Y{constructor(n){super();h(this,"knownTrees");h(this,"code",66);this.knownTrees=n}execute(n){const r=u.Buffer.from(n.subarray(1));if(r.length!==S+S)throw new Error("Invalid request, unexpected trailing data");const s=u.Buffer.from(r.subarray(0,S)).toString("hex"),a=u.Buffer.from(r.subarray(S,S+S)).toString("hex"),c=this.knownTrees.get(s);if(!c)throw new Error(`Requested Merkle leaf index for unknown root: ${s}`);let l=0,f=0;for(let g=0;g<c.size();g++)if(c.getLeafHash(g).toString("hex")===a){f=1,l=g;break}return u.Buffer.concat([u.Buffer.from([f]),$(l)])}}class kr extends Y{constructor(n){super();h(this,"queue");h(this,"code",160);this.queue=n}execute(n){if(n.length!==1)throw new Error("Invalid request, unexpected trailing data");const r=this.queue[0];if(r===void 0)throw new Error("No elements to get");const o=r.length;if(this.queue.some(c=>c.length!==o))throw new Error("The queue contains elements with different byte length, which is not expected");const s=Math.floor((bt-vr)/o),i=Math.min(s,this.queue.length),a=this.queue.splice(0,i);return u.Buffer.concat([u.Buffer.from([i]),u.Buffer.from([o]),...a])}}class Ur{constructor(t,n){h(this,"roots",new Map);h(this,"preimages",new Map);h(this,"yielded",[]);h(this,"queue",[]);h(this,"commands",new Map);const r=[new xr(this.yielded,t,n),new Nr(this.preimages,this.queue),new $r(this.roots),new Dr(this.roots,this.queue),new kr(this.queue)];for(const o of r){if(this.commands.has(o.code))throw new Error(`Multiple commands with code ${o.code}`);this.commands.set(o.code,o)}}getYielded(){return this.yielded}addKnownPreimage(t){this.preimages.set(w.crypto.sha256(t).toString("hex"),t)}addKnownList(t){for(const r of t){const o=u.Buffer.concat([u.Buffer.from([0]),r]);this.addKnownPreimage(o)}const n=new H(t.map(r=>F(r)));this.roots.set(n.getRoot().toString("hex"),n)}addKnownMapping(t){this.addKnownList(t.keys),this.addKnownList(t.values)}addKnownWalletPolicy(t){this.addKnownPreimage(t.serialize()),this.addKnownList(t.keys.map(n=>u.Buffer.from(n,"ascii"))),this.addKnownPreimage(u.Buffer.from(t.descriptorTemplate))}execute(t){if(t.length===0)throw new Error("Unexpected empty command");const n=t[0],r=this.commands.get(n);if(!r)throw new Error(`Unexpected command code ${n}`);return r.execute(t)}}class Vr{constructor(t,n){h(this,"keys");h(this,"keysTree");h(this,"values");h(this,"valuesTree");if(t.length!=n.length)throw new Error("keys and values should have the same length");for(let r=0;r<t.length-1;r++)if(t[r].toString("hex")>=t[r+1].toString("hex"))throw new Error("keys must be in strictly increasing order");this.keys=t,this.keysTree=new H(t.map(r=>F(r))),this.values=n,this.valuesTree=new H(n.map(r=>F(r)))}commitment(){return u.Buffer.concat([$(this.keys.length),this.keysTree.getRoot(),this.valuesTree.getRoot()])}}class K extends ye{constructor(n){super();h(this,"globalMerkleMap");h(this,"inputMerkleMaps",[]);h(this,"outputMerkleMaps",[]);h(this,"inputMapCommitments");h(this,"outputMapCommitments");n.copy(this),this.globalMerkleMap=K.createMerkleMap(this.globalMap);const r=this.getGlobalInputCount();if(this.inputMaps.length!==r)throw new Error(`Input map count ${this.inputMaps.length} != declared PSBT_GLOBAL_INPUT_COUNT ${r}`);for(let s=0;s<r;s++){const i=this.inputMaps[s];if(i===void 0)throw new Error(`Missing input map ${s}`);this.inputMerkleMaps.push(K.createMerkleMap(i))}this.inputMapCommitments=this.inputMerkleMaps.map(s=>s.commitment());const o=this.getGlobalOutputCount();if(this.outputMaps.length!==o)throw new Error(`Output map count ${this.outputMaps.length} != declared PSBT_GLOBAL_OUTPUT_COUNT ${o}`);for(let s=0;s<o;s++){const i=this.outputMaps[s];if(i===void 0)throw new Error(`Missing output map ${s}`);this.outputMerkleMaps.push(K.createMerkleMap(i))}this.outputMapCommitments=this.outputMerkleMaps.map(s=>s.commitment())}getGlobalSize(){return this.globalMap.size}getGlobalKeysValuesRoot(){return this.globalMerkleMap.commitment()}static createMerkleMap(n){const r=[...n.keys()].sort(),o=r.map(i=>{const a=n.get(i);if(!a)throw new Error("No value for key "+i);return a}),s=r.map(i=>u.Buffer.from(i,"hex"));return new Vr(s,o)}}const Gr=4,Kr=0,Hr=1,be=32,Fr=new Uint8Array(be),Yr=new Uint8Array(be),Xr=/^[0-9a-f]{64}$/,qr=/^(?:[0-9a-fA-F]{2})+$/;function Wr(e){const t=new H(e.inputMapCommitments.map(r=>F(r))).getRoot(),n=new H(e.outputMapCommitments.map(r=>F(r))).getRoot();return Uint8Array.from(u.Buffer.concat([e.getGlobalKeysValuesRoot(),$(e.getGlobalInputCount()),t,$(e.getGlobalOutputCount()),n,u.Buffer.from(Fr),u.Buffer.from(Yr)]))}function zr(e){return{cla:A,ins:Gr,p1:Kr,p2:Hr,data:e}}const jr=0;function Zr(e,t){for(const[n]of t.byInput){const r=e.data.inputs[n].sighashType;if(r!==void 0&&r!==jr)throw new p(`input ${n} requests sighash type ${r}, but vault flows sign SIGHASH_DEFAULT only`)}}function Qr(e,t){var n;for(const[r,o]of t.byInput){const s=e.data.inputs[r];if(s.finalScriptWitness||s.finalScriptSig)throw new p(`input ${r} is already finalized and this round signs it — pass an unsigned PSBT`);if(o.kind==="tapscript"){if((n=s.tapScriptSig)==null?void 0:n.some(a=>a.pubkey.toString("hex")===o.expectedSignerXOnlyHex&&o.expectedLeafHashHexes.has(a.leafHash.toString("hex"))))throw new p(`input ${r} already carries a tapScriptSig for a (key, leaf) we sign — pass an unsigned PSBT`);continue}if(s.tapKeySig)throw new p(`input ${r} already carries a tapKeySig and this round signs its keypath — pass an unsigned PSBT`)}}const Ae=new WeakMap;function Jr(e,t){const n={...e};return Ae.set(n,t),n}function Re(e){const t=Ae.get(e);if(!t)throw new p("unrecognised prepared signing state — use prepareSignPsbt's return value");return t}function Ce(e){const{psbtHex:t,depositorXOnlyHex:n}=e;if(!Xr.test(n))throw new p("depositorXOnlyHex must be 64 lowercase hex characters");if(!qr.test(t))throw new p("psbtHex is not even-length hexadecimal");let r;try{r=w.Psbt.fromHex(t)}catch(l){throw new p(`PSBT rejected at parse (merge target): ${l instanceof Error?l.message:String(l)}`)}const o=new ye;try{o.deserialize(u.Buffer.from(t,"hex"))}catch(l){throw new p(`PSBT rejected at parse: ${l instanceof Error?l.message:String(l)}`)}let s,i;try{s=new K(o),i=Cr({psbt:s,depositorXOnlyHex:n})}catch(l){throw l instanceof p?l:new p(`PSBT rejected at preflight: ${l instanceof Error?l.message:String(l)}`)}Qr(r,i),Zr(r,i);const a=Or(i),c=new Ur(void 0,l=>a.assertAndRecord(l));c.addKnownMapping(s.globalMerkleMap);for(const l of s.inputMerkleMaps)c.addKnownMapping(l);for(const l of s.outputMerkleMaps)c.addKnownMapping(l);return c.addKnownList(s.inputMapCommitments),c.addKnownList(s.outputMapCommitments),Jr({table:i,unsignedTxid:w.Transaction.fromBuffer(r.data.globalMap.unsignedTx.toBuffer()).getId()},{cdata:Wr(s),interpreter:c,collector:a,originalPsbtHex:t})}const to=248,eo=1,no=0,ro=0,oo=36864,so=57344,io=27264;async function ao(e,t,n){const{collector:r,interpreter:o,cdata:s}=Re(t),{table:i}=t;if(n.signal.aborted)throw new Q(r.yields.length,!1);const a=zr(s);let c=a,l=await e(a);if(l.sw===io&&n.resendOnceOnIncorrectData===!0){if(n.signal.aborted)throw new Q(r.yields.length,!1);l=await e(a)}let f=0;for(;l.sw===so;){let g;try{g=o.execute(u.Buffer.from(l.data))}catch(d){throw le(d)?d:he(d)?new p(d.detail,Z(r.yields)):new p(`client command failed: ${d instanceof Error?d.message:String(d)}`,Z(r.yields))}if(r.yields.length>f){f=r.yields.length;const d=r.lastYield;if(d!==void 0&&n.onProgress!==void 0)try{n.onProgress({inputIndex:d.inputIndex,yieldedCount:f,expectedYieldCount:i.expectedYieldCount})}catch{}}if(n.signal.aborted)throw new Q(r.yields.length,!0);c={cla:to,ins:eo,p1:no,p2:ro,data:g},l=await e(c)}if(l.sw!==oo){const g=Ee(l.sw,{...n.appIdentity,ins:c.ins,p1:c.p1});throw g===void 0?new p(`status word 0x${l.sw.toString(16)} escaped classification`,Z(r.yields)):g}return r.assertComplete(),r.yields}function uo(e,t){const n=w.Psbt.fromHex(e);for(const r of t)r.kind==="tapscript"?n.updateInput(r.inputIndex,{tapScriptSig:[{pubkey:u.Buffer.from(r.signerXOnlyHex,"hex"),leafHash:u.Buffer.from(r.leafHashHex,"hex"),signature:u.Buffer.from(r.signature)}]}):n.updateInput(r.inputIndex,{tapKeySig:u.Buffer.from(r.signature)});return n.toHex()}const ee=new WeakSet;async function Oe(e,t,n){const{originalPsbtHex:r}=Re(t);if(ee.has(t))throw new p("prepared signing state was already used — call prepareSignPsbt again for a retry");ee.add(t);const o=await ao(e,t,n);let s;try{s=uo(r,o)}catch(i){throw new p(`merge failed after signing: ${i instanceof Error?i.message:String(i)}`,Z(o))}return{signedPsbtHex:s,yields:[...o]}}async function co(e,t){const{psbtHex:n,depositorXOnlyHex:r,...o}=t,s=Ce({psbtHex:n,depositorXOnlyHex:r});return Oe(e,s,o)}exports.DEPOSIT_TERMS_REJECTED_ERROR_NAME=me;exports.DepositTermsRejectedError=_;exports.LEDGER_DEVICE_ERROR_NAME=Tt;exports.LEDGER_DEVICE_LOCKED_ERROR_NAME=mt;exports.LEDGER_SIGN_PSBT_ABORTED_ERROR_NAME=Pt;exports.LEDGER_SIGN_PSBT_INCOMPLETE_ERROR_NAME=It;exports.LEDGER_SIGN_PSBT_PROTOCOL_ERROR_NAME=yt;exports.LEDGER_USER_REFUSED_ERROR_NAME=_t;exports.LEDGER_YIELD_MISMATCH_ERROR_NAME=St;exports.LedgerDeviceError=ue;exports.LedgerDeviceLockedError=ae;exports.LedgerSignPsbtAbortedError=Q;exports.LedgerSignPsbtIncompleteError=ce;exports.LedgerSignPsbtProtocolError=p;exports.LedgerUserRefusedError=ie;exports.LedgerYieldMismatchError=I;exports.SW_BAD_STATE=pe;exports.SW_CAP_EXCEEDED=de;exports.approveVaultIntent=Sn;exports.assertDepositTermsDeviceCompatible=er;exports.closeDmk=Wn;exports.connectDmkSession=Fn;exports.createDmkApduSender=Gn;exports.createDmkRawApduSender=we;exports.deriveContextHash=Tn;exports.disconnectDmkSession=qn;exports.encodeIntentGroup=re;exports.encodeIntentScalars=ne;exports.encodeKeyBatches=oe;exports.getXOnlyPublicKeyHex=An;exports.isLedgerDeviceError=Bn;exports.isLedgerDeviceLockedError=Mn;exports.isLedgerSignPsbtAbortedError=vn;exports.isLedgerSignPsbtIncompleteError=Ln;exports.isLedgerSignPsbtProtocolError=he;exports.isLedgerUserRefusedError=On;exports.isLedgerYieldMismatchError=le;exports.isSessionAlive=Xn;exports.prepareSignPsbt=Ce;exports.signPreparedVaultPsbt=Oe;exports.signVaultPsbt=co;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|