@hwlt/era-connect 0.1.0 → 0.2.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 +25 -5
- package/dist/index.cjs +49 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.js +47 -1
- package/dist/index.js.map +1 -1
- package/dist/ton-5Uvi5ifg.js +86 -0
- package/dist/ton-5Uvi5ifg.js.map +1 -0
- package/dist/ton-C0UP-cf_.d.ts +51 -0
- package/dist/ton-DUJGXdGa.cjs +97 -0
- package/dist/ton-DUJGXdGa.cjs.map +1 -0
- package/dist/ton-DmeIvknN.d.cts +51 -0
- package/dist/ton.cjs +10 -0
- package/dist/ton.d.cts +3 -0
- package/dist/ton.d.ts +3 -0
- package/dist/ton.js +3 -0
- package/dist/verify.cjs +154 -13
- package/dist/verify.cjs.map +1 -1
- package/dist/verify.d.cts +24 -1
- package/dist/verify.d.ts +24 -1
- package/dist/verify.js +153 -14
- package/dist/verify.js.map +1 -1
- package/package.json +20 -8
- package/ton/package.json +6 -0
package/dist/verify.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_shared = require("./shared-nISrEktU.cjs");
|
|
3
3
|
const require_evm = require("./evm-BHj_2OTG.cjs");
|
|
4
|
+
const require_ton = require("./ton-DUJGXdGa.cjs");
|
|
4
5
|
const require_messages = require("./messages-BzcdWlg1.cjs");
|
|
5
6
|
let _noble_curves_secp256k1 = require("@noble/curves/secp256k1");
|
|
6
7
|
let _noble_hashes_sha2 = require("@noble/hashes/sha2");
|
|
@@ -22,7 +23,7 @@ const PsbtInputType = {
|
|
|
22
23
|
taprootKeySpendSignature: 19,
|
|
23
24
|
taprootScriptSpendSignature: 20
|
|
24
25
|
};
|
|
25
|
-
function err(message) {
|
|
26
|
+
function err$1(message) {
|
|
26
27
|
return new require_shared.EraSdkError("malformed-reply", `psbt: ${message}`);
|
|
27
28
|
}
|
|
28
29
|
var Reader = class {
|
|
@@ -35,7 +36,7 @@ var Reader = class {
|
|
|
35
36
|
}
|
|
36
37
|
u8() {
|
|
37
38
|
const b = this.bytes[this.offset];
|
|
38
|
-
if (b === void 0) throw err("truncated");
|
|
39
|
+
if (b === void 0) throw err$1("truncated");
|
|
39
40
|
this.offset += 1;
|
|
40
41
|
return b;
|
|
41
42
|
}
|
|
@@ -57,12 +58,12 @@ var Reader = class {
|
|
|
57
58
|
}
|
|
58
59
|
let value = 0n;
|
|
59
60
|
for (let i = 0; i < width; i++) value |= BigInt(this.u8()) << BigInt(8 * i);
|
|
60
|
-
if (value < minimum) throw err("non-minimal compact-size encoding");
|
|
61
|
-
if (value > BigInt(Number.MAX_SAFE_INTEGER)) throw err("length exceeds safe range");
|
|
61
|
+
if (value < minimum) throw err$1("non-minimal compact-size encoding");
|
|
62
|
+
if (value > BigInt(Number.MAX_SAFE_INTEGER)) throw err$1("length exceeds safe range");
|
|
62
63
|
return Number(value);
|
|
63
64
|
}
|
|
64
65
|
take(length) {
|
|
65
|
-
if (length > this.remaining) throw err("length exceeds input");
|
|
66
|
+
if (length > this.remaining) throw err$1("length exceeds input");
|
|
66
67
|
const out = this.bytes.slice(this.offset, this.offset + length);
|
|
67
68
|
this.offset += length;
|
|
68
69
|
return out;
|
|
@@ -78,7 +79,7 @@ function readMap(reader) {
|
|
|
78
79
|
const key = reader.take(keyLength);
|
|
79
80
|
const value = reader.take(reader.compactSize());
|
|
80
81
|
const keyId = Array.from(key).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
81
|
-
if (seen.has(keyId)) throw err("duplicate key within one map");
|
|
82
|
+
if (seen.has(keyId)) throw err$1("duplicate key within one map");
|
|
82
83
|
seen.add(keyId);
|
|
83
84
|
entries.push({
|
|
84
85
|
keyType: key[0],
|
|
@@ -92,7 +93,7 @@ function countTxInputsOutputs(tx) {
|
|
|
92
93
|
const reader = new Reader(tx);
|
|
93
94
|
reader.take(4);
|
|
94
95
|
const inputs = reader.compactSize();
|
|
95
|
-
if (inputs === 0) throw err("unsigned transaction has zero inputs (or carries witness data)");
|
|
96
|
+
if (inputs === 0) throw err$1("unsigned transaction has zero inputs (or carries witness data)");
|
|
96
97
|
for (let i = 0; i < inputs; i++) {
|
|
97
98
|
reader.take(36);
|
|
98
99
|
reader.take(reader.compactSize());
|
|
@@ -104,7 +105,7 @@ function countTxInputsOutputs(tx) {
|
|
|
104
105
|
reader.take(reader.compactSize());
|
|
105
106
|
}
|
|
106
107
|
reader.take(4);
|
|
107
|
-
if (reader.remaining !== 0) throw err("trailing bytes after the unsigned transaction");
|
|
108
|
+
if (reader.remaining !== 0) throw err$1("trailing bytes after the unsigned transaction");
|
|
108
109
|
return {
|
|
109
110
|
inputs,
|
|
110
111
|
outputs
|
|
@@ -112,25 +113,25 @@ function countTxInputsOutputs(tx) {
|
|
|
112
113
|
}
|
|
113
114
|
function parsePsbt(bytes) {
|
|
114
115
|
const reader = new Reader(bytes);
|
|
115
|
-
for (const expected of MAGIC) if (reader.u8() !== expected) throw err("bad magic");
|
|
116
|
+
for (const expected of MAGIC) if (reader.u8() !== expected) throw err$1("bad magic");
|
|
116
117
|
const globalMap = readMap(reader);
|
|
117
118
|
let unsignedTx = null;
|
|
118
119
|
let version = 0;
|
|
119
120
|
for (const entry of globalMap) {
|
|
120
121
|
if (entry.keyType === 0 && entry.keyData.length === 0) unsignedTx = entry.value;
|
|
121
122
|
if (entry.keyType === 251 && entry.keyData.length === 0) {
|
|
122
|
-
if (entry.value.length !== 4) throw err("bad version field");
|
|
123
|
+
if (entry.value.length !== 4) throw err$1("bad version field");
|
|
123
124
|
version = (entry.value[0] | entry.value[1] << 8 | entry.value[2] << 16 | entry.value[3] << 24) >>> 0;
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
|
-
if (unsignedTx === null) throw err("no global unsigned transaction — not a PSBT v0");
|
|
127
|
-
if (version !== 0) throw err(`unsupported PSBT version ${version}`);
|
|
127
|
+
if (unsignedTx === null) throw err$1("no global unsigned transaction — not a PSBT v0");
|
|
128
|
+
if (version !== 0) throw err$1(`unsupported PSBT version ${version}`);
|
|
128
129
|
const counts = countTxInputsOutputs(unsignedTx);
|
|
129
130
|
const inputs = [];
|
|
130
131
|
for (let i = 0; i < counts.inputs; i++) inputs.push(readMap(reader));
|
|
131
132
|
const outputs = [];
|
|
132
133
|
for (let i = 0; i < counts.outputs; i++) outputs.push(readMap(reader));
|
|
133
|
-
if (reader.remaining !== 0) throw err("trailing bytes after the output maps");
|
|
134
|
+
if (reader.remaining !== 0) throw err$1("trailing bytes after the output maps");
|
|
134
135
|
return {
|
|
135
136
|
unsignedTx,
|
|
136
137
|
version,
|
|
@@ -301,6 +302,144 @@ function verifySolanaSignature(args) {
|
|
|
301
302
|
return ok ? verified : failed("the signature does not belong to this account");
|
|
302
303
|
}
|
|
303
304
|
//#endregion
|
|
305
|
+
//#region src/verify/ton-boc.ts
|
|
306
|
+
/**
|
|
307
|
+
* Minimal TON Bag-of-Cells reader + cell representation hash — exactly the
|
|
308
|
+
* subset the device's signer implements: generic BoC, ordinary level-0 cells,
|
|
309
|
+
* first root. The transaction digest the device signs IS the root cell's
|
|
310
|
+
* representation hash, so this must agree with the firmware bit for bit.
|
|
311
|
+
*
|
|
312
|
+
* Hardened for scanned/untrusted input: size caps, bounds checks, and
|
|
313
|
+
* forward-only references (the standard BoC topological order; a backward
|
|
314
|
+
* reference would make the single-pass hash read an uncomputed child).
|
|
315
|
+
*/
|
|
316
|
+
const BOC_MAGIC = 3052313714;
|
|
317
|
+
const MAX_CELLS = 256;
|
|
318
|
+
const MAX_CELL_DATA_BYTES = 128;
|
|
319
|
+
const MAX_REFS = 4;
|
|
320
|
+
function err(message) {
|
|
321
|
+
return new require_shared.EraSdkError("malformed-reply", `ton boc: ${message}`);
|
|
322
|
+
}
|
|
323
|
+
/** Representation hash of the ROOT cell of a BoC — the bytes TON signs. */
|
|
324
|
+
function bocRootHash(boc) {
|
|
325
|
+
if (boc.length < 10) throw err("too short");
|
|
326
|
+
if ((boc[0] << 24 | boc[1] << 16 | boc[2] << 8 | boc[3]) >>> 0 !== BOC_MAGIC) throw err("not a generic BoC");
|
|
327
|
+
const flags = boc[4];
|
|
328
|
+
const hasIdx = flags >> 7 & 1;
|
|
329
|
+
const refSize = flags & 7;
|
|
330
|
+
const offSize = boc[5];
|
|
331
|
+
if (refSize === 0 || refSize > 4) throw err("bad ref size");
|
|
332
|
+
if (offSize === 0 || offSize > 8) throw err("bad offset size");
|
|
333
|
+
let pos = 6;
|
|
334
|
+
const readInt = (byteLen) => {
|
|
335
|
+
let value = 0;
|
|
336
|
+
for (let i = 0; i < byteLen; i++) {
|
|
337
|
+
if (pos >= boc.length) throw err("truncated header");
|
|
338
|
+
value = value * 256 + boc[pos++];
|
|
339
|
+
}
|
|
340
|
+
if (!Number.isSafeInteger(value)) throw err("header value out of range");
|
|
341
|
+
return value;
|
|
342
|
+
};
|
|
343
|
+
const cellCount = readInt(refSize);
|
|
344
|
+
const rootCount = readInt(refSize);
|
|
345
|
+
readInt(refSize);
|
|
346
|
+
readInt(offSize);
|
|
347
|
+
if (rootCount === 0) throw err("no roots");
|
|
348
|
+
if (cellCount === 0 || cellCount > MAX_CELLS) throw err("cell count out of range");
|
|
349
|
+
const rootIndex = readInt(refSize);
|
|
350
|
+
for (let i = 1; i < rootCount; i++) readInt(refSize);
|
|
351
|
+
if (rootIndex >= cellCount) throw err("root index out of range");
|
|
352
|
+
if (hasIdx) pos += cellCount * offSize;
|
|
353
|
+
const cells = [];
|
|
354
|
+
for (let i = 0; i < cellCount; i++) {
|
|
355
|
+
if (pos + 2 > boc.length) throw err("truncated cell");
|
|
356
|
+
const d1 = boc[pos++];
|
|
357
|
+
const d2 = boc[pos++];
|
|
358
|
+
const refCount = d1 & 7;
|
|
359
|
+
if (refCount > MAX_REFS) throw err("too many references");
|
|
360
|
+
const dataByteLen = d2 + 1 >> 1;
|
|
361
|
+
const incomplete = (d2 & 1) === 1;
|
|
362
|
+
if (dataByteLen > MAX_CELL_DATA_BYTES) throw err("cell data too large");
|
|
363
|
+
if (pos + dataByteLen > boc.length) throw err("truncated cell data");
|
|
364
|
+
const data = boc.slice(pos, pos + dataByteLen);
|
|
365
|
+
pos += dataByteLen;
|
|
366
|
+
let dataBits;
|
|
367
|
+
if (incomplete && dataByteLen > 0) {
|
|
368
|
+
const last = data[dataByteLen - 1];
|
|
369
|
+
if (last === 0) dataBits = (dataByteLen - 1) * 8;
|
|
370
|
+
else {
|
|
371
|
+
let trailingZeros = 0;
|
|
372
|
+
for (let b = 0; b < 8; b++) {
|
|
373
|
+
if (last & 1 << b) break;
|
|
374
|
+
trailingZeros++;
|
|
375
|
+
}
|
|
376
|
+
dataBits = dataByteLen * 8 - 1 - trailingZeros;
|
|
377
|
+
}
|
|
378
|
+
} else dataBits = dataByteLen * 8;
|
|
379
|
+
const refs = [];
|
|
380
|
+
for (let r = 0; r < refCount; r++) {
|
|
381
|
+
const ref = readInt(refSize);
|
|
382
|
+
if (ref >= cellCount) throw err("reference out of range");
|
|
383
|
+
if (ref <= i) throw err("non-topological cell reference");
|
|
384
|
+
refs.push(ref);
|
|
385
|
+
}
|
|
386
|
+
cells.push({
|
|
387
|
+
dataBits,
|
|
388
|
+
data,
|
|
389
|
+
refs,
|
|
390
|
+
depth: 0,
|
|
391
|
+
hash: /* @__PURE__ */ new Uint8Array(0)
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
for (let i = cellCount - 1; i >= 0; i--) {
|
|
395
|
+
const cell = cells[i];
|
|
396
|
+
let maxChildDepth = -1;
|
|
397
|
+
for (const r of cell.refs) maxChildDepth = Math.max(maxChildDepth, cells[r].depth);
|
|
398
|
+
cell.depth = cell.refs.length === 0 ? 0 : maxChildDepth + 1;
|
|
399
|
+
const dataBytes = cell.dataBits + 7 >> 3;
|
|
400
|
+
const incomplete = cell.dataBits % 8 !== 0;
|
|
401
|
+
const repr = [cell.refs.length, dataBytes * 2 - (incomplete ? 1 : 0)];
|
|
402
|
+
for (let b = 0; b < dataBytes; b++) repr.push(cell.data[b] ?? 0);
|
|
403
|
+
if (incomplete && dataBytes > 0) {
|
|
404
|
+
const shift = 7 - cell.dataBits % 8;
|
|
405
|
+
const last = repr.length - 1;
|
|
406
|
+
repr[last] = (repr[last] | 1 << shift) & 255 << shift & 255;
|
|
407
|
+
}
|
|
408
|
+
for (const r of cell.refs) repr.push(cells[r].depth >> 8 & 255, cells[r].depth & 255);
|
|
409
|
+
let bytes = new Uint8Array(repr);
|
|
410
|
+
for (const r of cell.refs) bytes = require_shared.concatBytes(bytes, cells[r].hash);
|
|
411
|
+
cell.hash = (0, _noble_hashes_sha2.sha256)(bytes);
|
|
412
|
+
}
|
|
413
|
+
return cells[rootIndex].hash;
|
|
414
|
+
}
|
|
415
|
+
//#endregion
|
|
416
|
+
//#region src/verify/ton.ts
|
|
417
|
+
/**
|
|
418
|
+
* Recompute the exact digest the device signs — the BoC ROOT CELL's
|
|
419
|
+
* representation hash for a transaction, or the TON Connect proof digest
|
|
420
|
+
* `sha256(0xFFFF || "ton-connect" || sha256(payload))` — and verify the
|
|
421
|
+
* Ed25519 signature against the linked key.
|
|
422
|
+
*/
|
|
423
|
+
function verifyTonSignature(args) {
|
|
424
|
+
if (args.signature.length !== 64) return failed("signature must be 64 bytes");
|
|
425
|
+
if (args.publicKey.length !== 32) return failed("public key must be 32 bytes");
|
|
426
|
+
let digest;
|
|
427
|
+
if (args.dataType === require_ton.TonDataType.tonProof) digest = (0, _noble_hashes_sha2.sha256)(require_shared.concatBytes(new Uint8Array([255, 255]), require_shared.utf8Encode("ton-connect"), (0, _noble_hashes_sha2.sha256)(args.signData)));
|
|
428
|
+
else if (args.dataType === require_ton.TonDataType.transaction) try {
|
|
429
|
+
digest = bocRootHash(args.signData);
|
|
430
|
+
} catch (e) {
|
|
431
|
+
return failed(`signData is not a readable BoC: ${e.message}`);
|
|
432
|
+
}
|
|
433
|
+
else return failed(`unknown dataType ${args.dataType}`);
|
|
434
|
+
let ok;
|
|
435
|
+
try {
|
|
436
|
+
ok = _noble_curves_ed25519.ed25519.verify(args.signature, digest, args.publicKey);
|
|
437
|
+
} catch (e) {
|
|
438
|
+
return failed(`TON signature could not be checked: ${e.message}`);
|
|
439
|
+
}
|
|
440
|
+
return ok ? verified : failed("the signature does not belong to this account");
|
|
441
|
+
}
|
|
442
|
+
//#endregion
|
|
304
443
|
//#region src/verify/tron.ts
|
|
305
444
|
const base58check = (0, _scure_base.createBase58check)(_noble_hashes_sha2.sha256);
|
|
306
445
|
/**
|
|
@@ -435,11 +574,13 @@ function compareWindow(repliedBytes, latestBlock) {
|
|
|
435
574
|
}
|
|
436
575
|
//#endregion
|
|
437
576
|
exports.PsbtInputType = PsbtInputType;
|
|
577
|
+
exports.bocRootHash = bocRootHash;
|
|
438
578
|
exports.parsePsbt = parsePsbt;
|
|
439
579
|
exports.verifyBtcMessageHeader = verifyBtcMessageHeader;
|
|
440
580
|
exports.verifyEvmSignature = verifyEvmSignature;
|
|
441
581
|
exports.verifySignedPsbt = verifySignedPsbt;
|
|
442
582
|
exports.verifySolanaSignature = verifySolanaSignature;
|
|
583
|
+
exports.verifyTonSignature = verifyTonSignature;
|
|
443
584
|
exports.verifyTronSignature = verifyTronSignature;
|
|
444
585
|
|
|
445
586
|
//# sourceMappingURL=verify.cjs.map
|
package/dist/verify.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.cjs","names":["EraSdkError","equalBytes","EraSdkError","utf8Encode","keccak_256","concatBytes","equalBytes","EvmDataType","foldRecoveryId","secp256k1","hexToBytes","bytesToHex","equalBytes","ed25519","createBase58check","sha256","splitSignedTronTx","equalBytes","secp256k1","keccak_256","concatBytes","readFields","firstBytes","utf8Decode","firstVarint"],"sources":["../src/verify/psbt-reader.ts","../src/verify/result.ts","../src/verify/btc.ts","../src/verify/evm.ts","../src/verify/solana.ts","../src/verify/tron.ts"],"sourcesContent":["import { EraSdkError } from '../core/errors';\n\n/**\n * Minimal PSBT v0 (BIP-174) reader — just enough structure for the\n * verification guard: the global unsigned transaction (verbatim slice, never\n * re-serialized), the PSBT version, and per-input key/value maps.\n *\n * Hardened: compact-size lengths bounds-checked before slicing, duplicate\n * keys within one map refused (a hostile PSBT carrying two final scriptSigs\n * for one input must not survive parsing).\n */\n\nexport interface PsbtKeyValue {\n readonly keyType: number;\n readonly keyData: Uint8Array;\n readonly value: Uint8Array;\n}\n\nexport interface ParsedPsbt {\n /** The global UNSIGNED_TX value, verbatim. */\n readonly unsignedTx: Uint8Array;\n /** Global PSBT_GLOBAL_VERSION (0xFB) if present; v0 files normally omit it. */\n readonly version: number;\n readonly inputs: readonly (readonly PsbtKeyValue[])[];\n readonly outputs: readonly (readonly PsbtKeyValue[])[];\n}\n\nconst MAGIC = [0x70, 0x73, 0x62, 0x74, 0xff]; // \"psbt\\xff\"\n\nexport const PsbtInputType = {\n partialSig: 0x02,\n finalScriptSig: 0x07,\n finalScriptWitness: 0x08,\n taprootKeySpendSignature: 0x13,\n taprootScriptSpendSignature: 0x14,\n} as const;\n\nfunction err(message: string): EraSdkError {\n return new EraSdkError('malformed-reply', `psbt: ${message}`);\n}\n\nclass Reader {\n offset = 0;\n constructor(readonly bytes: Uint8Array) {}\n\n get remaining(): number {\n return this.bytes.length - this.offset;\n }\n\n u8(): number {\n const b = this.bytes[this.offset];\n if (b === undefined) throw err('truncated');\n this.offset += 1;\n return b;\n }\n\n /** Bitcoin compact-size integer, MINIMAL encoding required (as consensus does). */\n compactSize(): number {\n const first = this.u8();\n if (first < 0xfd) return first;\n let width: number;\n let minimum: bigint;\n if (first === 0xfd) {\n width = 2;\n minimum = 0xfdn;\n } else if (first === 0xfe) {\n width = 4;\n minimum = 0x10000n;\n } else {\n width = 8;\n minimum = 0x100000000n;\n }\n let value = 0n;\n for (let i = 0; i < width; i++) value |= BigInt(this.u8()) << BigInt(8 * i);\n if (value < minimum) throw err('non-minimal compact-size encoding');\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) throw err('length exceeds safe range');\n return Number(value);\n }\n\n take(length: number): Uint8Array {\n if (length > this.remaining) throw err('length exceeds input');\n const out = this.bytes.slice(this.offset, this.offset + length);\n this.offset += length;\n return out;\n }\n}\n\n/** Read one key/value map (ends at the 0x00 separator). */\nfunction readMap(reader: Reader): PsbtKeyValue[] {\n const entries: PsbtKeyValue[] = [];\n const seen = new Set<string>();\n for (;;) {\n const keyLength = reader.compactSize();\n if (keyLength === 0) return entries;\n const key = reader.take(keyLength);\n const value = reader.take(reader.compactSize());\n const keyId = Array.from(key)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n if (seen.has(keyId)) throw err('duplicate key within one map');\n seen.add(keyId);\n entries.push({ keyType: key[0]!, keyData: key.slice(1), value });\n }\n}\n\n/** Count of inputs/outputs in a (non-witness) unsigned transaction. */\nfunction countTxInputsOutputs(tx: Uint8Array): { inputs: number; outputs: number } {\n const reader = new Reader(tx);\n reader.take(4); // version\n const inputs = reader.compactSize();\n if (inputs === 0) {\n // A zero here would be a segwit marker — the PSBT unsigned tx must not\n // carry witness data, so this is not a transaction we can count.\n throw err('unsigned transaction has zero inputs (or carries witness data)');\n }\n for (let i = 0; i < inputs; i++) {\n reader.take(32 + 4); // prevout\n reader.take(reader.compactSize()); // scriptSig (empty in a PSBT)\n reader.take(4); // sequence\n }\n const outputs = reader.compactSize();\n for (let i = 0; i < outputs; i++) {\n reader.take(8); // amount\n reader.take(reader.compactSize()); // scriptPubKey\n }\n reader.take(4); // locktime\n if (reader.remaining !== 0) throw err('trailing bytes after the unsigned transaction');\n return { inputs, outputs };\n}\n\nexport function parsePsbt(bytes: Uint8Array): ParsedPsbt {\n const reader = new Reader(bytes);\n for (const expected of MAGIC) {\n if (reader.u8() !== expected) throw err('bad magic');\n }\n const globalMap = readMap(reader);\n\n let unsignedTx: Uint8Array | null = null;\n let version = 0;\n for (const entry of globalMap) {\n if (entry.keyType === 0x00 && entry.keyData.length === 0) unsignedTx = entry.value;\n if (entry.keyType === 0xfb && entry.keyData.length === 0) {\n if (entry.value.length !== 4) throw err('bad version field');\n version =\n (entry.value[0]! |\n (entry.value[1]! << 8) |\n (entry.value[2]! << 16) |\n (entry.value[3]! << 24)) >>>\n 0;\n }\n }\n if (unsignedTx === null) {\n // The device's signer relies on the global UNSIGNED_TX that only PSBT v0\n // carries; its absence means v2 (or not a PSBT at all).\n throw err('no global unsigned transaction — not a PSBT v0');\n }\n if (version !== 0) throw err(`unsupported PSBT version ${version}`);\n\n const counts = countTxInputsOutputs(unsignedTx);\n const inputs: PsbtKeyValue[][] = [];\n for (let i = 0; i < counts.inputs; i++) inputs.push(readMap(reader));\n const outputs: PsbtKeyValue[][] = [];\n for (let i = 0; i < counts.outputs; i++) outputs.push(readMap(reader));\n if (reader.remaining !== 0) throw err('trailing bytes after the output maps');\n\n return { unsignedTx, version, inputs, outputs };\n}\n\nexport function inputEntries(\n psbt: ParsedPsbt,\n index: number,\n keyType: number,\n): readonly PsbtKeyValue[] {\n return (psbt.inputs[index] ?? []).filter((e) => e.keyType === keyType);\n}\n\nexport function inputHas(psbt: ParsedPsbt, index: number, keyType: number): boolean {\n return inputEntries(psbt, index, keyType).length > 0;\n}\n","/** Outcome of a verification helper. Helpers return, never throw, on mismatches. */\nexport type VerifyResult =\n /** Verified cryptographically / byte-for-byte. */\n | { readonly ok: true; readonly checked: true }\n /**\n * Nothing client-side is verifiable for this input (EIP-712 typed data:\n * the digest is the hash of the structure, which only the device computes).\n * The UR-type pin and the request-id echo are the whole binding.\n */\n | { readonly ok: true; readonly checked: false; readonly reason: string }\n | { readonly ok: false; readonly reason: string };\n\nexport const verified: VerifyResult = { ok: true, checked: true };\nexport const failed = (reason: string): VerifyResult => ({ ok: false, reason });\nexport const unverifiable = (reason: string): VerifyResult => ({\n ok: true,\n checked: false,\n reason,\n});\n","import { equalBytes } from '../core/bytes';\nimport { EraSdkError } from '../core/errors';\nimport type { ParsedPsbt } from './psbt-reader';\nimport { inputEntries, inputHas, PsbtInputType, parsePsbt } from './psbt-reader';\nimport type { VerifyResult } from './result';\nimport { failed, verified } from './result';\n\nexport interface VerifySignedPsbtArgs {\n /** The PSBT you sent to the device. */\n readonly sentPsbt: Uint8Array;\n /** The PSBT the device returned. */\n readonly signedPsbt: Uint8Array;\n /**\n * true (default) on flows where every input is yours (a plain send): a\n * reply that signed only part of the transaction is refused here with a\n * reason instead of failing later inside a finalizer. Set false for dApp\n * `signPsbt` hand-backs, where a PSBT legitimately carries inputs you\n * cannot sign.\n */\n readonly requireEveryInputSigned?: boolean;\n}\n\n/**\n * The `crypto-psbt` reply carries NO request id — this comparison IS the\n * anti-replay binding for Bitcoin. It is not optional.\n *\n * The unsigned transaction is compared byte for byte, which pins the input\n * set and order, the outputs, their amounts, the version and the locktime in\n * one shot — and therefore the txid. The device only ADDS per-input\n * signature fields, so a legitimate reply always matches.\n */\nexport function verifySignedPsbt(args: VerifySignedPsbtArgs): VerifyResult {\n let sent: ParsedPsbt;\n let signed: ParsedPsbt;\n try {\n sent = parsePsbt(args.sentPsbt);\n } catch (e) {\n return failed(`the PSBT we sent is not readable: ${message(e)}`);\n }\n try {\n signed = parsePsbt(args.signedPsbt);\n } catch (e) {\n return failed(`the PSBT the device returned is not readable: ${message(e)}`);\n }\n\n if (!equalBytes(sent.unsignedTx, signed.unsignedTx)) {\n return failed('the returned PSBT is a different transaction from the one approved');\n }\n\n // A finalized field carries the COMPLETE scriptSig/witness that will be\n // broadcast, and the unsigned-tx comparison above does not cover it (it\n // lives per input, the unsigned tx in the global map). An input that comes\n // back finalized must have been SENT that way, with byte-identical\n // values — the device echoes these fields, it never authors them.\n const finalizedTypes = [PsbtInputType.finalScriptSig, PsbtInputType.finalScriptWitness];\n for (let i = 0; i < signed.inputs.length; i++) {\n for (const type of finalizedTypes) {\n if (!inputHas(signed, i, type)) continue;\n if (!inputHas(sent, i, type)) {\n return failed(\n `input ${i} came back finalized (type 0x${type.toString(16)}) and was not sent that way — the script it would broadcast is not ours`,\n );\n }\n const a = inputEntries(sent, i, type);\n const b = inputEntries(signed, i, type);\n if (a.length !== b.length || !a.every((entry, k) => equalBytes(entry.value, b[k]!.value))) {\n return failed(\n `input ${i} came back with a different finalized script than the one we sent`,\n );\n }\n }\n }\n\n const isSigned = (i: number): boolean =>\n inputHas(signed, i, PsbtInputType.partialSig) ||\n inputHas(signed, i, PsbtInputType.taprootKeySpendSignature) ||\n inputHas(signed, i, PsbtInputType.taprootScriptSpendSignature);\n\n const indexes = signed.inputs.map((_, i) => i);\n if (args.requireEveryInputSigned ?? true) {\n if (!indexes.every(isSigned)) {\n return failed('the device signed only part of the transaction');\n }\n } else if (!indexes.some(isSigned)) {\n return failed('the returned PSBT carries no signature');\n }\n return verified;\n}\n\nexport interface VerifyBtcMessageHeaderArgs {\n /** The address the request asked the device to sign with. */\n readonly address: string;\n /** The raw 65-byte BIP-137 signature. */\n readonly signature: Uint8Array;\n}\n\n/**\n * BIP-137: the recovery header names the address type a verifier derives\n * before comparing. A header of the wrong range produces a signature that\n * LOOKS fine (65 bytes, valid base64) but fails every verifier downstream —\n * this check is the only place that difference is visible.\n */\nexport function verifyBtcMessageHeader(args: VerifyBtcMessageHeaderArgs): VerifyResult {\n if (args.signature.length === 0) {\n return failed('empty signature');\n }\n const header = args.signature[0]!;\n const range = headerRangeFor(args.address);\n if (range === null) {\n return {\n ok: true,\n checked: false,\n reason: 'address kind has no BIP-137 header range to check against',\n };\n }\n if (header >= range.low && header <= range.high) return verified;\n return failed(\n `recovery header ${header} does not match a ${range.label} address ` +\n `(BIP-137 expects ${range.low}..${range.high}); this signature would not verify against the address it was asked to sign for`,\n );\n}\n\ninterface HeaderRange {\n readonly low: number;\n readonly high: number;\n readonly label: string;\n}\n\nfunction headerRangeFor(address: string): HeaderRange | null {\n const a = address.toLowerCase();\n if (a.startsWith('bc1q') || a.startsWith('tb1q') || a.startsWith('bcrt1q')) {\n return { low: 39, high: 42, label: 'native segwit (P2WPKH)' };\n }\n if (a.startsWith('bc1p') || a.startsWith('tb1p') || a.startsWith('bcrt1p')) {\n return null; // Taproot: BIP-137 does not cover it (BIP-322 is the scheme).\n }\n // Base58 kinds matched on SHAPE, not first character alone — a guard that\n // invents a range for a string it does not understand is worse than one\n // that declines to judge.\n if (looksBase58(address)) {\n if (address.startsWith('3') || address.startsWith('2')) {\n return { low: 35, high: 38, label: 'P2SH (nested segwit)' };\n }\n if (address.startsWith('1') || address.startsWith('m') || address.startsWith('n')) {\n // Both the uncompressed and compressed P2PKH ranges — which one is\n // right depends on the key the device used, which we do not know.\n return { low: 27, high: 34, label: 'legacy P2PKH' };\n }\n }\n return null;\n}\n\nfunction looksBase58(address: string): boolean {\n return address.length >= 26 && address.length <= 35 && /^[1-9A-HJ-NP-Za-km-z]+$/.test(address);\n}\n\nfunction message(e: unknown): string {\n return e instanceof EraSdkError || e instanceof Error ? e.message : String(e);\n}\n","import { secp256k1 } from '@noble/curves/secp256k1';\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { EvmDataType, foldRecoveryId } from '../chains/evm';\nimport { bytesToHex, concatBytes, equalBytes, hexToBytes, utf8Encode } from '../core/bytes';\nimport type { VerifyResult } from './result';\nimport { failed, unverifiable, verified } from './result';\n\nexport interface VerifyEvmSignatureArgs {\n /** The exact bytes the request carried in `signData`. */\n readonly signData: Uint8Array;\n readonly dataType: EvmDataType;\n /** Raw `r || s || v` from the reply (65+ bytes; multi-byte legacy `v` handled). */\n readonly signature: Uint8Array;\n /** The signer address the request was built for. */\n readonly address: Uint8Array | `0x${string}`;\n /**\n * Optional: the signing payload re-derived from the transaction you are\n * ABOUT TO BROADCAST. Recovering against `signData` alone proves the device\n * signed something you asked for — this closes the second half: that it is\n * the transaction still in your hands (payloads can legitimately change\n * between build and send, e.g. a blockhash refresh in your own state).\n */\n readonly reEncodedSignData?: Uint8Array;\n}\n\n/** EIP-191: 0x19 || \"Ethereum Signed Message:\\n\" || len(message). */\nfunction personalSignDigest(message: Uint8Array): Uint8Array {\n const prefix = utf8Encode(`Ethereum Signed Message:\\n${message.length}`);\n return keccak_256(concatBytes(new Uint8Array([0x19]), prefix, message));\n}\n\n/**\n * \"Did the device sign exactly what I sent, with the key I expected?\"\n * keccak digest + public-key recovery; the recovered address must equal the\n * request's. Run it before broadcasting.\n */\nexport function verifyEvmSignature(args: VerifyEvmSignatureArgs): VerifyResult {\n if (args.signature.length < 65) {\n return failed('signature is shorter than 65 bytes');\n }\n if (args.reEncodedSignData !== undefined && !equalBytes(args.reEncodedSignData, args.signData)) {\n return failed('the transaction to broadcast is not the one the device signed');\n }\n\n let digest: Uint8Array;\n switch (args.dataType) {\n case EvmDataType.transaction:\n case EvmDataType.typedTransaction:\n digest = keccak_256(args.signData);\n break;\n case EvmDataType.personalMessage:\n digest = personalSignDigest(args.signData);\n break;\n case EvmDataType.typedData:\n return unverifiable(\n 'EIP-712: the digest is the hash of the structure, computed only on the device',\n );\n default:\n return failed(`unknown dataType ${args.dataType satisfies never}`);\n }\n\n let vBig = 0n;\n for (const b of args.signature.slice(64)) vBig = (vBig << 8n) | BigInt(b);\n const recoveryId = foldRecoveryId(vBig);\n if (recoveryId !== 0 && recoveryId !== 1) {\n return failed('implausible recovery value');\n }\n\n let recovered: Uint8Array;\n try {\n const point = secp256k1.Signature.fromCompact(args.signature.slice(0, 64))\n .addRecoveryBit(recoveryId)\n .recoverPublicKey(digest);\n recovered = keccak_256(point.toRawBytes(false).slice(1)).slice(12);\n } catch (e) {\n return failed(`signature could not be checked: ${(e as Error).message}`);\n }\n\n const expected = args.address instanceof Uint8Array ? args.address : hexToBytes(args.address);\n if (expected.length !== 20) {\n return failed(`expected address must be 20 bytes, got ${expected.length}`);\n }\n if (!equalBytes(recovered, expected)) {\n return failed(\n `the signature does not belong to this account (recovered 0x${bytesToHex(recovered)})`,\n );\n }\n return verified;\n}\n","import { ed25519 } from '@noble/curves/ed25519';\nimport { equalBytes } from '../core/bytes';\nimport type { VerifyResult } from './result';\nimport { failed, verified } from './result';\n\nexport interface VerifySolanaSignatureArgs {\n /** The exact bytes the request carried in `signData` (the compiled message). */\n readonly signData: Uint8Array;\n /** 64-byte Ed25519 signature from the reply. */\n readonly signature: Uint8Array;\n /** The 32-byte signer public key the request was built for. */\n readonly publicKey: Uint8Array;\n /**\n * Optional: the message bytes you are ABOUT TO BROADCAST. Matters most on\n * Solana — a blockhash refresh between build and send makes \"what was\n * signed\" and \"what will be sent\" two different objects that must agree.\n */\n readonly broadcastMessageBytes?: Uint8Array;\n}\n\nexport function verifySolanaSignature(args: VerifySolanaSignatureArgs): VerifyResult {\n if (\n args.broadcastMessageBytes !== undefined &&\n !equalBytes(args.broadcastMessageBytes, args.signData)\n ) {\n return failed('the message to broadcast is not the one the device signed');\n }\n let ok: boolean;\n try {\n ok = ed25519.verify(args.signature, args.signData, args.publicKey);\n } catch (e) {\n return failed(`Solana signature could not be checked: ${(e as Error).message}`);\n }\n return ok ? verified : failed('the signature does not belong to this account');\n}\n","import { secp256k1 } from '@noble/curves/secp256k1';\nimport { sha256 } from '@noble/hashes/sha2';\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { createBase58check } from '@scure/base';\nimport { concatBytes, equalBytes, utf8Decode } from '../core/bytes';\nimport type { SignedTronTx, TronLatestBlock } from '../tron-proto/messages';\nimport { splitSignedTronTx } from '../tron-proto/messages';\nimport { firstBytes, firstVarint, readFields } from '../tron-proto/wire';\nimport type { VerifyResult } from './result';\nimport { failed, verified } from './result';\n\nconst base58check = createBase58check(sha256);\n\nexport interface VerifyTronSignatureArgs {\n /** The `raw_data` bytes the request carried. */\n readonly rawData: Uint8Array;\n /** The base58 owner address the transaction spends from. */\n readonly from: string;\n /** The reference block the request carried (enables the rebuild-path window check). */\n readonly latestBlock?: TronLatestBlock;\n /** The reply: either the split frame from `TronSignatureResult.signedTx`, or the raw hex. */\n readonly signedTx: SignedTronTx | string;\n}\n\n/**\n * The Tron reply is a fully signed transaction broadcast VERBATIM, so it is\n * checked on both counts: every signature must recover to the owner address,\n * and the transaction must move what the user approved.\n *\n * Byte equality with the request's `rawData` is the strong form. When the\n * bytes differ (a firmware that rebuilds `raw_data` from the semantic\n * fields), the fallback compares the fields that decide where the money goes,\n * plus the validity window against the reference block.\n */\nexport function verifyTronSignature(args: VerifyTronSignatureArgs): VerifyResult {\n let signedTx: SignedTronTx;\n try {\n signedTx = typeof args.signedTx === 'string' ? splitSignedTronTx(args.signedTx) : args.signedTx;\n } catch (e) {\n return failed(`the returned Tron transaction is not readable: ${(e as Error).message}`);\n }\n if (signedTx.signatures.length === 0) {\n return failed('the returned Tron transaction carries no signature');\n }\n if (!args.from) {\n return failed('no owner address to check the signature against');\n }\n\n const digest = sha256(signedTx.rawData);\n for (const signature of signedTx.signatures) {\n const recovered = recoverTronAddress(digest, signature);\n if (recovered === null) return failed('signature could not be checked');\n if (recovered !== args.from) {\n return failed('the signature does not belong to this account');\n }\n }\n\n if (equalBytes(signedTx.rawData, args.rawData)) return verified;\n\n // Rebuild path: the firmware built its own raw_data from the semantic\n // fields. Compare the operation, then the validity window.\n const contractResult = compareContracts(args.rawData, signedTx.rawData);\n if (contractResult !== null) return contractResult;\n if (args.latestBlock === undefined) {\n return failed(\n 'the returned raw_data differs from the request and no latestBlock was provided to check the validity window',\n );\n }\n return compareWindow(signedTx.rawData, args.latestBlock);\n}\n\nfunction recoverTronAddress(digest: Uint8Array, signature: Uint8Array): string | null {\n if (signature.length < 65) return null;\n const recovery = signature[64]!;\n const recoveryId = recovery >= 27 ? (recovery - 27) & 1 : recovery & 1;\n try {\n const point = secp256k1.Signature.fromCompact(signature.slice(0, 64))\n .addRecoveryBit(recoveryId)\n .recoverPublicKey(digest);\n const hash = keccak_256(point.toRawBytes(false).slice(1));\n return base58check.encode(concatBytes(new Uint8Array([0x41]), hash.slice(12)));\n } catch {\n return null;\n }\n}\n\n// --- raw_data structural comparison ---------------------------------------\n\ninterface TronContract {\n readonly typeUrl: string;\n readonly type: bigint;\n readonly parameter: Uint8Array;\n}\n\ninterface TronRawData {\n readonly contracts: readonly TronContract[];\n readonly expiration: bigint;\n readonly timestamp: bigint;\n}\n\nfunction parseRawData(bytes: Uint8Array): TronRawData | null {\n try {\n const fields = readFields(bytes);\n const contracts: TronContract[] = [];\n for (const f of fields) {\n if (f.field === 11 && f.wireType === 2) {\n const c = readFields(f.bytes);\n const anyBytes = firstBytes(c, 2);\n const any = anyBytes ? readFields(anyBytes) : [];\n const typeUrlBytes = anyBytes ? firstBytes(any, 1) : null;\n contracts.push({\n typeUrl: typeUrlBytes ? utf8Decode(typeUrlBytes) : '',\n type: firstVarint(c, 1) ?? 0n,\n parameter: (anyBytes && firstBytes(any, 2)) || new Uint8Array(0),\n });\n }\n }\n return {\n contracts,\n expiration: firstVarint(fields, 8) ?? 0n,\n timestamp: firstVarint(fields, 14) ?? 0n,\n };\n } catch {\n return null;\n }\n}\n\n/** null = contracts match (continue to the window check); a result = verdict. */\nfunction compareContracts(askedBytes: Uint8Array, repliedBytes: Uint8Array): VerifyResult | null {\n const asked = parseRawData(askedBytes);\n const replied = parseRawData(repliedBytes);\n if (!asked) return failed('the Tron transaction built by the app could not be read');\n if (!replied) return failed('the Tron transaction built by the device could not be read');\n if (asked.contracts.length !== 1 || replied.contracts.length !== 1) {\n return failed('the Tron transaction does not carry exactly one contract');\n }\n const a = asked.contracts[0]!;\n const b = replied.contracts[0]!;\n const kindA = contractKind(a);\n const kindB = contractKind(b);\n if (kindA !== kindB) {\n return failed('the returned Tron transaction is a different kind of operation');\n }\n\n const pa = readFieldsSafe(a.parameter);\n const pb = readFieldsSafe(b.parameter);\n if (!pa || !pb) return failed('the Tron contract parameters could not be read');\n\n switch (kindA) {\n case 'transfer':\n // TransferContract {1: owner, 2: to, 3: amount}\n if (\n sameBytesField(pa, pb, 1) &&\n sameBytesField(pa, pb, 2) &&\n (firstVarint(pa, 3) ?? 0n) === (firstVarint(pb, 3) ?? 0n)\n ) {\n return null;\n }\n break;\n case 'transferAsset':\n // TransferAssetContract {1: asset, 2: owner, 3: to, 4: amount}\n if (\n sameBytesField(pa, pb, 1) &&\n sameBytesField(pa, pb, 2) &&\n sameBytesField(pa, pb, 3) &&\n (firstVarint(pa, 4) ?? 0n) === (firstVarint(pb, 4) ?? 0n)\n ) {\n return null;\n }\n break;\n case 'triggerSmartContract':\n // TriggerSmartContract {1: owner, 2: contract, 3: call_value, 4: data}.\n // call_value: zero and absent are the same thing — the two sides are\n // serialized by different protobuf writers that disagree on whether a\n // zero scalar is written, and every TRC-20 transfer carries call_value 0.\n if (\n sameBytesField(pa, pb, 1) &&\n sameBytesField(pa, pb, 2) &&\n (firstVarint(pa, 3) ?? 0n) === (firstVarint(pb, 3) ?? 0n) &&\n sameBytesField(pa, pb, 4)\n ) {\n return null;\n }\n break;\n default:\n // An operation this gate cannot compare field by field is not waved\n // through: without byte equality there is nothing left to bind it to\n // what the user approved.\n return failed('the returned Tron transaction carries an operation this check cannot compare');\n }\n return failed('the returned Tron transaction does not match the one approved');\n}\n\ntype ContractKind = 'transfer' | 'transferAsset' | 'triggerSmartContract' | 'other';\n\nfunction contractKind(contract: TronContract): ContractKind {\n if (contract.typeUrl.endsWith('.TransferContract') || contract.type === 1n) return 'transfer';\n if (contract.typeUrl.endsWith('.TransferAssetContract') || contract.type === 2n) {\n return 'transferAsset';\n }\n if (contract.typeUrl.endsWith('.TriggerSmartContract') || contract.type === 31n) {\n return 'triggerSmartContract';\n }\n return 'other';\n}\n\nfunction readFieldsSafe(bytes: Uint8Array): ReturnType<typeof readFields> | null {\n try {\n return readFields(bytes);\n } catch {\n return null;\n }\n}\n\nfunction sameBytesField(\n a: ReturnType<typeof readFields>,\n b: ReturnType<typeof readFields>,\n field: number,\n): boolean {\n const x = firstBytes(a, field) ?? new Uint8Array(0);\n const y = firstBytes(b, field) ?? new Uint8Array(0);\n return equalBytes(x, y);\n}\n\n/**\n * Firmware formulas, not policy: the two device-side transaction builders\n * stamp `timestamp` with the request's reference-block timestamp verbatim and\n * set `expiration` to +10 minutes (one builder) or +10 hours (the other). A\n * range spanning both cannot refuse a reply the live fleet produces.\n */\nconst MIN_EXPIRY_MS = 10n * 60n * 1000n;\nconst MAX_EXPIRY_MS = 10n * 60n * 60n * 1000n;\n\nfunction compareWindow(repliedBytes: Uint8Array, latestBlock: TronLatestBlock): VerifyResult {\n const replied = parseRawData(repliedBytes);\n if (!replied) return failed('the Tron transaction built by the device could not be read');\n const block = BigInt(latestBlock.timestamp);\n if (replied.timestamp !== block) {\n return failed(\n 'the returned Tron transaction is stamped against a different reference block than the one we sent',\n );\n }\n const validFor = replied.expiration - block;\n if (validFor < MIN_EXPIRY_MS || validFor > MAX_EXPIRY_MS) {\n return failed(\n `the returned Tron transaction is valid for ${validFor} ms after the reference block, outside the firmware's ${MIN_EXPIRY_MS}-${MAX_EXPIRY_MS} ms window`,\n );\n }\n return verified;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"verify.cjs","names":["err","EraSdkError","equalBytes","EraSdkError","utf8Encode","keccak_256","concatBytes","equalBytes","EvmDataType","foldRecoveryId","secp256k1","hexToBytes","bytesToHex","equalBytes","ed25519","EraSdkError","concatBytes","sha256","TonDataType","sha256","concatBytes","utf8Encode","ed25519","createBase58check","sha256","splitSignedTronTx","equalBytes","secp256k1","keccak_256","concatBytes","readFields","firstBytes","utf8Decode","firstVarint"],"sources":["../src/verify/psbt-reader.ts","../src/verify/result.ts","../src/verify/btc.ts","../src/verify/evm.ts","../src/verify/solana.ts","../src/verify/ton-boc.ts","../src/verify/ton.ts","../src/verify/tron.ts"],"sourcesContent":["import { EraSdkError } from '../core/errors';\n\n/**\n * Minimal PSBT v0 (BIP-174) reader — just enough structure for the\n * verification guard: the global unsigned transaction (verbatim slice, never\n * re-serialized), the PSBT version, and per-input key/value maps.\n *\n * Hardened: compact-size lengths bounds-checked before slicing, duplicate\n * keys within one map refused (a hostile PSBT carrying two final scriptSigs\n * for one input must not survive parsing).\n */\n\nexport interface PsbtKeyValue {\n readonly keyType: number;\n readonly keyData: Uint8Array;\n readonly value: Uint8Array;\n}\n\nexport interface ParsedPsbt {\n /** The global UNSIGNED_TX value, verbatim. */\n readonly unsignedTx: Uint8Array;\n /** Global PSBT_GLOBAL_VERSION (0xFB) if present; v0 files normally omit it. */\n readonly version: number;\n readonly inputs: readonly (readonly PsbtKeyValue[])[];\n readonly outputs: readonly (readonly PsbtKeyValue[])[];\n}\n\nconst MAGIC = [0x70, 0x73, 0x62, 0x74, 0xff]; // \"psbt\\xff\"\n\nexport const PsbtInputType = {\n partialSig: 0x02,\n finalScriptSig: 0x07,\n finalScriptWitness: 0x08,\n taprootKeySpendSignature: 0x13,\n taprootScriptSpendSignature: 0x14,\n} as const;\n\nfunction err(message: string): EraSdkError {\n return new EraSdkError('malformed-reply', `psbt: ${message}`);\n}\n\nclass Reader {\n offset = 0;\n constructor(readonly bytes: Uint8Array) {}\n\n get remaining(): number {\n return this.bytes.length - this.offset;\n }\n\n u8(): number {\n const b = this.bytes[this.offset];\n if (b === undefined) throw err('truncated');\n this.offset += 1;\n return b;\n }\n\n /** Bitcoin compact-size integer, MINIMAL encoding required (as consensus does). */\n compactSize(): number {\n const first = this.u8();\n if (first < 0xfd) return first;\n let width: number;\n let minimum: bigint;\n if (first === 0xfd) {\n width = 2;\n minimum = 0xfdn;\n } else if (first === 0xfe) {\n width = 4;\n minimum = 0x10000n;\n } else {\n width = 8;\n minimum = 0x100000000n;\n }\n let value = 0n;\n for (let i = 0; i < width; i++) value |= BigInt(this.u8()) << BigInt(8 * i);\n if (value < minimum) throw err('non-minimal compact-size encoding');\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) throw err('length exceeds safe range');\n return Number(value);\n }\n\n take(length: number): Uint8Array {\n if (length > this.remaining) throw err('length exceeds input');\n const out = this.bytes.slice(this.offset, this.offset + length);\n this.offset += length;\n return out;\n }\n}\n\n/** Read one key/value map (ends at the 0x00 separator). */\nfunction readMap(reader: Reader): PsbtKeyValue[] {\n const entries: PsbtKeyValue[] = [];\n const seen = new Set<string>();\n for (;;) {\n const keyLength = reader.compactSize();\n if (keyLength === 0) return entries;\n const key = reader.take(keyLength);\n const value = reader.take(reader.compactSize());\n const keyId = Array.from(key)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n if (seen.has(keyId)) throw err('duplicate key within one map');\n seen.add(keyId);\n entries.push({ keyType: key[0]!, keyData: key.slice(1), value });\n }\n}\n\n/** Count of inputs/outputs in a (non-witness) unsigned transaction. */\nfunction countTxInputsOutputs(tx: Uint8Array): { inputs: number; outputs: number } {\n const reader = new Reader(tx);\n reader.take(4); // version\n const inputs = reader.compactSize();\n if (inputs === 0) {\n // A zero here would be a segwit marker — the PSBT unsigned tx must not\n // carry witness data, so this is not a transaction we can count.\n throw err('unsigned transaction has zero inputs (or carries witness data)');\n }\n for (let i = 0; i < inputs; i++) {\n reader.take(32 + 4); // prevout\n reader.take(reader.compactSize()); // scriptSig (empty in a PSBT)\n reader.take(4); // sequence\n }\n const outputs = reader.compactSize();\n for (let i = 0; i < outputs; i++) {\n reader.take(8); // amount\n reader.take(reader.compactSize()); // scriptPubKey\n }\n reader.take(4); // locktime\n if (reader.remaining !== 0) throw err('trailing bytes after the unsigned transaction');\n return { inputs, outputs };\n}\n\nexport function parsePsbt(bytes: Uint8Array): ParsedPsbt {\n const reader = new Reader(bytes);\n for (const expected of MAGIC) {\n if (reader.u8() !== expected) throw err('bad magic');\n }\n const globalMap = readMap(reader);\n\n let unsignedTx: Uint8Array | null = null;\n let version = 0;\n for (const entry of globalMap) {\n if (entry.keyType === 0x00 && entry.keyData.length === 0) unsignedTx = entry.value;\n if (entry.keyType === 0xfb && entry.keyData.length === 0) {\n if (entry.value.length !== 4) throw err('bad version field');\n version =\n (entry.value[0]! |\n (entry.value[1]! << 8) |\n (entry.value[2]! << 16) |\n (entry.value[3]! << 24)) >>>\n 0;\n }\n }\n if (unsignedTx === null) {\n // The device's signer relies on the global UNSIGNED_TX that only PSBT v0\n // carries; its absence means v2 (or not a PSBT at all).\n throw err('no global unsigned transaction — not a PSBT v0');\n }\n if (version !== 0) throw err(`unsupported PSBT version ${version}`);\n\n const counts = countTxInputsOutputs(unsignedTx);\n const inputs: PsbtKeyValue[][] = [];\n for (let i = 0; i < counts.inputs; i++) inputs.push(readMap(reader));\n const outputs: PsbtKeyValue[][] = [];\n for (let i = 0; i < counts.outputs; i++) outputs.push(readMap(reader));\n if (reader.remaining !== 0) throw err('trailing bytes after the output maps');\n\n return { unsignedTx, version, inputs, outputs };\n}\n\nexport function inputEntries(\n psbt: ParsedPsbt,\n index: number,\n keyType: number,\n): readonly PsbtKeyValue[] {\n return (psbt.inputs[index] ?? []).filter((e) => e.keyType === keyType);\n}\n\nexport function inputHas(psbt: ParsedPsbt, index: number, keyType: number): boolean {\n return inputEntries(psbt, index, keyType).length > 0;\n}\n","/** Outcome of a verification helper. Helpers return, never throw, on mismatches. */\nexport type VerifyResult =\n /** Verified cryptographically / byte-for-byte. */\n | { readonly ok: true; readonly checked: true }\n /**\n * Nothing client-side is verifiable for this input (EIP-712 typed data:\n * the digest is the hash of the structure, which only the device computes).\n * The UR-type pin and the request-id echo are the whole binding.\n */\n | { readonly ok: true; readonly checked: false; readonly reason: string }\n | { readonly ok: false; readonly reason: string };\n\nexport const verified: VerifyResult = { ok: true, checked: true };\nexport const failed = (reason: string): VerifyResult => ({ ok: false, reason });\nexport const unverifiable = (reason: string): VerifyResult => ({\n ok: true,\n checked: false,\n reason,\n});\n","import { equalBytes } from '../core/bytes';\nimport { EraSdkError } from '../core/errors';\nimport type { ParsedPsbt } from './psbt-reader';\nimport { inputEntries, inputHas, PsbtInputType, parsePsbt } from './psbt-reader';\nimport type { VerifyResult } from './result';\nimport { failed, verified } from './result';\n\nexport interface VerifySignedPsbtArgs {\n /** The PSBT you sent to the device. */\n readonly sentPsbt: Uint8Array;\n /** The PSBT the device returned. */\n readonly signedPsbt: Uint8Array;\n /**\n * true (default) on flows where every input is yours (a plain send): a\n * reply that signed only part of the transaction is refused here with a\n * reason instead of failing later inside a finalizer. Set false for dApp\n * `signPsbt` hand-backs, where a PSBT legitimately carries inputs you\n * cannot sign.\n */\n readonly requireEveryInputSigned?: boolean;\n}\n\n/**\n * The `crypto-psbt` reply carries NO request id — this comparison IS the\n * anti-replay binding for Bitcoin. It is not optional.\n *\n * The unsigned transaction is compared byte for byte, which pins the input\n * set and order, the outputs, their amounts, the version and the locktime in\n * one shot — and therefore the txid. The device only ADDS per-input\n * signature fields, so a legitimate reply always matches.\n */\nexport function verifySignedPsbt(args: VerifySignedPsbtArgs): VerifyResult {\n let sent: ParsedPsbt;\n let signed: ParsedPsbt;\n try {\n sent = parsePsbt(args.sentPsbt);\n } catch (e) {\n return failed(`the PSBT we sent is not readable: ${message(e)}`);\n }\n try {\n signed = parsePsbt(args.signedPsbt);\n } catch (e) {\n return failed(`the PSBT the device returned is not readable: ${message(e)}`);\n }\n\n if (!equalBytes(sent.unsignedTx, signed.unsignedTx)) {\n return failed('the returned PSBT is a different transaction from the one approved');\n }\n\n // A finalized field carries the COMPLETE scriptSig/witness that will be\n // broadcast, and the unsigned-tx comparison above does not cover it (it\n // lives per input, the unsigned tx in the global map). An input that comes\n // back finalized must have been SENT that way, with byte-identical\n // values — the device echoes these fields, it never authors them.\n const finalizedTypes = [PsbtInputType.finalScriptSig, PsbtInputType.finalScriptWitness];\n for (let i = 0; i < signed.inputs.length; i++) {\n for (const type of finalizedTypes) {\n if (!inputHas(signed, i, type)) continue;\n if (!inputHas(sent, i, type)) {\n return failed(\n `input ${i} came back finalized (type 0x${type.toString(16)}) and was not sent that way — the script it would broadcast is not ours`,\n );\n }\n const a = inputEntries(sent, i, type);\n const b = inputEntries(signed, i, type);\n if (a.length !== b.length || !a.every((entry, k) => equalBytes(entry.value, b[k]!.value))) {\n return failed(\n `input ${i} came back with a different finalized script than the one we sent`,\n );\n }\n }\n }\n\n const isSigned = (i: number): boolean =>\n inputHas(signed, i, PsbtInputType.partialSig) ||\n inputHas(signed, i, PsbtInputType.taprootKeySpendSignature) ||\n inputHas(signed, i, PsbtInputType.taprootScriptSpendSignature);\n\n const indexes = signed.inputs.map((_, i) => i);\n if (args.requireEveryInputSigned ?? true) {\n if (!indexes.every(isSigned)) {\n return failed('the device signed only part of the transaction');\n }\n } else if (!indexes.some(isSigned)) {\n return failed('the returned PSBT carries no signature');\n }\n return verified;\n}\n\nexport interface VerifyBtcMessageHeaderArgs {\n /** The address the request asked the device to sign with. */\n readonly address: string;\n /** The raw 65-byte BIP-137 signature. */\n readonly signature: Uint8Array;\n}\n\n/**\n * BIP-137: the recovery header names the address type a verifier derives\n * before comparing. A header of the wrong range produces a signature that\n * LOOKS fine (65 bytes, valid base64) but fails every verifier downstream —\n * this check is the only place that difference is visible.\n */\nexport function verifyBtcMessageHeader(args: VerifyBtcMessageHeaderArgs): VerifyResult {\n if (args.signature.length === 0) {\n return failed('empty signature');\n }\n const header = args.signature[0]!;\n const range = headerRangeFor(args.address);\n if (range === null) {\n return {\n ok: true,\n checked: false,\n reason: 'address kind has no BIP-137 header range to check against',\n };\n }\n if (header >= range.low && header <= range.high) return verified;\n return failed(\n `recovery header ${header} does not match a ${range.label} address ` +\n `(BIP-137 expects ${range.low}..${range.high}); this signature would not verify against the address it was asked to sign for`,\n );\n}\n\ninterface HeaderRange {\n readonly low: number;\n readonly high: number;\n readonly label: string;\n}\n\nfunction headerRangeFor(address: string): HeaderRange | null {\n const a = address.toLowerCase();\n if (a.startsWith('bc1q') || a.startsWith('tb1q') || a.startsWith('bcrt1q')) {\n return { low: 39, high: 42, label: 'native segwit (P2WPKH)' };\n }\n if (a.startsWith('bc1p') || a.startsWith('tb1p') || a.startsWith('bcrt1p')) {\n return null; // Taproot: BIP-137 does not cover it (BIP-322 is the scheme).\n }\n // Base58 kinds matched on SHAPE, not first character alone — a guard that\n // invents a range for a string it does not understand is worse than one\n // that declines to judge.\n if (looksBase58(address)) {\n if (address.startsWith('3') || address.startsWith('2')) {\n return { low: 35, high: 38, label: 'P2SH (nested segwit)' };\n }\n if (address.startsWith('1') || address.startsWith('m') || address.startsWith('n')) {\n // Both the uncompressed and compressed P2PKH ranges — which one is\n // right depends on the key the device used, which we do not know.\n return { low: 27, high: 34, label: 'legacy P2PKH' };\n }\n }\n return null;\n}\n\nfunction looksBase58(address: string): boolean {\n return address.length >= 26 && address.length <= 35 && /^[1-9A-HJ-NP-Za-km-z]+$/.test(address);\n}\n\nfunction message(e: unknown): string {\n return e instanceof EraSdkError || e instanceof Error ? e.message : String(e);\n}\n","import { secp256k1 } from '@noble/curves/secp256k1';\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { EvmDataType, foldRecoveryId } from '../chains/evm';\nimport { bytesToHex, concatBytes, equalBytes, hexToBytes, utf8Encode } from '../core/bytes';\nimport type { VerifyResult } from './result';\nimport { failed, unverifiable, verified } from './result';\n\nexport interface VerifyEvmSignatureArgs {\n /** The exact bytes the request carried in `signData`. */\n readonly signData: Uint8Array;\n readonly dataType: EvmDataType;\n /** Raw `r || s || v` from the reply (65+ bytes; multi-byte legacy `v` handled). */\n readonly signature: Uint8Array;\n /** The signer address the request was built for. */\n readonly address: Uint8Array | `0x${string}`;\n /**\n * Optional: the signing payload re-derived from the transaction you are\n * ABOUT TO BROADCAST. Recovering against `signData` alone proves the device\n * signed something you asked for — this closes the second half: that it is\n * the transaction still in your hands (payloads can legitimately change\n * between build and send, e.g. a blockhash refresh in your own state).\n */\n readonly reEncodedSignData?: Uint8Array;\n}\n\n/** EIP-191: 0x19 || \"Ethereum Signed Message:\\n\" || len(message). */\nfunction personalSignDigest(message: Uint8Array): Uint8Array {\n const prefix = utf8Encode(`Ethereum Signed Message:\\n${message.length}`);\n return keccak_256(concatBytes(new Uint8Array([0x19]), prefix, message));\n}\n\n/**\n * \"Did the device sign exactly what I sent, with the key I expected?\"\n * keccak digest + public-key recovery; the recovered address must equal the\n * request's. Run it before broadcasting.\n */\nexport function verifyEvmSignature(args: VerifyEvmSignatureArgs): VerifyResult {\n if (args.signature.length < 65) {\n return failed('signature is shorter than 65 bytes');\n }\n if (args.reEncodedSignData !== undefined && !equalBytes(args.reEncodedSignData, args.signData)) {\n return failed('the transaction to broadcast is not the one the device signed');\n }\n\n let digest: Uint8Array;\n switch (args.dataType) {\n case EvmDataType.transaction:\n case EvmDataType.typedTransaction:\n digest = keccak_256(args.signData);\n break;\n case EvmDataType.personalMessage:\n digest = personalSignDigest(args.signData);\n break;\n case EvmDataType.typedData:\n return unverifiable(\n 'EIP-712: the digest is the hash of the structure, computed only on the device',\n );\n default:\n return failed(`unknown dataType ${args.dataType satisfies never}`);\n }\n\n let vBig = 0n;\n for (const b of args.signature.slice(64)) vBig = (vBig << 8n) | BigInt(b);\n const recoveryId = foldRecoveryId(vBig);\n if (recoveryId !== 0 && recoveryId !== 1) {\n return failed('implausible recovery value');\n }\n\n let recovered: Uint8Array;\n try {\n const point = secp256k1.Signature.fromCompact(args.signature.slice(0, 64))\n .addRecoveryBit(recoveryId)\n .recoverPublicKey(digest);\n recovered = keccak_256(point.toRawBytes(false).slice(1)).slice(12);\n } catch (e) {\n return failed(`signature could not be checked: ${(e as Error).message}`);\n }\n\n const expected = args.address instanceof Uint8Array ? args.address : hexToBytes(args.address);\n if (expected.length !== 20) {\n return failed(`expected address must be 20 bytes, got ${expected.length}`);\n }\n if (!equalBytes(recovered, expected)) {\n return failed(\n `the signature does not belong to this account (recovered 0x${bytesToHex(recovered)})`,\n );\n }\n return verified;\n}\n","import { ed25519 } from '@noble/curves/ed25519';\nimport { equalBytes } from '../core/bytes';\nimport type { VerifyResult } from './result';\nimport { failed, verified } from './result';\n\nexport interface VerifySolanaSignatureArgs {\n /** The exact bytes the request carried in `signData` (the compiled message). */\n readonly signData: Uint8Array;\n /** 64-byte Ed25519 signature from the reply. */\n readonly signature: Uint8Array;\n /** The 32-byte signer public key the request was built for. */\n readonly publicKey: Uint8Array;\n /**\n * Optional: the message bytes you are ABOUT TO BROADCAST. Matters most on\n * Solana — a blockhash refresh between build and send makes \"what was\n * signed\" and \"what will be sent\" two different objects that must agree.\n */\n readonly broadcastMessageBytes?: Uint8Array;\n}\n\nexport function verifySolanaSignature(args: VerifySolanaSignatureArgs): VerifyResult {\n if (\n args.broadcastMessageBytes !== undefined &&\n !equalBytes(args.broadcastMessageBytes, args.signData)\n ) {\n return failed('the message to broadcast is not the one the device signed');\n }\n let ok: boolean;\n try {\n ok = ed25519.verify(args.signature, args.signData, args.publicKey);\n } catch (e) {\n return failed(`Solana signature could not be checked: ${(e as Error).message}`);\n }\n return ok ? verified : failed('the signature does not belong to this account');\n}\n","import { sha256 } from '@noble/hashes/sha2';\nimport { concatBytes } from '../core/bytes';\nimport { EraSdkError } from '../core/errors';\n\n/**\n * Minimal TON Bag-of-Cells reader + cell representation hash — exactly the\n * subset the device's signer implements: generic BoC, ordinary level-0 cells,\n * first root. The transaction digest the device signs IS the root cell's\n * representation hash, so this must agree with the firmware bit for bit.\n *\n * Hardened for scanned/untrusted input: size caps, bounds checks, and\n * forward-only references (the standard BoC topological order; a backward\n * reference would make the single-pass hash read an uncomputed child).\n */\n\nconst BOC_MAGIC = 0xb5ee9c72;\nconst MAX_CELLS = 256;\nconst MAX_CELL_DATA_BYTES = 128;\nconst MAX_REFS = 4;\n\ninterface Cell {\n dataBits: number;\n data: Uint8Array;\n refs: number[];\n depth: number;\n hash: Uint8Array;\n}\n\nfunction err(message: string): EraSdkError {\n return new EraSdkError('malformed-reply', `ton boc: ${message}`);\n}\n\n/** Representation hash of the ROOT cell of a BoC — the bytes TON signs. */\nexport function bocRootHash(boc: Uint8Array): Uint8Array {\n if (boc.length < 10) throw err('too short');\n const magic = ((boc[0]! << 24) | (boc[1]! << 16) | (boc[2]! << 8) | boc[3]!) >>> 0;\n if (magic !== BOC_MAGIC) throw err('not a generic BoC');\n\n const flags = boc[4]!;\n const hasIdx = (flags >> 7) & 1;\n const refSize = flags & 0x07;\n const offSize = boc[5]!;\n if (refSize === 0 || refSize > 4) throw err('bad ref size');\n if (offSize === 0 || offSize > 8) throw err('bad offset size');\n\n let pos = 6;\n const readInt = (byteLen: number): number => {\n let value = 0;\n for (let i = 0; i < byteLen; i++) {\n if (pos >= boc.length) throw err('truncated header');\n value = value * 256 + boc[pos++]!;\n }\n if (!Number.isSafeInteger(value)) throw err('header value out of range');\n return value;\n };\n\n const cellCount = readInt(refSize);\n const rootCount = readInt(refSize);\n readInt(refSize); // absent count\n readInt(offSize); // total cell data size\n if (rootCount === 0) throw err('no roots');\n if (cellCount === 0 || cellCount > MAX_CELLS) throw err('cell count out of range');\n\n const rootIndex = readInt(refSize);\n for (let i = 1; i < rootCount; i++) readInt(refSize); // remaining root indices\n if (rootIndex >= cellCount) throw err('root index out of range');\n if (hasIdx) pos += cellCount * offSize; // skip the offsets index\n\n const cells: Cell[] = [];\n for (let i = 0; i < cellCount; i++) {\n if (pos + 2 > boc.length) throw err('truncated cell');\n const d1 = boc[pos++]!;\n const d2 = boc[pos++]!;\n const refCount = d1 & 0x07;\n if (refCount > MAX_REFS) throw err('too many references');\n\n const dataByteLen = (d2 + 1) >> 1;\n const incomplete = (d2 & 1) === 1;\n if (dataByteLen > MAX_CELL_DATA_BYTES) throw err('cell data too large');\n if (pos + dataByteLen > boc.length) throw err('truncated cell data');\n const data = boc.slice(pos, pos + dataByteLen);\n pos += dataByteLen;\n\n // Bit length from the completion tag (last set bit marks the end).\n let dataBits: number;\n if (incomplete && dataByteLen > 0) {\n const last = data[dataByteLen - 1]!;\n if (last === 0) {\n dataBits = (dataByteLen - 1) * 8;\n } else {\n let trailingZeros = 0;\n for (let b = 0; b < 8; b++) {\n if (last & (1 << b)) break;\n trailingZeros++;\n }\n dataBits = dataByteLen * 8 - 1 - trailingZeros;\n }\n } else {\n dataBits = dataByteLen * 8;\n }\n\n const refs: number[] = [];\n for (let r = 0; r < refCount; r++) {\n const ref = readInt(refSize);\n if (ref >= cellCount) throw err('reference out of range');\n if (ref <= i) throw err('non-topological cell reference');\n refs.push(ref);\n }\n cells.push({ dataBits, data, refs, depth: 0, hash: new Uint8Array(0) });\n }\n\n // Bottom-up (children first — guaranteed by the forward-only reference check).\n for (let i = cellCount - 1; i >= 0; i--) {\n const cell = cells[i]!;\n let maxChildDepth = -1;\n for (const r of cell.refs) {\n maxChildDepth = Math.max(maxChildDepth, cells[r]!.depth);\n }\n cell.depth = cell.refs.length === 0 ? 0 : maxChildDepth + 1;\n\n const dataBytes = (cell.dataBits + 7) >> 3;\n const incomplete = cell.dataBits % 8 !== 0;\n const repr: number[] = [cell.refs.length, dataBytes * 2 - (incomplete ? 1 : 0)];\n for (let b = 0; b < dataBytes; b++) repr.push(cell.data[b] ?? 0);\n if (incomplete && dataBytes > 0) {\n const shift = 7 - (cell.dataBits % 8);\n const last = repr.length - 1;\n repr[last] = (repr[last]! | (1 << shift)) & (0xff << shift) & 0xff;\n }\n for (const r of cell.refs) {\n repr.push((cells[r]!.depth >> 8) & 0xff, cells[r]!.depth & 0xff);\n }\n let bytes: Uint8Array = new Uint8Array(repr);\n for (const r of cell.refs) bytes = concatBytes(bytes, cells[r]!.hash);\n cell.hash = sha256(bytes);\n }\n\n return cells[rootIndex]!.hash;\n}\n","import { ed25519 } from '@noble/curves/ed25519';\nimport { sha256 } from '@noble/hashes/sha2';\nimport { TonDataType } from '../chains/ton';\nimport { concatBytes, utf8Encode } from '../core/bytes';\nimport type { VerifyResult } from './result';\nimport { failed, verified } from './result';\nimport { bocRootHash } from './ton-boc';\n\nexport interface VerifyTonSignatureArgs {\n /** The exact bytes the request carried in `signData`. */\n readonly signData: Uint8Array;\n readonly dataType: TonDataType;\n /** 64-byte Ed25519 signature from the reply. */\n readonly signature: Uint8Array;\n /** The 32-byte signer public key from linking (`accounts.ton()`). */\n readonly publicKey: Uint8Array;\n}\n\n/**\n * Recompute the exact digest the device signs — the BoC ROOT CELL's\n * representation hash for a transaction, or the TON Connect proof digest\n * `sha256(0xFFFF || \"ton-connect\" || sha256(payload))` — and verify the\n * Ed25519 signature against the linked key.\n */\nexport function verifyTonSignature(args: VerifyTonSignatureArgs): VerifyResult {\n if (args.signature.length !== 64) return failed('signature must be 64 bytes');\n if (args.publicKey.length !== 32) return failed('public key must be 32 bytes');\n\n let digest: Uint8Array;\n if (args.dataType === TonDataType.tonProof) {\n digest = sha256(\n concatBytes(new Uint8Array([0xff, 0xff]), utf8Encode('ton-connect'), sha256(args.signData)),\n );\n } else if (args.dataType === TonDataType.transaction) {\n try {\n digest = bocRootHash(args.signData);\n } catch (e) {\n return failed(`signData is not a readable BoC: ${(e as Error).message}`);\n }\n } else {\n return failed(`unknown dataType ${args.dataType satisfies never}`);\n }\n\n let ok: boolean;\n try {\n ok = ed25519.verify(args.signature, digest, args.publicKey);\n } catch (e) {\n return failed(`TON signature could not be checked: ${(e as Error).message}`);\n }\n return ok ? verified : failed('the signature does not belong to this account');\n}\n","import { secp256k1 } from '@noble/curves/secp256k1';\nimport { sha256 } from '@noble/hashes/sha2';\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { createBase58check } from '@scure/base';\nimport { concatBytes, equalBytes, utf8Decode } from '../core/bytes';\nimport type { SignedTronTx, TronLatestBlock } from '../tron-proto/messages';\nimport { splitSignedTronTx } from '../tron-proto/messages';\nimport { firstBytes, firstVarint, readFields } from '../tron-proto/wire';\nimport type { VerifyResult } from './result';\nimport { failed, verified } from './result';\n\nconst base58check = createBase58check(sha256);\n\nexport interface VerifyTronSignatureArgs {\n /** The `raw_data` bytes the request carried. */\n readonly rawData: Uint8Array;\n /** The base58 owner address the transaction spends from. */\n readonly from: string;\n /** The reference block the request carried (enables the rebuild-path window check). */\n readonly latestBlock?: TronLatestBlock;\n /** The reply: either the split frame from `TronSignatureResult.signedTx`, or the raw hex. */\n readonly signedTx: SignedTronTx | string;\n}\n\n/**\n * The Tron reply is a fully signed transaction broadcast VERBATIM, so it is\n * checked on both counts: every signature must recover to the owner address,\n * and the transaction must move what the user approved.\n *\n * Byte equality with the request's `rawData` is the strong form. When the\n * bytes differ (a firmware that rebuilds `raw_data` from the semantic\n * fields), the fallback compares the fields that decide where the money goes,\n * plus the validity window against the reference block.\n */\nexport function verifyTronSignature(args: VerifyTronSignatureArgs): VerifyResult {\n let signedTx: SignedTronTx;\n try {\n signedTx = typeof args.signedTx === 'string' ? splitSignedTronTx(args.signedTx) : args.signedTx;\n } catch (e) {\n return failed(`the returned Tron transaction is not readable: ${(e as Error).message}`);\n }\n if (signedTx.signatures.length === 0) {\n return failed('the returned Tron transaction carries no signature');\n }\n if (!args.from) {\n return failed('no owner address to check the signature against');\n }\n\n const digest = sha256(signedTx.rawData);\n for (const signature of signedTx.signatures) {\n const recovered = recoverTronAddress(digest, signature);\n if (recovered === null) return failed('signature could not be checked');\n if (recovered !== args.from) {\n return failed('the signature does not belong to this account');\n }\n }\n\n if (equalBytes(signedTx.rawData, args.rawData)) return verified;\n\n // Rebuild path: the firmware built its own raw_data from the semantic\n // fields. Compare the operation, then the validity window.\n const contractResult = compareContracts(args.rawData, signedTx.rawData);\n if (contractResult !== null) return contractResult;\n if (args.latestBlock === undefined) {\n return failed(\n 'the returned raw_data differs from the request and no latestBlock was provided to check the validity window',\n );\n }\n return compareWindow(signedTx.rawData, args.latestBlock);\n}\n\nfunction recoverTronAddress(digest: Uint8Array, signature: Uint8Array): string | null {\n if (signature.length < 65) return null;\n const recovery = signature[64]!;\n const recoveryId = recovery >= 27 ? (recovery - 27) & 1 : recovery & 1;\n try {\n const point = secp256k1.Signature.fromCompact(signature.slice(0, 64))\n .addRecoveryBit(recoveryId)\n .recoverPublicKey(digest);\n const hash = keccak_256(point.toRawBytes(false).slice(1));\n return base58check.encode(concatBytes(new Uint8Array([0x41]), hash.slice(12)));\n } catch {\n return null;\n }\n}\n\n// --- raw_data structural comparison ---------------------------------------\n\ninterface TronContract {\n readonly typeUrl: string;\n readonly type: bigint;\n readonly parameter: Uint8Array;\n}\n\ninterface TronRawData {\n readonly contracts: readonly TronContract[];\n readonly expiration: bigint;\n readonly timestamp: bigint;\n}\n\nfunction parseRawData(bytes: Uint8Array): TronRawData | null {\n try {\n const fields = readFields(bytes);\n const contracts: TronContract[] = [];\n for (const f of fields) {\n if (f.field === 11 && f.wireType === 2) {\n const c = readFields(f.bytes);\n const anyBytes = firstBytes(c, 2);\n const any = anyBytes ? readFields(anyBytes) : [];\n const typeUrlBytes = anyBytes ? firstBytes(any, 1) : null;\n contracts.push({\n typeUrl: typeUrlBytes ? utf8Decode(typeUrlBytes) : '',\n type: firstVarint(c, 1) ?? 0n,\n parameter: (anyBytes && firstBytes(any, 2)) || new Uint8Array(0),\n });\n }\n }\n return {\n contracts,\n expiration: firstVarint(fields, 8) ?? 0n,\n timestamp: firstVarint(fields, 14) ?? 0n,\n };\n } catch {\n return null;\n }\n}\n\n/** null = contracts match (continue to the window check); a result = verdict. */\nfunction compareContracts(askedBytes: Uint8Array, repliedBytes: Uint8Array): VerifyResult | null {\n const asked = parseRawData(askedBytes);\n const replied = parseRawData(repliedBytes);\n if (!asked) return failed('the Tron transaction built by the app could not be read');\n if (!replied) return failed('the Tron transaction built by the device could not be read');\n if (asked.contracts.length !== 1 || replied.contracts.length !== 1) {\n return failed('the Tron transaction does not carry exactly one contract');\n }\n const a = asked.contracts[0]!;\n const b = replied.contracts[0]!;\n const kindA = contractKind(a);\n const kindB = contractKind(b);\n if (kindA !== kindB) {\n return failed('the returned Tron transaction is a different kind of operation');\n }\n\n const pa = readFieldsSafe(a.parameter);\n const pb = readFieldsSafe(b.parameter);\n if (!pa || !pb) return failed('the Tron contract parameters could not be read');\n\n switch (kindA) {\n case 'transfer':\n // TransferContract {1: owner, 2: to, 3: amount}\n if (\n sameBytesField(pa, pb, 1) &&\n sameBytesField(pa, pb, 2) &&\n (firstVarint(pa, 3) ?? 0n) === (firstVarint(pb, 3) ?? 0n)\n ) {\n return null;\n }\n break;\n case 'transferAsset':\n // TransferAssetContract {1: asset, 2: owner, 3: to, 4: amount}\n if (\n sameBytesField(pa, pb, 1) &&\n sameBytesField(pa, pb, 2) &&\n sameBytesField(pa, pb, 3) &&\n (firstVarint(pa, 4) ?? 0n) === (firstVarint(pb, 4) ?? 0n)\n ) {\n return null;\n }\n break;\n case 'triggerSmartContract':\n // TriggerSmartContract {1: owner, 2: contract, 3: call_value, 4: data}.\n // call_value: zero and absent are the same thing — the two sides are\n // serialized by different protobuf writers that disagree on whether a\n // zero scalar is written, and every TRC-20 transfer carries call_value 0.\n if (\n sameBytesField(pa, pb, 1) &&\n sameBytesField(pa, pb, 2) &&\n (firstVarint(pa, 3) ?? 0n) === (firstVarint(pb, 3) ?? 0n) &&\n sameBytesField(pa, pb, 4)\n ) {\n return null;\n }\n break;\n default:\n // An operation this gate cannot compare field by field is not waved\n // through: without byte equality there is nothing left to bind it to\n // what the user approved.\n return failed('the returned Tron transaction carries an operation this check cannot compare');\n }\n return failed('the returned Tron transaction does not match the one approved');\n}\n\ntype ContractKind = 'transfer' | 'transferAsset' | 'triggerSmartContract' | 'other';\n\nfunction contractKind(contract: TronContract): ContractKind {\n if (contract.typeUrl.endsWith('.TransferContract') || contract.type === 1n) return 'transfer';\n if (contract.typeUrl.endsWith('.TransferAssetContract') || contract.type === 2n) {\n return 'transferAsset';\n }\n if (contract.typeUrl.endsWith('.TriggerSmartContract') || contract.type === 31n) {\n return 'triggerSmartContract';\n }\n return 'other';\n}\n\nfunction readFieldsSafe(bytes: Uint8Array): ReturnType<typeof readFields> | null {\n try {\n return readFields(bytes);\n } catch {\n return null;\n }\n}\n\nfunction sameBytesField(\n a: ReturnType<typeof readFields>,\n b: ReturnType<typeof readFields>,\n field: number,\n): boolean {\n const x = firstBytes(a, field) ?? new Uint8Array(0);\n const y = firstBytes(b, field) ?? new Uint8Array(0);\n return equalBytes(x, y);\n}\n\n/**\n * Firmware formulas, not policy: the two device-side transaction builders\n * stamp `timestamp` with the request's reference-block timestamp verbatim and\n * set `expiration` to +10 minutes (one builder) or +10 hours (the other). A\n * range spanning both cannot refuse a reply the live fleet produces.\n */\nconst MIN_EXPIRY_MS = 10n * 60n * 1000n;\nconst MAX_EXPIRY_MS = 10n * 60n * 60n * 1000n;\n\nfunction compareWindow(repliedBytes: Uint8Array, latestBlock: TronLatestBlock): VerifyResult {\n const replied = parseRawData(repliedBytes);\n if (!replied) return failed('the Tron transaction built by the device could not be read');\n const block = BigInt(latestBlock.timestamp);\n if (replied.timestamp !== block) {\n return failed(\n 'the returned Tron transaction is stamped against a different reference block than the one we sent',\n );\n }\n const validFor = replied.expiration - block;\n if (validFor < MIN_EXPIRY_MS || validFor > MAX_EXPIRY_MS) {\n return failed(\n `the returned Tron transaction is valid for ${validFor} ms after the reference block, outside the firmware's ${MIN_EXPIRY_MS}-${MAX_EXPIRY_MS} ms window`,\n );\n }\n return verified;\n}\n"],"mappings":";;;;;;;;;;;AA2BA,MAAM,QAAQ;CAAC;CAAM;CAAM;CAAM;CAAM;AAAI;AAE3C,MAAa,gBAAgB;CAC3B,YAAY;CACZ,gBAAgB;CAChB,oBAAoB;CACpB,0BAA0B;CAC1B,6BAA6B;AAC/B;AAEA,SAASA,MAAI,SAA8B;CACzC,OAAO,IAAIC,eAAAA,YAAY,mBAAmB,SAAS,SAAS;AAC9D;AAEA,IAAM,SAAN,MAAa;CAEX,YAAY,OAA4B;EAAnB,KAAA,QAAA;EADrB,KAAA,SAAS;CACgC;CAEzC,IAAI,YAAoB;EACtB,OAAO,KAAK,MAAM,SAAS,KAAK;CAClC;CAEA,KAAa;EACX,MAAM,IAAI,KAAK,MAAM,KAAK;EAC1B,IAAI,MAAM,KAAA,GAAW,MAAMD,MAAI,WAAW;EAC1C,KAAK,UAAU;EACf,OAAO;CACT;;CAGA,cAAsB;EACpB,MAAM,QAAQ,KAAK,GAAG;EACtB,IAAI,QAAQ,KAAM,OAAO;EACzB,IAAI;EACJ,IAAI;EACJ,IAAI,UAAU,KAAM;GAClB,QAAQ;GACR,UAAU;EACZ,OAAO,IAAI,UAAU,KAAM;GACzB,QAAQ;GACR,UAAU;EACZ,OAAO;GACL,QAAQ;GACR,UAAU;EACZ;EACA,IAAI,QAAQ;EACZ,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK,SAAS,OAAO,KAAK,GAAG,CAAC,KAAK,OAAO,IAAI,CAAC;EAC1E,IAAI,QAAQ,SAAS,MAAMA,MAAI,mCAAmC;EAClE,IAAI,QAAQ,OAAO,OAAO,gBAAgB,GAAG,MAAMA,MAAI,2BAA2B;EAClF,OAAO,OAAO,KAAK;CACrB;CAEA,KAAK,QAA4B;EAC/B,IAAI,SAAS,KAAK,WAAW,MAAMA,MAAI,sBAAsB;EAC7D,MAAM,MAAM,KAAK,MAAM,MAAM,KAAK,QAAQ,KAAK,SAAS,MAAM;EAC9D,KAAK,UAAU;EACf,OAAO;CACT;AACF;;AAGA,SAAS,QAAQ,QAAgC;CAC/C,MAAM,UAA0B,CAAC;CACjC,MAAM,uBAAO,IAAI,IAAY;CAC7B,SAAS;EACP,MAAM,YAAY,OAAO,YAAY;EACrC,IAAI,cAAc,GAAG,OAAO;EAC5B,MAAM,MAAM,OAAO,KAAK,SAAS;EACjC,MAAM,QAAQ,OAAO,KAAK,OAAO,YAAY,CAAC;EAC9C,MAAM,QAAQ,MAAM,KAAK,GAAG,CAAC,CAC1B,KAAK,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAC3C,KAAK,EAAE;EACV,IAAI,KAAK,IAAI,KAAK,GAAG,MAAMA,MAAI,8BAA8B;EAC7D,KAAK,IAAI,KAAK;EACd,QAAQ,KAAK;GAAE,SAAS,IAAI;GAAK,SAAS,IAAI,MAAM,CAAC;GAAG;EAAM,CAAC;CACjE;AACF;;AAGA,SAAS,qBAAqB,IAAqD;CACjF,MAAM,SAAS,IAAI,OAAO,EAAE;CAC5B,OAAO,KAAK,CAAC;CACb,MAAM,SAAS,OAAO,YAAY;CAClC,IAAI,WAAW,GAGb,MAAMA,MAAI,gEAAgE;CAE5E,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK;EAC/B,OAAO,KAAK,EAAM;EAClB,OAAO,KAAK,OAAO,YAAY,CAAC;EAChC,OAAO,KAAK,CAAC;CACf;CACA,MAAM,UAAU,OAAO,YAAY;CACnC,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,KAAK;EAChC,OAAO,KAAK,CAAC;EACb,OAAO,KAAK,OAAO,YAAY,CAAC;CAClC;CACA,OAAO,KAAK,CAAC;CACb,IAAI,OAAO,cAAc,GAAG,MAAMA,MAAI,+CAA+C;CACrF,OAAO;EAAE;EAAQ;CAAQ;AAC3B;AAEA,SAAgB,UAAU,OAA+B;CACvD,MAAM,SAAS,IAAI,OAAO,KAAK;CAC/B,KAAK,MAAM,YAAY,OACrB,IAAI,OAAO,GAAG,MAAM,UAAU,MAAMA,MAAI,WAAW;CAErD,MAAM,YAAY,QAAQ,MAAM;CAEhC,IAAI,aAAgC;CACpC,IAAI,UAAU;CACd,KAAK,MAAM,SAAS,WAAW;EAC7B,IAAI,MAAM,YAAY,KAAQ,MAAM,QAAQ,WAAW,GAAG,aAAa,MAAM;EAC7E,IAAI,MAAM,YAAY,OAAQ,MAAM,QAAQ,WAAW,GAAG;GACxD,IAAI,MAAM,MAAM,WAAW,GAAG,MAAMA,MAAI,mBAAmB;GAC3D,WACG,MAAM,MAAM,KACV,MAAM,MAAM,MAAO,IACnB,MAAM,MAAM,MAAO,KACnB,MAAM,MAAM,MAAO,QACtB;EACJ;CACF;CACA,IAAI,eAAe,MAGjB,MAAMA,MAAI,gDAAgD;CAE5D,IAAI,YAAY,GAAG,MAAMA,MAAI,4BAA4B,SAAS;CAElE,MAAM,SAAS,qBAAqB,UAAU;CAC9C,MAAM,SAA2B,CAAC;CAClC,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,OAAO,KAAK,QAAQ,MAAM,CAAC;CACnE,MAAM,UAA4B,CAAC;CACnC,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,SAAS,KAAK,QAAQ,KAAK,QAAQ,MAAM,CAAC;CACrE,IAAI,OAAO,cAAc,GAAG,MAAMA,MAAI,sCAAsC;CAE5E,OAAO;EAAE;EAAY;EAAS;EAAQ;CAAQ;AAChD;AAEA,SAAgB,aACd,MACA,OACA,SACyB;CACzB,QAAQ,KAAK,OAAO,UAAU,CAAC,EAAA,CAAG,QAAQ,MAAM,EAAE,YAAY,OAAO;AACvE;AAEA,SAAgB,SAAS,MAAkB,OAAe,SAA0B;CAClF,OAAO,aAAa,MAAM,OAAO,OAAO,CAAC,CAAC,SAAS;AACrD;;;ACtKA,MAAa,WAAyB;CAAE,IAAI;CAAM,SAAS;AAAK;AAChE,MAAa,UAAU,YAAkC;CAAE,IAAI;CAAO;AAAO;AAC7E,MAAa,gBAAgB,YAAkC;CAC7D,IAAI;CACJ,SAAS;CACT;AACF;;;;;;;;;;;;ACaA,SAAgB,iBAAiB,MAA0C;CACzE,IAAI;CACJ,IAAI;CACJ,IAAI;EACF,OAAO,UAAU,KAAK,QAAQ;CAChC,SAAS,GAAG;EACV,OAAO,OAAO,qCAAqC,QAAQ,CAAC,GAAG;CACjE;CACA,IAAI;EACF,SAAS,UAAU,KAAK,UAAU;CACpC,SAAS,GAAG;EACV,OAAO,OAAO,iDAAiD,QAAQ,CAAC,GAAG;CAC7E;CAEA,IAAI,CAACE,eAAAA,WAAW,KAAK,YAAY,OAAO,UAAU,GAChD,OAAO,OAAO,oEAAoE;CAQpF,MAAM,iBAAiB,CAAC,cAAc,gBAAgB,cAAc,kBAAkB;CACtF,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,OAAO,QAAQ,KACxC,KAAK,MAAM,QAAQ,gBAAgB;EACjC,IAAI,CAAC,SAAS,QAAQ,GAAG,IAAI,GAAG;EAChC,IAAI,CAAC,SAAS,MAAM,GAAG,IAAI,GACzB,OAAO,OACL,SAAS,EAAE,+BAA+B,KAAK,SAAS,EAAE,EAAE,wEAC9D;EAEF,MAAM,IAAI,aAAa,MAAM,GAAG,IAAI;EACpC,MAAM,IAAI,aAAa,QAAQ,GAAG,IAAI;EACtC,IAAI,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,OAAO,OAAO,MAAMA,eAAAA,WAAW,MAAM,OAAO,EAAE,EAAE,CAAE,KAAK,CAAC,GACtF,OAAO,OACL,SAAS,EAAE,kEACb;CAEJ;CAGF,MAAM,YAAY,MAChB,SAAS,QAAQ,GAAG,cAAc,UAAU,KAC5C,SAAS,QAAQ,GAAG,cAAc,wBAAwB,KAC1D,SAAS,QAAQ,GAAG,cAAc,2BAA2B;CAE/D,MAAM,UAAU,OAAO,OAAO,KAAK,GAAG,MAAM,CAAC;CAC7C,IAAI,KAAK,2BAA2B,MAC9B;MAAA,CAAC,QAAQ,MAAM,QAAQ,GACzB,OAAO,OAAO,gDAAgD;CAAA,OAE3D,IAAI,CAAC,QAAQ,KAAK,QAAQ,GAC/B,OAAO,OAAO,wCAAwC;CAExD,OAAO;AACT;;;;;;;AAeA,SAAgB,uBAAuB,MAAgD;CACrF,IAAI,KAAK,UAAU,WAAW,GAC5B,OAAO,OAAO,iBAAiB;CAEjC,MAAM,SAAS,KAAK,UAAU;CAC9B,MAAM,QAAQ,eAAe,KAAK,OAAO;CACzC,IAAI,UAAU,MACZ,OAAO;EACL,IAAI;EACJ,SAAS;EACT,QAAQ;CACV;CAEF,IAAI,UAAU,MAAM,OAAO,UAAU,MAAM,MAAM,OAAO;CACxD,OAAO,OACL,mBAAmB,OAAO,oBAAoB,MAAM,MAAM,4BACpC,MAAM,IAAI,IAAI,MAAM,KAAK,gFACjD;AACF;AAQA,SAAS,eAAe,SAAqC;CAC3D,MAAM,IAAI,QAAQ,YAAY;CAC9B,IAAI,EAAE,WAAW,MAAM,KAAK,EAAE,WAAW,MAAM,KAAK,EAAE,WAAW,QAAQ,GACvE,OAAO;EAAE,KAAK;EAAI,MAAM;EAAI,OAAO;CAAyB;CAE9D,IAAI,EAAE,WAAW,MAAM,KAAK,EAAE,WAAW,MAAM,KAAK,EAAE,WAAW,QAAQ,GACvE,OAAO;CAKT,IAAI,YAAY,OAAO,GAAG;EACxB,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,GAAG,GACnD,OAAO;GAAE,KAAK;GAAI,MAAM;GAAI,OAAO;EAAuB;EAE5D,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,GAAG,GAG9E,OAAO;GAAE,KAAK;GAAI,MAAM;GAAI,OAAO;EAAe;CAEtD;CACA,OAAO;AACT;AAEA,SAAS,YAAY,SAA0B;CAC7C,OAAO,QAAQ,UAAU,MAAM,QAAQ,UAAU,MAAM,0BAA0B,KAAK,OAAO;AAC/F;AAEA,SAAS,QAAQ,GAAoB;CACnC,OAAO,aAAaC,eAAAA,eAAe,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAC9E;;;;ACpIA,SAAS,mBAAmB,SAAiC;CAC3D,MAAM,SAASC,eAAAA,WAAW,6BAA6B,QAAQ,QAAQ;CACvE,QAAA,GAAOC,mBAAAA,WAAAA,CAAWC,eAAAA,YAAY,IAAI,WAAW,CAAC,EAAI,CAAC,GAAG,QAAQ,OAAO,CAAC;AACxE;;;;;;AAOA,SAAgB,mBAAmB,MAA4C;CAC7E,IAAI,KAAK,UAAU,SAAS,IAC1B,OAAO,OAAO,oCAAoC;CAEpD,IAAI,KAAK,sBAAsB,KAAA,KAAa,CAACC,eAAAA,WAAW,KAAK,mBAAmB,KAAK,QAAQ,GAC3F,OAAO,OAAO,+DAA+D;CAG/E,IAAI;CACJ,QAAQ,KAAK,UAAb;EACE,KAAKC,YAAAA,YAAY;EACjB,KAAKA,YAAAA,YAAY;GACf,UAAA,GAASH,mBAAAA,WAAAA,CAAW,KAAK,QAAQ;GACjC;EACF,KAAKG,YAAAA,YAAY;GACf,SAAS,mBAAmB,KAAK,QAAQ;GACzC;EACF,KAAKA,YAAAA,YAAY,WACf,OAAO,aACL,+EACF;EACF,SACE,OAAO,OAAO,oBAAoB,KAAK,UAA0B;CACrE;CAEA,IAAI,OAAO;CACX,KAAK,MAAM,KAAK,KAAK,UAAU,MAAM,EAAE,GAAG,OAAQ,QAAQ,KAAM,OAAO,CAAC;CACxE,MAAM,aAAaC,YAAAA,eAAe,IAAI;CACtC,IAAI,eAAe,KAAK,eAAe,GACrC,OAAO,OAAO,4BAA4B;CAG5C,IAAI;CACJ,IAAI;EACF,MAAM,QAAQC,wBAAAA,UAAU,UAAU,YAAY,KAAK,UAAU,MAAM,GAAG,EAAE,CAAC,CAAC,CACvE,eAAe,UAAU,CAAC,CAC1B,iBAAiB,MAAM;EAC1B,aAAA,GAAYL,mBAAAA,WAAAA,CAAW,MAAM,WAAW,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE;CACnE,SAAS,GAAG;EACV,OAAO,OAAO,mCAAoC,EAAY,SAAS;CACzE;CAEA,MAAM,WAAW,KAAK,mBAAmB,aAAa,KAAK,UAAUM,eAAAA,WAAW,KAAK,OAAO;CAC5F,IAAI,SAAS,WAAW,IACtB,OAAO,OAAO,0CAA0C,SAAS,QAAQ;CAE3E,IAAI,CAACJ,eAAAA,WAAW,WAAW,QAAQ,GACjC,OAAO,OACL,8DAA8DK,eAAAA,WAAW,SAAS,EAAE,EACtF;CAEF,OAAO;AACT;;;ACpEA,SAAgB,sBAAsB,MAA+C;CACnF,IACE,KAAK,0BAA0B,KAAA,KAC/B,CAACC,eAAAA,WAAW,KAAK,uBAAuB,KAAK,QAAQ,GAErD,OAAO,OAAO,2DAA2D;CAE3E,IAAI;CACJ,IAAI;EACF,KAAKC,sBAAAA,QAAQ,OAAO,KAAK,WAAW,KAAK,UAAU,KAAK,SAAS;CACnE,SAAS,GAAG;EACV,OAAO,OAAO,0CAA2C,EAAY,SAAS;CAChF;CACA,OAAO,KAAK,WAAW,OAAO,+CAA+C;AAC/E;;;;;;;;;;;;;ACnBA,MAAM,YAAY;AAClB,MAAM,YAAY;AAClB,MAAM,sBAAsB;AAC5B,MAAM,WAAW;AAUjB,SAAS,IAAI,SAA8B;CACzC,OAAO,IAAIC,eAAAA,YAAY,mBAAmB,YAAY,SAAS;AACjE;;AAGA,SAAgB,YAAY,KAA6B;CACvD,IAAI,IAAI,SAAS,IAAI,MAAM,IAAI,WAAW;CAE1C,KADgB,IAAI,MAAO,KAAO,IAAI,MAAO,KAAO,IAAI,MAAO,IAAK,IAAI,QAAS,MACnE,WAAW,MAAM,IAAI,mBAAmB;CAEtD,MAAM,QAAQ,IAAI;CAClB,MAAM,SAAU,SAAS,IAAK;CAC9B,MAAM,UAAU,QAAQ;CACxB,MAAM,UAAU,IAAI;CACpB,IAAI,YAAY,KAAK,UAAU,GAAG,MAAM,IAAI,cAAc;CAC1D,IAAI,YAAY,KAAK,UAAU,GAAG,MAAM,IAAI,iBAAiB;CAE7D,IAAI,MAAM;CACV,MAAM,WAAW,YAA4B;EAC3C,IAAI,QAAQ;EACZ,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,KAAK;GAChC,IAAI,OAAO,IAAI,QAAQ,MAAM,IAAI,kBAAkB;GACnD,QAAQ,QAAQ,MAAM,IAAI;EAC5B;EACA,IAAI,CAAC,OAAO,cAAc,KAAK,GAAG,MAAM,IAAI,2BAA2B;EACvE,OAAO;CACT;CAEA,MAAM,YAAY,QAAQ,OAAO;CACjC,MAAM,YAAY,QAAQ,OAAO;CACjC,QAAQ,OAAO;CACf,QAAQ,OAAO;CACf,IAAI,cAAc,GAAG,MAAM,IAAI,UAAU;CACzC,IAAI,cAAc,KAAK,YAAY,WAAW,MAAM,IAAI,yBAAyB;CAEjF,MAAM,YAAY,QAAQ,OAAO;CACjC,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,KAAK,QAAQ,OAAO;CACnD,IAAI,aAAa,WAAW,MAAM,IAAI,yBAAyB;CAC/D,IAAI,QAAQ,OAAO,YAAY;CAE/B,MAAM,QAAgB,CAAC;CACvB,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,KAAK;EAClC,IAAI,MAAM,IAAI,IAAI,QAAQ,MAAM,IAAI,gBAAgB;EACpD,MAAM,KAAK,IAAI;EACf,MAAM,KAAK,IAAI;EACf,MAAM,WAAW,KAAK;EACtB,IAAI,WAAW,UAAU,MAAM,IAAI,qBAAqB;EAExD,MAAM,cAAe,KAAK,KAAM;EAChC,MAAM,cAAc,KAAK,OAAO;EAChC,IAAI,cAAc,qBAAqB,MAAM,IAAI,qBAAqB;EACtE,IAAI,MAAM,cAAc,IAAI,QAAQ,MAAM,IAAI,qBAAqB;EACnE,MAAM,OAAO,IAAI,MAAM,KAAK,MAAM,WAAW;EAC7C,OAAO;EAGP,IAAI;EACJ,IAAI,cAAc,cAAc,GAAG;GACjC,MAAM,OAAO,KAAK,cAAc;GAChC,IAAI,SAAS,GACX,YAAY,cAAc,KAAK;QAC1B;IACL,IAAI,gBAAgB;IACpB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;KAC1B,IAAI,OAAQ,KAAK,GAAI;KACrB;IACF;IACA,WAAW,cAAc,IAAI,IAAI;GACnC;EACF,OACE,WAAW,cAAc;EAG3B,MAAM,OAAiB,CAAC;EACxB,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,KAAK;GACjC,MAAM,MAAM,QAAQ,OAAO;GAC3B,IAAI,OAAO,WAAW,MAAM,IAAI,wBAAwB;GACxD,IAAI,OAAO,GAAG,MAAM,IAAI,gCAAgC;GACxD,KAAK,KAAK,GAAG;EACf;EACA,MAAM,KAAK;GAAE;GAAU;GAAM;GAAM,OAAO;GAAG,sBAAM,IAAI,WAAW,CAAC;EAAE,CAAC;CACxE;CAGA,KAAK,IAAI,IAAI,YAAY,GAAG,KAAK,GAAG,KAAK;EACvC,MAAM,OAAO,MAAM;EACnB,IAAI,gBAAgB;EACpB,KAAK,MAAM,KAAK,KAAK,MACnB,gBAAgB,KAAK,IAAI,eAAe,MAAM,EAAE,CAAE,KAAK;EAEzD,KAAK,QAAQ,KAAK,KAAK,WAAW,IAAI,IAAI,gBAAgB;EAE1D,MAAM,YAAa,KAAK,WAAW,KAAM;EACzC,MAAM,aAAa,KAAK,WAAW,MAAM;EACzC,MAAM,OAAiB,CAAC,KAAK,KAAK,QAAQ,YAAY,KAAK,aAAa,IAAI,EAAE;EAC9E,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM,CAAC;EAC/D,IAAI,cAAc,YAAY,GAAG;GAC/B,MAAM,QAAQ,IAAK,KAAK,WAAW;GACnC,MAAM,OAAO,KAAK,SAAS;GAC3B,KAAK,SAAS,KAAK,QAAU,KAAK,SAAW,OAAQ,QAAS;EAChE;EACA,KAAK,MAAM,KAAK,KAAK,MACnB,KAAK,KAAM,MAAM,EAAE,CAAE,SAAS,IAAK,KAAM,MAAM,EAAE,CAAE,QAAQ,GAAI;EAEjE,IAAI,QAAoB,IAAI,WAAW,IAAI;EAC3C,KAAK,MAAM,KAAK,KAAK,MAAM,QAAQC,eAAAA,YAAY,OAAO,MAAM,EAAE,CAAE,IAAI;EACpE,KAAK,QAAA,GAAOC,mBAAAA,OAAAA,CAAO,KAAK;CAC1B;CAEA,OAAO,MAAM,UAAU,CAAE;AAC3B;;;;;;;;;AClHA,SAAgB,mBAAmB,MAA4C;CAC7E,IAAI,KAAK,UAAU,WAAW,IAAI,OAAO,OAAO,4BAA4B;CAC5E,IAAI,KAAK,UAAU,WAAW,IAAI,OAAO,OAAO,6BAA6B;CAE7E,IAAI;CACJ,IAAI,KAAK,aAAaC,YAAAA,YAAY,UAChC,UAAA,GAASC,mBAAAA,OAAAA,CACPC,eAAAA,YAAY,IAAI,WAAW,CAAC,KAAM,GAAI,CAAC,GAAGC,eAAAA,WAAW,aAAa,IAAA,GAAGF,mBAAAA,OAAAA,CAAO,KAAK,QAAQ,CAAC,CAC5F;MACK,IAAI,KAAK,aAAaD,YAAAA,YAAY,aACvC,IAAI;EACF,SAAS,YAAY,KAAK,QAAQ;CACpC,SAAS,GAAG;EACV,OAAO,OAAO,mCAAoC,EAAY,SAAS;CACzE;MAEA,OAAO,OAAO,oBAAoB,KAAK,UAA0B;CAGnE,IAAI;CACJ,IAAI;EACF,KAAKI,sBAAAA,QAAQ,OAAO,KAAK,WAAW,QAAQ,KAAK,SAAS;CAC5D,SAAS,GAAG;EACV,OAAO,OAAO,uCAAwC,EAAY,SAAS;CAC7E;CACA,OAAO,KAAK,WAAW,OAAO,+CAA+C;AAC/E;;;ACvCA,MAAM,eAAA,GAAcC,YAAAA,kBAAAA,CAAkBC,mBAAAA,MAAM;;;;;;;;;;;AAuB5C,SAAgB,oBAAoB,MAA6C;CAC/E,IAAI;CACJ,IAAI;EACF,WAAW,OAAO,KAAK,aAAa,WAAWC,iBAAAA,kBAAkB,KAAK,QAAQ,IAAI,KAAK;CACzF,SAAS,GAAG;EACV,OAAO,OAAO,kDAAmD,EAAY,SAAS;CACxF;CACA,IAAI,SAAS,WAAW,WAAW,GACjC,OAAO,OAAO,oDAAoD;CAEpE,IAAI,CAAC,KAAK,MACR,OAAO,OAAO,iDAAiD;CAGjE,MAAM,UAAA,GAASD,mBAAAA,OAAAA,CAAO,SAAS,OAAO;CACtC,KAAK,MAAM,aAAa,SAAS,YAAY;EAC3C,MAAM,YAAY,mBAAmB,QAAQ,SAAS;EACtD,IAAI,cAAc,MAAM,OAAO,OAAO,gCAAgC;EACtE,IAAI,cAAc,KAAK,MACrB,OAAO,OAAO,+CAA+C;CAEjE;CAEA,IAAIE,eAAAA,WAAW,SAAS,SAAS,KAAK,OAAO,GAAG,OAAO;CAIvD,MAAM,iBAAiB,iBAAiB,KAAK,SAAS,SAAS,OAAO;CACtE,IAAI,mBAAmB,MAAM,OAAO;CACpC,IAAI,KAAK,gBAAgB,KAAA,GACvB,OAAO,OACL,6GACF;CAEF,OAAO,cAAc,SAAS,SAAS,KAAK,WAAW;AACzD;AAEA,SAAS,mBAAmB,QAAoB,WAAsC;CACpF,IAAI,UAAU,SAAS,IAAI,OAAO;CAClC,MAAM,WAAW,UAAU;CAC3B,MAAM,aAAa,YAAY,KAAM,WAAW,KAAM,IAAI,WAAW;CACrE,IAAI;EACF,MAAM,QAAQC,wBAAAA,UAAU,UAAU,YAAY,UAAU,MAAM,GAAG,EAAE,CAAC,CAAC,CAClE,eAAe,UAAU,CAAC,CAC1B,iBAAiB,MAAM;EAC1B,MAAM,QAAA,GAAOC,mBAAAA,WAAAA,CAAW,MAAM,WAAW,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;EACxD,OAAO,YAAY,OAAOC,eAAAA,YAAY,IAAI,WAAW,CAAC,EAAI,CAAC,GAAG,KAAK,MAAM,EAAE,CAAC,CAAC;CAC/E,QAAQ;EACN,OAAO;CACT;AACF;AAgBA,SAAS,aAAa,OAAuC;CAC3D,IAAI;EACF,MAAM,SAASC,iBAAAA,WAAW,KAAK;EAC/B,MAAM,YAA4B,CAAC;EACnC,KAAK,MAAM,KAAK,QACd,IAAI,EAAE,UAAU,MAAM,EAAE,aAAa,GAAG;GACtC,MAAM,IAAIA,iBAAAA,WAAW,EAAE,KAAK;GAC5B,MAAM,WAAWC,iBAAAA,WAAW,GAAG,CAAC;GAChC,MAAM,MAAM,WAAWD,iBAAAA,WAAW,QAAQ,IAAI,CAAC;GAC/C,MAAM,eAAe,WAAWC,iBAAAA,WAAW,KAAK,CAAC,IAAI;GACrD,UAAU,KAAK;IACb,SAAS,eAAeC,eAAAA,WAAW,YAAY,IAAI;IACnD,MAAMC,iBAAAA,YAAY,GAAG,CAAC,KAAK;IAC3B,WAAY,YAAYF,iBAAAA,WAAW,KAAK,CAAC,qBAAM,IAAI,WAAW,CAAC;GACjE,CAAC;EACH;EAEF,OAAO;GACL;GACA,YAAYE,iBAAAA,YAAY,QAAQ,CAAC,KAAK;GACtC,WAAWA,iBAAAA,YAAY,QAAQ,EAAE,KAAK;EACxC;CACF,QAAQ;EACN,OAAO;CACT;AACF;;AAGA,SAAS,iBAAiB,YAAwB,cAA+C;CAC/F,MAAM,QAAQ,aAAa,UAAU;CACrC,MAAM,UAAU,aAAa,YAAY;CACzC,IAAI,CAAC,OAAO,OAAO,OAAO,yDAAyD;CACnF,IAAI,CAAC,SAAS,OAAO,OAAO,4DAA4D;CACxF,IAAI,MAAM,UAAU,WAAW,KAAK,QAAQ,UAAU,WAAW,GAC/D,OAAO,OAAO,0DAA0D;CAE1E,MAAM,IAAI,MAAM,UAAU;CAC1B,MAAM,IAAI,QAAQ,UAAU;CAC5B,MAAM,QAAQ,aAAa,CAAC;CAE5B,IAAI,UADU,aAAa,CACT,GAChB,OAAO,OAAO,gEAAgE;CAGhF,MAAM,KAAK,eAAe,EAAE,SAAS;CACrC,MAAM,KAAK,eAAe,EAAE,SAAS;CACrC,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,OAAO,gDAAgD;CAE9E,QAAQ,OAAR;EACE,KAAK;GAEH,IACE,eAAe,IAAI,IAAI,CAAC,KACxB,eAAe,IAAI,IAAI,CAAC,MACvBA,iBAAAA,YAAY,IAAI,CAAC,KAAK,SAASA,iBAAAA,YAAY,IAAI,CAAC,KAAK,KAEtD,OAAO;GAET;EACF,KAAK;GAEH,IACE,eAAe,IAAI,IAAI,CAAC,KACxB,eAAe,IAAI,IAAI,CAAC,KACxB,eAAe,IAAI,IAAI,CAAC,MACvBA,iBAAAA,YAAY,IAAI,CAAC,KAAK,SAASA,iBAAAA,YAAY,IAAI,CAAC,KAAK,KAEtD,OAAO;GAET;EACF,KAAK;GAKH,IACE,eAAe,IAAI,IAAI,CAAC,KACxB,eAAe,IAAI,IAAI,CAAC,MACvBA,iBAAAA,YAAY,IAAI,CAAC,KAAK,SAASA,iBAAAA,YAAY,IAAI,CAAC,KAAK,OACtD,eAAe,IAAI,IAAI,CAAC,GAExB,OAAO;GAET;EACF,SAIE,OAAO,OAAO,8EAA8E;CAChG;CACA,OAAO,OAAO,+DAA+D;AAC/E;AAIA,SAAS,aAAa,UAAsC;CAC1D,IAAI,SAAS,QAAQ,SAAS,mBAAmB,KAAK,SAAS,SAAS,IAAI,OAAO;CACnF,IAAI,SAAS,QAAQ,SAAS,wBAAwB,KAAK,SAAS,SAAS,IAC3E,OAAO;CAET,IAAI,SAAS,QAAQ,SAAS,uBAAuB,KAAK,SAAS,SAAS,KAC1E,OAAO;CAET,OAAO;AACT;AAEA,SAAS,eAAe,OAAyD;CAC/E,IAAI;EACF,OAAOH,iBAAAA,WAAW,KAAK;CACzB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,eACP,GACA,GACA,OACS;CACT,MAAM,IAAIC,iBAAAA,WAAW,GAAG,KAAK,qBAAK,IAAI,WAAW,CAAC;CAClD,MAAM,IAAIA,iBAAAA,WAAW,GAAG,KAAK,qBAAK,IAAI,WAAW,CAAC;CAClD,OAAOL,eAAAA,WAAW,GAAG,CAAC;AACxB;;;;;;;AAQA,MAAM,gBAAgB,MAAM,MAAM;AAClC,MAAM,gBAAgB,MAAM,MAAM,MAAM;AAExC,SAAS,cAAc,cAA0B,aAA4C;CAC3F,MAAM,UAAU,aAAa,YAAY;CACzC,IAAI,CAAC,SAAS,OAAO,OAAO,4DAA4D;CACxF,MAAM,QAAQ,OAAO,YAAY,SAAS;CAC1C,IAAI,QAAQ,cAAc,OACxB,OAAO,OACL,mGACF;CAEF,MAAM,WAAW,QAAQ,aAAa;CACtC,IAAI,WAAW,iBAAiB,WAAW,eACzC,OAAO,OACL,8CAA8C,SAAS,wDAAwD,cAAc,GAAG,cAAc,WAChJ;CAEF,OAAO;AACT"}
|
package/dist/verify.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { n as EvmDataType } from "./evm-DJxGGAbD.cjs";
|
|
2
|
+
import { n as TonDataType } from "./ton-DmeIvknN.cjs";
|
|
2
3
|
import { n as TronLatestBlock, t as SignedTronTx } from "./messages-DsPvW8Oi.cjs";
|
|
3
4
|
//#region src/verify/result.d.ts
|
|
4
5
|
/** Outcome of a verification helper. Helpers return, never throw, on mismatches. */
|
|
@@ -135,6 +136,28 @@ interface VerifySolanaSignatureArgs {
|
|
|
135
136
|
}
|
|
136
137
|
declare function verifySolanaSignature(args: VerifySolanaSignatureArgs): VerifyResult;
|
|
137
138
|
//#endregion
|
|
139
|
+
//#region src/verify/ton.d.ts
|
|
140
|
+
interface VerifyTonSignatureArgs {
|
|
141
|
+
/** The exact bytes the request carried in `signData`. */
|
|
142
|
+
readonly signData: Uint8Array;
|
|
143
|
+
readonly dataType: TonDataType;
|
|
144
|
+
/** 64-byte Ed25519 signature from the reply. */
|
|
145
|
+
readonly signature: Uint8Array;
|
|
146
|
+
/** The 32-byte signer public key from linking (`accounts.ton()`). */
|
|
147
|
+
readonly publicKey: Uint8Array;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Recompute the exact digest the device signs — the BoC ROOT CELL's
|
|
151
|
+
* representation hash for a transaction, or the TON Connect proof digest
|
|
152
|
+
* `sha256(0xFFFF || "ton-connect" || sha256(payload))` — and verify the
|
|
153
|
+
* Ed25519 signature against the linked key.
|
|
154
|
+
*/
|
|
155
|
+
declare function verifyTonSignature(args: VerifyTonSignatureArgs): VerifyResult;
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/verify/ton-boc.d.ts
|
|
158
|
+
/** Representation hash of the ROOT cell of a BoC — the bytes TON signs. */
|
|
159
|
+
declare function bocRootHash(boc: Uint8Array): Uint8Array;
|
|
160
|
+
//#endregion
|
|
138
161
|
//#region src/verify/tron.d.ts
|
|
139
162
|
interface VerifyTronSignatureArgs {
|
|
140
163
|
/** The `raw_data` bytes the request carried. */
|
|
@@ -158,5 +181,5 @@ interface VerifyTronSignatureArgs {
|
|
|
158
181
|
*/
|
|
159
182
|
declare function verifyTronSignature(args: VerifyTronSignatureArgs): VerifyResult;
|
|
160
183
|
//#endregion
|
|
161
|
-
export { type ParsedPsbt, PsbtInputType, type PsbtKeyValue, type VerifyBtcMessageHeaderArgs, type VerifyEvmSignatureArgs, type VerifyResult, type VerifySignedPsbtArgs, type VerifySolanaSignatureArgs, type VerifyTronSignatureArgs, parsePsbt, verifyBtcMessageHeader, verifyEvmSignature, verifySignedPsbt, verifySolanaSignature, verifyTronSignature };
|
|
184
|
+
export { type ParsedPsbt, PsbtInputType, type PsbtKeyValue, type VerifyBtcMessageHeaderArgs, type VerifyEvmSignatureArgs, type VerifyResult, type VerifySignedPsbtArgs, type VerifySolanaSignatureArgs, type VerifyTonSignatureArgs, type VerifyTronSignatureArgs, bocRootHash, parsePsbt, verifyBtcMessageHeader, verifyEvmSignature, verifySignedPsbt, verifySolanaSignature, verifyTonSignature, verifyTronSignature };
|
|
162
185
|
//# sourceMappingURL=verify.d.cts.map
|
package/dist/verify.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { n as EvmDataType } from "./evm-KrV5wK08.js";
|
|
2
|
+
import { n as TonDataType } from "./ton-C0UP-cf_.js";
|
|
2
3
|
import { n as TronLatestBlock, t as SignedTronTx } from "./messages-DsPvW8Oi.js";
|
|
3
4
|
//#region src/verify/result.d.ts
|
|
4
5
|
/** Outcome of a verification helper. Helpers return, never throw, on mismatches. */
|
|
@@ -135,6 +136,28 @@ interface VerifySolanaSignatureArgs {
|
|
|
135
136
|
}
|
|
136
137
|
declare function verifySolanaSignature(args: VerifySolanaSignatureArgs): VerifyResult;
|
|
137
138
|
//#endregion
|
|
139
|
+
//#region src/verify/ton.d.ts
|
|
140
|
+
interface VerifyTonSignatureArgs {
|
|
141
|
+
/** The exact bytes the request carried in `signData`. */
|
|
142
|
+
readonly signData: Uint8Array;
|
|
143
|
+
readonly dataType: TonDataType;
|
|
144
|
+
/** 64-byte Ed25519 signature from the reply. */
|
|
145
|
+
readonly signature: Uint8Array;
|
|
146
|
+
/** The 32-byte signer public key from linking (`accounts.ton()`). */
|
|
147
|
+
readonly publicKey: Uint8Array;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Recompute the exact digest the device signs — the BoC ROOT CELL's
|
|
151
|
+
* representation hash for a transaction, or the TON Connect proof digest
|
|
152
|
+
* `sha256(0xFFFF || "ton-connect" || sha256(payload))` — and verify the
|
|
153
|
+
* Ed25519 signature against the linked key.
|
|
154
|
+
*/
|
|
155
|
+
declare function verifyTonSignature(args: VerifyTonSignatureArgs): VerifyResult;
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/verify/ton-boc.d.ts
|
|
158
|
+
/** Representation hash of the ROOT cell of a BoC — the bytes TON signs. */
|
|
159
|
+
declare function bocRootHash(boc: Uint8Array): Uint8Array;
|
|
160
|
+
//#endregion
|
|
138
161
|
//#region src/verify/tron.d.ts
|
|
139
162
|
interface VerifyTronSignatureArgs {
|
|
140
163
|
/** The `raw_data` bytes the request carried. */
|
|
@@ -158,5 +181,5 @@ interface VerifyTronSignatureArgs {
|
|
|
158
181
|
*/
|
|
159
182
|
declare function verifyTronSignature(args: VerifyTronSignatureArgs): VerifyResult;
|
|
160
183
|
//#endregion
|
|
161
|
-
export { type ParsedPsbt, PsbtInputType, type PsbtKeyValue, type VerifyBtcMessageHeaderArgs, type VerifyEvmSignatureArgs, type VerifyResult, type VerifySignedPsbtArgs, type VerifySolanaSignatureArgs, type VerifyTronSignatureArgs, parsePsbt, verifyBtcMessageHeader, verifyEvmSignature, verifySignedPsbt, verifySolanaSignature, verifyTronSignature };
|
|
184
|
+
export { type ParsedPsbt, PsbtInputType, type PsbtKeyValue, type VerifyBtcMessageHeaderArgs, type VerifyEvmSignatureArgs, type VerifyResult, type VerifySignedPsbtArgs, type VerifySolanaSignatureArgs, type VerifyTonSignatureArgs, type VerifyTronSignatureArgs, bocRootHash, parsePsbt, verifyBtcMessageHeader, verifyEvmSignature, verifySignedPsbt, verifySolanaSignature, verifyTonSignature, verifyTronSignature };
|
|
162
185
|
//# sourceMappingURL=verify.d.ts.map
|