@monolythium/core-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,593 @@
1
+ 'use strict';
2
+
3
+ var mlDsa_js = require('@noble/post-quantum/ml-dsa.js');
4
+ var sha3_js = require('@noble/hashes/sha3.js');
5
+ var bip39 = require('@scure/bip39');
6
+ var english_js = require('@scure/bip39/wordlists/english.js');
7
+ var mlKem_js = require('@noble/post-quantum/ml-kem.js');
8
+ var chacha_js = require('@noble/ciphers/chacha.js');
9
+ var utils_js = require('@noble/hashes/utils.js');
10
+
11
+ // src/crypto/bincode.ts
12
+ var BincodeWriter = class {
13
+ #chunks = [];
14
+ u8(value) {
15
+ this.#int(value, 1);
16
+ }
17
+ u16(value) {
18
+ this.#int(value, 2);
19
+ }
20
+ u32(value) {
21
+ this.#int(value, 4);
22
+ }
23
+ u64(value) {
24
+ this.#big(value, 8);
25
+ }
26
+ u128(value) {
27
+ this.#big(value, 16);
28
+ }
29
+ enumVariant(value) {
30
+ this.u32(value);
31
+ }
32
+ rawBytes(bytes) {
33
+ for (const b of bytes) this.#chunks.push(b);
34
+ }
35
+ bytes(bytes) {
36
+ this.u64(BigInt(bytes.length));
37
+ this.rawBytes(bytes);
38
+ }
39
+ optionBytes(bytes) {
40
+ if (bytes === null) {
41
+ this.u8(0);
42
+ return;
43
+ }
44
+ this.u8(1);
45
+ this.rawBytes(bytes);
46
+ }
47
+ toBytes() {
48
+ return Uint8Array.from(this.#chunks);
49
+ }
50
+ #int(value, bytes) {
51
+ if (!Number.isSafeInteger(value) || value < 0 || value >= 2 ** (bytes * 8)) {
52
+ throw new Error(`integer out of u${bytes * 8} range`);
53
+ }
54
+ for (let i = 0; i < bytes; i++) {
55
+ this.#chunks.push(value >> 8 * i & 255);
56
+ }
57
+ }
58
+ #big(value, bytes) {
59
+ let v = typeof value === "bigint" ? value : BigInt(value);
60
+ if (v < 0n || v >= 1n << BigInt(bytes * 8)) {
61
+ throw new Error(`integer out of u${bytes * 8} range`);
62
+ }
63
+ for (let i = 0; i < bytes; i++) {
64
+ this.#chunks.push(Number(v & 0xffn));
65
+ v >>= 8n;
66
+ }
67
+ }
68
+ };
69
+
70
+ // src/crypto/bytes.ts
71
+ function concatBytes(...chunks) {
72
+ const len = chunks.reduce((n, c) => n + c.length, 0);
73
+ const out = new Uint8Array(len);
74
+ let off = 0;
75
+ for (const chunk of chunks) {
76
+ out.set(chunk, off);
77
+ off += chunk.length;
78
+ }
79
+ return out;
80
+ }
81
+ function bytesToHex(bytes) {
82
+ let out = "0x";
83
+ for (let i = 0; i < bytes.length; i++) {
84
+ out += bytes[i].toString(16).padStart(2, "0");
85
+ }
86
+ return out;
87
+ }
88
+ function hexToBytes(hex, label = "hex") {
89
+ const stripped = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
90
+ if (stripped.length % 2 !== 0) {
91
+ throw new Error(`${label} must have even length`);
92
+ }
93
+ const out = new Uint8Array(stripped.length / 2);
94
+ for (let i = 0; i < out.length; i++) {
95
+ const b = Number.parseInt(stripped.slice(i * 2, i * 2 + 2), 16);
96
+ if (Number.isNaN(b)) {
97
+ throw new Error(`${label} contains invalid hex`);
98
+ }
99
+ out[i] = b;
100
+ }
101
+ return out;
102
+ }
103
+ function expectBytes(value, len, label) {
104
+ if (value.length !== len) {
105
+ throw new Error(`${label} must be ${len} bytes, got ${value.length}`);
106
+ }
107
+ return value instanceof Uint8Array ? value : Uint8Array.from(value);
108
+ }
109
+ function bigintToBeBytes(value, bytes, label) {
110
+ if (value < 0n || value >= 1n << BigInt(bytes * 8)) {
111
+ throw new Error(`${label} out of ${bytes * 8}-bit range`);
112
+ }
113
+ const out = new Uint8Array(bytes);
114
+ let v = value;
115
+ for (let i = bytes - 1; i >= 0; i--) {
116
+ out[i] = Number(v & 0xffn);
117
+ v >>= 8n;
118
+ }
119
+ return out;
120
+ }
121
+ function parseBigint(value, label) {
122
+ if (value === void 0) throw new Error(`${label} missing`);
123
+ if (typeof value === "bigint") return value;
124
+ if (typeof value === "number") {
125
+ if (!Number.isSafeInteger(value) || value < 0) throw new Error(`${label} must be a non-negative safe integer`);
126
+ return BigInt(value);
127
+ }
128
+ if (value.startsWith("0x") || value.startsWith("0X")) return BigInt(value);
129
+ return BigInt(value);
130
+ }
131
+
132
+ // src/crypto/tx.ts
133
+ function encodeTransactionForHash(fields, tag) {
134
+ const n = normalizeTxFields(fields);
135
+ return concatBytes(
136
+ Uint8Array.of(tag),
137
+ bigintToBeBytes(n.chainId, 8, "chainId"),
138
+ bigintToBeBytes(n.nonce, 8, "nonce"),
139
+ bigintToBeBytes(n.maxPriorityFeePerGas, 32, "maxPriorityFeePerGas"),
140
+ bigintToBeBytes(n.maxFeePerGas, 32, "maxFeePerGas"),
141
+ bigintToBeBytes(n.gasLimit, 8, "gasLimit"),
142
+ n.to === null ? Uint8Array.of(0) : concatBytes(Uint8Array.of(1), n.to),
143
+ bigintToBeBytes(n.value, 32, "value"),
144
+ bigintToBeBytes(BigInt(n.input.length), 4, "input.length"),
145
+ n.input,
146
+ new Uint8Array(4),
147
+ // access_list length
148
+ new Uint8Array(4)
149
+ // extensions length
150
+ );
151
+ }
152
+ function bincodeSignedTransaction(fields, signature, publicKey) {
153
+ const n = normalizeTxFields(fields);
154
+ const sig = expectBytes(signature, ML_DSA_65_SIGNATURE_LEN, "ML-DSA-65 signature");
155
+ const pk = expectBytes(publicKey, ML_DSA_65_PUBLIC_KEY_LEN, "ML-DSA-65 public key");
156
+ const w = new BincodeWriter();
157
+ w.u64(n.chainId);
158
+ w.u64(n.nonce);
159
+ w.rawBytes(uint256Le(n.maxPriorityFeePerGas, "maxPriorityFeePerGas"));
160
+ w.rawBytes(uint256Le(n.maxFeePerGas, "maxFeePerGas"));
161
+ w.u64(n.gasLimit);
162
+ w.optionBytes(n.to);
163
+ w.rawBytes(uint256Le(n.value, "value"));
164
+ w.bytes(n.input);
165
+ w.u64(0n);
166
+ w.u64(0n);
167
+ bincodeMlDsa65OpaqueInto(w, sig);
168
+ bincodeMlDsa65OpaqueInto(w, pk);
169
+ return w.toBytes();
170
+ }
171
+ function normalizeTxFields(fields) {
172
+ return {
173
+ chainId: parseBigint(fields.chainId, "chainId"),
174
+ nonce: parseBigint(fields.nonce, "nonce"),
175
+ maxPriorityFeePerGas: parseBigint(fields.maxPriorityFeePerGas, "maxPriorityFeePerGas"),
176
+ maxFeePerGas: parseBigint(fields.maxFeePerGas, "maxFeePerGas"),
177
+ gasLimit: parseBigint(fields.gasLimit, "gasLimit"),
178
+ to: normalizeTo(fields.to),
179
+ value: parseBigint(fields.value, "value"),
180
+ input: normalizeBytes(fields.input ?? new Uint8Array(0), "input")
181
+ };
182
+ }
183
+ function normalizeTo(value) {
184
+ if (value === null) return null;
185
+ const bytes = normalizeBytes(value, "to");
186
+ return expectBytes(bytes, 20, "to");
187
+ }
188
+ function normalizeBytes(value, label) {
189
+ if (typeof value === "string") return hexToBytes(value, label);
190
+ return value instanceof Uint8Array ? value : Uint8Array.from(value);
191
+ }
192
+ function uint256Le(value, label) {
193
+ if (value < 0n || value >= 1n << 256n) throw new Error(`${label} out of u256 range`);
194
+ const out = new Uint8Array(32);
195
+ let v = value;
196
+ for (let i = 0; i < 32; i++) {
197
+ out[i] = Number(v & 0xffn);
198
+ v >>= 8n;
199
+ }
200
+ return out;
201
+ }
202
+ function bincodeMlDsa65OpaqueInto(w, raw) {
203
+ w.enumVariant(ENUM_VARIANT_INDEX_ML_DSA_65);
204
+ w.u16(STANDARD_ALGO_NUMBER_ML_DSA_65);
205
+ w.bytes(raw);
206
+ }
207
+
208
+ // src/crypto/ml-dsa.ts
209
+ var ML_DSA_65_SEED_LEN = 32;
210
+ var ML_DSA_65_SIGNING_KEY_LEN = 4032;
211
+ var ML_DSA_65_PUBLIC_KEY_LEN = 1952;
212
+ var ML_DSA_65_SIGNATURE_LEN = 3309;
213
+ var STANDARD_ALGO_NUMBER_ML_DSA_65 = 1001;
214
+ var ENUM_VARIANT_INDEX_ML_DSA_65 = 5;
215
+ var MlDsa65Backend = class _MlDsa65Backend {
216
+ #secretKey;
217
+ #publicKey;
218
+ #addressBytes;
219
+ constructor(secretKey, publicKey) {
220
+ this.#secretKey = expectBytes(secretKey, ML_DSA_65_SIGNING_KEY_LEN, "ML-DSA-65 secret key").slice();
221
+ this.#publicKey = expectBytes(publicKey, ML_DSA_65_PUBLIC_KEY_LEN, "ML-DSA-65 public key").slice();
222
+ this.#addressBytes = sha3_js.keccak_256(this.#publicKey).slice(12);
223
+ }
224
+ static fromSeed(seed) {
225
+ const kp = mlDsa_js.ml_dsa65.keygen(expectBytes(seed, ML_DSA_65_SEED_LEN, "ML-DSA-65 seed"));
226
+ return new _MlDsa65Backend(kp.secretKey, kp.publicKey);
227
+ }
228
+ publicKey() {
229
+ return this.#publicKey.slice();
230
+ }
231
+ addressBytes() {
232
+ return this.#addressBytes.slice();
233
+ }
234
+ getAddress() {
235
+ return bytesToHex(this.#addressBytes);
236
+ }
237
+ sign(message) {
238
+ return mlDsa_js.ml_dsa65.sign(message, this.#secretKey, { extraEntropy: false });
239
+ }
240
+ signPrehash(digest) {
241
+ return this.sign(expectBytes(digest, 32, "prehash"));
242
+ }
243
+ verify(message, signature) {
244
+ return mlDsa_js.ml_dsa65.verify(
245
+ expectBytes(signature, ML_DSA_65_SIGNATURE_LEN, "ML-DSA-65 signature"),
246
+ message,
247
+ this.#publicKey
248
+ );
249
+ }
250
+ signEvmTx(fields) {
251
+ const txHashPreimage = encodeTransactionForHash(fields, 1);
252
+ const sighash = sha3_js.keccak_256(txHashPreimage);
253
+ const signature = this.sign(sighash);
254
+ const wireBytes = bincodeSignedTransaction(fields, signature, this.#publicKey);
255
+ const txHash = sha3_js.keccak_256(
256
+ concatBytes(
257
+ encodeTransactionForHash(fields, 2),
258
+ signature,
259
+ this.#publicKey
260
+ )
261
+ );
262
+ return {
263
+ wireHex: bytesToHex(wireBytes).slice(2),
264
+ wireBytes,
265
+ sighash,
266
+ txHash
267
+ };
268
+ }
269
+ };
270
+ function mlDsa65AddressFromPublicKey(publicKey) {
271
+ return bytesToHex(sha3_js.keccak_256(expectBytes(publicKey, ML_DSA_65_PUBLIC_KEY_LEN, "ML-DSA-65 public key")).slice(12));
272
+ }
273
+ function encodeMlDsa65Opaque(raw) {
274
+ const bytes = raw instanceof Uint8Array ? raw : Uint8Array.from(raw);
275
+ const len = bytes.length === ML_DSA_65_PUBLIC_KEY_LEN ? ML_DSA_65_PUBLIC_KEY_LEN : ML_DSA_65_SIGNATURE_LEN;
276
+ expectBytes(bytes, len, "ML-DSA-65 opaque bytes");
277
+ const out = new Uint8Array(4 + 2 + 8 + bytes.length);
278
+ const dv = new DataView(out.buffer);
279
+ dv.setUint32(0, ENUM_VARIANT_INDEX_ML_DSA_65, true);
280
+ dv.setUint16(4, STANDARD_ALGO_NUMBER_ML_DSA_65, true);
281
+ dv.setBigUint64(6, BigInt(bytes.length), true);
282
+ out.set(bytes, 14);
283
+ return out;
284
+ }
285
+ var PQM1_ALGO_TAG_MLDSA65 = 1;
286
+ var PQM1_ALGO_TAG_MLDSA87_RESERVED = 2;
287
+ var PQM1_ALGO_TAG_SLHDSA128S_RESERVED = 3;
288
+ var PQM1_ALGO_TAG_FALCON512_RESERVED = 4;
289
+ var PQM1_VERSION_V1 = 1;
290
+ var PQM1_PAYLOAD_LEN = 32;
291
+ var PQM1_ENTROPY_LEN = 30;
292
+ var PQM1_V1_MNEMONIC_WORDS = 24;
293
+ var PQM1_V1_MLDSA65_DOMAIN_TAG = "monolythium.pqm1.v1.mldsa65";
294
+ var Pqm1Error = class extends Error {
295
+ constructor(kind, message) {
296
+ super(message);
297
+ this.kind = kind;
298
+ this.name = "Pqm1Error";
299
+ }
300
+ kind;
301
+ };
302
+ var DOMAIN_BYTES = new TextEncoder().encode(PQM1_V1_MLDSA65_DOMAIN_TAG);
303
+ function normalizeMnemonic(mnemonic) {
304
+ return mnemonic.trim().toLowerCase().replace(/\s+/g, " ");
305
+ }
306
+ function ensureSupportedPayload(bytes) {
307
+ if (bytes.length !== PQM1_PAYLOAD_LEN) {
308
+ throw new Pqm1Error("badPayloadLength", `PQM-1 payload must be ${PQM1_PAYLOAD_LEN} bytes, got ${bytes.length}`);
309
+ }
310
+ if (bytes[0] !== PQM1_ALGO_TAG_MLDSA65) {
311
+ throw new Pqm1Error("unsupportedAlgorithm", `unsupported PQM-1 algorithm tag 0x${bytes[0].toString(16).padStart(2, "0")}`);
312
+ }
313
+ if (bytes[1] !== PQM1_VERSION_V1) {
314
+ throw new Pqm1Error("unsupportedVersion", `unsupported PQM-1 version 0x${bytes[1].toString(16).padStart(2, "0")}`);
315
+ }
316
+ }
317
+ function defaultRandomFill(bytes) {
318
+ const cryptoObj = globalThis.crypto;
319
+ if (!cryptoObj?.getRandomValues) {
320
+ throw new Pqm1Error("missingRandom", "globalThis.crypto.getRandomValues is unavailable");
321
+ }
322
+ cryptoObj.getRandomValues(bytes);
323
+ }
324
+ function assemblePqm1Payload(entropy) {
325
+ const ent = expectBytes(entropy, PQM1_ENTROPY_LEN, "PQM-1 entropy");
326
+ const payload = new Uint8Array(PQM1_PAYLOAD_LEN);
327
+ payload[0] = PQM1_ALGO_TAG_MLDSA65;
328
+ payload[1] = PQM1_VERSION_V1;
329
+ payload.set(ent, 2);
330
+ return payload;
331
+ }
332
+ function parsePqm1Payload(payload) {
333
+ const bytes = expectBytes(payload, PQM1_PAYLOAD_LEN, "PQM-1 payload").slice();
334
+ ensureSupportedPayload(bytes);
335
+ return {
336
+ algoTag: PQM1_ALGO_TAG_MLDSA65,
337
+ version: PQM1_VERSION_V1,
338
+ entropy: bytes.slice(2),
339
+ bytes
340
+ };
341
+ }
342
+ function pqm1PayloadToMnemonic(payload) {
343
+ const parsed = parsePqm1Payload(payload);
344
+ return bip39.entropyToMnemonic(parsed.bytes, english_js.wordlist);
345
+ }
346
+ function pqm1MnemonicToPayload(mnemonic) {
347
+ const normalized = normalizeMnemonic(mnemonic);
348
+ const words = normalized.length === 0 ? [] : normalized.split(" ");
349
+ if (words.length !== PQM1_V1_MNEMONIC_WORDS) {
350
+ throw new Pqm1Error("badWordCount", `PQM-1 mnemonic must be ${PQM1_V1_MNEMONIC_WORDS} words, got ${words.length}`);
351
+ }
352
+ let payload;
353
+ try {
354
+ payload = bip39.mnemonicToEntropy(normalized, english_js.wordlist);
355
+ } catch (e) {
356
+ throw new Pqm1Error("bip39Decode", `invalid PQM-1 mnemonic: ${e.message}`);
357
+ }
358
+ return parsePqm1Payload(payload);
359
+ }
360
+ function derivePqm1MlDsa65SeedFromPayload(payload) {
361
+ const parsed = parsePqm1Payload(payload);
362
+ return sha3_js.shake256(concatBytes(DOMAIN_BYTES, parsed.bytes), { dkLen: ML_DSA_65_SEED_LEN });
363
+ }
364
+ function pqm1MnemonicToMlDsa65Seed(mnemonic) {
365
+ return derivePqm1MlDsa65SeedFromPayload(pqm1MnemonicToPayload(mnemonic).bytes);
366
+ }
367
+ function pqm1MnemonicToMlDsa65Backend(mnemonic) {
368
+ return MlDsa65Backend.fromSeed(pqm1MnemonicToMlDsa65Seed(mnemonic));
369
+ }
370
+ function pqm1MnemonicToAddress(mnemonic) {
371
+ return pqm1MnemonicToMlDsa65Backend(mnemonic).getAddress();
372
+ }
373
+ function generatePqm1Mnemonic(rng = defaultRandomFill) {
374
+ const entropy = new Uint8Array(PQM1_ENTROPY_LEN);
375
+ rng(entropy);
376
+ return pqm1PayloadToMnemonic(assemblePqm1Payload(entropy));
377
+ }
378
+ var DKG_AEAD_DOMAIN_TAG = new TextEncoder().encode("protocore/v2/mempool/dkg-mlkem768/1");
379
+ var ML_KEM_768_CIPHERTEXT_LEN = 1088;
380
+ var ML_KEM_768_ENCAPSULATION_KEY_LEN = 1184;
381
+ var ML_KEM_768_SHARED_SECRET_LEN = 32;
382
+ var DKG_NONCE_LEN = 12;
383
+ var DKG_AEAD_TAG_LEN = 16;
384
+ var MempoolClass = {
385
+ Transfer: 0,
386
+ ContractCall: 1,
387
+ PrivacyOp: 2,
388
+ CLOBOp: 3,
389
+ AgentOp: 4,
390
+ GovernanceOp: 5,
391
+ RWAOp: 6
392
+ };
393
+ function bincodeNonceAad(aad) {
394
+ const w = new BincodeWriter();
395
+ w.bytes(expectBytes(aad.sender, 20, "NonceAad.sender"));
396
+ w.u64(aad.nonce);
397
+ w.u64(aad.chainId);
398
+ w.enumVariant(aad.class);
399
+ w.u128(aad.maxFeePerGas);
400
+ w.u128(aad.maxPriorityFeePerGas);
401
+ w.u64(aad.gasLimit);
402
+ return w.toBytes();
403
+ }
404
+ function bincodeDecryptHint(hint) {
405
+ const w = new BincodeWriter();
406
+ w.u64(hint.epoch);
407
+ w.u16(hint.scheme);
408
+ return w.toBytes();
409
+ }
410
+ function bincodeEncryptedEnvelope(env) {
411
+ const w = new BincodeWriter();
412
+ w.rawBytes(bincodeNonceAad(env.nonceAad));
413
+ w.bytes(env.ciphertext);
414
+ w.rawBytes(bincodeDecryptHint(env.decryptionHint));
415
+ bincodeMlDsa65OpaqueInto2(w, expectBytes(env.senderPubkey, ML_DSA_65_PUBLIC_KEY_LEN, "senderPubkey"));
416
+ bincodeMlDsa65OpaqueInto2(w, expectBytes(env.outerSignature, ML_DSA_65_SIGNATURE_LEN, "outerSignature"));
417
+ w.bytes(expectBytes(env.sender, 20, "sender"));
418
+ return w.toBytes();
419
+ }
420
+ function encryptInnerTx(signedInnerTxBincode, nonceAad, kemEncapsulationKey) {
421
+ expectBytes(kemEncapsulationKey, ML_KEM_768_ENCAPSULATION_KEY_LEN, "kemEncapsulationKey");
422
+ const { cipherText: kemCt, sharedSecret } = mlKem_js.ml_kem768.encapsulate(kemEncapsulationKey);
423
+ const nonce = utils_js.randomBytes(DKG_NONCE_LEN);
424
+ const cipher = chacha_js.chacha20poly1305(sharedSecret, nonce, aadFor(nonceAad));
425
+ const aeadCt = cipher.encrypt(signedInnerTxBincode);
426
+ sharedSecret.fill(0);
427
+ return concatBytes(kemCt, nonce, aeadCt);
428
+ }
429
+ function outerSigDigest(nonceAad, ciphertext, decryptionHint, senderPubkey) {
430
+ const aad = bincodeNonceAad(nonceAad);
431
+ const hint = bincodeDecryptHint(decryptionHint);
432
+ return sha3_js.keccak_256(concatBytes(aad, ciphertext, hint, expectBytes(senderPubkey, ML_DSA_65_PUBLIC_KEY_LEN, "senderPubkey")));
433
+ }
434
+ async function buildEncryptedEnvelope(args) {
435
+ const ciphertext = encryptInnerTx(args.signedInnerTxBincode, args.nonceAad, args.kemEncapsulationKey);
436
+ const digest = outerSigDigest(args.nonceAad, ciphertext, args.decryptionHint, args.senderPubkey);
437
+ const outerSignature = await args.signOuterDigest(digest);
438
+ const envelope = {
439
+ nonceAad: args.nonceAad,
440
+ ciphertext,
441
+ decryptionHint: args.decryptionHint,
442
+ senderPubkey: expectBytes(args.senderPubkey, ML_DSA_65_PUBLIC_KEY_LEN, "senderPubkey"),
443
+ outerSignature: expectBytes(outerSignature, ML_DSA_65_SIGNATURE_LEN, "outerSignature"),
444
+ sender: expectBytes(args.senderAddress, 20, "senderAddress")
445
+ };
446
+ const wireBytes = bincodeEncryptedEnvelope(envelope);
447
+ return { envelope, wireBytes, wireHex: bytesToHex(wireBytes) };
448
+ }
449
+ function aadFor(aad) {
450
+ return concatBytes(DKG_AEAD_DOMAIN_TAG, bincodeNonceAad(aad));
451
+ }
452
+ function bincodeMlDsa65OpaqueInto2(w, raw) {
453
+ w.enumVariant(ENUM_VARIANT_INDEX_ML_DSA_65);
454
+ w.u16(STANDARD_ALGO_NUMBER_ML_DSA_65);
455
+ w.bytes(raw);
456
+ }
457
+
458
+ // src/address.ts
459
+ var CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
460
+ new Map([...CHARSET].map((c, i) => [c, i]));
461
+ var HEX_20_BYTE_RE = /^0x[0-9a-fA-F]{40}$/;
462
+ var AddressError = class extends Error {
463
+ constructor(message) {
464
+ super(message);
465
+ this.name = "AddressError";
466
+ }
467
+ };
468
+ function hexToAddressBytes(address) {
469
+ if (!HEX_20_BYTE_RE.test(address)) {
470
+ throw new AddressError("expected 0x-prefixed 20-byte hex address");
471
+ }
472
+ const out = new Uint8Array(20);
473
+ const body = address.slice(2);
474
+ for (let i = 0; i < 20; i++) {
475
+ out[i] = Number.parseInt(body.slice(i * 2, i * 2 + 2), 16);
476
+ }
477
+ return out;
478
+ }
479
+
480
+ // src/crypto/submission.ts
481
+ async function fetchEncryptionKey(client) {
482
+ const result = await client.call(
483
+ "lyth_getEncryptionKey",
484
+ []
485
+ );
486
+ return {
487
+ algo: result.algo ?? "ml-kem-768",
488
+ epoch: typeof result.epoch === "string" ? BigInt(result.epoch) : BigInt(result.epoch),
489
+ encapsulationKey: hexToBytes(result.encapsulationKey, "encapsulationKey")
490
+ };
491
+ }
492
+ async function buildEncryptedSubmission(args) {
493
+ const signed = args.backend.signEvmTx(args.tx);
494
+ const input = normalizeInput(args.tx.input);
495
+ const to = normalizeTo2(args.tx.to);
496
+ const nonceAad = {
497
+ sender: args.backend.addressBytes(),
498
+ nonce: parseBigint(args.tx.nonce, "nonce"),
499
+ chainId: parseBigint(args.tx.chainId, "chainId"),
500
+ class: args.class ?? (to !== null && input.length === 0 ? MempoolClass.Transfer : MempoolClass.ContractCall),
501
+ maxFeePerGas: u128Saturate(parseBigint(args.tx.maxFeePerGas, "maxFeePerGas")),
502
+ maxPriorityFeePerGas: u128Saturate(parseBigint(args.tx.maxPriorityFeePerGas, "maxPriorityFeePerGas")),
503
+ gasLimit: parseBigint(args.tx.gasLimit, "gasLimit")
504
+ };
505
+ const decryptionHint = { epoch: args.encryptionKey.epoch, scheme: 0 };
506
+ const built = await buildEncryptedEnvelope({
507
+ signedInnerTxBincode: signed.wireBytes,
508
+ nonceAad,
509
+ decryptionHint,
510
+ kemEncapsulationKey: args.encryptionKey.encapsulationKey,
511
+ senderAddress: args.backend.addressBytes(),
512
+ senderPubkey: args.backend.publicKey(),
513
+ signOuterDigest: (digest) => args.backend.signPrehash(digest)
514
+ });
515
+ return {
516
+ envelopeWireHex: built.wireHex,
517
+ innerSighashHex: `0x${[...signed.sighash].map((b) => b.toString(16).padStart(2, "0")).join("")}`,
518
+ innerWireBytes: signed.wireBytes.length
519
+ };
520
+ }
521
+ async function submitEncryptedEnvelope(client, envelopeWireHex) {
522
+ return client.call("lyth_submitEncrypted", [envelopeWireHex]);
523
+ }
524
+ function u128Saturate(value) {
525
+ const cap = (1n << 128n) - 1n;
526
+ if (value < 0n) return 0n;
527
+ return value > cap ? cap : value;
528
+ }
529
+ function normalizeTo2(value) {
530
+ if (value === null) return null;
531
+ if (typeof value === "string") return hexToAddressBytes(value);
532
+ const bytes = value instanceof Uint8Array ? value : Uint8Array.from(value);
533
+ if (bytes.length !== 20) throw new Error("to must be 20 bytes");
534
+ return bytes;
535
+ }
536
+ function normalizeInput(value) {
537
+ if (value === void 0) return new Uint8Array(0);
538
+ if (typeof value === "string") return hexToBytes(value, "input");
539
+ return value instanceof Uint8Array ? value : Uint8Array.from(value);
540
+ }
541
+
542
+ exports.BincodeWriter = BincodeWriter;
543
+ exports.DKG_AEAD_TAG_LEN = DKG_AEAD_TAG_LEN;
544
+ exports.DKG_NONCE_LEN = DKG_NONCE_LEN;
545
+ exports.ENUM_VARIANT_INDEX_ML_DSA_65 = ENUM_VARIANT_INDEX_ML_DSA_65;
546
+ exports.ML_DSA_65_PUBLIC_KEY_LEN = ML_DSA_65_PUBLIC_KEY_LEN;
547
+ exports.ML_DSA_65_SEED_LEN = ML_DSA_65_SEED_LEN;
548
+ exports.ML_DSA_65_SIGNATURE_LEN = ML_DSA_65_SIGNATURE_LEN;
549
+ exports.ML_DSA_65_SIGNING_KEY_LEN = ML_DSA_65_SIGNING_KEY_LEN;
550
+ exports.ML_KEM_768_CIPHERTEXT_LEN = ML_KEM_768_CIPHERTEXT_LEN;
551
+ exports.ML_KEM_768_ENCAPSULATION_KEY_LEN = ML_KEM_768_ENCAPSULATION_KEY_LEN;
552
+ exports.ML_KEM_768_SHARED_SECRET_LEN = ML_KEM_768_SHARED_SECRET_LEN;
553
+ exports.MempoolClass = MempoolClass;
554
+ exports.MlDsa65Backend = MlDsa65Backend;
555
+ exports.PQM1_ALGO_TAG_FALCON512_RESERVED = PQM1_ALGO_TAG_FALCON512_RESERVED;
556
+ exports.PQM1_ALGO_TAG_MLDSA65 = PQM1_ALGO_TAG_MLDSA65;
557
+ exports.PQM1_ALGO_TAG_MLDSA87_RESERVED = PQM1_ALGO_TAG_MLDSA87_RESERVED;
558
+ exports.PQM1_ALGO_TAG_SLHDSA128S_RESERVED = PQM1_ALGO_TAG_SLHDSA128S_RESERVED;
559
+ exports.PQM1_ENTROPY_LEN = PQM1_ENTROPY_LEN;
560
+ exports.PQM1_PAYLOAD_LEN = PQM1_PAYLOAD_LEN;
561
+ exports.PQM1_V1_MLDSA65_DOMAIN_TAG = PQM1_V1_MLDSA65_DOMAIN_TAG;
562
+ exports.PQM1_V1_MNEMONIC_WORDS = PQM1_V1_MNEMONIC_WORDS;
563
+ exports.PQM1_VERSION_V1 = PQM1_VERSION_V1;
564
+ exports.Pqm1Error = Pqm1Error;
565
+ exports.STANDARD_ALGO_NUMBER_ML_DSA_65 = STANDARD_ALGO_NUMBER_ML_DSA_65;
566
+ exports.assemblePqm1Payload = assemblePqm1Payload;
567
+ exports.bincodeDecryptHint = bincodeDecryptHint;
568
+ exports.bincodeEncryptedEnvelope = bincodeEncryptedEnvelope;
569
+ exports.bincodeNonceAad = bincodeNonceAad;
570
+ exports.bincodeSignedTransaction = bincodeSignedTransaction;
571
+ exports.buildEncryptedEnvelope = buildEncryptedEnvelope;
572
+ exports.buildEncryptedSubmission = buildEncryptedSubmission;
573
+ exports.bytesToHex = bytesToHex;
574
+ exports.concatBytes = concatBytes;
575
+ exports.derivePqm1MlDsa65SeedFromPayload = derivePqm1MlDsa65SeedFromPayload;
576
+ exports.encodeMlDsa65Opaque = encodeMlDsa65Opaque;
577
+ exports.encodeTransactionForHash = encodeTransactionForHash;
578
+ exports.encryptInnerTx = encryptInnerTx;
579
+ exports.expectBytes = expectBytes;
580
+ exports.fetchEncryptionKey = fetchEncryptionKey;
581
+ exports.generatePqm1Mnemonic = generatePqm1Mnemonic;
582
+ exports.hexToBytes = hexToBytes;
583
+ exports.mlDsa65AddressFromPublicKey = mlDsa65AddressFromPublicKey;
584
+ exports.outerSigDigest = outerSigDigest;
585
+ exports.parsePqm1Payload = parsePqm1Payload;
586
+ exports.pqm1MnemonicToAddress = pqm1MnemonicToAddress;
587
+ exports.pqm1MnemonicToMlDsa65Backend = pqm1MnemonicToMlDsa65Backend;
588
+ exports.pqm1MnemonicToMlDsa65Seed = pqm1MnemonicToMlDsa65Seed;
589
+ exports.pqm1MnemonicToPayload = pqm1MnemonicToPayload;
590
+ exports.pqm1PayloadToMnemonic = pqm1PayloadToMnemonic;
591
+ exports.submitEncryptedEnvelope = submitEncryptedEnvelope;
592
+ //# sourceMappingURL=index.cjs.map
593
+ //# sourceMappingURL=index.cjs.map