@orbinum/sdk 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -20,29 +20,40 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ AccountId: () => import_substrate_bindings3.AccountId,
23
24
  AccountMappingModule: () => AccountMappingModule,
24
25
  AccountMappingPrecompile: () => AccountMappingPrecompile,
25
- ChainModule: () => ChainModule,
26
+ Blake2256: () => import_substrate_bindings3.Blake2256,
27
+ CircuitId: () => CircuitId,
26
28
  CryptoPrecompiles: () => CryptoPrecompiles,
27
29
  EncryptedMemo: () => EncryptedMemo,
28
30
  EvmClient: () => EvmClient,
31
+ EvmExplorer: () => EvmExplorer,
32
+ IndexerClient: () => IndexerClient,
29
33
  KNOWN_PRECOMPILES: () => KNOWN_PRECOMPILES,
30
- MerkleModule: () => MerkleModule,
34
+ Keccak256: () => import_substrate_bindings3.Keccak256,
31
35
  NoteBuilder: () => NoteBuilder,
32
36
  OrbinumClient: () => OrbinumClient,
37
+ OrbinumClientProvider: () => OrbinumClientProvider,
33
38
  PRECOMPILE_ADDR: () => PRECOMPILE_ADDR,
34
39
  PrivacyKeyManager: () => PrivacyKeyManager,
40
+ PrivacyModule: () => PrivacyModule,
35
41
  SLIP0044_NAMESPACE: () => SLIP0044_NAMESPACE,
36
42
  ShieldedPoolModule: () => ShieldedPoolModule,
37
43
  ShieldedPoolPrecompile: () => ShieldedPoolPrecompile,
44
+ SignatureScheme: () => SignatureScheme,
45
+ Storage: () => import_substrate_bindings3.Storage,
38
46
  SubstrateClient: () => SubstrateClient,
47
+ ZkVerifierModule: () => ZkVerifierModule,
39
48
  accountIdHexToSs58: () => accountIdHexToSs58,
40
49
  addressToAccountIdHex: () => addressToAccountIdHex,
50
+ base58: () => import_base.base58,
41
51
  bigintTo32Be: () => bigintTo32Be,
42
52
  bigintTo32Le: () => bigintTo32Le,
43
53
  bigintTo32LeArr: () => bigintTo32LeArr,
44
54
  bytesToBigintLE: () => bytesToBigintLE,
45
55
  computePathIndices: () => computePathIndices,
56
+ decodePrecompileCalldata: () => decodePrecompileCalldata,
46
57
  decryptJson: () => decryptJson,
47
58
  deriveOwnerPk: () => deriveOwnerPk,
48
59
  deriveSpendingKeyFromSignature: () => deriveSpendingKeyFromSignature,
@@ -53,11 +64,18 @@ __export(index_exports, {
53
64
  ensureHexPrefix: () => ensureHexPrefix,
54
65
  evmAddressToAccountId: () => evmAddressToAccountId,
55
66
  evmToImplicitSubstrate: () => evmToImplicitSubstrate,
67
+ evmToMappedAccountHex: () => evmToMappedAccountHex,
56
68
  evmToSubstrate: () => evmToSubstrate,
69
+ formatBalance: () => formatBalance,
70
+ formatORB: () => formatORB,
71
+ fromBase64: () => fromBase64,
57
72
  fromHex: () => fromHex,
58
73
  getPolkadotSigner: () => import_signer.getPolkadotSigner,
59
74
  getPolkadotSignerFromPjs: () => import_pjs_signer.getPolkadotSignerFromPjs,
60
75
  getPrecompileLabel: () => getPrecompileLabel,
76
+ getSs58AddressInfo: () => import_polkadot_api4.getSs58AddressInfo,
77
+ hexToBigint: () => hexToBigint,
78
+ hexToNumber: () => hexToNumber,
61
79
  implicitSubstrateToEvm: () => implicitSubstrateToEvm,
62
80
  isEvmAddress: () => isEvmAddress,
63
81
  isImplicitEvmAccount: () => isImplicitEvmAccount,
@@ -65,11 +83,19 @@ __export(index_exports, {
65
83
  isSubstrateAddress: () => isSubstrateAddress,
66
84
  isUnifiedAddress: () => isUnifiedAddress,
67
85
  leHexToBigint: () => leHexToBigint,
86
+ mapExtrinsicArgs: () => mapExtrinsicArgs,
87
+ mapZkEventData: () => mapZkEventData,
68
88
  normalizeEvmAddress: () => normalizeEvmAddress,
89
+ shortHash: () => shortHash,
69
90
  substrateSs58ToAccountIdHex: () => substrateSs58ToAccountIdHex,
70
91
  substrateToEvm: () => substrateToEvm,
92
+ toBase64: () => toBase64,
71
93
  toHex: () => toHex,
94
+ toTxResult: () => toTxResult,
95
+ truncateMiddle: () => truncateMiddle,
72
96
  tryDecryptNote: () => tryDecryptNote,
97
+ u128: () => import_substrate_bindings3.u128,
98
+ u64: () => import_substrate_bindings3.u64,
73
99
  vaultReplacer: () => vaultReplacer,
74
100
  vaultReviver: () => vaultReviver
75
101
  });
@@ -78,10 +104,45 @@ module.exports = __toCommonJS(index_exports);
78
104
  // src/substrate/SubstrateClient.ts
79
105
  var import_polkadot_api = require("polkadot-api");
80
106
  var import_ws_provider = require("polkadot-api/ws-provider");
107
+ var import_metadata_builders = require("@polkadot-api/metadata-builders");
108
+ var import_substrate_bindings = require("@polkadot-api/substrate-bindings");
109
+ var import_substrate_bindings2 = require("@polkadot-api/substrate-bindings");
110
+ var import_tx_utils = require("@polkadot-api/tx-utils");
111
+
112
+ // src/utils/hex.ts
113
+ function toHex(bytes) {
114
+ return "0x" + Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
115
+ }
116
+ function fromHex(hex) {
117
+ const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
118
+ if (clean.length % 2 !== 0) {
119
+ throw new Error(`Invalid hex string \u2014 odd length: "${hex}"`);
120
+ }
121
+ const bytes = new Uint8Array(clean.length / 2);
122
+ for (let i = 0; i < bytes.length; i++) {
123
+ const byte = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
124
+ if (isNaN(byte)) throw new Error(`Invalid hex character at position ${i * 2}`);
125
+ bytes[i] = byte;
126
+ }
127
+ return bytes;
128
+ }
129
+ function ensureHexPrefix(hex) {
130
+ return hex.startsWith("0x") ? hex : `0x${hex}`;
131
+ }
132
+ function hexToNumber(hex) {
133
+ return parseInt(hex, 16);
134
+ }
135
+ function hexToBigint(hex) {
136
+ return BigInt(hex);
137
+ }
138
+
139
+ // src/substrate/SubstrateClient.ts
81
140
  var SubstrateClient = class _SubstrateClient {
82
141
  constructor(_papi) {
83
142
  this._papi = _papi;
84
143
  }
144
+ _dynamicBuilder = null;
145
+ _extDecoder = null;
85
146
  /**
86
147
  * Connects to the Orbinum node via WebSocket.
87
148
  * Throws if the node does not respond within `timeoutMs`.
@@ -107,13 +168,145 @@ var SubstrateClient = class _SubstrateClient {
107
168
  async request(method, params = []) {
108
169
  return this._papi._request(method, params);
109
170
  }
171
+ /**
172
+ * Returns basic chain information from the node.
173
+ * Combines `system_name`, `system_chain`, `system_properties`, and `state_getRuntimeVersion`.
174
+ */
175
+ async getChainInfo() {
176
+ const [chainName, version, props] = await Promise.all([
177
+ this.request("system_chain", []),
178
+ this.request("state_getRuntimeVersion", []),
179
+ this.request(
180
+ "system_properties",
181
+ []
182
+ )
183
+ ]);
184
+ const rawSymbol = props.tokenSymbol;
185
+ const rawDecimals = props.tokenDecimals;
186
+ return {
187
+ name: chainName,
188
+ version: String(version.specVersion),
189
+ ss58Prefix: version.ss58Prefix ?? 42,
190
+ symbol: Array.isArray(rawSymbol) ? rawSymbol[0] ?? "ORB" : rawSymbol ?? "ORB",
191
+ decimals: Array.isArray(rawDecimals) ? rawDecimals[0] ?? 18 : rawDecimals ?? 18
192
+ };
193
+ }
194
+ /**
195
+ * Returns the node's peer count and sync status.
196
+ */
197
+ async getHealth() {
198
+ return this.request("system_health", []);
199
+ }
200
+ /**
201
+ * Returns the node's software version string.
202
+ */
203
+ async getNodeVersion() {
204
+ return this.request("system_version", []);
205
+ }
206
+ /**
207
+ * Returns the genesis hash hex.
208
+ */
209
+ async getGenesisHash() {
210
+ return this.request("chain_getBlockHash", [0]);
211
+ }
212
+ /**
213
+ * Returns the block hash for a given block number.
214
+ * Returns null when the block does not exist or has been pruned.
215
+ */
216
+ async getBlockHash(blockNumber) {
217
+ const hash = await this.request("chain_getBlockHash", [blockNumber]);
218
+ if (!hash || /^0x0+$/.test(hash) || hash === "0x" + "00".repeat(32)) return null;
219
+ return hash;
220
+ }
221
+ /**
222
+ * Fetches a block by hash or number, enriched with timestamp and block author.
223
+ *
224
+ * Uses `chain_getBlock` (works for all non-pruned blocks, unlike PAPI chainHead
225
+ * which only pins recent blocks). Timestamp is read from `Timestamp.Now` storage
226
+ * with a fallback via the `timestamp.set` extrinsic argument. Author is decoded
227
+ * from PreRuntime digest logs using the chain's SS58 prefix.
228
+ *
229
+ * @param hashOrNumber - A `0x`-prefixed block hash or a block number (number or decimal string).
230
+ * @returns `BlockInfo` or `null` if the block is not found.
231
+ */
232
+ async getBlock(hashOrNumber) {
233
+ try {
234
+ let blockHash;
235
+ if (typeof hashOrNumber === "number" || /^\d+$/.test(String(hashOrNumber))) {
236
+ const num = typeof hashOrNumber === "number" ? hashOrNumber : parseInt(hashOrNumber, 10);
237
+ const h = await this.getBlockHash(num);
238
+ if (!h) return null;
239
+ blockHash = h;
240
+ } else {
241
+ blockHash = hashOrNumber;
242
+ }
243
+ const raw = await this.request("chain_getBlock", [blockHash]);
244
+ if (!raw?.block) return null;
245
+ const { header, extrinsics } = raw.block;
246
+ const builder = await this.getDynamicBuilder().catch(() => null);
247
+ const ss58Prefix = builder?.ss58Prefix ?? 42;
248
+ let timestampMs = null;
249
+ if (builder) {
250
+ try {
251
+ const tsStore = builder.buildStorage("Timestamp", "Now");
252
+ const tsRaw = await this.request("state_getStorage", [
253
+ tsStore.keys.enc(),
254
+ blockHash
255
+ ]);
256
+ if (tsRaw) {
257
+ timestampMs = Number(tsStore.value.dec(fromHex(tsRaw)));
258
+ }
259
+ } catch {
260
+ }
261
+ }
262
+ if (!timestampMs) {
263
+ const tsHex = extrinsics.find((hex) => {
264
+ try {
265
+ const b = fromHex(hex);
266
+ return b.length > 6 && b[4] === 3 && b[5] === 0;
267
+ } catch {
268
+ return false;
269
+ }
270
+ });
271
+ if (tsHex) {
272
+ try {
273
+ const b = fromHex(tsHex);
274
+ const view = new DataView(b.buffer, b.byteOffset + 6, 8);
275
+ const lo = view.getUint32(0, true);
276
+ const hi = view.getUint32(4, true);
277
+ const ms = lo + hi * 4294967296;
278
+ if (ms > 0) timestampMs = ms;
279
+ } catch {
280
+ }
281
+ }
282
+ }
283
+ const author = _SubstrateClient.extractAuthorFromLogs(header.digest.logs, ss58Prefix);
284
+ return { header, extrinsics, timestampMs, author };
285
+ } catch {
286
+ return null;
287
+ }
288
+ }
110
289
  /**
111
290
  * Returns the underlying PolkadotClient instance.
112
- * Use for block subscriptions (`blocks$`), raw metadata access, and advanced SCALE operations.
291
+ * Use for raw metadata access and advanced SCALE operations.
113
292
  */
114
293
  get polkadotClient() {
115
294
  return this._papi;
116
295
  }
296
+ /**
297
+ * Observable that emits a new entry each time a best-block is reported by the node.
298
+ * Delegates to PAPI's `blocks$`.
299
+ */
300
+ get blocks$() {
301
+ return this._papi.blocks$;
302
+ }
303
+ /**
304
+ * Returns the block header for a given tag or block hash.
305
+ * Delegates to PAPI's `getBlockHeader`.
306
+ */
307
+ getBlockHeader(...args) {
308
+ return this._papi.getBlockHeader(...args);
309
+ }
117
310
  /**
118
311
  * Returns the PAPI UnsafeApi for dynamic, metadata-driven transaction building.
119
312
  * The first access triggers a metadata fetch from the node.
@@ -158,34 +351,148 @@ var SubstrateClient = class _SubstrateClient {
158
351
  destroy() {
159
352
  this._papi.destroy();
160
353
  }
161
- };
162
-
163
- // src/utils/hex.ts
164
- function toHex(bytes) {
165
- return "0x" + Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
166
- }
167
- function fromHex(hex) {
168
- const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
169
- if (clean.length % 2 !== 0) {
170
- throw new Error(`Invalid hex string \u2014 odd length: "${hex}"`);
354
+ /**
355
+ * Fetches and decodes all events for a given block hash.
356
+ * Queries `System.Events` storage via SCALE codec built from on-chain metadata.
357
+ *
358
+ * @param blockHash - The `0x`-prefixed block hash string.
359
+ * @returns Array of `EventRecord` or `null` if unavailable.
360
+ */
361
+ async queryBlockEvents(blockHash) {
362
+ try {
363
+ const builder = await this.getDynamicBuilder();
364
+ const { keys, value } = builder.buildStorage("System", "Events");
365
+ const raw = await this.request("state_getStorage", [
366
+ keys.enc(),
367
+ blockHash
368
+ ]);
369
+ if (!raw) return null;
370
+ const decoded = value.dec(fromHex(raw));
371
+ return _SubstrateClient._toEventRecords(decoded);
372
+ } catch {
373
+ return null;
374
+ }
171
375
  }
172
- const bytes = new Uint8Array(clean.length / 2);
173
- for (let i = 0; i < bytes.length; i++) {
174
- const byte = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
175
- if (isNaN(byte)) throw new Error(`Invalid hex character at position ${i * 2}`);
176
- bytes[i] = byte;
376
+ // ─── Internal helpers ─────────────────────────────────────────────────────
377
+ async getDynamicBuilder() {
378
+ if (this._dynamicBuilder) return this._dynamicBuilder;
379
+ const rawMetadata = await this._papi.getMetadata("best");
380
+ const metadata = (0, import_substrate_bindings.decAnyMetadata)(rawMetadata);
381
+ const unified = (0, import_substrate_bindings.unifyMetadata)(metadata);
382
+ const lookup = (0, import_metadata_builders.getLookupFn)(unified);
383
+ this._dynamicBuilder = (0, import_metadata_builders.getDynamicBuilder)(lookup);
384
+ return this._dynamicBuilder;
385
+ }
386
+ async getExtrinsicDecoder() {
387
+ if (this._extDecoder) return this._extDecoder;
388
+ const rawMetadata = await this._papi.getMetadata("best");
389
+ this._extDecoder = (0, import_tx_utils.getExtrinsicDecoder)(rawMetadata);
390
+ return this._extDecoder;
391
+ }
392
+ static _buildDataProxy(value) {
393
+ const formatValue = (v) => {
394
+ if (v instanceof Uint8Array) return fromHex(v).toString();
395
+ if (typeof v === "bigint") return v.toString();
396
+ return String(v);
397
+ };
398
+ const jsonifyValue = (v) => {
399
+ if (v === null || v === void 0) return v;
400
+ if (typeof v === "bigint") return v.toString();
401
+ if (v instanceof Uint8Array)
402
+ return Array.from(v).map((b) => b.toString(16).padStart(2, "0")).join("");
403
+ if (Array.isArray(v)) return v.map(jsonifyValue);
404
+ if (typeof v === "object") {
405
+ return Object.fromEntries(
406
+ Object.entries(v).filter(([, val]) => typeof val !== "function").map(([k, val]) => [k, jsonifyValue(val)])
407
+ );
408
+ }
409
+ return v;
410
+ };
411
+ const entries = Array.isArray(value) ? value : value !== null && typeof value === "object" ? Object.values(value) : [value];
412
+ const items = entries.map((v) => ({
413
+ toString: () => formatValue(v),
414
+ toJSON: () => jsonifyValue(v),
415
+ toHuman: () => jsonifyValue(v),
416
+ ...v !== null && typeof v === "object" ? v : {}
417
+ }));
418
+ return Object.assign(items, {
419
+ toJSON: () => jsonifyValue(value),
420
+ toHuman: () => jsonifyValue(value)
421
+ });
177
422
  }
178
- return bytes;
179
- }
180
- function ensureHexPrefix(hex) {
181
- return hex.startsWith("0x") ? hex : `0x${hex}`;
182
- }
183
- function hexToNumber(hex) {
184
- return parseInt(hex, 16);
185
- }
186
- function hexToBigint(hex) {
187
- return BigInt(hex);
188
- }
423
+ /**
424
+ * Extracts the block author (validator/collator) from raw digest log hex strings.
425
+ * Looks for a PreRuntime log (tag byte = 6) and decodes the first 32 bytes of the
426
+ * SCALE-compact payload as an SS58 address using the given prefix.
427
+ *
428
+ * Can be used standalone with raw logs from `chain_getBlock` responses.
429
+ */
430
+ static extractAuthorFromLogs(logs, ss58Prefix) {
431
+ try {
432
+ for (const hex of logs) {
433
+ const bytes = fromHex(hex);
434
+ if (bytes.length < 6 || bytes[0] !== 6) continue;
435
+ const firstLenByte = bytes[5];
436
+ const mode = firstLenByte & 3;
437
+ let payloadStart;
438
+ let payloadLen;
439
+ if (mode === 0) {
440
+ payloadLen = firstLenByte >> 2;
441
+ payloadStart = 6;
442
+ } else if (mode === 1) {
443
+ if (bytes.length < 7) continue;
444
+ payloadLen = firstLenByte >> 2 | bytes[6] << 6;
445
+ payloadStart = 7;
446
+ } else if (mode === 2) {
447
+ if (bytes.length < 9) continue;
448
+ payloadLen = (firstLenByte >> 2 | bytes[6] << 6 | bytes[7] << 14 | bytes[8] << 22) >>> 0;
449
+ payloadStart = 9;
450
+ } else {
451
+ continue;
452
+ }
453
+ const payload = bytes.slice(payloadStart, payloadStart + payloadLen);
454
+ if (payload.length >= 32) {
455
+ try {
456
+ return (0, import_substrate_bindings2.AccountId)(ss58Prefix).dec(payload.slice(0, 32));
457
+ } catch {
458
+ return toHex(payload.slice(0, 32));
459
+ }
460
+ }
461
+ }
462
+ } catch {
463
+ }
464
+ return null;
465
+ }
466
+ static _toEventRecords(decoded) {
467
+ return decoded.flatMap((e) => {
468
+ try {
469
+ const raw = e;
470
+ const isApply = raw.phase.type === "ApplyExtrinsic";
471
+ const extIdx = isApply ? raw.phase.value : 0;
472
+ const section = raw.event.type.charAt(0).toLowerCase() + raw.event.type.slice(1);
473
+ const method = raw.event.value.type;
474
+ const record = {
475
+ phase: {
476
+ isApplyExtrinsic: isApply,
477
+ asApplyExtrinsic: {
478
+ eq: (n) => n === extIdx,
479
+ toString: () => String(extIdx),
480
+ toNumber: () => extIdx
481
+ }
482
+ },
483
+ event: {
484
+ section,
485
+ method,
486
+ data: _SubstrateClient._buildDataProxy(raw.event.value.value)
487
+ }
488
+ };
489
+ return [record];
490
+ } catch {
491
+ return [];
492
+ }
493
+ });
494
+ }
495
+ };
189
496
 
190
497
  // src/evm/EvmClient.ts
191
498
  var EvmClient = class {
@@ -282,85 +589,590 @@ var EvmClient = class {
282
589
  * Returns a transaction receipt by hash, or null if not yet mined.
283
590
  */
284
591
  async getTransactionReceipt(txHash) {
285
- return this.request("eth_getTransactionReceipt", [txHash]);
592
+ const res = await fetch(this.rpcUrl, {
593
+ method: "POST",
594
+ headers: { "Content-Type": "application/json" },
595
+ body: JSON.stringify({
596
+ id: 1,
597
+ jsonrpc: "2.0",
598
+ method: "eth_getTransactionReceipt",
599
+ params: [txHash]
600
+ })
601
+ });
602
+ if (!res.ok) throw new Error(`EVM HTTP ${res.status}: ${res.statusText}`);
603
+ const json = await res.json();
604
+ if (json.error) {
605
+ throw new Error(`EVM RPC [${json.error.code}]: ${json.error.message}`);
606
+ }
607
+ return json.result ?? null;
286
608
  }
287
609
  };
288
610
 
289
- // src/shielded-pool/MerkleModule.ts
290
- var MerkleModule = class {
291
- constructor(substrate) {
292
- this.substrate = substrate;
611
+ // src/utils/format.ts
612
+ var LOCALE_DECIMAL_SEP = new Intl.NumberFormat(void 0).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
613
+ function formatIntegerLocale(intPart) {
614
+ try {
615
+ return BigInt(intPart || "0").toLocaleString(void 0);
616
+ } catch {
617
+ return (intPart || "0").replace(/\B(?=(\d{3})+(?!\d))/g, ",");
293
618
  }
294
- /**
295
- * Returns the current Merkle tree state: root, number of leaves, and depth.
296
- */
297
- async getTreeInfo() {
298
- const raw = await this.substrate.request(
299
- "shieldedPool_getMerkleTreeInfo",
300
- []
619
+ }
620
+ function normalizeDecimalForDisplay(raw, maxFractionDigits) {
621
+ let value = raw.trim();
622
+ if (!value) return null;
623
+ let sign = "";
624
+ if (value.startsWith("-")) {
625
+ sign = "-";
626
+ value = value.slice(1);
627
+ }
628
+ if (!/^\d*(\.\d*)?$/.test(value)) return null;
629
+ let [integerPart = "0", fractionPart = ""] = value.split(".");
630
+ integerPart = integerPart.replace(/^0+(?=\d)/, "") || "0";
631
+ const limit = Math.max(0, maxFractionDigits);
632
+ fractionPart = fractionPart.slice(0, limit).replace(/0+$/, "");
633
+ const formattedInt = formatIntegerLocale(integerPart);
634
+ return fractionPart ? `${sign}${formattedInt}${LOCALE_DECIMAL_SEP}${fractionPart}` : `${sign}${formattedInt}`;
635
+ }
636
+ function bigintFormatUnits(value, decimals) {
637
+ const negative = value < 0n;
638
+ const abs = negative ? -value : value;
639
+ const divider = 10n ** BigInt(decimals);
640
+ const intPart = abs / divider;
641
+ const fracPart = abs % divider;
642
+ const fracStr = fracPart.toString().padStart(decimals, "0");
643
+ return (negative ? "-" : "") + intPart.toString() + "." + fracStr;
644
+ }
645
+ function isCanonicalDecimal(value) {
646
+ return /^-?(?:\d+\.\d*|\d*\.\d+)$/.test(value);
647
+ }
648
+ function isBigIntLikeInteger(value) {
649
+ return /^-?\d+$/.test(value) || /^0[xX][0-9a-fA-F]+$/.test(value);
650
+ }
651
+ function formatBalance(raw, options = {}) {
652
+ const opts = typeof options === "number" ? { decimals: options } : options;
653
+ const { decimals = 18, symbol = "ORB", showSymbol = true, precision = 6 } = opts;
654
+ const zero = showSymbol ? `0 ${symbol}` : "0";
655
+ if (raw === null || raw === void 0) return zero;
656
+ if (typeof raw === "number" && !Number.isFinite(raw)) return zero;
657
+ const rawStr = String(raw).trim();
658
+ if (!rawStr) return zero;
659
+ if (isCanonicalDecimal(rawStr)) {
660
+ const formatted = normalizeDecimalForDisplay(rawStr, precision);
661
+ if (!formatted || formatted === "0" || formatted === "-0") return zero;
662
+ return showSymbol ? `${formatted} ${symbol}` : formatted;
663
+ }
664
+ if (!isBigIntLikeInteger(rawStr)) return zero;
665
+ try {
666
+ const n = BigInt(rawStr);
667
+ const decimalStr = bigintFormatUnits(n, decimals);
668
+ const formatted = normalizeDecimalForDisplay(decimalStr, precision);
669
+ if (!formatted || formatted === "0" || formatted === "-0") return zero;
670
+ return showSymbol ? `${formatted} ${symbol}` : formatted;
671
+ } catch {
672
+ return zero;
673
+ }
674
+ }
675
+ function formatORB(raw, precision = 6) {
676
+ return formatBalance(raw, { decimals: 18, symbol: "ORB", showSymbol: true, precision });
677
+ }
678
+
679
+ // src/evm-explorer/EvmExplorer.ts
680
+ var EvmExplorer = class _EvmExplorer {
681
+ constructor(evm) {
682
+ this.evm = evm;
683
+ }
684
+ // --- Blocks ---
685
+ async getLatestBlocks(count = 10) {
686
+ const latest = await this.evm.getBlockNumber();
687
+ const nums = Array.from({ length: Math.min(count, latest + 1) }, (_, i) => latest - i);
688
+ const results = await Promise.all(
689
+ nums.map(
690
+ (n) => this.evm.request("eth_getBlockByNumber", [
691
+ `0x${n.toString(16)}`,
692
+ false
693
+ ]).catch(() => null)
694
+ )
695
+ );
696
+ return results.filter((b) => b !== null && !!b.hash).map((b) => this.parseBlock(b));
697
+ }
698
+ async getBlock(hashOrNumber) {
699
+ const b = await this.fetchBlock(hashOrNumber, false);
700
+ return b ? this.parseBlock(b) : null;
701
+ }
702
+ async getBlockTransactions(hashOrNumber) {
703
+ try {
704
+ const b = await this.fetchBlock(hashOrNumber, true);
705
+ if (!b || !b.transactions.length) return [];
706
+ const txs = b.transactions;
707
+ const receipts = await this.evm.batchRequest(txs.map((tx) => ({ method: "eth_getTransactionReceipt", params: [tx.hash] }))).catch(() => txs.map(() => null));
708
+ return txs.map((tx, i) => this.parseTx(tx, receipts[i] ?? null));
709
+ } catch {
710
+ return [];
711
+ }
712
+ }
713
+ // --- Transactions ---
714
+ async getTransaction(hash) {
715
+ try {
716
+ const [tx, receipt] = await Promise.all([
717
+ this.evm.request("eth_getTransactionByHash", [hash]),
718
+ this.evm.request("eth_getTransactionReceipt", [hash]).catch(() => null)
719
+ ]);
720
+ if (!tx) return null;
721
+ return this.parseTx(tx, receipt);
722
+ } catch {
723
+ return null;
724
+ }
725
+ }
726
+ async getTransactionsByAddress(address, maxBlocks = 300) {
727
+ const addr = address.toLowerCase();
728
+ const latest = await this.evm.getBlockNumber();
729
+ const from = Math.max(0, latest - maxBlocks + 1);
730
+ const blockNums = Array.from({ length: latest - from + 1 }, (_, i) => latest - i);
731
+ const blocks = await Promise.all(
732
+ blockNums.map(
733
+ (n) => this.evm.request("eth_getBlockByNumber", [
734
+ `0x${n.toString(16)}`,
735
+ true
736
+ ]).catch(() => null)
737
+ )
301
738
  );
739
+ const matchingTxs = [];
740
+ for (const block of blocks) {
741
+ if (!block?.transactions) continue;
742
+ const blockTimestamp = block.timestamp ? hexToNumber(block.timestamp) : null;
743
+ for (const tx of block.transactions) {
744
+ if (tx.from?.toLowerCase() === addr || tx.to?.toLowerCase() === addr) {
745
+ matchingTxs.push({ tx, timestamp: blockTimestamp });
746
+ }
747
+ }
748
+ }
749
+ if (!matchingTxs.length) return [];
750
+ const receipts = await this.evm.batchRequest(
751
+ matchingTxs.map(({ tx }) => ({
752
+ method: "eth_getTransactionReceipt",
753
+ params: [tx.hash]
754
+ }))
755
+ ).catch(() => matchingTxs.map(() => null));
756
+ const results = matchingTxs.map(({ tx, timestamp }, i) => {
757
+ const receipt = receipts[i] ?? null;
758
+ return {
759
+ hash: tx.hash,
760
+ blockNumber: hexToNumber(tx.blockNumber),
761
+ timestamp,
762
+ from: tx.from,
763
+ to: tx.to,
764
+ value: tx.value ?? "0x0",
765
+ input: tx.input ?? "0x",
766
+ gasUsed: receipt ? hexToNumber(receipt.gasUsed) : hexToNumber(tx.gas),
767
+ gasPrice: tx.gasPrice ?? "0x0",
768
+ status: receipt ? receipt.status === "0x1" : true,
769
+ isContractCreation: !tx.to,
770
+ contractAddress: receipt?.contractAddress ?? null
771
+ };
772
+ });
773
+ results.sort((a, b) => b.blockNumber - a.blockNumber);
774
+ return results;
775
+ }
776
+ // --- Address ---
777
+ async getAddressInfo(address) {
778
+ const latest = await this.evm.getBlockNumber().catch(() => 0);
779
+ const fromBlock = `0x${Math.max(0, latest - 5e3).toString(16)}`;
780
+ const [balance, nonce, code, logs] = await Promise.all([
781
+ this.evm.request("eth_getBalance", [address, "latest"]).catch(() => null),
782
+ this.evm.getTransactionCount(address).catch(() => 0),
783
+ this.evm.request("eth_getCode", [address, "latest"]).catch(() => null),
784
+ this.evm.request("eth_getLogs", [{ fromBlock, toBlock: "latest", address }]).catch(() => [])
785
+ ]);
786
+ const codeHex = code ?? "0x";
787
+ const isContract = codeHex !== "0x" && codeHex.length > 2;
788
+ const codeBytes = isContract ? Math.floor((codeHex.length - 2) / 2) : 0;
789
+ const recentLogs = (logs ?? []).slice(-50).map((l) => ({
790
+ address: l.address,
791
+ topics: l.topics,
792
+ data: l.data,
793
+ blockNumber: hexToNumber(l.blockNumber),
794
+ transactionHash: l.transactionHash,
795
+ logIndex: hexToNumber(l.logIndex)
796
+ }));
302
797
  return {
303
- root: raw.root,
304
- treeSize: raw.tree_size,
305
- depth: raw.depth
798
+ address,
799
+ isContract,
800
+ balance: balance ?? "0x0",
801
+ nonce: typeof nonce === "number" ? nonce : hexToNumber(nonce ?? "0x0"),
802
+ codeSize: codeBytes,
803
+ code: isContract ? codeHex.length > 202 ? `${codeHex.slice(0, 202)}\u2026` : codeHex : "0x",
804
+ recentLogs
306
805
  };
307
806
  }
308
- /**
309
- * Returns the Merkle inclusion proof for a leaf at `leafIndex`.
310
- */
311
- async getProof(leafIndex) {
312
- const raw = await this.substrate.request("shieldedPool_getMerkleProof", [
313
- leafIndex
314
- ]);
807
+ async getBalance(address) {
808
+ try {
809
+ const val = await this.evm.getBalance(address);
810
+ return formatBalance(val, { showSymbol: false, precision: 18 });
811
+ } catch {
812
+ return "0";
813
+ }
814
+ }
815
+ async getNonce(address) {
816
+ try {
817
+ return await this.evm.getTransactionCount(address);
818
+ } catch {
819
+ return 0;
820
+ }
821
+ }
822
+ async getIsContract(address) {
823
+ try {
824
+ const code = await this.evm.request("eth_getCode", [address, "latest"]);
825
+ return code !== "0x" && code !== "0x0" && code.length > 2;
826
+ } catch {
827
+ return false;
828
+ }
829
+ }
830
+ // --- Tokens ---
831
+ async getTokenInfo(address) {
832
+ const addr = address.toLowerCase();
833
+ const [name, symbol, decimals, totalSupply] = await this.evm.batchRequest([
834
+ { method: "eth_call", params: [{ to: addr, data: "0x06fdde03" }, "latest"] },
835
+ { method: "eth_call", params: [{ to: addr, data: "0x95d89b41" }, "latest"] },
836
+ { method: "eth_call", params: [{ to: addr, data: "0x313ce567" }, "latest"] },
837
+ { method: "eth_call", params: [{ to: addr, data: "0x18160ddd" }, "latest"] }
838
+ ]).catch(() => [null, null, null, null]);
839
+ const isErc20 = !!(totalSupply && totalSupply !== "0x" && symbol && decimals);
840
+ if (!isErc20 && !name && !symbol) return null;
315
841
  return {
316
- root: raw.root,
317
- leafIndex: raw.leaf_index,
318
- siblings: raw.siblings
842
+ address: addr,
843
+ name: name ? _EvmExplorer.decodeAbiString(name) : "",
844
+ symbol: symbol ? _EvmExplorer.decodeAbiString(symbol) : "",
845
+ decimals: decimals ? Number(_EvmExplorer.decodeAbiUint(decimals)) : 18,
846
+ totalSupply: totalSupply ?? "0x0",
847
+ isErc20
319
848
  };
320
849
  }
321
- /**
322
- * Returns the Merkle inclusion proof for a given commitment (0x-prefixed hex).
323
- * Searches the tree for the commitment and returns its proof.
324
- */
325
- async getProofByCommitment(commitmentHex) {
326
- const raw = await this.substrate.request("shieldedPool_getMerkleProof", [
327
- commitmentHex
328
- ]);
850
+ async getTokenTransfers(address, holderAddress) {
851
+ const TRANSFER = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
852
+ const latest = await this.evm.getBlockNumber().catch(() => 0);
853
+ const fromBlock = `0x${Math.max(0, latest - 5e3).toString(16)}`;
854
+ let logs;
855
+ if (holderAddress) {
856
+ const padded = `0x${holderAddress.replace(/^0x/, "").toLowerCase().padStart(64, "0")}`;
857
+ const [sent, received] = await Promise.all([
858
+ this.evm.request("eth_getLogs", [{ fromBlock, toBlock: "latest", address, topics: [TRANSFER, padded] }]).catch(() => []),
859
+ this.evm.request("eth_getLogs", [{ fromBlock, toBlock: "latest", address, topics: [TRANSFER, null, padded] }]).catch(() => [])
860
+ ]);
861
+ const merged = [...sent ?? [], ...received ?? []];
862
+ merged.sort((a, b) => hexToNumber(b.blockNumber) - hexToNumber(a.blockNumber));
863
+ logs = merged.slice(0, 100);
864
+ } else {
865
+ const all = await this.evm.request("eth_getLogs", [{ fromBlock, toBlock: "latest", address, topics: [TRANSFER] }]).catch(() => []);
866
+ logs = (all ?? []).slice(-100).reverse();
867
+ }
868
+ return logs.map((l) => ({
869
+ transactionHash: l.transactionHash,
870
+ blockNumber: hexToNumber(l.blockNumber),
871
+ from: `0x${(l.topics[1] ?? "").slice(-40)}`,
872
+ to: `0x${(l.topics[2] ?? "").slice(-40)}`,
873
+ value: l.data,
874
+ logIndex: hexToNumber(l.logIndex)
875
+ }));
876
+ }
877
+ async getTokenBalance(tokenAddress, holderAddress) {
878
+ const padded = holderAddress.replace(/^0x/, "").toLowerCase().padStart(64, "0");
879
+ const result = await this.ethCall(tokenAddress, `0x70a08231${padded}`);
880
+ return result ?? "0x0";
881
+ }
882
+ // --- Private: parsers ---
883
+ parseBlock(b) {
329
884
  return {
330
- root: raw.root,
331
- leafIndex: raw.leaf_index,
332
- siblings: raw.siblings
885
+ hash: b.hash,
886
+ number: hexToNumber(b.number),
887
+ timestamp: hexToNumber(b.timestamp),
888
+ transactions: b.transactions.map((tx) => typeof tx === "string" ? tx : tx.hash),
889
+ gasUsed: hexToNumber(b.gasUsed).toString(),
890
+ gasLimit: hexToNumber(b.gasLimit).toString(),
891
+ miner: b.miner,
892
+ parentHash: b.parentHash
333
893
  };
334
894
  }
335
- /**
336
- * Returns the current Merkle root without fetching the full tree info.
337
- */
338
- async getRoot() {
339
- const info = await this.getTreeInfo();
340
- return info.root;
895
+ parseTx(tx, receipt) {
896
+ const parsed = {
897
+ hash: tx.hash,
898
+ blockNumber: tx.blockNumber ? hexToNumber(tx.blockNumber) : 0,
899
+ from: tx.from,
900
+ to: tx.to ?? null,
901
+ value: tx.value,
902
+ gasUsed: receipt ? hexToNumber(receipt.gasUsed).toString() : "0",
903
+ gasPrice: _EvmExplorer.hexToDecimalStr(tx.gasPrice),
904
+ nonce: hexToNumber(tx.nonce),
905
+ input: tx.input ?? "0x",
906
+ status: receipt ? hexToNumber(receipt.status) : 0,
907
+ contractAddress: receipt?.contractAddress ?? null,
908
+ timestamp: null
909
+ };
910
+ if (tx.blockHash) parsed.blockHash = tx.blockHash;
911
+ return parsed;
341
912
  }
342
- /**
343
- * Returns an array of commitment leaves from index `from` to `to` (inclusive).
344
- * Defaults to returning all leaves.
345
- */
346
- async getLeaves(from = 0, to) {
347
- return this.substrate.request("shieldedPool_getMerkleLeaves", [from, to ?? null]);
913
+ // --- Private: fetch helpers ---
914
+ async fetchBlock(hashOrNumber, withTxObjects) {
915
+ try {
916
+ if (typeof hashOrNumber === "number" || /^\d+$/.test(String(hashOrNumber))) {
917
+ const hexN = `0x${parseInt(String(hashOrNumber), 10).toString(16)}`;
918
+ return await this.evm.request("eth_getBlockByNumber", [
919
+ hexN,
920
+ withTxObjects
921
+ ]);
922
+ }
923
+ return await this.evm.request("eth_getBlockByHash", [
924
+ hashOrNumber,
925
+ withTxObjects
926
+ ]);
927
+ } catch {
928
+ return null;
929
+ }
930
+ }
931
+ async ethCall(to, data) {
932
+ try {
933
+ return await this.evm.call(to, data);
934
+ } catch {
935
+ return null;
936
+ }
937
+ }
938
+ // --- Private static: ABI decoders ---
939
+ static decodeAbiString(hex) {
940
+ if (!hex || hex === "0x") return "";
941
+ const data = hex.startsWith("0x") ? hex.slice(2) : hex;
942
+ if (data.length < 128) return "";
943
+ const length = parseInt(data.slice(64, 128), 16);
944
+ if (!length) return "";
945
+ const strHex = data.slice(128, 128 + length * 2);
946
+ try {
947
+ const bytes = new Uint8Array(strHex.match(/../g)?.map((b) => parseInt(b, 16)) ?? []);
948
+ return new TextDecoder("utf-8", { fatal: false }).decode(bytes).replace(/\0/g, "");
949
+ } catch {
950
+ return "";
951
+ }
952
+ }
953
+ static decodeAbiUint(hex) {
954
+ if (!hex || hex === "0x") return 0n;
955
+ const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
956
+ return BigInt(`0x${clean || "0"}`);
957
+ }
958
+ static hexToDecimalStr(hex) {
959
+ try {
960
+ return BigInt(hex).toString();
961
+ } catch {
962
+ return "0";
963
+ }
348
964
  }
349
965
  };
350
966
 
351
- // src/shielded-pool/ShieldedPoolModule.ts
352
- var import_polkadot_api2 = require("polkadot-api");
353
-
354
- // src/shielded-pool/EncryptedMemo.ts
355
- var import_sha2 = require("@noble/hashes/sha2.js");
356
- var import_chacha = require("@noble/ciphers/chacha.js");
357
- var import_utils = require("@noble/ciphers/utils.js");
358
-
359
- // src/utils/bytes.ts
360
- function bigintTo32Le(n) {
361
- const buf = new Uint8Array(32);
362
- let v = n;
363
- for (let i = 0; i < 32; i++) {
967
+ // src/indexer/IndexerClient.ts
968
+ var IndexerClient = class {
969
+ baseUrl;
970
+ timeoutMs;
971
+ constructor(config) {
972
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
973
+ this.timeoutMs = config.timeoutMs ?? 1e4;
974
+ }
975
+ // ─── Internal helpers ──────────────────────────────────────────────────────
976
+ async _fetchResponse(path) {
977
+ const controller = new AbortController();
978
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
979
+ try {
980
+ return await fetch(`${this.baseUrl}${path}`, { signal: controller.signal });
981
+ } finally {
982
+ clearTimeout(timer);
983
+ }
984
+ }
985
+ async get(path) {
986
+ const res = await this._fetchResponse(path);
987
+ if (!res.ok) {
988
+ throw new Error(`IndexerClient: HTTP ${res.status} for ${path}`);
989
+ }
990
+ return res.json();
991
+ }
992
+ async getOrNull(path) {
993
+ const res = await this._fetchResponse(path);
994
+ if (res.status === 404) return null;
995
+ if (!res.ok) {
996
+ throw new Error(`IndexerClient: HTTP ${res.status} for ${path}`);
997
+ }
998
+ return res.json();
999
+ }
1000
+ buildQuery(params) {
1001
+ const entries = Object.entries(params).filter(([, v]) => v !== void 0);
1002
+ if (entries.length === 0) return "";
1003
+ const qs = entries.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
1004
+ return `?${qs}`;
1005
+ }
1006
+ // ─── Commitments ───────────────────────────────────────────────────────────
1007
+ /** Returns the total count of shielded commitments. */
1008
+ async getCommitmentsCount() {
1009
+ const res = await this.get("/shielded/commitments/count");
1010
+ return res.total;
1011
+ }
1012
+ /** Returns a paginated list of shielded commitments. */
1013
+ async getCommitments(params) {
1014
+ const qs = this.buildQuery({
1015
+ page: params?.page,
1016
+ limit: params?.limit,
1017
+ since_leaf_index: params?.sinceLeafIndex
1018
+ });
1019
+ return this.get(`/shielded/commitments${qs}`);
1020
+ }
1021
+ /** Returns a single commitment by its hex string, or null if not found. */
1022
+ async getCommitmentByHex(hex) {
1023
+ return this.getOrNull(
1024
+ `/shielded/commitments/${encodeURIComponent(hex)}`
1025
+ );
1026
+ }
1027
+ // ─── Nullifiers ────────────────────────────────────────────────────────────
1028
+ /** Returns a paginated list of spent nullifiers. */
1029
+ async getNullifiers(params) {
1030
+ const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1031
+ return this.get(`/shielded/nullifiers${qs}`);
1032
+ }
1033
+ /** Returns the spent/unspent status of a nullifier. */
1034
+ async getNullifierStatus(hex) {
1035
+ return this.get(
1036
+ `/shielded/nullifier/${encodeURIComponent(hex)}/status`
1037
+ );
1038
+ }
1039
+ // ─── Private transfers ─────────────────────────────────────────────────────
1040
+ /** Returns a paginated list of private transfer events. */
1041
+ async getTransfers(params) {
1042
+ const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1043
+ return this.get(`/shielded/transfers${qs}`);
1044
+ }
1045
+ // ─── Unshields ─────────────────────────────────────────────────────────────
1046
+ /** Returns a paginated list of unshield events. */
1047
+ async getUnshields(params) {
1048
+ const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1049
+ return this.get(`/shielded/unshields${qs}`);
1050
+ }
1051
+ // ─── Merkle roots ──────────────────────────────────────────────────────────
1052
+ /** Returns a paginated list of Merkle root checkpoints. */
1053
+ async getMerkleRoots(params) {
1054
+ const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1055
+ return this.get(`/shielded/merkle-roots${qs}`);
1056
+ }
1057
+ /** Returns the latest Merkle root, or null if none exists. */
1058
+ async getLatestMerkleRoot() {
1059
+ return this.getOrNull("/shielded/merkle-roots/latest");
1060
+ }
1061
+ // ─── Address activity ──────────────────────────────────────────────────────
1062
+ /** Returns a paginated list of extrinsics signed by the given address. */
1063
+ async getAddressExtrinsics(address, params) {
1064
+ const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1065
+ return this.get(
1066
+ `/address/${encodeURIComponent(address.toLowerCase())}/extrinsics${qs}`
1067
+ );
1068
+ }
1069
+ /** Returns a paginated list of EVM transactions filtered by address and/or block number. */
1070
+ async getEvmTransactions(params) {
1071
+ const qs = this.buildQuery({
1072
+ page: params?.page,
1073
+ limit: params?.limit,
1074
+ address: params?.address?.toLowerCase(),
1075
+ blockNumber: params?.blockNumber
1076
+ });
1077
+ return this.get(`/evm/transactions${qs}`);
1078
+ }
1079
+ /** Returns a single EVM transaction by hash, or null if not found. */
1080
+ async getEvmTransactionByHash(hash) {
1081
+ return this.getOrNull(
1082
+ `/evm/transactions/${encodeURIComponent(hash.toLowerCase())}`
1083
+ );
1084
+ }
1085
+ // ─── Blocks ────────────────────────────────────────────────────────────────
1086
+ /** Returns a paginated list of indexed blocks. */
1087
+ async getBlocks(params) {
1088
+ const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1089
+ return this.get(`/blocks${qs}`);
1090
+ }
1091
+ /** Returns a single block by number or hash, or null if not found. */
1092
+ async getBlock(numberOrHash) {
1093
+ return this.getOrNull(`/blocks/${encodeURIComponent(String(numberOrHash))}`);
1094
+ }
1095
+ // ─── Address commitments ───────────────────────────────────────────────────
1096
+ /** Returns a paginated list of shielded commitments initiated by an address. */
1097
+ async getAddressCommitments(address, params) {
1098
+ const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1099
+ return this.get(
1100
+ `/address/${encodeURIComponent(address.toLowerCase())}/shielded${qs}`
1101
+ );
1102
+ }
1103
+ /**
1104
+ * Returns a paginated list of all shielded activity (commitments, unshields,
1105
+ * private transfers) associated with the given address.
1106
+ * Each item is tagged with a `kind` discriminant.
1107
+ */
1108
+ async getAddressShieldedActivity(address, params) {
1109
+ const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1110
+ return this.get(
1111
+ `/shielded/address/${encodeURIComponent(address.toLowerCase())}${qs}`
1112
+ );
1113
+ }
1114
+ // ─── Stats & Health ────────────────────────────────────────────────────────
1115
+ /** Returns aggregated indexer statistics. */
1116
+ async getStats() {
1117
+ return this.get("/stats");
1118
+ }
1119
+ /** Returns true if the indexer health endpoint responds OK. */
1120
+ async isHealthy() {
1121
+ try {
1122
+ const controller = new AbortController();
1123
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
1124
+ try {
1125
+ const res = await fetch(`${this.baseUrl}/health`, {
1126
+ signal: controller.signal
1127
+ });
1128
+ return res.ok;
1129
+ } finally {
1130
+ clearTimeout(timer);
1131
+ }
1132
+ } catch {
1133
+ return false;
1134
+ }
1135
+ }
1136
+ };
1137
+
1138
+ // src/shielded-pool/ShieldedPoolModule.ts
1139
+ var import_polkadot_api2 = require("polkadot-api");
1140
+
1141
+ // src/utils/tx.ts
1142
+ function toTxResult(payload) {
1143
+ const base = {
1144
+ txHash: payload.txHash,
1145
+ blockHash: payload.block.hash,
1146
+ blockNumber: payload.block.number,
1147
+ ok: payload.ok
1148
+ };
1149
+ if (!payload.ok) {
1150
+ return { ...base, error: payload.dispatchError.type };
1151
+ }
1152
+ return base;
1153
+ }
1154
+ function callUnsafeTx(txEntry, ...args) {
1155
+ return txEntry(...args);
1156
+ }
1157
+ function resolveTx(unsafe, pallet, call) {
1158
+ const u = unsafe;
1159
+ const p = u["tx"]?.[pallet];
1160
+ if (p === void 0) throw new Error(`Pallet "${pallet}" not found in runtime metadata`);
1161
+ const entry = p[call];
1162
+ if (entry === void 0)
1163
+ throw new Error(`Call "${pallet}.${call}" not found in runtime metadata`);
1164
+ return entry;
1165
+ }
1166
+
1167
+ // src/shielded-pool/EncryptedMemo.ts
1168
+ var import_chacha = require("@noble/ciphers/chacha.js");
1169
+ var import_utils = require("@noble/ciphers/utils.js");
1170
+
1171
+ // src/utils/bytes.ts
1172
+ function bigintTo32Le(n) {
1173
+ const buf = new Uint8Array(32);
1174
+ let v = n;
1175
+ for (let i = 0; i < 32; i++) {
364
1176
  buf[i] = Number(v & 0xffn);
365
1177
  v >>= 8n;
366
1178
  }
@@ -409,11 +1221,10 @@ function leHexToBigint(hex) {
409
1221
  return bytesToBigintLE(bytes);
410
1222
  }
411
1223
 
412
- // src/shielded-pool/EncryptedMemo.ts
1224
+ // src/shielded-pool/helpers.ts
1225
+ var import_sha2 = require("@noble/hashes/sha2.js");
413
1226
  var KEY_DOMAIN = new TextEncoder().encode("orbinum-note-encryption-v1");
414
- var NONCE_SIZE = 12;
415
1227
  var MEMO_PLAINTEXT_SIZE = 76;
416
- var ENCRYPTED_MEMO_SIZE = 104;
417
1228
  function serializeMemo(value, ownerPk, blinding, assetId) {
418
1229
  const buf = new Uint8Array(MEMO_PLAINTEXT_SIZE);
419
1230
  const view = new DataView(buf.buffer);
@@ -430,6 +1241,22 @@ function deriveEncryptionKey(viewingKey, commitment) {
430
1241
  h.update(KEY_DOMAIN);
431
1242
  return h.digest();
432
1243
  }
1244
+ function toBase64(buf) {
1245
+ const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
1246
+ let str = "";
1247
+ for (const b of bytes) str += String.fromCharCode(b);
1248
+ return btoa(str);
1249
+ }
1250
+ function fromBase64(b64) {
1251
+ const bin = atob(b64);
1252
+ const out = new Uint8Array(bin.length);
1253
+ for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
1254
+ return out;
1255
+ }
1256
+
1257
+ // src/shielded-pool/EncryptedMemo.ts
1258
+ var NONCE_SIZE = 12;
1259
+ var ENCRYPTED_MEMO_SIZE = 104;
433
1260
  var EncryptedMemo = {
434
1261
  /**
435
1262
  * Build and encrypt a memo for a note.
@@ -575,34 +1402,9 @@ var NoteBuilder = class {
575
1402
  };
576
1403
 
577
1404
  // src/shielded-pool/ShieldedPoolModule.ts
578
- function toTxResult(payload) {
579
- const base = {
580
- txHash: payload.txHash,
581
- blockHash: payload.block.hash,
582
- blockNumber: payload.block.number,
583
- ok: payload.ok
584
- };
585
- if (!payload.ok) {
586
- return { ...base, error: payload.dispatchError.type };
587
- }
588
- return base;
589
- }
590
- function callUnsafeTx(txEntry, ...args) {
591
- return txEntry(...args);
592
- }
593
- function resolveTx(unsafe, pallet, call) {
594
- const u = unsafe;
595
- const p = u["tx"]?.[pallet];
596
- if (p === void 0) throw new Error(`Pallet "${pallet}" not found in runtime metadata`);
597
- const entry = p[call];
598
- if (entry === void 0)
599
- throw new Error(`Call "${pallet}.${call}" not found in runtime metadata`);
600
- return entry;
601
- }
602
1405
  var ShieldedPoolModule = class {
603
- constructor(substrate, merkle) {
1406
+ constructor(substrate) {
604
1407
  this.substrate = substrate;
605
- this.merkle = merkle;
606
1408
  }
607
1409
  // ─── Extrinsics ────────────────────────────────────────────────────────────
608
1410
  /**
@@ -694,44 +1496,26 @@ var ShieldedPoolModule = class {
694
1496
  );
695
1497
  return toTxResult(await tx.signAndSubmit(signer));
696
1498
  }
697
- // ─── Queries ───────────────────────────────────────────────────────────────
698
- /** Returns whether a nullifier has already been spent. */
699
- async isNullifierSpent(nullifierHex) {
700
- const raw = await this.substrate.request(
701
- "privacy_getNullifierStatus",
702
- [nullifierHex]
703
- );
704
- return raw.is_spent;
705
- }
706
- /** Returns the full nullifier status object. */
707
- async getNullifierStatus(nullifierHex) {
708
- const raw = await this.substrate.request(
709
- "privacy_getNullifierStatus",
710
- [nullifierHex]
711
- );
712
- return { nullifier: raw.nullifier, isSpent: raw.is_spent };
713
- }
714
- /** Returns the total locked balance in the pool for a given asset. */
715
- async getPoolBalance(assetId) {
716
- const raw = await this.substrate.request(
717
- "shieldedPool_getPoolBalance",
718
- [assetId]
719
- );
720
- return { assetId, balance: BigInt(raw.balance) };
721
- }
722
1499
  /**
723
- * Returns Merkle tree info and pool balance for a given asset in a single call.
724
- * Convenience wrapper used by both `app` and `privacy-explorer`.
1500
+ * Deposits multiple notes into the shielded pool in a single extrinsic.
1501
+ * Extrinsic: shieldedPool.shieldBatch(operations) max 20 items.
725
1502
  */
726
- async getPoolStats(assetId = 0) {
727
- const [merkle, balance] = await Promise.all([
728
- this.merkle.getTreeInfo(),
729
- this.getPoolBalance(assetId)
730
- ]);
731
- return { merkle, balance };
1503
+ async shieldBatch(params, signer) {
1504
+ const operations = params.items.map((item) => ({
1505
+ assetId: item.assetId,
1506
+ amount: item.amount.toString(),
1507
+ commitment: import_polkadot_api2.Binary.fromHex(item.commitment),
1508
+ encryptedMemo: import_polkadot_api2.Binary.fromBytes(item.encryptedMemo ?? EncryptedMemo.dummy())
1509
+ }));
1510
+ const entry = resolveTx(this.substrate.unsafe, "shieldedPool", "shieldBatch");
1511
+ const tx = callUnsafeTx(entry, operations);
1512
+ return toTxResult(await tx.signAndSubmit(signer));
732
1513
  }
733
1514
  };
734
1515
 
1516
+ // src/account-mapping/AccountMappingModule.ts
1517
+ var import_polkadot_api3 = require("polkadot-api");
1518
+
735
1519
  // src/utils/address.ts
736
1520
  var import_util_crypto = require("@polkadot/util-crypto");
737
1521
  function normalizeEvmAddress(addr) {
@@ -762,6 +1546,10 @@ function evmToImplicitSubstrate(evmAddr) {
762
1546
  }
763
1547
  return "0x" + clean.toLowerCase() + "0".repeat(24);
764
1548
  }
1549
+ function evmToMappedAccountHex(address) {
1550
+ if (!isEvmAddress(address)) return null;
1551
+ return evmToImplicitSubstrate(address);
1552
+ }
765
1553
  function isImplicitEvmAccount(accountHex) {
766
1554
  const clean = accountHex.startsWith("0x") ? accountHex.slice(2) : accountHex;
767
1555
  if (clean.length !== 64) return false;
@@ -864,139 +1652,14 @@ function addressToAccountIdHex(addr) {
864
1652
  return substrateSs58ToAccountIdHex(addr);
865
1653
  }
866
1654
 
867
- // src/chain/ChainModule.ts
868
- var ChainModule = class {
869
- constructor(substrate, evm) {
870
- this.substrate = substrate;
871
- this.evm = evm;
872
- }
873
- // ─── Node info ─────────────────────────────────────────────────────────────
874
- /**
875
- * Returns basic chain information from the node.
876
- */
877
- async getChainInfo() {
878
- const [name, version] = await Promise.all([
879
- this.substrate.request("system_name", []),
880
- this.substrate.request("state_getRuntimeVersion", [])
881
- ]);
882
- return {
883
- name,
884
- version: String(version.specVersion),
885
- ss58Prefix: version.ss58Prefix ?? 42
886
- };
887
- }
888
- /**
889
- * Returns the node's peer count and sync status.
890
- */
891
- async getHealth() {
892
- return this.substrate.request("system_health", []);
893
- }
894
- /**
895
- * Returns the node's software version string.
896
- */
897
- async getNodeVersion() {
898
- return this.substrate.request("system_version", []);
899
- }
900
- /**
901
- * Returns the genesis hash hex.
902
- */
903
- async getGenesisHash() {
904
- return this.substrate.request("chain_getBlockHash", [0]);
905
- }
906
- // ─── Account mapping ───────────────────────────────────────────────────────
907
- /**
908
- * Resolves the full identity (Substrate + EVM addresses, alias) for an account.
909
- * Accepts an EVM address (0x...) or a Substrate account hex (0x...32bytes).
910
- */
911
- async getFullIdentity(address) {
912
- try {
913
- const raw = await this.substrate.request(
914
- "accountMapping_resolveFullIdentity",
915
- [address]
916
- );
917
- return {
918
- substrateAddress: raw.substrate_address ?? null,
919
- evmAddress: raw.evm_address ? normalizeEvmAddress(raw.evm_address) : null,
920
- alias: raw.alias ?? null
921
- };
922
- } catch {
923
- return null;
924
- }
925
- }
926
- /**
927
- * Returns the mapped Substrate account hex for a given EVM address, or null.
928
- */
929
- async getMappedAccountByEvm(evmAddress) {
930
- try {
931
- return await this.substrate.request("accountMapping_getMappedAccount", [
932
- normalizeEvmAddress(evmAddress)
933
- ]);
934
- } catch {
935
- return null;
936
- }
937
- }
938
- /**
939
- * Returns the alias registered for a Substrate account, or null.
940
- */
941
- async getAliasOf(accountHex) {
942
- try {
943
- return await this.substrate.request("accountMapping_getAliasOf", [
944
- accountHex
945
- ]);
946
- } catch {
947
- return null;
948
- }
949
- }
950
- // ─── EVM helpers ───────────────────────────────────────────────────────────
951
- /**
952
- * Returns estimated EVM chain ID from the EVM RPC endpoint. Requires evmRpc
953
- * to have been provided in `OrbinumClientConfig`.
954
- */
955
- async getEvmChainId() {
956
- if (!this.evm)
957
- throw new Error("No EVM RPC URL configured. Set evmRpc in OrbinumClientConfig.");
958
- return this.evm.getChainId();
959
- }
960
- /**
961
- * Returns the current EVM block number.
962
- */
963
- async getEvmBlockNumber() {
964
- if (!this.evm) throw new Error("No EVM RPC URL configured.");
965
- return this.evm.getBlockNumber();
966
- }
967
- };
968
-
969
- // src/account-mapping/AccountMappingModule.ts
970
- var import_polkadot_api3 = require("polkadot-api");
971
- function toTxResult2(payload) {
972
- const base = {
973
- txHash: payload.txHash,
974
- blockHash: payload.block.hash,
975
- blockNumber: payload.block.number,
976
- ok: payload.ok
977
- };
978
- if (!payload.ok) {
979
- return { ...base, error: payload.dispatchError.type };
980
- }
981
- return base;
982
- }
983
- function callUnsafeTx2(txEntry, ...args) {
984
- return txEntry(...args);
985
- }
986
- function resolveTx2(unsafe, pallet, call) {
987
- const u = unsafe;
988
- const p = u["tx"]?.[pallet];
989
- if (p === void 0) throw new Error(`Pallet "${pallet}" not found in runtime metadata`);
990
- const entry = p[call];
991
- if (entry === void 0)
992
- throw new Error(`Call "${pallet}.${call}" not found in runtime metadata`);
993
- return entry;
994
- }
1655
+ // src/account-mapping/helpers.ts
995
1656
  function mapRawScheme(raw) {
996
1657
  if (raw === "Eip191" || raw === "eip191") return "Eip191";
997
1658
  if (raw === "Ed25519" || raw === "ed25519") return "Ed25519";
998
1659
  return raw;
999
1660
  }
1661
+
1662
+ // src/account-mapping/AccountMappingModule.ts
1000
1663
  var AccountMappingModule = class {
1001
1664
  constructor(substrate) {
1002
1665
  this.substrate = substrate;
@@ -1236,18 +1899,18 @@ var AccountMappingModule = class {
1236
1899
  * Extrinsic: accountMapping.mapAccount()
1237
1900
  */
1238
1901
  async mapAccount(signer) {
1239
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "mapAccount");
1240
- const tx = callUnsafeTx2(entry);
1241
- return toTxResult2(await tx.signAndSubmit(signer));
1902
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "mapAccount");
1903
+ const tx = callUnsafeTx(entry);
1904
+ return toTxResult(await tx.signAndSubmit(signer));
1242
1905
  }
1243
1906
  /**
1244
1907
  * Removes the EVM → Substrate mapping for the caller.
1245
1908
  * Extrinsic: accountMapping.unmapAccount()
1246
1909
  */
1247
1910
  async unmapAccount(signer) {
1248
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "unmapAccount");
1249
- const tx = callUnsafeTx2(entry);
1250
- return toTxResult2(await tx.signAndSubmit(signer));
1911
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "unmapAccount");
1912
+ const tx = callUnsafeTx(entry);
1913
+ return toTxResult(await tx.signAndSubmit(signer));
1251
1914
  }
1252
1915
  /**
1253
1916
  * Registers a unique @alias for the caller.
@@ -1255,27 +1918,27 @@ var AccountMappingModule = class {
1255
1918
  * Extrinsic: accountMapping.registerAlias(alias)
1256
1919
  */
1257
1920
  async registerAlias(alias, signer) {
1258
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "registerAlias");
1259
- const tx = callUnsafeTx2(entry, import_polkadot_api3.Binary.fromText(alias));
1260
- return toTxResult2(await tx.signAndSubmit(signer));
1921
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "registerAlias");
1922
+ const tx = callUnsafeTx(entry, import_polkadot_api3.Binary.fromText(alias));
1923
+ return toTxResult(await tx.signAndSubmit(signer));
1261
1924
  }
1262
1925
  /**
1263
1926
  * Releases the caller's alias and recovers the deposit.
1264
1927
  * Extrinsic: accountMapping.releaseAlias()
1265
1928
  */
1266
1929
  async releaseAlias(signer) {
1267
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "releaseAlias");
1268
- const tx = callUnsafeTx2(entry);
1269
- return toTxResult2(await tx.signAndSubmit(signer));
1930
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "releaseAlias");
1931
+ const tx = callUnsafeTx(entry);
1932
+ return toTxResult(await tx.signAndSubmit(signer));
1270
1933
  }
1271
1934
  /**
1272
1935
  * Transfers the caller's alias to another account.
1273
1936
  * Extrinsic: accountMapping.transferAlias(newOwner)
1274
1937
  */
1275
1938
  async transferAlias(newOwnerHex, signer) {
1276
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "transferAlias");
1277
- const tx = callUnsafeTx2(entry, newOwnerHex);
1278
- return toTxResult2(await tx.signAndSubmit(signer));
1939
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "transferAlias");
1940
+ const tx = callUnsafeTx(entry, newOwnerHex);
1941
+ return toTxResult(await tx.signAndSubmit(signer));
1279
1942
  }
1280
1943
  /**
1281
1944
  * Adds a verified public link to an external-chain wallet.
@@ -1288,65 +1951,65 @@ var AccountMappingModule = class {
1288
1951
  * Extrinsic: accountMapping.addChainLink(chainId, address, signature)
1289
1952
  */
1290
1953
  async addChainLink(params, signer) {
1291
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "addChainLink");
1292
- const tx = callUnsafeTx2(
1954
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "addChainLink");
1955
+ const tx = callUnsafeTx(
1293
1956
  entry,
1294
1957
  params.chainId,
1295
1958
  import_polkadot_api3.Binary.fromBytes(params.address),
1296
1959
  import_polkadot_api3.Binary.fromBytes(params.signature)
1297
1960
  );
1298
- return toTxResult2(await tx.signAndSubmit(signer));
1961
+ return toTxResult(await tx.signAndSubmit(signer));
1299
1962
  }
1300
1963
  /**
1301
1964
  * Removes the external-chain link for the given chain ID.
1302
1965
  * Extrinsic: accountMapping.removeChainLink(chainId)
1303
1966
  */
1304
1967
  async removeChainLink(chainId, signer) {
1305
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "removeChainLink");
1306
- const tx = callUnsafeTx2(entry, chainId);
1307
- return toTxResult2(await tx.signAndSubmit(signer));
1968
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "removeChainLink");
1969
+ const tx = callUnsafeTx(entry, chainId);
1970
+ return toTxResult(await tx.signAndSubmit(signer));
1308
1971
  }
1309
1972
  /**
1310
1973
  * Updates the caller's public profile metadata.
1311
1974
  * Extrinsic: accountMapping.setAccountMetadata(displayName, bio, avatar)
1312
1975
  */
1313
1976
  async setAccountMetadata(params, signer) {
1314
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "setAccountMetadata");
1977
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "setAccountMetadata");
1315
1978
  const encode2 = (v) => v != null ? import_polkadot_api3.Binary.fromText(v) : void 0;
1316
- const tx = callUnsafeTx2(
1979
+ const tx = callUnsafeTx(
1317
1980
  entry,
1318
1981
  encode2(params.displayName),
1319
1982
  encode2(params.bio),
1320
1983
  encode2(params.avatar)
1321
1984
  );
1322
- return toTxResult2(await tx.signAndSubmit(signer));
1985
+ return toTxResult(await tx.signAndSubmit(signer));
1323
1986
  }
1324
1987
  /**
1325
1988
  * Lists the caller's alias for sale on the alias marketplace.
1326
1989
  * Extrinsic: accountMapping.putAliasOnSale(price, isPrivate)
1327
1990
  */
1328
1991
  async putAliasOnSale(params, signer) {
1329
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "putAliasOnSale");
1330
- const tx = callUnsafeTx2(entry, params.price.toString(), params.isPrivate);
1331
- return toTxResult2(await tx.signAndSubmit(signer));
1992
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "putAliasOnSale");
1993
+ const tx = callUnsafeTx(entry, params.price.toString(), params.isPrivate);
1994
+ return toTxResult(await tx.signAndSubmit(signer));
1332
1995
  }
1333
1996
  /**
1334
1997
  * Cancels an active alias sale listing.
1335
1998
  * Extrinsic: accountMapping.cancelSale()
1336
1999
  */
1337
2000
  async cancelSale(signer) {
1338
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "cancelSale");
1339
- const tx = callUnsafeTx2(entry);
1340
- return toTxResult2(await tx.signAndSubmit(signer));
2001
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "cancelSale");
2002
+ const tx = callUnsafeTx(entry);
2003
+ return toTxResult(await tx.signAndSubmit(signer));
1341
2004
  }
1342
2005
  /**
1343
2006
  * Purchases an alias listed for sale.
1344
2007
  * Extrinsic: accountMapping.buyAlias(alias)
1345
2008
  */
1346
2009
  async buyAlias(alias, signer) {
1347
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "buyAlias");
1348
- const tx = callUnsafeTx2(entry, import_polkadot_api3.Binary.fromText(alias));
1349
- return toTxResult2(await tx.signAndSubmit(signer));
2010
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "buyAlias");
2011
+ const tx = callUnsafeTx(entry, import_polkadot_api3.Binary.fromText(alias));
2012
+ return toTxResult(await tx.signAndSubmit(signer));
1350
2013
  }
1351
2014
  /**
1352
2015
  * Dispatches an arbitrary call on behalf of a linked external-chain wallet.
@@ -1360,8 +2023,8 @@ var AccountMappingModule = class {
1360
2023
  * Extrinsic: accountMapping.dispatchAsLinkedAccount(owner, chainId, address, signature, call)
1361
2024
  */
1362
2025
  async dispatchAsLinkedAccount(params, signer) {
1363
- const entry = resolveTx2(this.substrate.unsafe, "accountMapping", "dispatchAsLinkedAccount");
1364
- const tx = callUnsafeTx2(
2026
+ const entry = resolveTx(this.substrate.unsafe, "accountMapping", "dispatchAsLinkedAccount");
2027
+ const tx = callUnsafeTx(
1365
2028
  entry,
1366
2029
  params.owner,
1367
2030
  params.chainId,
@@ -1369,29 +2032,128 @@ var AccountMappingModule = class {
1369
2032
  import_polkadot_api3.Binary.fromBytes(params.signature),
1370
2033
  import_polkadot_api3.Binary.fromBytes(params.callData)
1371
2034
  );
1372
- return toTxResult2(await tx.signAndSubmit(signer));
2035
+ return toTxResult(await tx.signAndSubmit(signer));
1373
2036
  }
1374
2037
  };
1375
2038
 
1376
- // src/precompiles/abi.ts
1377
- function concat(arrays) {
1378
- const total = arrays.reduce((s, a) => s + a.length, 0);
1379
- const out = new Uint8Array(total);
1380
- let o = 0;
1381
- for (const a of arrays) {
1382
- out.set(a, o);
1383
- o += a.length;
1384
- }
1385
- return out;
1386
- }
1387
- function padTo32Multiple(data) {
1388
- const rem = data.length % 32;
1389
- if (rem === 0) return data;
1390
- const padded = new Uint8Array(data.length + (32 - rem));
1391
- padded.set(data);
1392
- return padded;
2039
+ // src/rpc-v2/helpers.ts
2040
+ function mapAssetBalance(balance) {
2041
+ return {
2042
+ assetId: balance.asset_id,
2043
+ balance: balance.balance.toString()
2044
+ };
2045
+ }
2046
+
2047
+ // src/rpc-v2/PrivacyModule.ts
2048
+ var PrivacyModule = class {
2049
+ constructor(substrate) {
2050
+ this.substrate = substrate;
2051
+ }
2052
+ /** Returns the current Merkle tree root. */
2053
+ async getMerkleRoot() {
2054
+ return this.substrate.request("privacy_getMerkleRoot", []);
2055
+ }
2056
+ /** Returns the Merkle proof for the given leaf index or commitment hex. */
2057
+ async getMerkleProof(leafIndex) {
2058
+ const raw = await this.substrate.request("privacy_getMerkleProof", [
2059
+ leafIndex
2060
+ ]);
2061
+ return {
2062
+ path: raw.path,
2063
+ leafIndex: raw.leaf_index,
2064
+ treeDepth: raw.tree_depth
2065
+ };
2066
+ }
2067
+ /**
2068
+ * Returns the Merkle inclusion proof for a given commitment hex,
2069
+ * bundled with the current Merkle root.
2070
+ */
2071
+ async getMerkleProofByCommitment(commitmentHex) {
2072
+ const [proof, root] = await Promise.all([
2073
+ this.getMerkleProof(commitmentHex),
2074
+ this.getMerkleRoot()
2075
+ ]);
2076
+ return { ...proof, root };
2077
+ }
2078
+ /** Returns the spend status of a nullifier. */
2079
+ async getNullifierStatus(nullifier) {
2080
+ const raw = await this.substrate.request(
2081
+ "privacy_getNullifierStatus",
2082
+ [nullifier]
2083
+ );
2084
+ return {
2085
+ nullifier: raw.nullifier,
2086
+ isSpent: raw.is_spent
2087
+ };
2088
+ }
2089
+ /** Returns aggregated statistics for the shielded pool from `rpc-v2`. */
2090
+ async getPoolStats() {
2091
+ const raw = await this.substrate.request("privacy_getPoolStats", []);
2092
+ return {
2093
+ merkleRoot: raw.merkle_root,
2094
+ commitmentCount: raw.commitment_count,
2095
+ totalBalance: raw.total_balance.toString(),
2096
+ assetBalances: raw.asset_balances.map(mapAssetBalance),
2097
+ treeDepth: raw.tree_depth
2098
+ };
2099
+ }
2100
+ };
2101
+
2102
+ // src/zk-verifier/ZkVerifierModule.ts
2103
+ function mapVkHash(raw) {
2104
+ return { version: raw.version, vkHash: raw.vk_hash };
2105
+ }
2106
+ function mapCircuitVersionInfo(raw) {
2107
+ return {
2108
+ circuitId: raw.circuit_id,
2109
+ activeVersion: raw.active_version,
2110
+ proofSystem: "Groth16",
2111
+ supportedVersions: raw.supported_versions,
2112
+ vkHashes: raw.vk_hashes.map(mapVkHash),
2113
+ historicalVersions: []
2114
+ };
2115
+ }
2116
+ var ZkVerifierModule = class {
2117
+ constructor(substrate) {
2118
+ this.substrate = substrate;
2119
+ }
2120
+ /** Returns basic version info for all registered circuits. */
2121
+ async getAllCircuitVersions() {
2122
+ const raw = await this.substrate.request(
2123
+ "zkVerifier_getAllCircuitVersions",
2124
+ []
2125
+ );
2126
+ return raw.map(mapCircuitVersionInfo);
2127
+ }
2128
+ /** Returns version info for a specific circuit, or null if not found. */
2129
+ async getCircuitVersionInfo(circuitId) {
2130
+ const raw = await this.substrate.request(
2131
+ "zkVerifier_getCircuitVersionInfo",
2132
+ [circuitId]
2133
+ );
2134
+ return raw ? mapCircuitVersionInfo(raw) : null;
2135
+ }
2136
+ };
2137
+
2138
+ // src/precompiles/helpers.ts
2139
+ var STATIC_TYPES = /* @__PURE__ */ new Set(["uint", "bytes32", "address", "bool"]);
2140
+ function concat(arrays) {
2141
+ const total = arrays.reduce((sum, array) => sum + array.length, 0);
2142
+ const out = new Uint8Array(total);
2143
+ let offset = 0;
2144
+ for (const array of arrays) {
2145
+ out.set(array, offset);
2146
+ offset += array.length;
2147
+ }
2148
+ return out;
2149
+ }
2150
+ function padTo32Multiple(data) {
2151
+ const rem = data.length % 32;
2152
+ if (rem === 0) return data;
2153
+ const padded = new Uint8Array(data.length + (32 - rem));
2154
+ padded.set(data);
2155
+ return padded;
1393
2156
  }
1394
- var STATIC_TYPES = /* @__PURE__ */ new Set(["uint", "bytes32", "address", "bool"]);
1395
2157
  function encodeStaticParam(param) {
1396
2158
  const buf = new Uint8Array(32);
1397
2159
  switch (param.type) {
@@ -1472,6 +2234,8 @@ function encodeDynamicParam(param) {
1472
2234
  );
1473
2235
  }
1474
2236
  }
2237
+
2238
+ // src/precompiles/abi.ts
1475
2239
  function encode(selector, ...params) {
1476
2240
  const n = params.length;
1477
2241
  const headSize = n * 32;
@@ -1996,23 +2760,28 @@ var AccountMappingPrecompile = class {
1996
2760
  return signer({ to: this.addr, data });
1997
2761
  }
1998
2762
  /**
1999
- * Updates the signer's public profile metadata.
2000
- * Pass `null` for any field to leave it unchanged.
2001
- *
2002
- * Extrinsic: `accountMapping.setAccountMetadata(displayName, bio, avatar)`
2003
- */
2004
- async setAccountMetadata(displayName, bio, avatar, signer) {
2005
- const enc = (v) => v != null ? new TextEncoder().encode(v) : new Uint8Array(0);
2006
- const data = encodeHex(
2007
- AM_SEL.SET_ACCOUNT_METADATA,
2008
- { type: "bytes", value: enc(displayName) },
2009
- { type: "bytes", value: enc(bio) },
2010
- { type: "bytes", value: enc(avatar) }
2011
- );
2012
- return signer({ to: this.addr, data });
2013
- }
2014
- // ─── Calldata builders (for custom signing / batching) ─────────────────────
2015
- /** Returns the raw ABI-encoded calldata for `registerAlias`. */
2763
+ * Updates the signer's public profile metadata.
2764
+ * Pass `null` for any field to leave it unchanged.
2765
+ }
2766
+ displayName: string | null,
2767
+ bio: string | null,
2768
+ avatar: string | null,
2769
+ signer: EvmSigner
2770
+ ): Promise<string> {
2771
+ const enc = (v: string | null): Uint8Array =>
2772
+ v != null ? new TextEncoder().encode(v) : new Uint8Array(0);
2773
+ const data = encodeHex(
2774
+ AM_SEL.SET_ACCOUNT_METADATA,
2775
+ { type: 'bytes', value: enc(displayName) },
2776
+ { type: 'bytes', value: enc(bio) },
2777
+ { type: 'bytes', value: enc(avatar) }
2778
+ );
2779
+ return signer({ to: this.addr, data });
2780
+ }
2781
+
2782
+ // ─── Calldata builders (for custom signing / batching) ─────────────────────
2783
+
2784
+ /** Returns the raw ABI-encoded calldata for `registerAlias`. */
2016
2785
  buildRegisterAliasCalldata(alias) {
2017
2786
  return encodeHex(AM_SEL.REGISTER_ALIAS, { type: "string", value: alias });
2018
2787
  }
@@ -2134,30 +2903,44 @@ var CryptoPrecompiles = class {
2134
2903
  }
2135
2904
  };
2136
2905
 
2137
- // src/client.ts
2906
+ // src/client/OrbinumClient.ts
2138
2907
  var OrbinumClient = class _OrbinumClient {
2139
2908
  /** Raw access to the Substrate WebSocket connection and RPC. */
2140
2909
  substrate;
2141
2910
  /** Raw access to the EVM HTTP JSON-RPC endpoint (if configured). */
2142
2911
  evm;
2912
+ /**
2913
+ * High-level EVM block and transaction explorer (if `evmRpc` is configured).
2914
+ * Provides enriched queries for blocks, transactions, addresses, and token transfers.
2915
+ */
2916
+ evmExplorer;
2917
+ /**
2918
+ * HTTP client for the Orbinum indexer REST API (if `indexerUrl` is configured).
2919
+ * Provides paginated access to indexed blocks, extrinsics, shielded events, and nullifiers.
2920
+ */
2921
+ indexer;
2143
2922
  /** Shielded-pool operations: shield, unshield, privateTransfer, and merkle queries. */
2144
2923
  shieldedPool;
2145
- /** General chain queries: node info, identity resolution. */
2146
- chain;
2147
2924
  /** Account mapping: aliases, chain links, metadata, marketplace, and identity extrinsics. */
2148
2925
  accountMapping;
2926
+ /** Typed access to Orbinum `privacy_*` RPC endpoints. */
2927
+ privacy;
2928
+ /** Typed access to zkVerifier_* RPC endpoints. */
2929
+ zkVerifier;
2149
2930
  /**
2150
2931
  * EVM precompiles: shielded pool + account mapping callable from an EVM wallet.
2151
2932
  * Only available when `evmRpc` is configured. Methods throw if `evm` is null.
2152
2933
  */
2153
2934
  precompiles;
2154
- constructor(substrate, evm) {
2935
+ constructor(substrate, evm, indexer) {
2155
2936
  this.substrate = substrate;
2156
2937
  this.evm = evm;
2157
- const merkle = new MerkleModule(substrate);
2158
- this.shieldedPool = new ShieldedPoolModule(substrate, merkle);
2159
- this.chain = new ChainModule(substrate, evm);
2938
+ this.evmExplorer = evm ? new EvmExplorer(evm) : null;
2939
+ this.indexer = indexer;
2940
+ this.shieldedPool = new ShieldedPoolModule(substrate);
2160
2941
  this.accountMapping = new AccountMappingModule(substrate);
2942
+ this.privacy = new PrivacyModule(substrate);
2943
+ this.zkVerifier = new ZkVerifierModule(substrate);
2161
2944
  this.precompiles = evm ? {
2162
2945
  shieldedPool: new ShieldedPoolPrecompile(evm),
2163
2946
  accountMapping: new AccountMappingPrecompile(evm),
@@ -2174,13 +2957,8 @@ var OrbinumClient = class _OrbinumClient {
2174
2957
  config.connectTimeoutMs ?? 15e3
2175
2958
  );
2176
2959
  const evm = config.evmRpc ? new EvmClient(config.evmRpc) : null;
2177
- return new _OrbinumClient(substrate, evm);
2178
- }
2179
- /**
2180
- * Convenience getter for the Merkle module (shortcut for `shieldedPool.merkle`).
2181
- */
2182
- get merkle() {
2183
- return this.shieldedPool.merkle;
2960
+ const indexer = config.indexerUrl ? new IndexerClient({ baseUrl: config.indexerUrl }) : null;
2961
+ return new _OrbinumClient(substrate, evm, indexer);
2184
2962
  }
2185
2963
  /** Closes the WebSocket connection to the Substrate node. */
2186
2964
  destroy() {
@@ -2188,6 +2966,215 @@ var OrbinumClient = class _OrbinumClient {
2188
2966
  }
2189
2967
  };
2190
2968
 
2969
+ // src/client/OrbinumClientProvider.ts
2970
+ var DEFAULT_CONNECT_TIMEOUT_MS = 8e3;
2971
+ var DEFAULT_HEARTBEAT_INTERVAL_MS = 5e3;
2972
+ var DEFAULT_HEARTBEAT_TIMEOUT_MS = 4e3;
2973
+ var DEFAULT_RECONNECT_BASE_MS = 3e3;
2974
+ var DEFAULT_RECONNECT_MAX_MS = 3e4;
2975
+ var OrbinumClientProvider = class {
2976
+ config;
2977
+ connectTimeoutMs;
2978
+ heartbeatIntervalMs;
2979
+ heartbeatTimeoutMs;
2980
+ reconnectBaseMs;
2981
+ reconnectMaxMs;
2982
+ // ─── State ──────────────────────────────────────────────────────────────
2983
+ _status = "idle";
2984
+ _orbinumClient = null;
2985
+ _connectingPromise = null;
2986
+ // ─── Timers ─────────────────────────────────────────────────────────────
2987
+ _heartbeatTimer = null;
2988
+ _reconnectTimer = null;
2989
+ _reconnectAttempt = 0;
2990
+ // ─── Events ─────────────────────────────────────────────────────────────
2991
+ _listeners = /* @__PURE__ */ new Set();
2992
+ constructor(config) {
2993
+ this.config = config;
2994
+ this.connectTimeoutMs = config.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;
2995
+ this.heartbeatIntervalMs = config.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;
2996
+ this.heartbeatTimeoutMs = config.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS;
2997
+ this.reconnectBaseMs = config.reconnectBaseMs ?? DEFAULT_RECONNECT_BASE_MS;
2998
+ this.reconnectMaxMs = config.reconnectMaxMs ?? DEFAULT_RECONNECT_MAX_MS;
2999
+ }
3000
+ // ─── Status ─────────────────────────────────────────────────────────────
3001
+ get status() {
3002
+ return this._status;
3003
+ }
3004
+ setStatus(status, error) {
3005
+ this._status = status;
3006
+ const event = { status, ...error ? { error } : {} };
3007
+ this._listeners.forEach((fn) => {
3008
+ try {
3009
+ fn(event);
3010
+ } catch {
3011
+ }
3012
+ });
3013
+ }
3014
+ onStatusChange(listener) {
3015
+ this._listeners.add(listener);
3016
+ return () => {
3017
+ this._listeners.delete(listener);
3018
+ };
3019
+ }
3020
+ // ─── Lifecycle ──────────────────────────────────────────────────────────
3021
+ connect() {
3022
+ if (this._status !== "idle") return;
3023
+ this.startConnectAttempt();
3024
+ }
3025
+ reset() {
3026
+ this.cancelReconnect();
3027
+ this.teardownClient();
3028
+ this._reconnectAttempt = 0;
3029
+ this.setStatus("idle");
3030
+ }
3031
+ // ─── Internal connection flow ───────────────────────────────────────────
3032
+ startConnectAttempt() {
3033
+ this.setStatus("connecting");
3034
+ this._connectingPromise = this.attemptConnect();
3035
+ this._connectingPromise.catch(() => {
3036
+ if (this._status !== "idle") this.scheduleReconnect();
3037
+ });
3038
+ }
3039
+ async attemptConnect() {
3040
+ let timeoutId = null;
3041
+ let orphanClient = null;
3042
+ const timeoutPromise = new Promise((_, reject) => {
3043
+ timeoutId = setTimeout(
3044
+ () => reject(
3045
+ new Error(
3046
+ `Node unavailable \u2014 could not connect to ${this.config.substrateWs} within ${this.connectTimeoutMs / 1e3}s`
3047
+ )
3048
+ ),
3049
+ this.connectTimeoutMs
3050
+ );
3051
+ });
3052
+ try {
3053
+ const connectConfig = {
3054
+ substrateWs: this.config.substrateWs
3055
+ };
3056
+ if (this.config.evmRpc) connectConfig.evmRpc = this.config.evmRpc;
3057
+ if (this.config.indexerUrl) connectConfig.indexerUrl = this.config.indexerUrl;
3058
+ const clientPromise = OrbinumClient.connect(connectConfig);
3059
+ const client = await Promise.race([clientPromise, timeoutPromise]);
3060
+ orphanClient = client;
3061
+ clearTimeout(timeoutId);
3062
+ orphanClient = null;
3063
+ this._orbinumClient = client;
3064
+ this._connectingPromise = null;
3065
+ this._reconnectAttempt = 0;
3066
+ this.setStatus("connected");
3067
+ this.startHeartbeat();
3068
+ return client;
3069
+ } catch (err) {
3070
+ clearTimeout(timeoutId);
3071
+ if (orphanClient) {
3072
+ try {
3073
+ orphanClient.destroy();
3074
+ } catch {
3075
+ }
3076
+ }
3077
+ this._connectingPromise = null;
3078
+ this.setStatus(
3079
+ "disconnected",
3080
+ err instanceof Error ? err.message : "Connection failed"
3081
+ );
3082
+ throw err;
3083
+ }
3084
+ }
3085
+ // ─── Heartbeat ──────────────────────────────────────────────────────────
3086
+ startHeartbeat() {
3087
+ this.stopHeartbeat();
3088
+ this._heartbeatTimer = setInterval(async () => {
3089
+ if (this._status !== "connected" || !this._orbinumClient) return;
3090
+ const alive = await this.probe();
3091
+ if (!alive && this._status === "connected") {
3092
+ this.setStatus("disconnected", "Node is unreachable");
3093
+ this.teardownClient();
3094
+ this.scheduleReconnect();
3095
+ }
3096
+ }, this.heartbeatIntervalMs);
3097
+ }
3098
+ stopHeartbeat() {
3099
+ if (this._heartbeatTimer) {
3100
+ clearInterval(this._heartbeatTimer);
3101
+ this._heartbeatTimer = null;
3102
+ }
3103
+ }
3104
+ async probe() {
3105
+ if (!this._orbinumClient) return false;
3106
+ try {
3107
+ await Promise.race([
3108
+ this._orbinumClient.substrate.request("system_health", []),
3109
+ new Promise(
3110
+ (_, reject) => setTimeout(() => reject(new Error("timeout")), this.heartbeatTimeoutMs)
3111
+ )
3112
+ ]);
3113
+ return true;
3114
+ } catch {
3115
+ return false;
3116
+ }
3117
+ }
3118
+ // ─── Reconnection ───────────────────────────────────────────────────────
3119
+ scheduleReconnect() {
3120
+ if (this._reconnectTimer) clearTimeout(this._reconnectTimer);
3121
+ const delay = Math.min(
3122
+ this.reconnectBaseMs * 2 ** this._reconnectAttempt,
3123
+ this.reconnectMaxMs
3124
+ );
3125
+ this._reconnectAttempt++;
3126
+ this.setStatus("reconnecting");
3127
+ this._reconnectTimer = setTimeout(() => {
3128
+ this._reconnectTimer = null;
3129
+ if (this._status !== "idle") this.startConnectAttempt();
3130
+ }, delay);
3131
+ }
3132
+ cancelReconnect() {
3133
+ if (this._reconnectTimer) {
3134
+ clearTimeout(this._reconnectTimer);
3135
+ this._reconnectTimer = null;
3136
+ }
3137
+ }
3138
+ // ─── Client teardown ────────────────────────────────────────────────────
3139
+ teardownClient() {
3140
+ this.stopHeartbeat();
3141
+ try {
3142
+ this._orbinumClient?.destroy();
3143
+ } catch {
3144
+ }
3145
+ this._orbinumClient = null;
3146
+ this._connectingPromise = null;
3147
+ }
3148
+ // ─── Client access ──────────────────────────────────────────────────────
3149
+ async getOrbinumClient() {
3150
+ if (this._orbinumClient) return this._orbinumClient;
3151
+ if (this._connectingPromise) return this._connectingPromise;
3152
+ throw new Error(`OrbinumClientProvider: cannot get client in status '${this._status}'`);
3153
+ }
3154
+ async tryGetOrbinumClient() {
3155
+ try {
3156
+ return await this.getOrbinumClient();
3157
+ } catch {
3158
+ return null;
3159
+ }
3160
+ }
3161
+ // ─── Convenience RPC helpers ────────────────────────────────────────────
3162
+ async rpcSend(method, params = []) {
3163
+ const client = await this.getOrbinumClient();
3164
+ return client.substrate.request(method, params);
3165
+ }
3166
+ async evmRpc(method, params = []) {
3167
+ const client = await this.getOrbinumClient();
3168
+ if (!client.evm) throw new Error("EVM RPC not configured");
3169
+ return client.evm.request(method, params);
3170
+ }
3171
+ async evmRpcBatch(calls) {
3172
+ const client = await this.getOrbinumClient();
3173
+ if (!client.evm) throw new Error("EVM RPC not configured");
3174
+ return client.evm.batchRequest(calls);
3175
+ }
3176
+ };
3177
+
2191
3178
  // src/shielded-pool/NoteDecryptor.ts
2192
3179
  var import_poseidon_lite2 = require("poseidon-lite");
2193
3180
  function tryDecryptNote(commitment, viewingKey, spendingKey) {
@@ -2230,7 +3217,11 @@ function tryDecryptNote(commitment, viewingKey, spendingKey) {
2230
3217
  var import_hkdf = require("@noble/hashes/hkdf.js");
2231
3218
  var import_sha22 = require("@noble/hashes/sha2.js");
2232
3219
  var import_baby_jubjub = require("@zk-kit/baby-jubjub");
3220
+
3221
+ // src/shielded-pool/constants.ts
2233
3222
  var BN254_R = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
3223
+
3224
+ // src/shielded-pool/PrivacyKeys.ts
2234
3225
  var IVK_DOMAIN = new TextEncoder().encode("orbinum-ivk-v1");
2235
3226
  function deriveSpendingKeyMessage(chainId, address) {
2236
3227
  return `orbinum-spending-key-v1
@@ -2261,13 +3252,12 @@ function deriveOwnerPk(spendingKey) {
2261
3252
  }
2262
3253
 
2263
3254
  // src/shielded-pool/PrivacyKeyManager.ts
2264
- var BN254_R2 = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
2265
- var _state = {
2266
- spendingKey: null,
2267
- viewingKey: null,
2268
- ownerPk: null
2269
- };
2270
- var PrivacyKeyManager = {
3255
+ var PrivacyKeyManager = class {
3256
+ _state = {
3257
+ spendingKey: null,
3258
+ viewingKey: null,
3259
+ ownerPk: null
3260
+ };
2271
3261
  /**
2272
3262
  * Load a spending key into the in-memory session.
2273
3263
  * Derives viewingKey and ownerPk immediately.
@@ -2276,52 +3266,52 @@ var PrivacyKeyManager = {
2276
3266
  async load(spendingKey) {
2277
3267
  const viewingKey = deriveViewingKey(spendingKey);
2278
3268
  const ownerPk = deriveOwnerPk(spendingKey);
2279
- _state = { spendingKey, viewingKey, ownerPk };
2280
- },
3269
+ this._state = { spendingKey, viewingKey, ownerPk };
3270
+ }
2281
3271
  /** Clear all key material from memory. Call on vault lock / sign-out. */
2282
3272
  clear() {
2283
- _state = { spendingKey: null, viewingKey: null, ownerPk: null };
2284
- },
3273
+ this._state = { spendingKey: null, viewingKey: null, ownerPk: null };
3274
+ }
2285
3275
  /** Returns true if a spending key has been loaded. */
2286
3276
  isLoaded() {
2287
- return _state.spendingKey !== null;
2288
- },
3277
+ return this._state.spendingKey !== null;
3278
+ }
2289
3279
  /** Returns the spending key. Throws if not loaded. */
2290
3280
  getSpendingKey() {
2291
- if (_state.spendingKey === null) {
3281
+ if (this._state.spendingKey === null) {
2292
3282
  throw new Error("PrivacyKeyManager: no key loaded. Call load() first.");
2293
3283
  }
2294
- return _state.spendingKey;
2295
- },
3284
+ return this._state.spendingKey;
3285
+ }
2296
3286
  /** Returns the 32-byte viewing key. Throws if not loaded. */
2297
3287
  getViewingKey() {
2298
- if (_state.viewingKey === null) {
3288
+ if (this._state.viewingKey === null) {
2299
3289
  throw new Error("PrivacyKeyManager: no key loaded. Call load() first.");
2300
3290
  }
2301
- return _state.viewingKey;
2302
- },
3291
+ return this._state.viewingKey;
3292
+ }
2303
3293
  /** Returns the BabyJubJub owner public key (x-coordinate). Throws if not loaded. */
2304
3294
  getOwnerPk() {
2305
- if (_state.ownerPk === null) {
3295
+ if (this._state.ownerPk === null) {
2306
3296
  throw new Error("PrivacyKeyManager: no key loaded. Call load() first.");
2307
3297
  }
2308
- return _state.ownerPk;
2309
- },
3298
+ return this._state.ownerPk;
3299
+ }
2310
3300
  /** Returns the spending key as a 32-byte little-endian Uint8Array. Throws if not loaded. */
2311
3301
  getSpendingKeyBytes() {
2312
3302
  return bigintTo32Le(this.getSpendingKey());
2313
- },
3303
+ }
2314
3304
  /** Exports the spending key as a 0x-prefixed 64-char hex string. Throws if not loaded. */
2315
3305
  exportHex() {
2316
3306
  return "0x" + this.getSpendingKey().toString(16).padStart(64, "0");
2317
- },
3307
+ }
2318
3308
  /**
2319
3309
  * Load a spending key from a 0x-prefixed or bare hex string.
2320
3310
  * Validates the key is in the valid range [1, BN254_R).
2321
3311
  */
2322
3312
  async importFromHex(hex) {
2323
3313
  const key = BigInt(hex.startsWith("0x") ? hex : "0x" + hex);
2324
- if (key === 0n || key >= BN254_R2) {
3314
+ if (key === 0n || key >= BN254_R) {
2325
3315
  throw new Error("PrivacyKeyManager: invalid spending key \u2014 out of BN254 range.");
2326
3316
  }
2327
3317
  await this.load(key);
@@ -2339,18 +3329,6 @@ function vaultReviver(_key, value) {
2339
3329
  }
2340
3330
  return value;
2341
3331
  }
2342
- function toBase64(buf) {
2343
- const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
2344
- let str = "";
2345
- for (const b of bytes) str += String.fromCharCode(b);
2346
- return btoa(str);
2347
- }
2348
- function fromBase64(b64) {
2349
- const bin = atob(b64);
2350
- const out = new Uint8Array(bin.length);
2351
- for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
2352
- return out;
2353
- }
2354
3332
  var VAULT_KEY_INFO = new TextEncoder().encode("orbinum-vault-key-v1");
2355
3333
  var IV_BYTES = 12;
2356
3334
  async function deriveVaultKey(spendingKeyBytes) {
@@ -2389,37 +3367,853 @@ async function decryptJson(key, iv, ciphertext) {
2389
3367
  return JSON.parse(new TextDecoder().decode(plainBuf), vaultReviver);
2390
3368
  }
2391
3369
 
2392
- // src/types.ts
3370
+ // src/account-mapping/types/index.ts
3371
+ var SignatureScheme = {
3372
+ Eip191: "Eip191",
3373
+ Ed25519: "Ed25519"
3374
+ };
2393
3375
  var SLIP0044_NAMESPACE = 2147483648;
2394
3376
 
3377
+ // src/precompiles/decode.ts
3378
+ function decodePrecompileCalldata(address, input) {
3379
+ const info = KNOWN_PRECOMPILES[address.toLowerCase()];
3380
+ if (!info || !input || input.length < 10) return null;
3381
+ const selector = input.slice(2, 10).toLowerCase();
3382
+ const fnSig = info.functions[selector];
3383
+ if (!fnSig) return null;
3384
+ if (fnSig.startsWith("registerAlias")) {
3385
+ try {
3386
+ const data = hexToBytes(input.slice(10));
3387
+ const alias = decodeString(data, 0);
3388
+ return { fnSig, args: { alias } };
3389
+ } catch {
3390
+ return { fnSig, args: {} };
3391
+ }
3392
+ }
3393
+ if (fnSig.startsWith("shield(")) {
3394
+ try {
3395
+ const data = hexToBytes(input.slice(10));
3396
+ const assetId = decodeUint(data, 0);
3397
+ const amount = decodeUint(data, 32);
3398
+ const commitment = toHex(data.slice(64, 96));
3399
+ return { fnSig, args: { assetId, amount, commitment } };
3400
+ } catch {
3401
+ return { fnSig, args: {} };
3402
+ }
3403
+ }
3404
+ if (fnSig.startsWith("unshield(")) {
3405
+ try {
3406
+ const data = hexToBytes(input.slice(10));
3407
+ const root = toHex(data.slice(32, 64));
3408
+ const nullifier = toHex(data.slice(64, 96));
3409
+ const assetId = decodeUint(data, 96);
3410
+ const amount = decodeUint(data, 128);
3411
+ const recipient = toHex(data.slice(160, 192));
3412
+ return { fnSig, args: { root, nullifier, assetId, amount, recipient } };
3413
+ } catch {
3414
+ return { fnSig, args: {} };
3415
+ }
3416
+ }
3417
+ if (fnSig.startsWith("privateTransfer(")) {
3418
+ try {
3419
+ const data = hexToBytes(input.slice(10));
3420
+ const root = toHex(data.slice(32, 64));
3421
+ const nullOffset = Number(decodeUint(data, 64));
3422
+ const commOffset = Number(decodeUint(data, 96));
3423
+ const nullifiers = Number(decodeUint(data, nullOffset));
3424
+ const commitments = Number(decodeUint(data, commOffset));
3425
+ return { fnSig, args: { root, nullifiers, commitments } };
3426
+ } catch {
3427
+ return { fnSig, args: {} };
3428
+ }
3429
+ }
3430
+ return { fnSig, args: {} };
3431
+ }
3432
+
3433
+ // src/zk-verifier/types/pallet-extrinsics.ts
3434
+ var CircuitId = {
3435
+ Transfer: 1,
3436
+ Unshield: 2,
3437
+ Disclosure: 3,
3438
+ PrivateLink: 4
3439
+ };
3440
+
3441
+ // src/utils/string.ts
3442
+ function truncateMiddle(str, start, end) {
3443
+ if (!str) return "";
3444
+ if (str.length <= start + end + 1) return str;
3445
+ return `${str.slice(0, start)}\u2026${str.slice(-end)}`;
3446
+ }
3447
+ function shortHash(h, start = 8, end = 6) {
3448
+ return truncateMiddle(h, start, end);
3449
+ }
3450
+
3451
+ // src/extrinsic/index.ts
3452
+ function mapExtrinsicArgs(section, method, args) {
3453
+ if (!args || Object.keys(args).length === 0) return args;
3454
+ const s = section.toLowerCase();
3455
+ const m = method.toLowerCase();
3456
+ const get = (idx, name) => {
3457
+ if (name in args) return args[name];
3458
+ const argKey = `arg${idx}`;
3459
+ if (argKey in args) return args[argKey];
3460
+ if (idx in args) return args[idx];
3461
+ const strIdx = idx.toString();
3462
+ if (strIdx in args) return args[strIdx];
3463
+ return void 0;
3464
+ };
3465
+ if (s === "system") {
3466
+ const m_norm = m.replace(/_/g, "");
3467
+ if (m_norm === "remark" || m_norm === "remarkwithevent") {
3468
+ return { remark: get(0, "remark") };
3469
+ }
3470
+ if (m_norm === "setheappages") {
3471
+ return { pages: get(0, "pages") };
3472
+ }
3473
+ if (m_norm === "setcode" || m_norm === "setcodewithoutchecks") {
3474
+ return { code: get(0, "code") };
3475
+ }
3476
+ if (m_norm === "setstorage") {
3477
+ return { items: get(0, "items") };
3478
+ }
3479
+ if (m_norm === "killstorage") {
3480
+ return { keys: get(0, "keys") };
3481
+ }
3482
+ if (m_norm === "killprefix") {
3483
+ return {
3484
+ prefix: get(0, "prefix"),
3485
+ subkeys: get(1, "subkeys")
3486
+ };
3487
+ }
3488
+ if (m_norm === "authorizeupgrade" || m_norm === "authorizeupgradewithoutchecks") {
3489
+ return { code_hash: get(0, "code_hash") };
3490
+ }
3491
+ if (m_norm === "applyauthorizedupgrade") {
3492
+ return { code: get(0, "code") };
3493
+ }
3494
+ }
3495
+ if (s === "timestamp") {
3496
+ if (m === "set") {
3497
+ return { now: get(0, "now") };
3498
+ }
3499
+ }
3500
+ if (s === "balances") {
3501
+ const m_norm = m.replace(/_/g, "");
3502
+ if (m_norm.startsWith("transfer")) {
3503
+ return {
3504
+ recipient: get(0, "dest") || get(0, "destination") || get(0, "recipient"),
3505
+ amount: get(1, "value") || get(1, "amount")
3506
+ };
3507
+ }
3508
+ if (m_norm === "forcetransfer") {
3509
+ return {
3510
+ source: get(0, "source"),
3511
+ dest: get(1, "dest"),
3512
+ value: get(2, "value")
3513
+ };
3514
+ }
3515
+ if (m_norm === "forceunreserve") {
3516
+ return {
3517
+ who: get(0, "who"),
3518
+ amount: get(1, "amount")
3519
+ };
3520
+ }
3521
+ if (m_norm === "upgradeaccounts") {
3522
+ return { who: get(0, "who") };
3523
+ }
3524
+ if (m_norm === "forcesetbalance") {
3525
+ return {
3526
+ who: get(0, "who"),
3527
+ new_free: get(1, "new_free")
3528
+ };
3529
+ }
3530
+ if (m_norm === "forceadjusttotalissuance") {
3531
+ return {
3532
+ direction: get(0, "direction"),
3533
+ delta: get(1, "delta")
3534
+ };
3535
+ }
3536
+ if (m_norm === "burn") {
3537
+ return {
3538
+ value: get(0, "value"),
3539
+ keep_alive: get(1, "keep_alive")
3540
+ };
3541
+ }
3542
+ }
3543
+ if (s === "sudo") {
3544
+ const m_norm = m.replace(/_/g, "");
3545
+ if (m_norm === "sudo") {
3546
+ return { call: get(0, "call") };
3547
+ }
3548
+ if (m_norm === "sudouncheckedweight") {
3549
+ return {
3550
+ call: get(0, "call"),
3551
+ weight: get(1, "weight")
3552
+ };
3553
+ }
3554
+ if (m_norm === "setkey") {
3555
+ return { new: get(0, "new") };
3556
+ }
3557
+ if (m_norm === "sudoas") {
3558
+ return {
3559
+ who: get(0, "who"),
3560
+ call: get(1, "call")
3561
+ };
3562
+ }
3563
+ }
3564
+ if (s === "grandpa") {
3565
+ const m_norm = m.replace(/_/g, "");
3566
+ if (m_norm === "reportequivocation" || m_norm === "reportequivocationunsigned") {
3567
+ return {
3568
+ equivocation_proof: get(0, "equivocation_proof"),
3569
+ key_owner_proof: get(1, "key_owner_proof")
3570
+ };
3571
+ }
3572
+ if (m_norm === "notestalled") {
3573
+ return {
3574
+ delay: get(0, "delay"),
3575
+ best_finalized_block_number: get(1, "best_finalized_block_number")
3576
+ };
3577
+ }
3578
+ }
3579
+ if (s === "shieldedpool") {
3580
+ const m_norm = m.replace(/_/g, "");
3581
+ if (m_norm === "shield") {
3582
+ return {
3583
+ asset_id: get(0, "asset_id"),
3584
+ amount: get(1, "amount"),
3585
+ commitment: get(2, "commitment"),
3586
+ encrypted_memo: get(3, "encrypted_memo")
3587
+ };
3588
+ }
3589
+ if (m_norm === "shieldbatch") {
3590
+ const ops = get(0, "operations") || get(0, "arg0");
3591
+ if (Array.isArray(ops)) {
3592
+ return {
3593
+ operations: ops.map((op) => {
3594
+ if (Array.isArray(op)) {
3595
+ return {
3596
+ asset_id: op[0],
3597
+ amount: op[1],
3598
+ commitment: op[2],
3599
+ encrypted_memo: op[3]
3600
+ };
3601
+ }
3602
+ return op;
3603
+ })
3604
+ };
3605
+ }
3606
+ return { operations: ops };
3607
+ }
3608
+ if (m_norm === "privatetransfer" || m_norm === "transfer") {
3609
+ return {
3610
+ proof: get(0, "proof"),
3611
+ merkle_root: get(1, "merkle_root"),
3612
+ nullifiers: get(2, "nullifiers"),
3613
+ commitments: get(3, "commitments"),
3614
+ encrypted_memos: get(4, "encrypted_memos")
3615
+ };
3616
+ }
3617
+ if (m_norm === "unshield") {
3618
+ return {
3619
+ proof: get(0, "proof"),
3620
+ merkle_root: get(1, "merkle_root"),
3621
+ nullifier: get(2, "nullifier"),
3622
+ asset_id: get(3, "asset_id"),
3623
+ amount: get(4, "amount"),
3624
+ recipient: get(5, "recipient")
3625
+ };
3626
+ }
3627
+ if (m_norm === "setauditpolicy") {
3628
+ return {
3629
+ auditors: get(0, "auditors"),
3630
+ conditions: get(1, "conditions"),
3631
+ max_frequency: get(2, "max_frequency"),
3632
+ valid_until: get(3, "valid_until")
3633
+ };
3634
+ }
3635
+ if (m_norm === "requestdisclosure") {
3636
+ return {
3637
+ target: get(0, "target"),
3638
+ reason: get(1, "reason")
3639
+ };
3640
+ }
3641
+ if (m_norm === "disclose") {
3642
+ return {
3643
+ commitment: get(0, "commitment"),
3644
+ proof_bytes: get(1, "proof_bytes"),
3645
+ public_signals: get(2, "public_signals"),
3646
+ auditor: get(3, "auditor")
3647
+ };
3648
+ }
3649
+ if (m_norm === "rejectdisclosure") {
3650
+ return {
3651
+ auditor: get(0, "auditor"),
3652
+ reason: get(1, "reason")
3653
+ };
3654
+ }
3655
+ if (m_norm === "registerasset") {
3656
+ return {
3657
+ name: get(0, "name"),
3658
+ symbol: get(1, "symbol"),
3659
+ decimals: get(2, "decimals"),
3660
+ contract_address: get(3, "contract_address")
3661
+ };
3662
+ }
3663
+ if (m_norm === "verifyasset") {
3664
+ return { asset_id: get(0, "asset_id") };
3665
+ }
3666
+ if (m_norm === "unverifyasset") {
3667
+ return { asset_id: get(0, "asset_id") };
3668
+ }
3669
+ if (m_norm === "batchsubmitdisclosureproofs") {
3670
+ return { submissions: get(0, "submissions") };
3671
+ }
3672
+ if (m_norm === "pruneexpiredrequest") {
3673
+ return {
3674
+ target: get(0, "target"),
3675
+ auditor: get(1, "auditor")
3676
+ };
3677
+ }
3678
+ if (m_norm === "revokedisclosurerecord") {
3679
+ return { commitment: get(0, "commitment") };
3680
+ }
3681
+ }
3682
+ if (s === "ethereum" && m === "transact") {
3683
+ return { transaction: get(0, "transaction") };
3684
+ }
3685
+ if (s === "evm") {
3686
+ if (m === "withdraw") {
3687
+ return {
3688
+ address: get(0, "address"),
3689
+ value: get(1, "value")
3690
+ };
3691
+ }
3692
+ if (m === "call") {
3693
+ return {
3694
+ source: get(0, "source"),
3695
+ target: get(1, "target"),
3696
+ input: get(2, "input"),
3697
+ value: get(3, "value"),
3698
+ gas_limit: get(4, "gas_limit"),
3699
+ max_fee_per_gas: get(5, "max_fee_per_gas"),
3700
+ max_priority_fee_per_gas: get(6, "max_priority_fee_per_gas"),
3701
+ nonce: get(7, "nonce"),
3702
+ access_list: get(8, "access_list"),
3703
+ authorization_list: get(9, "authorization_list")
3704
+ };
3705
+ }
3706
+ if (m === "create") {
3707
+ return {
3708
+ source: get(0, "source"),
3709
+ init: get(1, "init"),
3710
+ value: get(2, "value"),
3711
+ gas_limit: get(3, "gas_limit"),
3712
+ max_fee_per_gas: get(4, "max_fee_per_gas"),
3713
+ max_priority_fee_per_gas: get(5, "max_priority_fee_per_gas"),
3714
+ nonce: get(6, "nonce"),
3715
+ access_list: get(7, "access_list"),
3716
+ authorization_list: get(8, "authorization_list")
3717
+ };
3718
+ }
3719
+ if (m === "create2") {
3720
+ return {
3721
+ source: get(0, "source"),
3722
+ init: get(1, "init"),
3723
+ salt: get(2, "salt"),
3724
+ value: get(3, "value"),
3725
+ gas_limit: get(4, "gas_limit"),
3726
+ max_fee_per_gas: get(5, "max_fee_per_gas"),
3727
+ max_priority_fee_per_gas: get(6, "max_priority_fee_per_gas"),
3728
+ nonce: get(7, "nonce"),
3729
+ access_list: get(8, "access_list"),
3730
+ authorization_list: get(9, "authorization_list")
3731
+ };
3732
+ }
3733
+ }
3734
+ if (s === "accountmapping") {
3735
+ const m_norm = m.replace(/_/g, "");
3736
+ if (m_norm === "registeralias") {
3737
+ return { alias: get(0, "alias") };
3738
+ }
3739
+ if (m_norm === "transferalias") {
3740
+ return { new_owner: get(0, "new_owner") };
3741
+ }
3742
+ if (m_norm === "putaliasonsale") {
3743
+ return {
3744
+ price: get(0, "price"),
3745
+ allowed_buyers: get(1, "allowed_buyers")
3746
+ };
3747
+ }
3748
+ if (m_norm === "buyalias") {
3749
+ return { alias: get(0, "alias") };
3750
+ }
3751
+ if (m_norm === "addchainlink") {
3752
+ return {
3753
+ chain_id: get(0, "chain_id"),
3754
+ address: get(1, "address"),
3755
+ signature: get(2, "signature")
3756
+ };
3757
+ }
3758
+ if (m_norm === "removechainlink") {
3759
+ return { chain_id: get(0, "chain_id") };
3760
+ }
3761
+ if (m_norm === "setaccountmetadata") {
3762
+ return {
3763
+ display_name: get(0, "display_name"),
3764
+ bio: get(1, "bio"),
3765
+ avatar: get(2, "avatar")
3766
+ };
3767
+ }
3768
+ if (m_norm === "addsupportedchain") {
3769
+ return {
3770
+ chain_id: get(0, "chain_id"),
3771
+ scheme: get(1, "scheme")
3772
+ };
3773
+ }
3774
+ if (m_norm === "removesupportedchain") {
3775
+ return { chain_id: get(0, "chain_id") };
3776
+ }
3777
+ if (m_norm === "dispatchaslinkedaccount") {
3778
+ return {
3779
+ owner: get(0, "owner"),
3780
+ chain_id: get(1, "chain_id"),
3781
+ address: get(2, "address"),
3782
+ signature: get(3, "signature"),
3783
+ call: get(4, "call")
3784
+ };
3785
+ }
3786
+ if (m_norm === "registerprivatelink") {
3787
+ return {
3788
+ chain_id: get(0, "chain_id"),
3789
+ commitment: get(1, "commitment")
3790
+ };
3791
+ }
3792
+ if (m_norm === "removeprivatelink") {
3793
+ return { commitment: get(0, "commitment") };
3794
+ }
3795
+ if (m_norm === "revealprivatelink") {
3796
+ return {
3797
+ commitment: get(0, "commitment"),
3798
+ address: get(1, "address"),
3799
+ blinding: get(2, "blinding"),
3800
+ signature: get(3, "signature")
3801
+ };
3802
+ }
3803
+ if (m_norm === "dispatchasprivatelink") {
3804
+ return {
3805
+ owner: get(0, "owner"),
3806
+ commitment: get(1, "commitment"),
3807
+ zk_proof: get(2, "zk_proof"),
3808
+ call: get(3, "call")
3809
+ };
3810
+ }
3811
+ }
3812
+ if (s === "zkverifier") {
3813
+ const m_norm = m.replace(/_/g, "");
3814
+ if (m_norm === "batchregisterverificationkeys") {
3815
+ const entries = get(0, "entries");
3816
+ if (Array.isArray(entries)) {
3817
+ return {
3818
+ entries: entries.map((e) => ({
3819
+ circuit_id: e["circuit_id"],
3820
+ version: e["version"],
3821
+ verification_key: e["verification_key"],
3822
+ set_active: e["set_active"]
3823
+ }))
3824
+ };
3825
+ }
3826
+ return { entries };
3827
+ }
3828
+ if (m_norm === "registerverificationkey") {
3829
+ return {
3830
+ circuit_id: get(0, "circuit_id"),
3831
+ version: get(1, "version"),
3832
+ verification_key: get(2, "verification_key")
3833
+ };
3834
+ }
3835
+ if (m_norm === "setactiveversion") {
3836
+ return {
3837
+ circuit_id: get(0, "circuit_id"),
3838
+ version: get(1, "version")
3839
+ };
3840
+ }
3841
+ if (m_norm === "removeverificationkey") {
3842
+ return {
3843
+ circuit_id: get(0, "circuit_id"),
3844
+ version: get(1, "version")
3845
+ };
3846
+ }
3847
+ if (m_norm === "verifyproof") {
3848
+ return {
3849
+ circuit_id: get(0, "circuit_id"),
3850
+ proof: get(1, "proof"),
3851
+ public_inputs: get(2, "public_inputs")
3852
+ };
3853
+ }
3854
+ }
3855
+ return args;
3856
+ }
3857
+ function mapZkEventData(method, data) {
3858
+ const m = method.toLowerCase();
3859
+ const get = (idx, name) => {
3860
+ if (name in data) return data[name];
3861
+ const argKey = `arg${idx}`;
3862
+ if (argKey in data) return data[argKey];
3863
+ if (idx in data) return data[idx];
3864
+ const strIdx = idx.toString();
3865
+ if (strIdx in data) return data[strIdx];
3866
+ return void 0;
3867
+ };
3868
+ const formatAmount = (val) => {
3869
+ if (val === void 0 || val === null) return null;
3870
+ return formatBalance(String(val));
3871
+ };
3872
+ if (m === "shielded" || m === "deposit") {
3873
+ return {
3874
+ sender: get(0, "depositor") || get(0, "sender"),
3875
+ amount: formatAmount(get(1, "amount")),
3876
+ commitment: get(2, "commitment"),
3877
+ memo: get(3, "encrypted_memo") || get(3, "memo"),
3878
+ index: get(4, "leaf_index") || get(4, "index")
3879
+ };
3880
+ }
3881
+ if (m === "privatetransfer") {
3882
+ return {
3883
+ nullifiers: get(0, "nullifiers"),
3884
+ commitments: get(1, "commitments"),
3885
+ memos: get(2, "encrypted_memos") || get(2, "memos"),
3886
+ indices: get(3, "leaf_indices") || get(3, "indices")
3887
+ };
3888
+ }
3889
+ if (m === "unshielded" || m === "withdraw") {
3890
+ return {
3891
+ nullifier: get(0, "nullifier"),
3892
+ amount: formatAmount(get(1, "amount")),
3893
+ recipient: get(2, "recipient")
3894
+ };
3895
+ }
3896
+ if (m === "merklerootupdated" || m === "merkleroot") {
3897
+ return {
3898
+ old_root: get(0, "old_root"),
3899
+ new_root: get(1, "new_root"),
3900
+ size: get(2, "tree_size") || get(2, "size")
3901
+ };
3902
+ }
3903
+ const m_norm = m.replace(/_/g, "");
3904
+ if (m_norm === "auditpolicyset") {
3905
+ return {
3906
+ account: get(0, "account"),
3907
+ version: get(1, "version")
3908
+ };
3909
+ }
3910
+ if (m_norm === "disclosed") {
3911
+ return {
3912
+ who: get(0, "who"),
3913
+ commitment: get(1, "commitment"),
3914
+ auditor: get(2, "auditor")
3915
+ };
3916
+ }
3917
+ if (m_norm === "disclosurerequested") {
3918
+ return {
3919
+ target: get(0, "target"),
3920
+ auditor: get(1, "auditor"),
3921
+ reason: get(2, "reason")
3922
+ };
3923
+ }
3924
+ if (m_norm === "disclosurerejected") {
3925
+ return {
3926
+ target: get(0, "target"),
3927
+ auditor: get(1, "auditor"),
3928
+ reason: get(2, "reason")
3929
+ };
3930
+ }
3931
+ if (m_norm === "disclosurerequestexpired") {
3932
+ return {
3933
+ target: get(0, "target"),
3934
+ auditor: get(1, "auditor")
3935
+ };
3936
+ }
3937
+ if (m_norm === "disclosurerecordrevoked") {
3938
+ return {
3939
+ who: get(0, "who"),
3940
+ commitment: get(1, "commitment")
3941
+ };
3942
+ }
3943
+ if (m_norm === "assetregistered") {
3944
+ return { asset_id: get(0, "asset_id") };
3945
+ }
3946
+ if (m_norm === "assetverified") {
3947
+ return { asset_id: get(0, "asset_id") };
3948
+ }
3949
+ if (m_norm === "assetunverified") {
3950
+ return { asset_id: get(0, "asset_id") };
3951
+ }
3952
+ if (m_norm === "accountmapped" || m_norm === "accountunmapped") {
3953
+ return {
3954
+ account: get(0, "account"),
3955
+ address: get(1, "address")
3956
+ };
3957
+ }
3958
+ if (m_norm === "aliasregistered") {
3959
+ return {
3960
+ account: get(0, "account"),
3961
+ alias: get(1, "alias"),
3962
+ evm_address: get(2, "evm_address")
3963
+ };
3964
+ }
3965
+ if (m_norm === "aliasreleased") {
3966
+ return {
3967
+ account: get(0, "account"),
3968
+ alias: get(1, "alias")
3969
+ };
3970
+ }
3971
+ if (m_norm === "aliastransferred") {
3972
+ return {
3973
+ from: get(0, "from"),
3974
+ to: get(1, "to"),
3975
+ alias: get(2, "alias")
3976
+ };
3977
+ }
3978
+ if (m_norm === "aliaslistedforsale") {
3979
+ return {
3980
+ seller: get(0, "seller"),
3981
+ alias: get(1, "alias"),
3982
+ price: get(2, "price"),
3983
+ private: get(3, "private")
3984
+ };
3985
+ }
3986
+ if (m_norm === "aliassalecancelled") {
3987
+ return {
3988
+ seller: get(0, "seller"),
3989
+ alias: get(1, "alias")
3990
+ };
3991
+ }
3992
+ if (m_norm === "aliassold") {
3993
+ return {
3994
+ seller: get(0, "seller"),
3995
+ buyer: get(1, "buyer"),
3996
+ alias: get(2, "alias"),
3997
+ price: get(3, "price")
3998
+ };
3999
+ }
4000
+ if (m_norm === "chainlinkadded") {
4001
+ return {
4002
+ account: get(0, "account"),
4003
+ chain_id: get(1, "chain_id"),
4004
+ address: get(2, "address")
4005
+ };
4006
+ }
4007
+ if (m_norm === "chainlinkremoved") {
4008
+ return {
4009
+ account: get(0, "account"),
4010
+ chain_id: get(1, "chain_id")
4011
+ };
4012
+ }
4013
+ if (m_norm === "metadataupdated") {
4014
+ return { account: get(0, "account") };
4015
+ }
4016
+ if (m_norm === "supportedchainadded") {
4017
+ return {
4018
+ chain_id: get(0, "chain_id"),
4019
+ scheme: get(1, "scheme")
4020
+ };
4021
+ }
4022
+ if (m_norm === "supportedchainremoved") {
4023
+ return { chain_id: get(0, "chain_id") };
4024
+ }
4025
+ if (m_norm === "proxycallexecuted") {
4026
+ return {
4027
+ owner: get(0, "owner"),
4028
+ chain_id: get(1, "chain_id"),
4029
+ address: get(2, "address")
4030
+ };
4031
+ }
4032
+ if (m_norm === "privatechainlinkadded" || m_norm === "privatechainlinkremoved") {
4033
+ return {
4034
+ account: get(0, "account"),
4035
+ chain_id: get(1, "chain_id"),
4036
+ commitment: get(2, "commitment")
4037
+ };
4038
+ }
4039
+ if (m_norm === "privatechainlinkrevealed") {
4040
+ return {
4041
+ account: get(0, "account"),
4042
+ chain_id: get(1, "chain_id"),
4043
+ address: get(2, "address")
4044
+ };
4045
+ }
4046
+ if (m_norm === "privatelinkdispatchexecuted") {
4047
+ return {
4048
+ owner: get(0, "owner"),
4049
+ commitment: get(1, "commitment")
4050
+ };
4051
+ }
4052
+ if (m_norm === "verificationkeyregistered" || m_norm === "activeversionset" || m_norm === "verificationkeyremoved" || m_norm === "proofverified" || m_norm === "proofverificationfailed") {
4053
+ return {
4054
+ circuit_id: get(0, "circuit_id"),
4055
+ version: get(1, "version")
4056
+ };
4057
+ }
4058
+ if (m_norm === "log") {
4059
+ return { log: get(0, "log") };
4060
+ }
4061
+ if (m_norm === "created" || m_norm === "createdfailed" || m_norm === "executed" || m_norm === "executedfailed") {
4062
+ return { address: get(0, "address") };
4063
+ }
4064
+ if (m_norm === "executed") {
4065
+ return {
4066
+ from: get(0, "from"),
4067
+ to: get(1, "to"),
4068
+ transaction_hash: get(2, "transaction_hash"),
4069
+ exit_reason: get(3, "exit_reason")
4070
+ };
4071
+ }
4072
+ if (m_norm === "extrinsicsuccess") {
4073
+ return { dispatch_info: get(0, "dispatch_info") };
4074
+ }
4075
+ if (m_norm === "extrinsicfailed") {
4076
+ return {
4077
+ dispatch_error: get(0, "dispatch_error"),
4078
+ dispatch_info: get(1, "dispatch_info")
4079
+ };
4080
+ }
4081
+ if (m_norm === "newaccount" || m_norm === "killedaccount") {
4082
+ return { account: get(0, "account") };
4083
+ }
4084
+ if (m_norm === "remarked") {
4085
+ return {
4086
+ sender: get(0, "sender"),
4087
+ hash: get(1, "hash")
4088
+ };
4089
+ }
4090
+ if (m_norm === "upgradeauthorized") {
4091
+ return {
4092
+ code_hash: get(0, "code_hash"),
4093
+ check_version: get(1, "check_version")
4094
+ };
4095
+ }
4096
+ if (m_norm === "rejectedinvalidauthorizedupgrade") {
4097
+ return {
4098
+ code_hash: get(0, "code_hash"),
4099
+ error: get(1, "error")
4100
+ };
4101
+ }
4102
+ if (m_norm === "endowed") {
4103
+ return {
4104
+ account: get(0, "account"),
4105
+ free_balance: get(1, "free_balance")
4106
+ };
4107
+ }
4108
+ if (m_norm === "dustlost") {
4109
+ return {
4110
+ account: get(0, "account"),
4111
+ amount: get(1, "amount")
4112
+ };
4113
+ }
4114
+ if (m_norm === "transfer") {
4115
+ return {
4116
+ from: get(0, "from"),
4117
+ to: get(1, "to"),
4118
+ amount: get(2, "amount")
4119
+ };
4120
+ }
4121
+ if (m_norm === "balanceset") {
4122
+ return {
4123
+ who: get(0, "who"),
4124
+ free: get(1, "free")
4125
+ };
4126
+ }
4127
+ if (m_norm === "reserved" || m_norm === "unreserved" || m_norm === "deposit" || m_norm === "slashed" || m_norm === "minted" || m_norm === "burned" || m_norm === "suspended" || m_norm === "restored" || m_norm === "locked" || m_norm === "unlocked" || m_norm === "frozen" || m_norm === "thawed") {
4128
+ return {
4129
+ who: get(0, "who"),
4130
+ amount: get(1, "amount")
4131
+ };
4132
+ }
4133
+ if (m_norm === "reserverepatriated") {
4134
+ return {
4135
+ from: get(0, "from"),
4136
+ to: get(1, "to"),
4137
+ amount: get(2, "amount"),
4138
+ destination_status: get(3, "destination_status")
4139
+ };
4140
+ }
4141
+ if (m_norm === "upgraded") {
4142
+ return { who: get(0, "who") };
4143
+ }
4144
+ if (m_norm === "issued" || m_norm === "rescinded") {
4145
+ return { amount: get(0, "amount") };
4146
+ }
4147
+ if (m_norm === "totalissuanceforced") {
4148
+ return {
4149
+ old: get(0, "old"),
4150
+ new: get(1, "new")
4151
+ };
4152
+ }
4153
+ if (m_norm === "sudid" || m_norm === "sudoasdone") {
4154
+ return { sudo_result: get(0, "sudo_result") };
4155
+ }
4156
+ if (m_norm === "keychanged") {
4157
+ return {
4158
+ old: get(0, "old"),
4159
+ new: get(1, "new")
4160
+ };
4161
+ }
4162
+ if (m_norm === "newauthorities") {
4163
+ return { authority_set: get(0, "authority_set") };
4164
+ }
4165
+ if (m_norm === "transactionfeepaid") {
4166
+ return {
4167
+ who: get(0, "who"),
4168
+ actual_fee: get(1, "actual_fee"),
4169
+ tip: get(2, "tip")
4170
+ };
4171
+ }
4172
+ return data;
4173
+ }
4174
+
2395
4175
  // src/index.ts
4176
+ var import_substrate_bindings3 = require("@polkadot-api/substrate-bindings");
4177
+ var import_base = require("@scure/base");
2396
4178
  var import_signer = require("polkadot-api/signer");
2397
4179
  var import_pjs_signer = require("polkadot-api/pjs-signer");
4180
+ var import_polkadot_api4 = require("polkadot-api");
2398
4181
  // Annotate the CommonJS export names for ESM import in node:
2399
4182
  0 && (module.exports = {
4183
+ AccountId,
2400
4184
  AccountMappingModule,
2401
4185
  AccountMappingPrecompile,
2402
- ChainModule,
4186
+ Blake2256,
4187
+ CircuitId,
2403
4188
  CryptoPrecompiles,
2404
4189
  EncryptedMemo,
2405
4190
  EvmClient,
4191
+ EvmExplorer,
4192
+ IndexerClient,
2406
4193
  KNOWN_PRECOMPILES,
2407
- MerkleModule,
4194
+ Keccak256,
2408
4195
  NoteBuilder,
2409
4196
  OrbinumClient,
4197
+ OrbinumClientProvider,
2410
4198
  PRECOMPILE_ADDR,
2411
4199
  PrivacyKeyManager,
4200
+ PrivacyModule,
2412
4201
  SLIP0044_NAMESPACE,
2413
4202
  ShieldedPoolModule,
2414
4203
  ShieldedPoolPrecompile,
4204
+ SignatureScheme,
4205
+ Storage,
2415
4206
  SubstrateClient,
4207
+ ZkVerifierModule,
2416
4208
  accountIdHexToSs58,
2417
4209
  addressToAccountIdHex,
4210
+ base58,
2418
4211
  bigintTo32Be,
2419
4212
  bigintTo32Le,
2420
4213
  bigintTo32LeArr,
2421
4214
  bytesToBigintLE,
2422
4215
  computePathIndices,
4216
+ decodePrecompileCalldata,
2423
4217
  decryptJson,
2424
4218
  deriveOwnerPk,
2425
4219
  deriveSpendingKeyFromSignature,
@@ -2430,11 +4224,18 @@ var import_pjs_signer = require("polkadot-api/pjs-signer");
2430
4224
  ensureHexPrefix,
2431
4225
  evmAddressToAccountId,
2432
4226
  evmToImplicitSubstrate,
4227
+ evmToMappedAccountHex,
2433
4228
  evmToSubstrate,
4229
+ formatBalance,
4230
+ formatORB,
4231
+ fromBase64,
2434
4232
  fromHex,
2435
4233
  getPolkadotSigner,
2436
4234
  getPolkadotSignerFromPjs,
2437
4235
  getPrecompileLabel,
4236
+ getSs58AddressInfo,
4237
+ hexToBigint,
4238
+ hexToNumber,
2438
4239
  implicitSubstrateToEvm,
2439
4240
  isEvmAddress,
2440
4241
  isImplicitEvmAccount,
@@ -2442,11 +4243,19 @@ var import_pjs_signer = require("polkadot-api/pjs-signer");
2442
4243
  isSubstrateAddress,
2443
4244
  isUnifiedAddress,
2444
4245
  leHexToBigint,
4246
+ mapExtrinsicArgs,
4247
+ mapZkEventData,
2445
4248
  normalizeEvmAddress,
4249
+ shortHash,
2446
4250
  substrateSs58ToAccountIdHex,
2447
4251
  substrateToEvm,
4252
+ toBase64,
2448
4253
  toHex,
4254
+ toTxResult,
4255
+ truncateMiddle,
2449
4256
  tryDecryptNote,
4257
+ u128,
4258
+ u64,
2450
4259
  vaultReplacer,
2451
4260
  vaultReviver
2452
4261
  });