@hwlt/era-connect 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/cardano/package.json +6 -0
- package/cosmos/package.json +6 -0
- package/dist/{btc-DfQ0q79G.d.ts → btc-B8LfSEkv.d.ts} +11 -2
- package/dist/{btc-VyJKXq7d.js → btc-B_Nq2H4T.js} +16 -7
- package/dist/btc-B_Nq2H4T.js.map +1 -0
- package/dist/{btc-Fr6Jz4Fi.cjs → btc-ByzjzUKs.cjs} +19 -10
- package/dist/btc-ByzjzUKs.cjs.map +1 -0
- package/dist/{btc-Dn6_Y12c.d.cts → btc-C4dVkxHb.d.cts} +11 -2
- package/dist/btc.cjs +2 -2
- package/dist/btc.d.cts +1 -1
- package/dist/btc.d.ts +1 -1
- package/dist/btc.js +2 -2
- package/dist/cardano-BCT55gwf.js +95 -0
- package/dist/cardano-BCT55gwf.js.map +1 -0
- package/dist/cardano-CzYswGzK.cjs +106 -0
- package/dist/cardano-CzYswGzK.cjs.map +1 -0
- package/dist/cardano-Do1ahUlK.d.cts +62 -0
- package/dist/cardano-OzjWZHh6.d.ts +62 -0
- package/dist/cardano.cjs +10 -0
- package/dist/cardano.d.cts +3 -0
- package/dist/cardano.d.ts +3 -0
- package/dist/cardano.js +3 -0
- package/dist/cosmos-BYrhIqRk.d.cts +77 -0
- package/dist/cosmos-DDsgtUki.cjs +113 -0
- package/dist/cosmos-DDsgtUki.cjs.map +1 -0
- package/dist/cosmos-DqyjA6lg.d.ts +77 -0
- package/dist/cosmos-jUHNxgWC.js +102 -0
- package/dist/cosmos-jUHNxgWC.js.map +1 -0
- package/dist/cosmos.cjs +10 -0
- package/dist/cosmos.d.cts +3 -0
- package/dist/cosmos.d.ts +3 -0
- package/dist/cosmos.js +3 -0
- package/dist/derive-BayrpfJk.cjs +188 -0
- package/dist/derive-BayrpfJk.cjs.map +1 -0
- package/dist/derive-CK9Nc9Jc.js +123 -0
- package/dist/derive-CK9Nc9Jc.js.map +1 -0
- package/dist/{evm-kJb3-oiR.js → evm-CI1cuZsp.js} +3 -2
- package/dist/{evm-kJb3-oiR.js.map → evm-CI1cuZsp.js.map} +1 -1
- package/dist/{evm-BHj_2OTG.cjs → evm-yfKOc2dy.cjs} +6 -5
- package/dist/{evm-BHj_2OTG.cjs.map → evm-yfKOc2dy.cjs.map} +1 -1
- package/dist/evm.cjs +2 -2
- package/dist/evm.js +2 -2
- package/dist/index.cjs +156 -116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -9
- package/dist/index.d.ts +68 -9
- package/dist/index.js +125 -94
- package/dist/index.js.map +1 -1
- package/dist/keypath-Bvv_cfHt.js +75 -0
- package/dist/keypath-Bvv_cfHt.js.map +1 -0
- package/dist/keypath-pzm_YIfN.cjs +116 -0
- package/dist/keypath-pzm_YIfN.cjs.map +1 -0
- package/dist/{messages-BzcdWlg1.cjs → messages-BZXDY29v.cjs} +2 -2
- package/dist/{messages-BzcdWlg1.cjs.map → messages-BZXDY29v.cjs.map} +1 -1
- package/dist/{messages-17Oup0-Z.js → messages-DbnXy3dC.js} +2 -2
- package/dist/{messages-17Oup0-Z.js.map → messages-DbnXy3dC.js.map} +1 -1
- package/dist/{shared-B8Wc7ViU.js → shared-Bbgejrus.js} +2 -73
- package/dist/shared-Bbgejrus.js.map +1 -0
- package/dist/{shared-nISrEktU.cjs → shared-Cu2yynP9.cjs} +13 -114
- package/dist/shared-Cu2yynP9.cjs.map +1 -0
- package/dist/{solana-DdEn24X4.cjs → solana-BoQBy0hu.cjs} +6 -5
- package/dist/{solana-DdEn24X4.cjs.map → solana-BoQBy0hu.cjs.map} +1 -1
- package/dist/{solana-C7JQEAec.js → solana-BukH3AI3.js} +3 -2
- package/dist/{solana-C7JQEAec.js.map → solana-BukH3AI3.js.map} +1 -1
- package/dist/solana.cjs +2 -2
- package/dist/solana.js +2 -2
- package/dist/sui-6WX6VPlW.d.cts +49 -0
- package/dist/sui-BtbPG6Xt.js +71 -0
- package/dist/sui-BtbPG6Xt.js.map +1 -0
- package/dist/sui-CYRn331O.cjs +82 -0
- package/dist/sui-CYRn331O.cjs.map +1 -0
- package/dist/sui-DI0ruW7E.d.ts +49 -0
- package/dist/sui.cjs +10 -0
- package/dist/sui.d.cts +3 -0
- package/dist/sui.d.ts +3 -0
- package/dist/sui.js +3 -0
- package/dist/{ton-5Uvi5ifg.js → ton-BSPKU5B9.js} +3 -2
- package/dist/{ton-5Uvi5ifg.js.map → ton-BSPKU5B9.js.map} +1 -1
- package/dist/{ton-DUJGXdGa.cjs → ton-CI2s9puH.cjs} +6 -5
- package/dist/{ton-DUJGXdGa.cjs.map → ton-CI2s9puH.cjs.map} +1 -1
- package/dist/ton.cjs +2 -2
- package/dist/ton.js +2 -2
- package/dist/{tron-CQIEqjCA.cjs → tron-B9wXdzlA.cjs} +7 -6
- package/dist/{tron-CQIEqjCA.cjs.map → tron-B9wXdzlA.cjs.map} +1 -1
- package/dist/{tron-Bo9HnvVE.js → tron-fufBDNuQ.js} +4 -3
- package/dist/{tron-Bo9HnvVE.js.map → tron-fufBDNuQ.js.map} +1 -1
- package/dist/tron.cjs +3 -3
- package/dist/tron.js +3 -3
- package/dist/verify.cjs +335 -4
- package/dist/verify.cjs.map +1 -1
- package/dist/verify.d.cts +86 -1
- package/dist/verify.d.ts +86 -1
- package/dist/verify.js +333 -6
- package/dist/verify.js.map +1 -1
- package/dist/xrp-BXAeK4iH.d.cts +32 -0
- package/dist/xrp-BrHXUnX5.cjs +52 -0
- package/dist/xrp-BrHXUnX5.cjs.map +1 -0
- package/dist/xrp-C8LJO5b-.js +47 -0
- package/dist/xrp-C8LJO5b-.js.map +1 -0
- package/dist/xrp-DqCXGYEk.d.ts +32 -0
- package/dist/xrp.cjs +9 -0
- package/dist/xrp.d.cts +3 -0
- package/dist/xrp.d.ts +3 -0
- package/dist/xrp.js +3 -0
- package/package.json +49 -1
- package/sui/package.json +6 -0
- package/xrp/package.json +6 -0
- package/dist/btc-Fr6Jz4Fi.cjs.map +0 -1
- package/dist/btc-VyJKXq7d.js.map +0 -1
- package/dist/shared-B8Wc7ViU.js.map +0 -1
- package/dist/shared-nISrEktU.cjs.map +0 -1
package/dist/verify.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { A as utf8Encode, D as hexToBytes, E as equalBytes,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { A as utf8Encode, D as hexToBytes, E as equalBytes, K as EraSdkError, T as concatBytes, k as utf8Decode, w as bytesToHex } from "./shared-Bbgejrus.js";
|
|
2
|
+
import { i as parsePath } from "./keypath-Bvv_cfHt.js";
|
|
3
|
+
import { a as cardanoSoftDerivePath } from "./derive-CK9Nc9Jc.js";
|
|
4
|
+
import { n as parseWitnessSet } from "./cardano-BCT55gwf.js";
|
|
5
|
+
import { n as EvmDataType, r as foldRecoveryId } from "./evm-CI1cuZsp.js";
|
|
6
|
+
import { n as suiIntentDigest } from "./sui-BtbPG6Xt.js";
|
|
7
|
+
import { n as TonDataType } from "./ton-BSPKU5B9.js";
|
|
8
|
+
import { a as firstVarint, i as firstBytes, o as readFields, r as splitSignedTronTx } from "./messages-DbnXy3dC.js";
|
|
5
9
|
import { secp256k1 } from "@noble/curves/secp256k1";
|
|
6
|
-
import {
|
|
10
|
+
import { blake2b } from "@noble/hashes/blake2b";
|
|
11
|
+
import { sha256, sha512 } from "@noble/hashes/sha2";
|
|
7
12
|
import { keccak_256 } from "@noble/hashes/sha3";
|
|
8
13
|
import { createBase58check } from "@scure/base";
|
|
9
14
|
import { ed25519 } from "@noble/curves/ed25519";
|
|
@@ -246,6 +251,165 @@ function message(e) {
|
|
|
246
251
|
return e instanceof EraSdkError || e instanceof Error ? e.message : String(e);
|
|
247
252
|
}
|
|
248
253
|
//#endregion
|
|
254
|
+
//#region src/verify/cardano.ts
|
|
255
|
+
/**
|
|
256
|
+
* Recompute the digest the device signs — BLAKE2b-256 of the ENCODED FIRST
|
|
257
|
+
* ELEMENT of the transaction CBOR array (the tx body) — and verify every
|
|
258
|
+
* `[vkey, signature]` pair against it. With `account` + `signerPaths`, the
|
|
259
|
+
* vkeys are additionally required to be exactly the soft-derived children of
|
|
260
|
+
* YOUR linked account at the request's own paths.
|
|
261
|
+
*/
|
|
262
|
+
function verifyCardanoSignature(args) {
|
|
263
|
+
let witnesses;
|
|
264
|
+
try {
|
|
265
|
+
witnesses = args.witnesses ?? (args.witnessSet ? parseWitnessSet(args.witnessSet) : []);
|
|
266
|
+
} catch (e) {
|
|
267
|
+
return failed(`witness set is not readable: ${e.message}`);
|
|
268
|
+
}
|
|
269
|
+
if (witnesses.length === 0) return failed("no witnesses to verify");
|
|
270
|
+
let digest;
|
|
271
|
+
try {
|
|
272
|
+
digest = blake2b(firstArrayItemBytes(args.signData), { dkLen: 32 });
|
|
273
|
+
} catch (e) {
|
|
274
|
+
return failed(`signData is not a readable transaction array: ${e.message}`);
|
|
275
|
+
}
|
|
276
|
+
for (const witness of witnesses) {
|
|
277
|
+
let ok;
|
|
278
|
+
try {
|
|
279
|
+
ok = ed25519.verify(witness.signature, digest, witness.vkey);
|
|
280
|
+
} catch (e) {
|
|
281
|
+
return failed(`Cardano signature could not be checked: ${e.message}`);
|
|
282
|
+
}
|
|
283
|
+
if (!ok) return failed("a witness signature does not verify against its own vkey");
|
|
284
|
+
}
|
|
285
|
+
if (args.account && args.signerPaths && args.signerPaths.length > 0) {
|
|
286
|
+
const accountLevels = parsePath(args.account.accountPath);
|
|
287
|
+
const expected = /* @__PURE__ */ new Map();
|
|
288
|
+
for (const path of new Set(args.signerPaths)) {
|
|
289
|
+
const levels = parsePath(path);
|
|
290
|
+
if (levels.length !== accountLevels.length + 2 || !accountLevels.every((l, i) => levels[i].index === l.index && levels[i].hardened === l.hardened) || levels.slice(accountLevels.length).some((l) => l.hardened)) return failed(`signer path ${path} does not extend the account path with two soft components`);
|
|
291
|
+
const tail = levels.slice(accountLevels.length).map((l) => l.index);
|
|
292
|
+
const vkey = cardanoSoftDerivePath(args.account.publicKey, args.account.chainCode, tail);
|
|
293
|
+
expected.set(bytesToHex(vkey), path);
|
|
294
|
+
}
|
|
295
|
+
for (const [vkeyHex, path] of expected) if (!witnesses.some((w) => bytesToHex(w.vkey) === vkeyHex)) return failed(`no witness for the requested signer path ${path}`);
|
|
296
|
+
for (const witness of witnesses) if (!expected.has(bytesToHex(witness.vkey))) return failed("the witness set carries a key your request did not ask for");
|
|
297
|
+
}
|
|
298
|
+
return verified;
|
|
299
|
+
}
|
|
300
|
+
function firstArrayItemBytes(bytes) {
|
|
301
|
+
const top = bytes[0];
|
|
302
|
+
if (top === void 0) throw new Error("empty input");
|
|
303
|
+
if (top >> 5 !== 4) throw new Error("not a CBOR array");
|
|
304
|
+
let start;
|
|
305
|
+
if ((top & 31) === 31) start = 1;
|
|
306
|
+
else {
|
|
307
|
+
const head = readHead(bytes, 0);
|
|
308
|
+
if (head.value === 0n) throw new Error("transaction array is empty");
|
|
309
|
+
start = head.next;
|
|
310
|
+
}
|
|
311
|
+
const end = skipItem(bytes, start, 0);
|
|
312
|
+
return bytes.slice(start, end);
|
|
313
|
+
}
|
|
314
|
+
function readHead(bytes, offset) {
|
|
315
|
+
const initial = bytes[offset];
|
|
316
|
+
if (initial === void 0) throw new Error("truncated");
|
|
317
|
+
const info = initial & 31;
|
|
318
|
+
if (info < 24) return {
|
|
319
|
+
value: BigInt(info),
|
|
320
|
+
next: offset + 1
|
|
321
|
+
};
|
|
322
|
+
if (info === 31) return {
|
|
323
|
+
value: -1n,
|
|
324
|
+
next: offset + 1
|
|
325
|
+
};
|
|
326
|
+
let width;
|
|
327
|
+
if (info === 24) width = 1;
|
|
328
|
+
else if (info === 25) width = 2;
|
|
329
|
+
else if (info === 26) width = 4;
|
|
330
|
+
else if (info === 27) width = 8;
|
|
331
|
+
else throw new Error("reserved length encoding");
|
|
332
|
+
let value = 0n;
|
|
333
|
+
for (let i = 0; i < width; i++) {
|
|
334
|
+
const b = bytes[offset + 1 + i];
|
|
335
|
+
if (b === void 0) throw new Error("truncated");
|
|
336
|
+
value = value << 8n | BigInt(b);
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
value,
|
|
340
|
+
next: offset + 1 + width
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/** Returns the offset just past the item starting at `offset`. */
|
|
344
|
+
function skipItem(bytes, offset, depth) {
|
|
345
|
+
if (depth > 32) throw new Error("nesting too deep");
|
|
346
|
+
const initial = bytes[offset];
|
|
347
|
+
if (initial === void 0) throw new Error("truncated");
|
|
348
|
+
const major = initial >> 5;
|
|
349
|
+
const head = readHead(bytes, offset);
|
|
350
|
+
switch (major) {
|
|
351
|
+
case 0:
|
|
352
|
+
case 1:
|
|
353
|
+
if (head.value === -1n) throw new Error("malformed integer");
|
|
354
|
+
return head.next;
|
|
355
|
+
case 2:
|
|
356
|
+
case 3: {
|
|
357
|
+
if (head.value === -1n) {
|
|
358
|
+
let pos = head.next;
|
|
359
|
+
while (bytes[pos] !== 255) {
|
|
360
|
+
const chunk = readHead(bytes, pos);
|
|
361
|
+
if (chunk.value < 0n) throw new Error("malformed chunk");
|
|
362
|
+
pos = chunk.next + Number(chunk.value);
|
|
363
|
+
if (pos > bytes.length) throw new Error("truncated string");
|
|
364
|
+
}
|
|
365
|
+
return pos + 1;
|
|
366
|
+
}
|
|
367
|
+
const end = head.next + Number(head.value);
|
|
368
|
+
if (end > bytes.length) throw new Error("truncated string");
|
|
369
|
+
return end;
|
|
370
|
+
}
|
|
371
|
+
case 4:
|
|
372
|
+
case 5: {
|
|
373
|
+
const perEntry = major === 5 ? 2 : 1;
|
|
374
|
+
if (head.value === -1n) {
|
|
375
|
+
let pos = head.next;
|
|
376
|
+
while (bytes[pos] !== 255) for (let i = 0; i < perEntry; i++) pos = skipItem(bytes, pos, depth + 1);
|
|
377
|
+
return pos + 1;
|
|
378
|
+
}
|
|
379
|
+
let pos = head.next;
|
|
380
|
+
const count = Number(head.value) * perEntry;
|
|
381
|
+
if (count > 1e6) throw new Error("container too large");
|
|
382
|
+
for (let i = 0; i < count; i++) pos = skipItem(bytes, pos, depth + 1);
|
|
383
|
+
return pos;
|
|
384
|
+
}
|
|
385
|
+
case 6:
|
|
386
|
+
if (head.value === -1n) throw new Error("malformed tag");
|
|
387
|
+
return skipItem(bytes, head.next, depth + 1);
|
|
388
|
+
case 7:
|
|
389
|
+
if ((initial & 31) === 31) throw new Error("unexpected break");
|
|
390
|
+
if ((initial & 31) === 25) return offset + 3;
|
|
391
|
+
if ((initial & 31) === 26) return offset + 5;
|
|
392
|
+
if ((initial & 31) === 27) return offset + 9;
|
|
393
|
+
return head.next;
|
|
394
|
+
default: throw new Error("unreachable");
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
//#endregion
|
|
398
|
+
//#region src/verify/cosmos.ts
|
|
399
|
+
function verifyCosmosSignature(args) {
|
|
400
|
+
if (args.signature.length !== 64) return failed("signature must be 64 bytes (compact r||s)");
|
|
401
|
+
if (args.publicKey.length !== 33) return failed("publicKey must be 33 bytes (compressed)");
|
|
402
|
+
if (args.expectedPublicKey !== void 0 && !equalBytes(args.publicKey, args.expectedPublicKey)) return failed("the reply public key is not the linked account key");
|
|
403
|
+
const digest = args.digest === "keccak256" ? keccak_256(args.signData) : sha256(args.signData);
|
|
404
|
+
let ok;
|
|
405
|
+
try {
|
|
406
|
+
ok = secp256k1.verify(args.signature, digest, args.publicKey);
|
|
407
|
+
} catch (e) {
|
|
408
|
+
return failed(`Cosmos signature could not be checked: ${e.message}`);
|
|
409
|
+
}
|
|
410
|
+
return ok ? verified : failed("the signature does not belong to this account");
|
|
411
|
+
}
|
|
412
|
+
//#endregion
|
|
249
413
|
//#region src/verify/evm.ts
|
|
250
414
|
/** EIP-191: 0x19 || "Ethereum Signed Message:\n" || len(message). */
|
|
251
415
|
function personalSignDigest(message) {
|
|
@@ -301,6 +465,25 @@ function verifySolanaSignature(args) {
|
|
|
301
465
|
return ok ? verified : failed("the signature does not belong to this account");
|
|
302
466
|
}
|
|
303
467
|
//#endregion
|
|
468
|
+
//#region src/verify/sui.ts
|
|
469
|
+
/** BLAKE2b-256 of the intent message (or the given hash) + Ed25519 verification. */
|
|
470
|
+
function verifySuiSignature(args) {
|
|
471
|
+
let digest;
|
|
472
|
+
if (args.messageHash !== void 0) {
|
|
473
|
+
if (args.messageHash.length !== 32) return failed("messageHash must be 32 bytes");
|
|
474
|
+
digest = args.messageHash;
|
|
475
|
+
} else if (args.intentMessage !== void 0) digest = suiIntentDigest(args.intentMessage);
|
|
476
|
+
else return failed("provide intentMessage or messageHash");
|
|
477
|
+
if (args.expectedPublicKey !== void 0 && !equalBytes(args.publicKey, args.expectedPublicKey)) return failed("the reply public key is not the linked account key");
|
|
478
|
+
let ok;
|
|
479
|
+
try {
|
|
480
|
+
ok = ed25519.verify(args.signature, digest, args.publicKey);
|
|
481
|
+
} catch (e) {
|
|
482
|
+
return failed(`Sui signature could not be checked: ${e.message}`);
|
|
483
|
+
}
|
|
484
|
+
return ok ? verified : failed("the signature does not belong to this account");
|
|
485
|
+
}
|
|
486
|
+
//#endregion
|
|
304
487
|
//#region src/verify/ton-boc.ts
|
|
305
488
|
/**
|
|
306
489
|
* Minimal TON Bag-of-Cells reader + cell representation hash — exactly the
|
|
@@ -572,6 +755,150 @@ function compareWindow(repliedBytes, latestBlock) {
|
|
|
572
755
|
return verified;
|
|
573
756
|
}
|
|
574
757
|
//#endregion
|
|
575
|
-
|
|
758
|
+
//#region src/verify/xrp.ts
|
|
759
|
+
/**
|
|
760
|
+
* XRP has no request id — this check IS the binding. The signed binary is
|
|
761
|
+
* split into its canonical fields; `TxnSignature` is removed; the remainder
|
|
762
|
+
* (prefixed with the XRPL signing tag `STX\0`) is hashed with SHA-512-half
|
|
763
|
+
* and the DER signature is verified against `SigningPubKey`, which must also
|
|
764
|
+
* equal the key your request carried.
|
|
765
|
+
*
|
|
766
|
+
* The field walker covers the types Payment-class transactions use; a
|
|
767
|
+
* transaction carrying an exotic field type comes back `checked: false`
|
|
768
|
+
* rather than a false verdict.
|
|
769
|
+
*/
|
|
770
|
+
function verifyXrpSignature(args) {
|
|
771
|
+
let fields;
|
|
772
|
+
try {
|
|
773
|
+
fields = splitFields(args.signedTx);
|
|
774
|
+
} catch (e) {
|
|
775
|
+
const message = e.message;
|
|
776
|
+
if (message === "unsupported-field") return unverifiable("the transaction carries a field type this checker does not walk");
|
|
777
|
+
return failed(`the signed transaction is not readable: ${message}`);
|
|
778
|
+
}
|
|
779
|
+
const signingPubKey = fields.find((f) => f.header === 115);
|
|
780
|
+
const txnSignature = fields.find((f) => f.header === 116);
|
|
781
|
+
if (!signingPubKey || !txnSignature) return failed("the signed transaction is missing SigningPubKey or TxnSignature");
|
|
782
|
+
const expected = hexToBytes(args.expectedSigningPubKey);
|
|
783
|
+
if (!equalBytes(signingPubKey.value, expected)) return failed(`the transaction was signed with a different key (${bytesToHex(signingPubKey.value)})`);
|
|
784
|
+
const payload = concatBytes(new Uint8Array([
|
|
785
|
+
83,
|
|
786
|
+
84,
|
|
787
|
+
88,
|
|
788
|
+
0
|
|
789
|
+
]), ...fields.filter((f) => f.header !== 116).map((f) => f.raw));
|
|
790
|
+
const digest = sha512(payload).slice(0, 32);
|
|
791
|
+
let ok;
|
|
792
|
+
try {
|
|
793
|
+
ok = secp256k1.verify(secp256k1.Signature.fromDER(txnSignature.value).toCompactRawBytes(), digest, expected);
|
|
794
|
+
} catch (e) {
|
|
795
|
+
return failed(`XRP signature could not be checked: ${e.message}`);
|
|
796
|
+
}
|
|
797
|
+
return ok ? verified : failed("the signature does not verify against SigningPubKey");
|
|
798
|
+
}
|
|
799
|
+
/** Split a canonical STObject into its top-level fields. */
|
|
800
|
+
function splitFields(bytes) {
|
|
801
|
+
const fields = [];
|
|
802
|
+
let pos = 0;
|
|
803
|
+
while (pos < bytes.length) {
|
|
804
|
+
const field = parseField(bytes, pos);
|
|
805
|
+
fields.push(field.field);
|
|
806
|
+
pos = field.end;
|
|
807
|
+
}
|
|
808
|
+
return fields;
|
|
809
|
+
}
|
|
810
|
+
/** Parse ONE field at `pos`; returns the field and the offset past it. */
|
|
811
|
+
function parseField(bytes, pos) {
|
|
812
|
+
const start = pos;
|
|
813
|
+
const first = bytes[pos++];
|
|
814
|
+
if (first === void 0) throw new Error("truncated");
|
|
815
|
+
let type = first >> 4;
|
|
816
|
+
let fieldCode = first & 15;
|
|
817
|
+
if (type === 0) {
|
|
818
|
+
const t = bytes[pos++];
|
|
819
|
+
if (t === void 0) throw new Error("truncated type");
|
|
820
|
+
type = t;
|
|
821
|
+
}
|
|
822
|
+
if (fieldCode === 0) {
|
|
823
|
+
const f = bytes[pos++];
|
|
824
|
+
if (f === void 0) throw new Error("truncated field code");
|
|
825
|
+
fieldCode = f;
|
|
826
|
+
}
|
|
827
|
+
let valueStart = pos;
|
|
828
|
+
switch (type) {
|
|
829
|
+
case 1:
|
|
830
|
+
pos += 2;
|
|
831
|
+
break;
|
|
832
|
+
case 2:
|
|
833
|
+
pos += 4;
|
|
834
|
+
break;
|
|
835
|
+
case 5:
|
|
836
|
+
pos += 32;
|
|
837
|
+
break;
|
|
838
|
+
case 6: {
|
|
839
|
+
const head = bytes[pos];
|
|
840
|
+
if (head === void 0) throw new Error("truncated amount");
|
|
841
|
+
pos += (head & 128) !== 0 ? 48 : 8;
|
|
842
|
+
break;
|
|
843
|
+
}
|
|
844
|
+
case 7:
|
|
845
|
+
case 8: {
|
|
846
|
+
const vl = readVl(bytes, pos);
|
|
847
|
+
valueStart = vl.next;
|
|
848
|
+
pos = vl.next + vl.length;
|
|
849
|
+
break;
|
|
850
|
+
}
|
|
851
|
+
case 14:
|
|
852
|
+
while (bytes[pos] !== 225) {
|
|
853
|
+
if (pos >= bytes.length) throw new Error("unterminated inner object");
|
|
854
|
+
pos = parseField(bytes, pos).end;
|
|
855
|
+
}
|
|
856
|
+
pos += 1;
|
|
857
|
+
break;
|
|
858
|
+
case 15:
|
|
859
|
+
while (bytes[pos] !== 241) {
|
|
860
|
+
if (pos >= bytes.length) throw new Error("unterminated array");
|
|
861
|
+
pos = parseField(bytes, pos).end;
|
|
862
|
+
}
|
|
863
|
+
pos += 1;
|
|
864
|
+
break;
|
|
865
|
+
default: throw new Error("unsupported-field");
|
|
866
|
+
}
|
|
867
|
+
if (pos > bytes.length) throw new Error("truncated field");
|
|
868
|
+
return {
|
|
869
|
+
field: {
|
|
870
|
+
header: type << 4 | (fieldCode <= 15 ? fieldCode : 0),
|
|
871
|
+
value: bytes.slice(valueStart, pos),
|
|
872
|
+
raw: bytes.slice(start, pos)
|
|
873
|
+
},
|
|
874
|
+
end: pos
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
/** XRPL variable-length prefix. */
|
|
878
|
+
function readVl(bytes, pos) {
|
|
879
|
+
const b1 = bytes[pos];
|
|
880
|
+
if (b1 === void 0) throw new Error("truncated length");
|
|
881
|
+
if (b1 <= 192) return {
|
|
882
|
+
length: b1,
|
|
883
|
+
next: pos + 1
|
|
884
|
+
};
|
|
885
|
+
if (b1 <= 240) {
|
|
886
|
+
const b2 = bytes[pos + 1];
|
|
887
|
+
if (b2 === void 0) throw new Error("truncated length");
|
|
888
|
+
return {
|
|
889
|
+
length: 193 + (b1 - 193) * 256 + b2,
|
|
890
|
+
next: pos + 2
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
const b2 = bytes[pos + 1];
|
|
894
|
+
const b3 = bytes[pos + 2];
|
|
895
|
+
if (b2 === void 0 || b3 === void 0) throw new Error("truncated length");
|
|
896
|
+
return {
|
|
897
|
+
length: 12481 + (b1 - 241) * 65536 + b2 * 256 + b3,
|
|
898
|
+
next: pos + 3
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
//#endregion
|
|
902
|
+
export { PsbtInputType, bocRootHash, parsePsbt, verifyBtcMessageHeader, verifyCardanoSignature, verifyCosmosSignature, verifyEvmSignature, verifySignedPsbt, verifySolanaSignature, verifySuiSignature, verifyTonSignature, verifyTronSignature, verifyXrpSignature };
|
|
576
903
|
|
|
577
904
|
//# sourceMappingURL=verify.js.map
|