@pushchain/core 6.0.19 → 6.0.21

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.
Files changed (112) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/package.json +1 -1
  3. package/src/lib/cache/cache.js +2 -0
  4. package/src/lib/constants/abi/index.d.ts +1 -0
  5. package/src/lib/constants/abi/index.js +8 -1
  6. package/src/lib/constants/abi/pc20.evm.d.ts +217 -0
  7. package/src/lib/constants/abi/pc20.evm.js +150 -0
  8. package/src/lib/constants/abi/prc20.evm.d.ts +172 -0
  9. package/src/lib/constants/abi/prc20.evm.js +97 -0
  10. package/src/lib/constants/abi/universalGatewayV0.json +1 -1
  11. package/src/lib/constants/chain.js +38 -8
  12. package/src/lib/constants/selectors.js +2 -2
  13. package/src/lib/constants/tokens.js +4 -3
  14. package/src/lib/formatters.js +16 -6
  15. package/src/lib/generated/uexecutor/v1/query.js +2 -4
  16. package/src/lib/generated/uexecutor/v1/types.d.ts +14 -0
  17. package/src/lib/generated/uexecutor/v1/types.js +90 -47
  18. package/src/lib/generated/uexecutor/v2/query.js +2 -4
  19. package/src/lib/generated/uexecutor/v2/types.d.ts +20 -0
  20. package/src/lib/generated/uexecutor/v2/types.js +49 -33
  21. package/src/lib/generated/v1/tx.js +30 -37
  22. package/src/lib/index.d.ts +4 -1
  23. package/src/lib/index.js +21 -3
  24. package/src/lib/internal/buffer.js +1 -2
  25. package/src/lib/orchestrator/cea-utils.js +73 -83
  26. package/src/lib/orchestrator/internals/account-manager.js +130 -139
  27. package/src/lib/orchestrator/internals/cascade.d.ts +0 -6
  28. package/src/lib/orchestrator/internals/cascade.js +1184 -1059
  29. package/src/lib/orchestrator/internals/confirmation.js +138 -148
  30. package/src/lib/orchestrator/internals/error-decoder.js +1 -1
  31. package/src/lib/orchestrator/internals/errors.js +12 -3
  32. package/src/lib/orchestrator/internals/execute-funds-only.d.ts +2 -2
  33. package/src/lib/orchestrator/internals/execute-funds-only.js +297 -259
  34. package/src/lib/orchestrator/internals/execute-funds-payload.d.ts +2 -2
  35. package/src/lib/orchestrator/internals/execute-funds-payload.js +220 -220
  36. package/src/lib/orchestrator/internals/execute-standard.d.ts +0 -8
  37. package/src/lib/orchestrator/internals/execute-standard.js +339 -342
  38. package/src/lib/orchestrator/internals/gas-calculator.js +497 -520
  39. package/src/lib/orchestrator/internals/gas-usd-sizer.js +101 -110
  40. package/src/lib/orchestrator/internals/gateway-client.js +102 -103
  41. package/src/lib/orchestrator/internals/helpers.js +30 -27
  42. package/src/lib/orchestrator/internals/inbound-tracker.js +234 -238
  43. package/src/lib/orchestrator/internals/outbound-sync.js +463 -452
  44. package/src/lib/orchestrator/internals/outbound-tracker.js +27 -34
  45. package/src/lib/orchestrator/internals/payload-builder.d.ts +2 -2
  46. package/src/lib/orchestrator/internals/payload-builder.js +119 -100
  47. package/src/lib/orchestrator/internals/pc-usd-oracle.js +121 -129
  48. package/src/lib/orchestrator/internals/pc20/address-codec.d.ts +31 -0
  49. package/src/lib/orchestrator/internals/pc20/address-codec.js +124 -0
  50. package/src/lib/orchestrator/internals/pc20/chain-namespace.d.ts +68 -0
  51. package/src/lib/orchestrator/internals/pc20/chain-namespace.js +136 -0
  52. package/src/lib/orchestrator/internals/pc20/errors.d.ts +160 -0
  53. package/src/lib/orchestrator/internals/pc20/errors.js +236 -0
  54. package/src/lib/orchestrator/internals/pc20/export.d.ts +172 -0
  55. package/src/lib/orchestrator/internals/pc20/export.js +412 -0
  56. package/src/lib/orchestrator/internals/pc20/gate.d.ts +67 -0
  57. package/src/lib/orchestrator/internals/pc20/gate.js +184 -0
  58. package/src/lib/orchestrator/internals/pc20/resolver.d.ts +187 -0
  59. package/src/lib/orchestrator/internals/pc20/resolver.js +658 -0
  60. package/src/lib/orchestrator/internals/pc20/svm.d.ts +189 -0
  61. package/src/lib/orchestrator/internals/pc20/svm.js +286 -0
  62. package/src/lib/orchestrator/internals/pc20/tracking.d.ts +46 -0
  63. package/src/lib/orchestrator/internals/pc20/tracking.js +109 -0
  64. package/src/lib/orchestrator/internals/preflight.js +1 -1
  65. package/src/lib/orchestrator/internals/progress-route-hooks.js +2 -2
  66. package/src/lib/orchestrator/internals/push-chain-tx.js +319 -331
  67. package/src/lib/orchestrator/internals/quote.js +90 -94
  68. package/src/lib/orchestrator/internals/rescue.js +76 -79
  69. package/src/lib/orchestrator/internals/response-builder.d.ts +28 -1
  70. package/src/lib/orchestrator/internals/response-builder.js +817 -701
  71. package/src/lib/orchestrator/internals/route-handlers.d.ts +7 -15
  72. package/src/lib/orchestrator/internals/route-handlers.js +1512 -1178
  73. package/src/lib/orchestrator/internals/signing.js +78 -83
  74. package/src/lib/orchestrator/internals/svm-bridge.d.ts +2 -2
  75. package/src/lib/orchestrator/internals/svm-bridge.js +161 -93
  76. package/src/lib/orchestrator/internals/svm-helpers.d.ts +15 -1
  77. package/src/lib/orchestrator/internals/svm-helpers.js +68 -24
  78. package/src/lib/orchestrator/internals/svm-rent.d.ts +19 -1
  79. package/src/lib/orchestrator/internals/svm-rent.js +163 -141
  80. package/src/lib/orchestrator/internals/tx-transformer.js +26 -23
  81. package/src/lib/orchestrator/internals/uea-manager.js +89 -86
  82. package/src/lib/orchestrator/max-pc-for-gas.js +5 -6
  83. package/src/lib/orchestrator/orchestrator.js +217 -200
  84. package/src/lib/orchestrator/orchestrator.types.d.ts +121 -1
  85. package/src/lib/orchestrator/orchestrator.types.js +19 -0
  86. package/src/lib/orchestrator/payload-builders.d.ts +2 -2
  87. package/src/lib/orchestrator/payload-builders.js +26 -24
  88. package/src/lib/orchestrator/route-detector.js +26 -9
  89. package/src/lib/orchestrator/svm-idl/ix-encoder.js +1 -2
  90. package/src/lib/orchestrator/svm-idl/normalize-address.js +2 -2
  91. package/src/lib/orchestrator/svm-idl/resolve.js +1 -2
  92. package/src/lib/price-fetch/price-fetch.js +67 -68
  93. package/src/lib/progress-hook/progress-hook.js +124 -72
  94. package/src/lib/push-chain/push-chain.js +171 -153
  95. package/src/lib/push-client/push-client.js +223 -237
  96. package/src/lib/universal/account/account.js +349 -365
  97. package/src/lib/universal/signer/signer.d.ts +2 -1
  98. package/src/lib/universal/signer/signer.js +315 -299
  99. package/src/lib/universal-tx-detector/auto-detect.js +55 -60
  100. package/src/lib/universal-tx-detector/cascade.js +160 -172
  101. package/src/lib/universal-tx-detector/child-inbounds.js +67 -75
  102. package/src/lib/universal-tx-detector/classify.js +2 -3
  103. package/src/lib/universal-tx-detector/detector-svm.js +139 -147
  104. package/src/lib/universal-tx-detector/detector.js +145 -157
  105. package/src/lib/universal-tx-detector/normalize.js +7 -7
  106. package/src/lib/utils/external-tx-hash.js +1 -2
  107. package/src/lib/utils.d.ts +44 -0
  108. package/src/lib/utils.js +762 -683
  109. package/src/lib/vm-client/evm-client.js +186 -202
  110. package/src/lib/vm-client/svm-client.d.ts +1 -1
  111. package/src/lib/vm-client/svm-client.js +220 -224
  112. package/src/lib/vm-client/vm-client.types.d.ts +14 -2
@@ -5,7 +5,6 @@ exports.deriveChildUniversalTxId = deriveChildUniversalTxId;
5
5
  exports.derivePcUniversalTxId = derivePcUniversalTxId;
6
6
  exports.resolveChildInboundsFromDetection = resolveChildInboundsFromDetection;
7
7
  exports.resolveChildInboundsFromLogs = resolveChildInboundsFromLogs;
8
- const tslib_1 = require("tslib");
9
8
  /**
10
9
  * Stage 2 — resolve child universal-txs spawned by the inbound legs of a
11
10
  * destination-chain transaction.
@@ -86,83 +85,35 @@ function derivePcUniversalTxId(pushChainCaip, pushTxHash) {
86
85
  *
87
86
  * Returns one entry per inbound log present in the receipt.
88
87
  */
89
- function resolveChildInboundsFromDetection(pushClient, detection, diagnostics) {
90
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
91
- const inboundLogs = detection.detections
92
- .filter((d) => INBOUND_EVENT_NAMES.has(d.log.eventName))
93
- .map((d) => d.log);
94
- const resolutions = yield resolveChildInboundsFromLogs(pushClient, detection.chain, detection.txHash, inboundLogs, diagnostics);
95
- // User-facing normalization pass: rewrites nested
96
- // `outboundHashes[n].externalTxHash` to base58 for SVM destinations.
97
- // `pcTxHashes` is Push Chain (EVM) and stays hex by chain type. The lower-
98
- // level `resolveChildInboundsFromLogs` is left producing raw hex so
99
- // internal callers (`findChildUtxIdFromExternalTx` via the detector path)
100
- // that go through it directly still see the canonical form.
101
- return resolutions.map(normalize_1.normalizeChildInboundResolutionForUser);
102
- });
88
+ async function resolveChildInboundsFromDetection(pushClient, detection, diagnostics) {
89
+ const inboundLogs = detection.detections
90
+ .filter((d) => INBOUND_EVENT_NAMES.has(d.log.eventName))
91
+ .map((d) => d.log);
92
+ const resolutions = await resolveChildInboundsFromLogs(pushClient, detection.chain, detection.txHash, inboundLogs, diagnostics);
93
+ // User-facing normalization pass: rewrites nested
94
+ // `outboundHashes[n].externalTxHash` to base58 for SVM destinations.
95
+ // `pcTxHashes` is Push Chain (EVM) and stays hex by chain type. The lower-
96
+ // level `resolveChildInboundsFromLogs` is left producing raw hex so
97
+ // internal callers (`findChildUtxIdFromExternalTx` via the detector path)
98
+ // that go through it directly still see the canonical form.
99
+ return resolutions.map(normalize_1.normalizeChildInboundResolutionForUser);
103
100
  }
104
101
  /**
105
102
  * Lower-level variant — resolve children from an explicit list of inbound
106
103
  * logs (each with a logIndex).
107
104
  */
108
- function resolveChildInboundsFromLogs(pushClient, sourceChainCaip, externalTxHash, inboundLogs, diagnostics) {
109
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
110
- var _a, _b, _c, _d;
111
- const out = [];
112
- for (const log of inboundLogs) {
113
- if (log.logIndex < 0) {
114
- diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.push(`skipped log with negative logIndex (eventName=${log.eventName})`);
115
- continue;
116
- }
117
- const utxIdHex = deriveChildUniversalTxId(sourceChainCaip, externalTxHash, log.logIndex);
118
- try {
119
- const resp = yield pushClient.getUniversalTxByIdV2(utxIdHex.slice(2));
120
- const utx = resp === null || resp === void 0 ? void 0 : resp.universalTx;
121
- if (!utx || !utx.id) {
122
- out.push({
123
- universalTxId: utxIdHex,
124
- sourceLogIndex: log.logIndex,
125
- sourceEventName: log.eventName,
126
- status: 0,
127
- statusName: STATUS_NAMES[0],
128
- pcTxHashes: [],
129
- outboundHashes: [],
130
- notFound: true,
131
- });
132
- continue;
133
- }
134
- const status = ((_a = utx.universalStatus) !== null && _a !== void 0 ? _a : 0);
135
- const pcTxHashes = ((_b = utx.pcTx) !== null && _b !== void 0 ? _b : [])
136
- .map((p) => p === null || p === void 0 ? void 0 : p.txHash)
137
- .filter((h) => Boolean(h));
138
- const outboundHashes = ((_c = utx.outboundTx) !== null && _c !== void 0 ? _c : []).map((ob) => {
139
- var _a, _b, _c, _d;
140
- return ({
141
- subTxId: (_a = ob.id) !== null && _a !== void 0 ? _a : '',
142
- status: (_b = OUTBOUND_STATUS_NAMES[ob.outboundStatus]) !== null && _b !== void 0 ? _b : `UNKNOWN(${ob.outboundStatus})`,
143
- destinationChain: (_c = ob.destinationChain) !== null && _c !== void 0 ? _c : '',
144
- externalTxHash: ((_d = ob.observedTx) === null || _d === void 0 ? void 0 : _d.txHash) || undefined,
145
- amount: ob.amount,
146
- recipient: ob.recipient,
147
- });
148
- });
149
- out.push({
150
- universalTxId: utxIdHex,
151
- sourceLogIndex: log.logIndex,
152
- sourceEventName: log.eventName,
153
- status,
154
- statusName: (_d = STATUS_NAMES[status]) !== null && _d !== void 0 ? _d : `UNKNOWN(${status})`,
155
- pcTxHashes,
156
- outboundHashes,
157
- });
158
- }
159
- catch (err) {
160
- diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.push(`getUniversalTxByIdV2(${utxIdHex}) failed: ${err instanceof Error ? err.message : String(err)}`);
161
- // Cosmos lookup failed (commonly NotFound while the indexer is still
162
- // catching up). The utxId is deterministically derived from the source
163
- // log, so surface it as notFound rather than dropping the entry —
164
- // otherwise callers like inbound-tracker repeatedly re-run the full
165
- // detector pass instead of advancing to lightweight status polling.
105
+ async function resolveChildInboundsFromLogs(pushClient, sourceChainCaip, externalTxHash, inboundLogs, diagnostics) {
106
+ const out = [];
107
+ for (const log of inboundLogs) {
108
+ if (log.logIndex < 0) {
109
+ diagnostics?.push(`skipped log with negative logIndex (eventName=${log.eventName})`);
110
+ continue;
111
+ }
112
+ const utxIdHex = deriveChildUniversalTxId(sourceChainCaip, externalTxHash, log.logIndex);
113
+ try {
114
+ const resp = await pushClient.getUniversalTxByIdV2(utxIdHex.slice(2));
115
+ const utx = resp?.universalTx;
116
+ if (!utx || !utx.id) {
166
117
  out.push({
167
118
  universalTxId: utxIdHex,
168
119
  sourceLogIndex: log.logIndex,
@@ -173,10 +124,51 @@ function resolveChildInboundsFromLogs(pushClient, sourceChainCaip, externalTxHas
173
124
  outboundHashes: [],
174
125
  notFound: true,
175
126
  });
127
+ continue;
176
128
  }
129
+ const status = (utx.universalStatus ?? 0);
130
+ const pcTxHashes = (utx.pcTx ?? [])
131
+ .map((p) => p?.txHash)
132
+ .filter((h) => Boolean(h));
133
+ const outboundHashes = (utx.outboundTx ?? []).map((ob) => ({
134
+ subTxId: ob.id ?? '',
135
+ status: OUTBOUND_STATUS_NAMES[ob.outboundStatus] ??
136
+ `UNKNOWN(${ob.outboundStatus})`,
137
+ destinationChain: ob.destinationChain ?? '',
138
+ externalTxHash: ob.observedTx?.txHash || undefined,
139
+ amount: ob.amount,
140
+ recipient: ob.recipient,
141
+ }));
142
+ out.push({
143
+ universalTxId: utxIdHex,
144
+ sourceLogIndex: log.logIndex,
145
+ sourceEventName: log.eventName,
146
+ status,
147
+ statusName: STATUS_NAMES[status] ?? `UNKNOWN(${status})`,
148
+ pcTxHashes,
149
+ outboundHashes,
150
+ });
151
+ }
152
+ catch (err) {
153
+ diagnostics?.push(`getUniversalTxByIdV2(${utxIdHex}) failed: ${err instanceof Error ? err.message : String(err)}`);
154
+ // Cosmos lookup failed (commonly NotFound while the indexer is still
155
+ // catching up). The utxId is deterministically derived from the source
156
+ // log, so surface it as notFound rather than dropping the entry —
157
+ // otherwise callers like inbound-tracker repeatedly re-run the full
158
+ // detector pass instead of advancing to lightweight status polling.
159
+ out.push({
160
+ universalTxId: utxIdHex,
161
+ sourceLogIndex: log.logIndex,
162
+ sourceEventName: log.eventName,
163
+ status: 0,
164
+ statusName: STATUS_NAMES[0],
165
+ pcTxHashes: [],
166
+ outboundHashes: [],
167
+ notFound: true,
168
+ });
177
169
  }
178
- return out;
179
- });
170
+ }
171
+ return out;
180
172
  }
181
173
  // Debug-only re-export (avoid importing into production paths).
182
174
  exports.__internal = { toHex: viem_1.toHex };
@@ -152,7 +152,7 @@ function asBigint(v) {
152
152
  try {
153
153
  return BigInt(v);
154
154
  }
155
- catch (_a) {
155
+ catch {
156
156
  return undefined;
157
157
  }
158
158
  }
@@ -164,7 +164,6 @@ function assignHex(out, key, v) {
164
164
  }
165
165
  }
166
166
  function setTxType(out, raw) {
167
- var _a;
168
167
  const n = typeof raw === 'number'
169
168
  ? raw
170
169
  : typeof raw === 'bigint'
@@ -173,7 +172,7 @@ function setTxType(out, raw) {
173
172
  if (n === undefined)
174
173
  return;
175
174
  out.txType = n;
176
- out.txTypeName = (_a = TX_TYPE_NAMES[n]) !== null && _a !== void 0 ? _a : 'UNKNOWN';
175
+ out.txTypeName = TX_TYPE_NAMES[n] ?? 'UNKNOWN';
177
176
  }
178
177
  function setPayload(out, raw) {
179
178
  if (typeof raw !== 'string' || !raw.startsWith('0x'))
@@ -37,158 +37,152 @@ const INBOUND_KINDS = new Set([
37
37
  * consumer (classify, cascade, child-inbounds, inbound-tracker) can treat
38
38
  * EVM and SVM results uniformly.
39
39
  */
40
- function detectUniversalTxSvm(signature_1, chain_2) {
41
- return tslib_1.__awaiter(this, arguments, void 0, function* (signature, chain, opts = {}) {
42
- var _a;
43
- const notes = [];
44
- const chainInfo = chain_1.CHAIN_INFO[chain];
45
- const castHash = signature; // intentional — we widen downstream
46
- if (!chainInfo) {
47
- throw new Error(`detectUniversalTxSvm: unknown chain ${chain}`);
48
- }
49
- const connection = yield resolveConnection(chain, opts);
50
- // The cascade (and cosmos) stores Solana signatures as 0x-prefixed hex of
51
- // the 64-byte signature bytes. Solana RPC needs base58 — normalize here
52
- // so callers can pass either form interchangeably.
53
- const rpcSig = normalizeSolanaSignature(signature);
54
- let tx;
40
+ async function detectUniversalTxSvm(signature, chain, opts = {}) {
41
+ const notes = [];
42
+ const chainInfo = chain_1.CHAIN_INFO[chain];
43
+ const castHash = signature; // intentional — we widen downstream
44
+ if (!chainInfo) {
45
+ throw new Error(`detectUniversalTxSvm: unknown chain ${chain}`);
46
+ }
47
+ const connection = await resolveConnection(chain, opts);
48
+ // The cascade (and cosmos) stores Solana signatures as 0x-prefixed hex of
49
+ // the 64-byte signature bytes. Solana RPC needs base58 — normalize here
50
+ // so callers can pass either form interchangeably.
51
+ const rpcSig = normalizeSolanaSignature(signature);
52
+ let tx;
53
+ try {
54
+ tx = await connection.getTransaction(rpcSig, {
55
+ commitment: 'confirmed',
56
+ maxSupportedTransactionVersion: 0,
57
+ });
58
+ }
59
+ catch (err) {
60
+ notes.push(`svm tx fetch failed: ${err instanceof Error ? err.message : String(err)}`);
61
+ return emptyDetection(castHash, chain, notes);
62
+ }
63
+ if (!tx || !tx.meta) {
64
+ notes.push('no svm tx returned by RPC');
65
+ return emptyDetection(castHash, chain, notes);
66
+ }
67
+ // Reverted with no logs — same early-out as EVM path.
68
+ const err = tx.meta.err;
69
+ const logMessages = (tx.meta.logMessages ?? []);
70
+ if (err && logMessages.length === 0) {
71
+ notes.push('svm tx reverted with no logs');
72
+ return emptyDetection(castHash, chain, notes);
73
+ }
74
+ // Emitter for SVM is the gateway program id from CHAIN_INFO.
75
+ // Encoded as 0x-prefixed 32-byte hex so MatchingLog.address stays
76
+ // assignable to the `0x${string}` type without widening.
77
+ const emitterBase58 = chainInfo.lockerContract || '';
78
+ let emitter = '0x';
79
+ if (emitterBase58 && emitterBase58 !== 'TBD') {
55
80
  try {
56
- tx = yield connection.getTransaction(rpcSig, {
57
- commitment: 'confirmed',
58
- maxSupportedTransactionVersion: 0,
59
- });
81
+ emitter = (0, viem_1.bytesToHex)(new web3_js_1.PublicKey(emitterBase58).toBytes());
60
82
  }
61
- catch (err) {
62
- notes.push(`svm tx fetch failed: ${err instanceof Error ? err.message : String(err)}`);
63
- return emptyDetection(castHash, chain, notes);
83
+ catch {
84
+ emitter = '0x';
64
85
  }
65
- if (!tx || !tx.meta) {
66
- notes.push('no svm tx returned by RPC');
67
- return emptyDetection(castHash, chain, notes);
86
+ }
87
+ const eventCoder = new anchor_1.BorshEventCoder(universalGatewayV0_json_1.default);
88
+ const matchingLogs = [];
89
+ // Walk logMessages for `Program data:` entries. Each matched event keeps
90
+ // the actual Solana log-message index because that is the value validators
91
+ // submit as the inbound log_index and the keeper uses for the UTX key.
92
+ for (let logIndex = 0; logIndex < logMessages.length; logIndex++) {
93
+ const rawLog = logMessages[logIndex];
94
+ if (typeof rawLog !== 'string')
95
+ continue;
96
+ const prefix = 'Program data: ';
97
+ if (!rawLog.startsWith(prefix))
98
+ continue;
99
+ const base64Data = rawLog.slice(prefix.length).trim();
100
+ // Fast discriminator check — skip non-universal events without running
101
+ // the full Borsh decode.
102
+ let bytes;
103
+ try {
104
+ bytes = new Uint8Array(Buffer.from(base64Data, 'base64'));
68
105
  }
69
- // Reverted with no logs — same early-out as EVM path.
70
- const err = tx.meta.err;
71
- const logMessages = ((_a = tx.meta.logMessages) !== null && _a !== void 0 ? _a : []);
72
- if (err && logMessages.length === 0) {
73
- notes.push('svm tx reverted with no logs');
74
- return emptyDetection(castHash, chain, notes);
106
+ catch {
107
+ continue;
75
108
  }
76
- // Emitter for SVM is the gateway program id from CHAIN_INFO.
77
- // Encoded as 0x-prefixed 32-byte hex so MatchingLog.address stays
78
- // assignable to the `0x${string}` type without widening.
79
- const emitterBase58 = chainInfo.lockerContract || '';
80
- let emitter = '0x';
81
- if (emitterBase58 && emitterBase58 !== 'TBD') {
82
- try {
83
- emitter = (0, viem_1.bytesToHex)(new web3_js_1.PublicKey(emitterBase58).toBytes());
84
- }
85
- catch (_b) {
86
- emitter = '0x';
87
- }
109
+ const disc = (0, svm_events_1.discriminatorHex)(bytes);
110
+ const eventName = svm_events_1.SVM_EVENT_DISCRIMINATORS[disc];
111
+ if (!eventName)
112
+ continue;
113
+ // BorshEventCoder can throw when the on-chain layout drifts from the
114
+ // bundled IDL (seen with older UniversalTx emissions). Isolate the
115
+ // failure to this event so the rest of the matching logs still surface.
116
+ let decoded = null;
117
+ try {
118
+ decoded = eventCoder.decode(base64Data);
88
119
  }
89
- const eventCoder = new anchor_1.BorshEventCoder(universalGatewayV0_json_1.default);
90
- const matchingLogs = [];
91
- // Walk logMessages for `Program data:` entries. Each matched event keeps
92
- // the actual Solana log-message index because that is the value validators
93
- // submit as the inbound log_index and the keeper uses for the UTX key.
94
- for (let logIndex = 0; logIndex < logMessages.length; logIndex++) {
95
- const rawLog = logMessages[logIndex];
96
- if (typeof rawLog !== 'string')
97
- continue;
98
- const prefix = 'Program data: ';
99
- if (!rawLog.startsWith(prefix))
100
- continue;
101
- const base64Data = rawLog.slice(prefix.length).trim();
102
- // Fast discriminator check — skip non-universal events without running
103
- // the full Borsh decode.
104
- let bytes;
105
- try {
106
- bytes = new Uint8Array(Buffer.from(base64Data, 'base64'));
107
- }
108
- catch (_c) {
109
- continue;
110
- }
111
- const disc = (0, svm_events_1.discriminatorHex)(bytes);
112
- const eventName = svm_events_1.SVM_EVENT_DISCRIMINATORS[disc];
113
- if (!eventName)
114
- continue;
115
- // BorshEventCoder can throw when the on-chain layout drifts from the
116
- // bundled IDL (seen with older UniversalTx emissions). Isolate the
117
- // failure to this event so the rest of the matching logs still surface.
118
- let decoded = null;
119
- try {
120
- decoded = eventCoder.decode(base64Data);
121
- }
122
- catch (e) {
123
- notes.push(`svm: borsh decode threw for ${eventName}: ${e instanceof Error ? e.message : String(e)}`);
124
- continue;
125
- }
126
- if (!decoded || decoded.name !== eventName) {
127
- notes.push(`svm: discriminator matched ${eventName} but borsh decode failed`);
128
- continue;
129
- }
130
- const args = normalizeSvmEventArgs(eventName, decoded.data);
131
- matchingLogs.push({
132
- eventName,
133
- address: emitter,
134
- logIndex,
135
- args,
136
- });
120
+ catch (e) {
121
+ notes.push(`svm: borsh decode threw for ${eventName}: ${e instanceof Error ? e.message : String(e)}`);
122
+ continue;
137
123
  }
138
- if (matchingLogs.length === 0) {
139
- notes.push('svm tx has no decoded universal-tx events');
140
- return emptyDetection(castHash, chain, notes);
124
+ if (!decoded || decoded.name !== eventName) {
125
+ notes.push(`svm: discriminator matched ${eventName} but borsh decode failed`);
126
+ continue;
141
127
  }
142
- const classified = (0, classify_1.classify)(matchingLogs);
143
- notes.push(...classified.notes);
144
- const decoded = Object.assign({}, classified.decoded);
145
- // Inbound fallback for universalTxId: same formula the EVM branch uses,
146
- // with the canonical 0x-hex Solana signature and log-message index.
147
- if (!decoded.universalTxId) {
148
- const caip = chain;
149
- if (INBOUND_KINDS.has(classified.kind) &&
150
- classified.primaryLog &&
151
- classified.primaryLog.logIndex >= 0) {
152
- // Use the hex form (matches cosmos keeper's on-chain storage).
153
- const hexSig = solanaSigToHex(rpcSig);
154
- const input = `${caip}:${hexSig}:${classified.primaryLog.logIndex}`;
155
- decoded.universalTxId = (0, viem_1.sha256)((0, viem_1.toBytes)(input));
156
- notes.push(`universalTxId derived via sha256("${caip}:<hexSig>:${classified.primaryLog.logIndex}") — svm`);
157
- }
128
+ const args = normalizeSvmEventArgs(eventName, decoded.data);
129
+ matchingLogs.push({
130
+ eventName,
131
+ address: emitter,
132
+ logIndex,
133
+ args,
134
+ });
135
+ }
136
+ if (matchingLogs.length === 0) {
137
+ notes.push('svm tx has no decoded universal-tx events');
138
+ return emptyDetection(castHash, chain, notes);
139
+ }
140
+ const classified = (0, classify_1.classify)(matchingLogs);
141
+ notes.push(...classified.notes);
142
+ const decoded = { ...classified.decoded };
143
+ // Inbound fallback for universalTxId: same formula the EVM branch uses,
144
+ // with the canonical 0x-hex Solana signature and log-message index.
145
+ if (!decoded.universalTxId) {
146
+ const caip = chain;
147
+ if (INBOUND_KINDS.has(classified.kind) &&
148
+ classified.primaryLog &&
149
+ classified.primaryLog.logIndex >= 0) {
150
+ // Use the hex form (matches cosmos keeper's on-chain storage).
151
+ const hexSig = solanaSigToHex(rpcSig);
152
+ const input = `${caip}:${hexSig}:${classified.primaryLog.logIndex}`;
153
+ decoded.universalTxId = (0, viem_1.sha256)((0, viem_1.toBytes)(input));
154
+ notes.push(`universalTxId derived via sha256("${caip}:<hexSig>:${classified.primaryLog.logIndex}") — svm`);
158
155
  }
159
- const detections = (0, classify_1.classifyAll)(classified.matchingLogs);
160
- return {
161
- txHash: castHash,
162
- chain,
163
- kind: classified.kind,
164
- emitters: classified.emitters,
165
- decoded,
166
- matchingLogs: classified.matchingLogs,
167
- detections,
168
- // SVM detector doesn't do the cosmos cross-reference itself; upstream
169
- // (orchestrator / cascade) already does its own lookup when needed.
170
- notes,
171
- };
172
- });
156
+ }
157
+ const detections = (0, classify_1.classifyAll)(classified.matchingLogs);
158
+ return {
159
+ txHash: castHash,
160
+ chain,
161
+ kind: classified.kind,
162
+ emitters: classified.emitters,
163
+ decoded,
164
+ matchingLogs: classified.matchingLogs,
165
+ detections,
166
+ // SVM detector doesn't do the cosmos cross-reference itself; upstream
167
+ // (orchestrator / cascade) already does its own lookup when needed.
168
+ notes,
169
+ };
173
170
  }
174
171
  // ── Helpers ───────────────────────────────────────────────────────────
175
- function resolveConnection(chain, opts) {
176
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
177
- var _a, _b;
178
- if (opts.connection)
179
- return opts.connection;
180
- const info = chain_1.CHAIN_INFO[chain];
181
- const rpcUrls = ((_a = opts.rpcUrls) === null || _a === void 0 ? void 0 : _a[chain]) && opts.rpcUrls[chain].length > 0
182
- ? opts.rpcUrls[chain]
183
- : ((_b = info === null || info === void 0 ? void 0 : info.defaultRPC) !== null && _b !== void 0 ? _b : []).filter((r) => r && r.length > 0);
184
- if (rpcUrls.length === 0) {
185
- throw new Error(`detectUniversalTxSvm: no RPC URL configured for ${chain}`);
186
- }
187
- // Lazy import to avoid a top-level dependency cycle through @solana/web3.js
188
- // for consumers of the EVM-only path.
189
- const { Connection } = yield Promise.resolve().then(() => tslib_1.__importStar(require('@solana/web3.js')));
190
- return new Connection(rpcUrls[0], 'confirmed');
191
- });
172
+ async function resolveConnection(chain, opts) {
173
+ if (opts.connection)
174
+ return opts.connection;
175
+ const info = chain_1.CHAIN_INFO[chain];
176
+ const rpcUrls = opts.rpcUrls?.[chain] && opts.rpcUrls[chain].length > 0
177
+ ? opts.rpcUrls[chain]
178
+ : (info?.defaultRPC ?? []).filter((r) => r && r.length > 0);
179
+ if (rpcUrls.length === 0) {
180
+ throw new Error(`detectUniversalTxSvm: no RPC URL configured for ${chain}`);
181
+ }
182
+ // Lazy import to avoid a top-level dependency cycle through @solana/web3.js
183
+ // for consumers of the EVM-only path.
184
+ const { Connection } = await Promise.resolve().then(() => tslib_1.__importStar(require('@solana/web3.js')));
185
+ return new Connection(rpcUrls[0], 'confirmed');
192
186
  }
193
187
  function emptyDetection(txHash, chain, notes) {
194
188
  return {
@@ -215,14 +209,13 @@ function emptyDetection(txHash, chain, notes) {
215
209
  * the expected keys.
216
210
  */
217
211
  function normalizeSvmEventArgs(eventName, raw) {
218
- var _a, _b;
219
212
  const src = raw;
220
213
  const out = {};
221
214
  for (const [srcKey, value] of Object.entries(src)) {
222
- const renamed = (_a = svm_events_1.SVM_FIELD_RENAMES[srcKey]) !== null && _a !== void 0 ? _a : srcKey;
215
+ const renamed = svm_events_1.SVM_FIELD_RENAMES[srcKey] ?? srcKey;
223
216
  out[renamed] = coerceArgValue(srcKey, renamed, value);
224
217
  }
225
- const aliases = (_b = svm_events_1.SVM_EVENT_FIELD_ALIASES[eventName]) !== null && _b !== void 0 ? _b : [];
218
+ const aliases = svm_events_1.SVM_EVENT_FIELD_ALIASES[eventName] ?? [];
226
219
  for (const { from, to } of aliases) {
227
220
  if (out[to] === undefined && out[from] !== undefined) {
228
221
  out[to] = out[from];
@@ -231,7 +224,6 @@ function normalizeSvmEventArgs(eventName, raw) {
231
224
  return out;
232
225
  }
233
226
  function coerceArgValue(srcKey, renamedKey, value) {
234
- var _a;
235
227
  // Anchor returns PublicKey instances for `pubkey` types. Normalize to
236
228
  // `0x${hex}` so asAddress() in classify.ts accepts them.
237
229
  if (value && typeof value === 'object' && value instanceof web3_js_1.PublicKey) {
@@ -255,12 +247,12 @@ function coerceArgValue(srcKey, renamedKey, value) {
255
247
  // BN from anchor — has toString().
256
248
  if (value && typeof value === 'object' && typeof value.toString === 'function') {
257
249
  const proto = Object.getPrototypeOf(value);
258
- const ctorName = (_a = proto === null || proto === void 0 ? void 0 : proto.constructor) === null || _a === void 0 ? void 0 : _a.name;
250
+ const ctorName = proto?.constructor?.name;
259
251
  if (ctorName === 'BN') {
260
252
  try {
261
253
  return BigInt(value.toString(10));
262
254
  }
263
- catch (_b) {
255
+ catch {
264
256
  return undefined;
265
257
  }
266
258
  }