@pushchain/core 5.1.5-alpha.1 → 5.1.5

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 (86) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/package.json +1 -1
  3. package/src/lib/constants/abi/index.d.ts +2 -0
  4. package/src/lib/constants/abi/index.js +6 -1
  5. package/src/lib/constants/abi/uniswap-v3-router.evm.d.ts +58 -0
  6. package/src/lib/constants/abi/uniswap-v3-router.evm.js +41 -0
  7. package/src/lib/constants/abi/wpc.evm.d.ts +24 -0
  8. package/src/lib/constants/abi/wpc.evm.js +27 -0
  9. package/src/lib/constants/chain.d.ts +1 -0
  10. package/src/lib/constants/chain.js +8 -6
  11. package/src/lib/constants/tokens.js +3 -3
  12. package/src/lib/generated/uexecutor/v2/types.d.ts +14 -0
  13. package/src/lib/generated/uexecutor/v2/types.js +96 -3
  14. package/src/lib/orchestrator/internals/cascade.d.ts +1 -1
  15. package/src/lib/orchestrator/internals/cascade.js +521 -239
  16. package/src/lib/orchestrator/internals/confirmation.js +60 -15
  17. package/src/lib/orchestrator/internals/context.d.ts +23 -0
  18. package/src/lib/orchestrator/internals/context.js +54 -0
  19. package/src/lib/orchestrator/internals/execute-funds-only.js +47 -21
  20. package/src/lib/orchestrator/internals/execute-funds-payload.js +53 -31
  21. package/src/lib/orchestrator/internals/execute-standard.js +137 -26
  22. package/src/lib/orchestrator/internals/gas-calculator.d.ts +5 -2
  23. package/src/lib/orchestrator/internals/gas-calculator.js +59 -11
  24. package/src/lib/orchestrator/internals/gas-usd-sizer.d.ts +53 -0
  25. package/src/lib/orchestrator/internals/gas-usd-sizer.js +165 -0
  26. package/src/lib/orchestrator/internals/helpers.js +2 -0
  27. package/src/lib/orchestrator/internals/inbound-tracker.d.ts +83 -0
  28. package/src/lib/orchestrator/internals/inbound-tracker.js +322 -0
  29. package/src/lib/orchestrator/internals/index.d.ts +3 -1
  30. package/src/lib/orchestrator/internals/index.js +8 -2
  31. package/src/lib/orchestrator/internals/outbound-sync.d.ts +32 -1
  32. package/src/lib/orchestrator/internals/outbound-sync.js +154 -17
  33. package/src/lib/orchestrator/internals/pc-usd-oracle.d.ts +28 -0
  34. package/src/lib/orchestrator/internals/pc-usd-oracle.js +285 -0
  35. package/src/lib/orchestrator/internals/progress-route-hooks.d.ts +23 -0
  36. package/src/lib/orchestrator/internals/progress-route-hooks.js +72 -0
  37. package/src/lib/orchestrator/internals/push-chain-tx.d.ts +27 -1
  38. package/src/lib/orchestrator/internals/push-chain-tx.js +111 -15
  39. package/src/lib/orchestrator/internals/rescue.js +1 -1
  40. package/src/lib/orchestrator/internals/response-builder.d.ts +5 -0
  41. package/src/lib/orchestrator/internals/response-builder.js +242 -66
  42. package/src/lib/orchestrator/internals/route-handlers.js +480 -206
  43. package/src/lib/orchestrator/internals/tx-transformer.js +293 -35
  44. package/src/lib/orchestrator/orchestrator.d.ts +7 -1
  45. package/src/lib/orchestrator/orchestrator.js +108 -56
  46. package/src/lib/orchestrator/orchestrator.types.d.ts +111 -5
  47. package/src/lib/orchestrator/payload-builders.d.ts +16 -0
  48. package/src/lib/orchestrator/payload-builders.js +6 -5
  49. package/src/lib/orchestrator/route-detector.js +20 -8
  50. package/src/lib/orchestrator/svm-idl/normalize-address.d.ts +19 -0
  51. package/src/lib/orchestrator/svm-idl/normalize-address.js +56 -0
  52. package/src/lib/orchestrator/svm-idl/registry.d.ts +13 -4
  53. package/src/lib/orchestrator/svm-idl/registry.js +15 -14
  54. package/src/lib/orchestrator/svm-idl/resolve.js +5 -2
  55. package/src/lib/progress-hook/progress-hook.d.ts +28 -0
  56. package/src/lib/progress-hook/progress-hook.js +545 -131
  57. package/src/lib/progress-hook/progress-hook.types.d.ts +76 -29
  58. package/src/lib/progress-hook/progress-hook.types.js +74 -35
  59. package/src/lib/push-client/push-client.d.ts +7 -0
  60. package/src/lib/push-client/push-client.js +18 -1
  61. package/src/lib/universal-tx-detector/__tests__/fixtures/builders.d.ts +32 -0
  62. package/src/lib/universal-tx-detector/__tests__/fixtures/builders.js +65 -0
  63. package/src/lib/universal-tx-detector/__tests__/fixtures/scenarios.d.ts +72 -0
  64. package/src/lib/universal-tx-detector/__tests__/fixtures/scenarios.js +669 -0
  65. package/src/lib/universal-tx-detector/auto-detect.d.ts +37 -0
  66. package/src/lib/universal-tx-detector/auto-detect.js +112 -0
  67. package/src/lib/universal-tx-detector/cascade.d.ts +64 -0
  68. package/src/lib/universal-tx-detector/cascade.js +254 -0
  69. package/src/lib/universal-tx-detector/child-inbounds.d.ts +58 -0
  70. package/src/lib/universal-tx-detector/child-inbounds.js +145 -0
  71. package/src/lib/universal-tx-detector/classify.d.ts +33 -0
  72. package/src/lib/universal-tx-detector/classify.js +228 -0
  73. package/src/lib/universal-tx-detector/detector-svm.d.ts +46 -0
  74. package/src/lib/universal-tx-detector/detector-svm.js +324 -0
  75. package/src/lib/universal-tx-detector/detector.d.ts +13 -0
  76. package/src/lib/universal-tx-detector/detector.js +233 -0
  77. package/src/lib/universal-tx-detector/events.d.ts +765 -0
  78. package/src/lib/universal-tx-detector/events.js +241 -0
  79. package/src/lib/universal-tx-detector/index.d.ts +18 -0
  80. package/src/lib/universal-tx-detector/index.js +36 -0
  81. package/src/lib/universal-tx-detector/svm-events.d.ts +41 -0
  82. package/src/lib/universal-tx-detector/svm-events.js +68 -0
  83. package/src/lib/universal-tx-detector/types.d.ts +100 -0
  84. package/src/lib/universal-tx-detector/types.js +3 -0
  85. package/src/lib/utils.d.ts +30 -13
  86. package/src/lib/utils.js +47 -21
@@ -0,0 +1,669 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.derivePcUniversalTxId = exports.deriveChildUniversalTxId = exports.SCENARIOS = void 0;
4
+ exports.matchingLogsForFixture = matchingLogsForFixture;
5
+ exports.receiptForFixture = receiptForFixture;
6
+ exports.receiptForExtra = receiptForExtra;
7
+ exports.utxRecordMap = utxRecordMap;
8
+ exports.receiptMap = receiptMap;
9
+ const enums_1 = require("../../../constants/enums");
10
+ const events_1 = require("../../events");
11
+ const child_inbounds_1 = require("../../child-inbounds");
12
+ Object.defineProperty(exports, "deriveChildUniversalTxId", { enumerable: true, get: function () { return child_inbounds_1.deriveChildUniversalTxId; } });
13
+ Object.defineProperty(exports, "derivePcUniversalTxId", { enumerable: true, get: function () { return child_inbounds_1.derivePcUniversalTxId; } });
14
+ const builders_1 = require("./builders");
15
+ // ── Shared constants ──────────────────────────────────────────────────
16
+ const ADDR = {
17
+ gatewayBsc: '0x44aFFC61983F4348DdddB886349eb992C061EaC0',
18
+ vaultBsc: '0xE52AC4f8DD3e0263bDF748F3390cdFA1f02be881',
19
+ gatewaySepolia: '0x05bD7a3D18324c1F7e216f7fbf2b15985aE5281A',
20
+ vaultSepolia: '0xD019Eb12D0d6eF8D299661f22B4B7d262eD4b965',
21
+ pcGateway: '0x00000000000000000000000000000000000000c1',
22
+ uea: '0x4A701114F991bf75685584c8156Db983c0DF95a0',
23
+ cea: '0x30a9dB8E3cCe83e8A8720EB61B8728F98449ee6b',
24
+ sender: '0xaaaa000000000000000000000000000000000001',
25
+ recipient: '0xbbbb000000000000000000000000000000000002',
26
+ token: '0x0000000000000000000000000000000000000000',
27
+ pushToken: '0x7169D38820dfd117C3FA1f22a697dBA58d90BA06',
28
+ revertTo: '0xdddd000000000000000000000000000000000004',
29
+ };
30
+ const HASH = {
31
+ // Stable test hashes — each pattern identifies one scenario.
32
+ sA: '0xaa01000000000000000000000000000000000000000000000000000000000001',
33
+ sC: '0xcc01000000000000000000000000000000000000000000000000000000000001',
34
+ sD: '0xdd01000000000000000000000000000000000000000000000000000000000001',
35
+ sE: '0xee01000000000000000000000000000000000000000000000000000000000001',
36
+ sF: '0xff01000000000000000000000000000000000000000000000000000000000001',
37
+ sG: '0x0701000000000000000000000000000000000000000000000000000000000001',
38
+ sH: '0x0801000000000000000000000000000000000000000000000000000000000001',
39
+ sI: '0x0901000000000000000000000000000000000000000000000000000000000001',
40
+ sJ: '0x0a01000000000000000000000000000000000000000000000000000000000001',
41
+ sK: '0x0b01000000000000000000000000000000000000000000000000000000000001',
42
+ sL: '0x0c01000000000000000000000000000000000000000000000000000000000001',
43
+ sM: '0x0d01000000000000000000000000000000000000000000000000000000000001',
44
+ sN: '0x0e01000000000000000000000000000000000000000000000000000000000001',
45
+ // Destinations for cascade follow-ups.
46
+ bscDest: '0xbcbc000000000000000000000000000000000000000000000000000000000001',
47
+ sepoliaDest: '0x5e5e000000000000000000000000000000000000000000000000000000000001',
48
+ solanaDest: '0x5a5a000000000000000000000000000000000000000000000000000000000001',
49
+ // Refund txs on Push Chain.
50
+ pcRefundA: '0xfa01000000000000000000000000000000000000000000000000000000000001',
51
+ pcRefundB: '0xfb01000000000000000000000000000000000000000000000000000000000001',
52
+ pcRevertA: '0xfc01000000000000000000000000000000000000000000000000000000000001',
53
+ };
54
+ const SUB_TX = '0x1111111111111111111111111111111111111111111111111111111111111111';
55
+ const SUB_TX_2 = '0x2222222222222222222222222222222222222222222222222222222222222222';
56
+ const SUB_TX_3 = '0x3333333333333333333333333333333333333333333333333333333333333333';
57
+ const UTX_A = '0xabcd000000000000000000000000000000000000000000000000000000000001';
58
+ // ── Derived helpers ───────────────────────────────────────────────────
59
+ function matchingLogsForFixture(f) {
60
+ return f.logs.map((l) => ({
61
+ eventName: l.event.name,
62
+ address: l.address,
63
+ logIndex: l.logIndex,
64
+ args: l.args,
65
+ }));
66
+ }
67
+ function receiptForFixture(f) {
68
+ const built = f.logs.map((l) => (0, builders_1.buildLog)(l.event, l.args, l.address, l.logIndex, f.txHash));
69
+ return (0, builders_1.buildReceipt)(built, f.to, f.txHash);
70
+ }
71
+ function receiptForExtra(r) {
72
+ const built = r.logs.map((l) => (0, builders_1.buildLog)(l.event, l.args, l.address, l.logIndex, r.txHash));
73
+ return (0, builders_1.buildReceipt)(built, r.to, r.txHash);
74
+ }
75
+ /**
76
+ * Flatten all utxRecord entries across a scenario and its linked fixtures
77
+ * into a single Map keyed by the lowercased id (no 0x prefix).
78
+ */
79
+ function utxRecordMap(fixtures) {
80
+ var _a;
81
+ const out = new Map();
82
+ for (const f of fixtures) {
83
+ for (const r of (_a = f.utxRecords) !== null && _a !== void 0 ? _a : []) {
84
+ out.set(r.id.toLowerCase().replace(/^0x/, ''), r.record);
85
+ }
86
+ }
87
+ return out;
88
+ }
89
+ /**
90
+ * Build a Map<txHashLower, TransactionReceipt> covering the primary tx +
91
+ * all extraReceipts across every fixture.
92
+ */
93
+ function receiptMap(fixtures) {
94
+ var _a;
95
+ const out = new Map();
96
+ for (const f of fixtures) {
97
+ out.set(f.txHash.toLowerCase(), receiptForFixture(f));
98
+ for (const r of (_a = f.extraReceipts) !== null && _a !== void 0 ? _a : []) {
99
+ out.set(r.txHash.toLowerCase(), receiptForExtra(r));
100
+ }
101
+ }
102
+ return out;
103
+ }
104
+ // ── Catalogue ─────────────────────────────────────────────────────────
105
+ const REVERT_INSTRUCTION_TUPLE = [ADDR.revertTo, '0xcafe'];
106
+ const universalTxArgs = (fromCEA, txType = 2) => ({
107
+ sender: ADDR.sender,
108
+ recipient: ADDR.recipient,
109
+ token: ADDR.token,
110
+ amount: BigInt(1000),
111
+ payload: '0x',
112
+ revertRecipient: ADDR.revertTo,
113
+ txType,
114
+ signatureData: '0x',
115
+ fromCEA,
116
+ });
117
+ const outboundArgs = (subTxId, chainNamespace, txType = 3) => ({
118
+ subTxId,
119
+ sender: ADDR.sender,
120
+ chainNamespace,
121
+ token: ADDR.token,
122
+ recipient: '0xdead',
123
+ amount: BigInt(42),
124
+ gasToken: ADDR.token,
125
+ gasFee: BigInt(3),
126
+ gasLimit: BigInt(100000),
127
+ payload: '0x',
128
+ protocolFee: BigInt(1),
129
+ revertRecipient: ADDR.revertTo,
130
+ txType,
131
+ gasPrice: BigInt(9),
132
+ });
133
+ // Helper — synthesize the utx record that expandPushOutbounds expects.
134
+ function pcUtxRecord(opts) {
135
+ var _a;
136
+ return {
137
+ id: (0, child_inbounds_1.derivePcUniversalTxId)(enums_1.CHAIN.PUSH_TESTNET_DONUT, opts.txHash).slice(2),
138
+ universalStatus: (_a = opts.universalStatus) !== null && _a !== void 0 ? _a : 7,
139
+ pcTx: [{ txHash: opts.txHash }],
140
+ outboundTx: opts.outboundTx,
141
+ };
142
+ }
143
+ function outboundTuple(opts) {
144
+ var _a;
145
+ return {
146
+ id: opts.subTxId.slice(2),
147
+ outboundStatus: (_a = opts.outboundStatus) !== null && _a !== void 0 ? _a : 2,
148
+ destinationChain: opts.destinationChain,
149
+ observedTx: opts.externalTxHash
150
+ ? { txHash: opts.externalTxHash, success: true, gasFeeUsed: '100' }
151
+ : { txHash: '', success: false },
152
+ amount: '0',
153
+ recipient: ADDR.recipient,
154
+ pcRefundExecution: opts.pcRefundExecution,
155
+ pcRevertExecution: opts.pcRevertExecution,
156
+ };
157
+ }
158
+ function refundTx(txHash, gasUsed = 100000) {
159
+ return {
160
+ txHash,
161
+ sender: ADDR.sender,
162
+ gasUsed,
163
+ blockHeight: 1,
164
+ status: 'SUCCESS',
165
+ errorMsg: '',
166
+ };
167
+ }
168
+ // ── Fixtures ──────────────────────────────────────────────────────────
169
+ exports.SCENARIOS = [
170
+ // S-A — INBOUND_FROM_EOA (EOA sends FUNDS to UEA)
171
+ {
172
+ id: 'S-A',
173
+ name: 'INBOUND_FROM_EOA — Sepolia EOA sends FUNDS',
174
+ kind: 'INBOUND_FROM_EOA',
175
+ chain: enums_1.CHAIN.ETHEREUM_SEPOLIA,
176
+ txHash: HASH.sA,
177
+ to: ADDR.gatewaySepolia,
178
+ logs: [
179
+ {
180
+ event: events_1.EVENT_UNIVERSAL_TX,
181
+ args: universalTxArgs(false, 2),
182
+ address: ADDR.gatewaySepolia,
183
+ logIndex: 10,
184
+ },
185
+ ],
186
+ expectedDecoded: { fromCEA: false, txType: 2, txTypeName: 'FUNDS' },
187
+ expectedClassifyAll: ['INBOUND_FROM_EOA'],
188
+ },
189
+ // S-C — INBOUND_FROM_CEA (CEA round-trip inbound)
190
+ {
191
+ id: 'S-C',
192
+ name: 'INBOUND_FROM_CEA — Sepolia CEA round-trip',
193
+ kind: 'INBOUND_FROM_CEA',
194
+ chain: enums_1.CHAIN.ETHEREUM_SEPOLIA,
195
+ txHash: HASH.sC,
196
+ to: ADDR.gatewaySepolia,
197
+ logs: [
198
+ {
199
+ event: events_1.EVENT_UNIVERSAL_TX,
200
+ args: universalTxArgs(true, 1),
201
+ address: ADDR.gatewaySepolia,
202
+ logIndex: 20,
203
+ },
204
+ ],
205
+ expectedDecoded: { fromCEA: true, txTypeName: 'GAS_AND_PAYLOAD' },
206
+ expectedClassifyAll: ['INBOUND_FROM_CEA'],
207
+ },
208
+ // S-D — OUTBOUND_INITIATED (Push root with one EVM outbound)
209
+ {
210
+ id: 'S-D',
211
+ name: 'OUTBOUND_INITIATED — Push root with one OBSERVED outbound to BSC',
212
+ kind: 'OUTBOUND_INITIATED',
213
+ chain: enums_1.CHAIN.PUSH_TESTNET_DONUT,
214
+ txHash: HASH.sD,
215
+ to: ADDR.pcGateway,
216
+ logs: [
217
+ {
218
+ event: events_1.EVENT_UNIVERSAL_TX_OUTBOUND,
219
+ args: outboundArgs(SUB_TX, enums_1.CHAIN.BNB_TESTNET, 3),
220
+ address: ADDR.pcGateway,
221
+ logIndex: 5,
222
+ },
223
+ ],
224
+ extraReceipts: [
225
+ {
226
+ txHash: HASH.bscDest,
227
+ chain: enums_1.CHAIN.BNB_TESTNET,
228
+ to: ADDR.vaultBsc,
229
+ logs: [
230
+ {
231
+ event: events_1.EVENT_UNIVERSAL_TX_FINALIZED,
232
+ args: {
233
+ subTxId: SUB_TX,
234
+ universalTxId: (0, child_inbounds_1.derivePcUniversalTxId)(enums_1.CHAIN.PUSH_TESTNET_DONUT, HASH.sD),
235
+ pushAccount: ADDR.uea,
236
+ recipient: ADDR.recipient,
237
+ token: ADDR.token,
238
+ amount: BigInt(42),
239
+ data: '0x',
240
+ },
241
+ address: ADDR.vaultBsc,
242
+ logIndex: 0,
243
+ },
244
+ ],
245
+ },
246
+ ],
247
+ utxRecords: [
248
+ {
249
+ id: (0, child_inbounds_1.derivePcUniversalTxId)(enums_1.CHAIN.PUSH_TESTNET_DONUT, HASH.sD).slice(2),
250
+ record: pcUtxRecord({
251
+ txHash: HASH.sD,
252
+ outboundTx: [
253
+ outboundTuple({
254
+ subTxId: SUB_TX,
255
+ destinationChain: enums_1.CHAIN.BNB_TESTNET,
256
+ externalTxHash: HASH.bscDest,
257
+ pcRefundExecution: refundTx(HASH.pcRefundA),
258
+ }),
259
+ ],
260
+ }),
261
+ },
262
+ // Refund tx has no utx record of its own (terminal).
263
+ {
264
+ id: (0, child_inbounds_1.derivePcUniversalTxId)(enums_1.CHAIN.PUSH_TESTNET_DONUT, HASH.pcRefundA).slice(2),
265
+ record: null,
266
+ },
267
+ ],
268
+ expectedDecoded: { subTxId: SUB_TX, destinationChainNamespace: enums_1.CHAIN.BNB_TESTNET },
269
+ expectedClassifyAll: ['OUTBOUND_INITIATED'],
270
+ expectedCascade: {
271
+ rootKind: 'OUTBOUND_INITIATED',
272
+ outboundCount: 1,
273
+ refundCount: 1,
274
+ childInboundCount: 0,
275
+ outboundDestinations: [enums_1.CHAIN.BNB_TESTNET],
276
+ totalFlatNodes: 3, // root + bsc dest + pc-refund
277
+ },
278
+ },
279
+ // S-E — OUTBOUND_FINALIZED (destination Vault finalize with executed sibling)
280
+ {
281
+ id: 'S-E',
282
+ name: 'OUTBOUND_FINALIZED — Sepolia Vault finalize',
283
+ kind: 'OUTBOUND_FINALIZED',
284
+ chain: enums_1.CHAIN.ETHEREUM_SEPOLIA,
285
+ txHash: HASH.sE,
286
+ to: ADDR.vaultSepolia,
287
+ logs: [
288
+ {
289
+ event: events_1.EVENT_UNIVERSAL_TX_FINALIZED,
290
+ args: {
291
+ subTxId: SUB_TX,
292
+ universalTxId: UTX_A,
293
+ pushAccount: ADDR.uea,
294
+ recipient: ADDR.recipient,
295
+ token: ADDR.token,
296
+ amount: BigInt(500),
297
+ data: '0x',
298
+ },
299
+ address: ADDR.vaultSepolia,
300
+ logIndex: 5,
301
+ },
302
+ {
303
+ event: events_1.EVENT_UNIVERSAL_TX_EXECUTED,
304
+ args: {
305
+ subTxId: SUB_TX,
306
+ universalTxId: UTX_A,
307
+ pushAccount: ADDR.uea,
308
+ target: ADDR.recipient,
309
+ token: ADDR.token,
310
+ amount: BigInt(500),
311
+ data: '0x',
312
+ },
313
+ address: ADDR.gatewaySepolia,
314
+ logIndex: 6,
315
+ },
316
+ ],
317
+ expectedDecoded: {
318
+ subTxId: SUB_TX,
319
+ universalTxId: UTX_A,
320
+ pushAccount: ADDR.uea,
321
+ },
322
+ expectedClassifyAll: ['OUTBOUND_FINALIZED', 'EXECUTED_ON_DEST'],
323
+ },
324
+ // S-F — OUTBOUND_REVERTED (Vault reverted; pcRevertExecution refund)
325
+ {
326
+ id: 'S-F',
327
+ name: 'OUTBOUND_REVERTED — BSC Vault emitted UniversalTxReverted',
328
+ kind: 'OUTBOUND_REVERTED',
329
+ chain: enums_1.CHAIN.BNB_TESTNET,
330
+ txHash: HASH.sF,
331
+ to: ADDR.vaultBsc,
332
+ logs: [
333
+ {
334
+ event: events_1.EVENT_UNIVERSAL_TX_REVERTED,
335
+ args: {
336
+ subTxId: SUB_TX,
337
+ universalTxId: UTX_A,
338
+ token: ADDR.token,
339
+ amount: BigInt(999),
340
+ revertInstruction: REVERT_INSTRUCTION_TUPLE,
341
+ },
342
+ address: ADDR.vaultBsc,
343
+ logIndex: 3,
344
+ },
345
+ ],
346
+ expectedDecoded: {
347
+ subTxId: SUB_TX,
348
+ universalTxId: UTX_A,
349
+ revertRecipient: ADDR.revertTo,
350
+ },
351
+ expectedClassifyAll: ['OUTBOUND_REVERTED'],
352
+ },
353
+ // S-G — INBOUND_REVERTED (RevertUniversalTx on external chain)
354
+ {
355
+ id: 'S-G',
356
+ name: 'INBOUND_REVERTED — Sepolia RevertUniversalTx',
357
+ kind: 'INBOUND_REVERTED',
358
+ chain: enums_1.CHAIN.ETHEREUM_SEPOLIA,
359
+ txHash: HASH.sG,
360
+ to: ADDR.gatewaySepolia,
361
+ logs: [
362
+ {
363
+ event: events_1.EVENT_REVERT_UNIVERSAL_TX,
364
+ args: {
365
+ subTxId: SUB_TX,
366
+ universalTxId: UTX_A,
367
+ to: ADDR.recipient,
368
+ token: ADDR.token,
369
+ amount: BigInt(1),
370
+ revertInstruction: REVERT_INSTRUCTION_TUPLE,
371
+ },
372
+ address: ADDR.gatewaySepolia,
373
+ logIndex: 12,
374
+ },
375
+ ],
376
+ expectedDecoded: {
377
+ subTxId: SUB_TX,
378
+ universalTxId: UTX_A,
379
+ revertRecipient: ADDR.revertTo,
380
+ },
381
+ expectedClassifyAll: ['INBOUND_REVERTED'],
382
+ },
383
+ // S-H — EXECUTED_ON_DEST (only UniversalTxExecuted log)
384
+ {
385
+ id: 'S-H',
386
+ name: 'EXECUTED_ON_DEST — Destination payload executed',
387
+ kind: 'EXECUTED_ON_DEST',
388
+ chain: enums_1.CHAIN.BNB_TESTNET,
389
+ txHash: HASH.sH,
390
+ to: ADDR.gatewayBsc,
391
+ logs: [
392
+ {
393
+ event: events_1.EVENT_UNIVERSAL_TX_EXECUTED,
394
+ args: {
395
+ subTxId: SUB_TX,
396
+ universalTxId: UTX_A,
397
+ pushAccount: ADDR.uea,
398
+ target: ADDR.recipient,
399
+ token: ADDR.token,
400
+ amount: BigInt(100),
401
+ data: '0xdeadbeef',
402
+ },
403
+ address: ADDR.gatewayBsc,
404
+ logIndex: 0,
405
+ },
406
+ ],
407
+ expectedDecoded: { subTxId: SUB_TX, universalTxId: UTX_A, pushAccount: ADDR.uea },
408
+ expectedClassifyAll: ['EXECUTED_ON_DEST'],
409
+ },
410
+ // S-I — RESCUED_FUNDS (FundsRescued event)
411
+ {
412
+ id: 'S-I',
413
+ name: 'RESCUED_FUNDS — Vault-side FundsRescued',
414
+ kind: 'RESCUED_FUNDS',
415
+ chain: enums_1.CHAIN.BNB_TESTNET,
416
+ txHash: HASH.sI,
417
+ to: ADDR.vaultBsc,
418
+ logs: [
419
+ {
420
+ event: events_1.EVENT_FUNDS_RESCUED,
421
+ args: {
422
+ subTxId: SUB_TX,
423
+ universalTxId: UTX_A,
424
+ token: ADDR.token,
425
+ amount: BigInt(777),
426
+ revertInstruction: REVERT_INSTRUCTION_TUPLE,
427
+ },
428
+ address: ADDR.vaultBsc,
429
+ logIndex: 0,
430
+ },
431
+ ],
432
+ expectedDecoded: { subTxId: SUB_TX, universalTxId: UTX_A },
433
+ expectedClassifyAll: ['RESCUED_FUNDS'],
434
+ },
435
+ // S-J — UNKNOWN (receipt with no universal-tx events)
436
+ {
437
+ id: 'S-J',
438
+ name: 'UNKNOWN — receipt with no universal-tx events',
439
+ kind: 'UNKNOWN',
440
+ chain: enums_1.CHAIN.BNB_TESTNET,
441
+ txHash: HASH.sJ,
442
+ to: ADDR.gatewayBsc,
443
+ logs: [],
444
+ expectedClassifyAll: [],
445
+ },
446
+ // S-K — PENDING outbound (cascade-only; externalTxHash empty)
447
+ {
448
+ id: 'S-K',
449
+ name: 'PENDING outbound — Push root, outbound not yet observed',
450
+ kind: 'OUTBOUND_INITIATED',
451
+ chain: enums_1.CHAIN.PUSH_TESTNET_DONUT,
452
+ txHash: HASH.sK,
453
+ to: ADDR.pcGateway,
454
+ logs: [
455
+ {
456
+ event: events_1.EVENT_UNIVERSAL_TX_OUTBOUND,
457
+ args: outboundArgs(SUB_TX, enums_1.CHAIN.BNB_TESTNET, 3),
458
+ address: ADDR.pcGateway,
459
+ logIndex: 0,
460
+ },
461
+ ],
462
+ utxRecords: [
463
+ {
464
+ id: (0, child_inbounds_1.derivePcUniversalTxId)(enums_1.CHAIN.PUSH_TESTNET_DONUT, HASH.sK).slice(2),
465
+ record: pcUtxRecord({
466
+ txHash: HASH.sK,
467
+ universalStatus: 6, // OUTBOUND_PENDING
468
+ outboundTx: [
469
+ outboundTuple({
470
+ subTxId: SUB_TX,
471
+ destinationChain: enums_1.CHAIN.BNB_TESTNET,
472
+ outboundStatus: 1, // PENDING
473
+ // No externalTxHash → cascade edge has node=null
474
+ }),
475
+ ],
476
+ }),
477
+ },
478
+ ],
479
+ expectedCascade: {
480
+ rootKind: 'OUTBOUND_INITIATED',
481
+ outboundCount: 1,
482
+ refundCount: 0,
483
+ outboundDestinations: [enums_1.CHAIN.BNB_TESTNET],
484
+ totalFlatNodes: 1, // root only (outbound edge has node=null)
485
+ },
486
+ },
487
+ // S-L — Hash with no utx record (cascade-only)
488
+ {
489
+ id: 'S-L',
490
+ name: 'UNKNOWN + no utx record — cascade root resolves with zero children',
491
+ kind: 'UNKNOWN',
492
+ chain: enums_1.CHAIN.PUSH_TESTNET_DONUT,
493
+ txHash: HASH.sL,
494
+ to: ADDR.pcGateway,
495
+ logs: [],
496
+ utxRecords: [
497
+ {
498
+ id: (0, child_inbounds_1.derivePcUniversalTxId)(enums_1.CHAIN.PUSH_TESTNET_DONUT, HASH.sL).slice(2),
499
+ record: null,
500
+ },
501
+ ],
502
+ expectedClassifyAll: [],
503
+ expectedCascade: {
504
+ rootKind: 'UNKNOWN',
505
+ outboundCount: 0,
506
+ refundCount: 0,
507
+ childInboundCount: 0,
508
+ totalFlatNodes: 1,
509
+ },
510
+ },
511
+ // S-M — Mixed-destination fan-out (BSC + Sepolia EVM + Solana non-EVM)
512
+ {
513
+ id: 'S-M',
514
+ name: 'Mixed-destination fan-out — BSC + Sepolia + Solana',
515
+ kind: 'OUTBOUND_INITIATED',
516
+ chain: enums_1.CHAIN.PUSH_TESTNET_DONUT,
517
+ txHash: HASH.sM,
518
+ to: ADDR.pcGateway,
519
+ logs: [
520
+ {
521
+ event: events_1.EVENT_UNIVERSAL_TX_OUTBOUND,
522
+ args: outboundArgs(SUB_TX, enums_1.CHAIN.BNB_TESTNET, 3),
523
+ address: ADDR.pcGateway,
524
+ logIndex: 0,
525
+ },
526
+ {
527
+ event: events_1.EVENT_UNIVERSAL_TX_OUTBOUND,
528
+ args: outboundArgs(SUB_TX_2, enums_1.CHAIN.ETHEREUM_SEPOLIA, 3),
529
+ address: ADDR.pcGateway,
530
+ logIndex: 1,
531
+ },
532
+ {
533
+ event: events_1.EVENT_UNIVERSAL_TX_OUTBOUND,
534
+ args: outboundArgs(SUB_TX_3, enums_1.CHAIN.SOLANA_DEVNET, 3),
535
+ address: ADDR.pcGateway,
536
+ logIndex: 2,
537
+ },
538
+ ],
539
+ extraReceipts: [
540
+ {
541
+ txHash: HASH.bscDest,
542
+ chain: enums_1.CHAIN.BNB_TESTNET,
543
+ to: ADDR.vaultBsc,
544
+ logs: [], // terminal — no events needed for this scenario's assertions
545
+ },
546
+ {
547
+ txHash: HASH.sepoliaDest,
548
+ chain: enums_1.CHAIN.ETHEREUM_SEPOLIA,
549
+ to: ADDR.vaultSepolia,
550
+ logs: [],
551
+ },
552
+ ],
553
+ utxRecords: [
554
+ {
555
+ id: (0, child_inbounds_1.derivePcUniversalTxId)(enums_1.CHAIN.PUSH_TESTNET_DONUT, HASH.sM).slice(2),
556
+ record: pcUtxRecord({
557
+ txHash: HASH.sM,
558
+ outboundTx: [
559
+ outboundTuple({
560
+ subTxId: SUB_TX,
561
+ destinationChain: enums_1.CHAIN.BNB_TESTNET,
562
+ externalTxHash: HASH.bscDest,
563
+ }),
564
+ outboundTuple({
565
+ subTxId: SUB_TX_2,
566
+ destinationChain: enums_1.CHAIN.ETHEREUM_SEPOLIA,
567
+ externalTxHash: HASH.sepoliaDest,
568
+ }),
569
+ outboundTuple({
570
+ subTxId: SUB_TX_3,
571
+ destinationChain: enums_1.CHAIN.SOLANA_DEVNET,
572
+ externalTxHash: HASH.solanaDest,
573
+ }),
574
+ ],
575
+ }),
576
+ },
577
+ ],
578
+ expectedCascade: {
579
+ rootKind: 'OUTBOUND_INITIATED',
580
+ outboundCount: 3,
581
+ refundCount: 0,
582
+ outboundDestinations: [
583
+ enums_1.CHAIN.BNB_TESTNET,
584
+ enums_1.CHAIN.ETHEREUM_SEPOLIA,
585
+ enums_1.CHAIN.SOLANA_DEVNET,
586
+ ],
587
+ // root + BSC + Sepolia + Solana (SVM now expands; with no SVM fixture
588
+ // the Solana destination resolves to an empty UNKNOWN node but still
589
+ // contributes a CascadeNode to the flattened list)
590
+ totalFlatNodes: 4,
591
+ },
592
+ },
593
+ // S-N — Fan-out with one delivered + one reverted leg (dual refund edges)
594
+ {
595
+ id: 'S-N',
596
+ name: 'Fan-out delivered + reverted — dual pc-refund/pc-revert edges',
597
+ kind: 'OUTBOUND_INITIATED',
598
+ chain: enums_1.CHAIN.PUSH_TESTNET_DONUT,
599
+ txHash: HASH.sN,
600
+ to: ADDR.pcGateway,
601
+ logs: [
602
+ {
603
+ event: events_1.EVENT_UNIVERSAL_TX_OUTBOUND,
604
+ args: outboundArgs(SUB_TX, enums_1.CHAIN.BNB_TESTNET, 3),
605
+ address: ADDR.pcGateway,
606
+ logIndex: 0,
607
+ },
608
+ {
609
+ event: events_1.EVENT_UNIVERSAL_TX_OUTBOUND,
610
+ args: outboundArgs(SUB_TX_2, enums_1.CHAIN.BNB_TESTNET, 3),
611
+ address: ADDR.pcGateway,
612
+ logIndex: 1,
613
+ },
614
+ ],
615
+ extraReceipts: [
616
+ {
617
+ txHash: HASH.bscDest,
618
+ chain: enums_1.CHAIN.BNB_TESTNET,
619
+ to: ADDR.vaultBsc,
620
+ logs: [],
621
+ },
622
+ ],
623
+ utxRecords: [
624
+ {
625
+ id: (0, child_inbounds_1.derivePcUniversalTxId)(enums_1.CHAIN.PUSH_TESTNET_DONUT, HASH.sN).slice(2),
626
+ record: pcUtxRecord({
627
+ txHash: HASH.sN,
628
+ outboundTx: [
629
+ // Delivered leg
630
+ outboundTuple({
631
+ subTxId: SUB_TX,
632
+ destinationChain: enums_1.CHAIN.BNB_TESTNET,
633
+ externalTxHash: HASH.bscDest,
634
+ outboundStatus: 2, // OBSERVED
635
+ pcRefundExecution: refundTx(HASH.pcRefundA),
636
+ }),
637
+ // Reverted leg
638
+ outboundTuple({
639
+ subTxId: SUB_TX_2,
640
+ destinationChain: enums_1.CHAIN.BNB_TESTNET,
641
+ externalTxHash: HASH.bscDest,
642
+ outboundStatus: 3, // REVERTED
643
+ pcRevertExecution: refundTx(HASH.pcRevertA, 50000),
644
+ }),
645
+ ],
646
+ }),
647
+ },
648
+ {
649
+ id: (0, child_inbounds_1.derivePcUniversalTxId)(enums_1.CHAIN.PUSH_TESTNET_DONUT, HASH.pcRefundA).slice(2),
650
+ record: null,
651
+ },
652
+ {
653
+ id: (0, child_inbounds_1.derivePcUniversalTxId)(enums_1.CHAIN.PUSH_TESTNET_DONUT, HASH.pcRevertA).slice(2),
654
+ record: null,
655
+ },
656
+ ],
657
+ expectedCascade: {
658
+ rootKind: 'OUTBOUND_INITIATED',
659
+ outboundCount: 2,
660
+ refundCount: 2,
661
+ outboundDestinations: [enums_1.CHAIN.BNB_TESTNET, enums_1.CHAIN.BNB_TESTNET],
662
+ // root + 2 BSC dest nodes (only 1 visited due to cycle dedupe) + 2 refunds
663
+ // The walker visits each unique (chain, txHash) once — both outbound legs
664
+ // point at HASH.bscDest, so the second walk returns null (cycle guard).
665
+ totalFlatNodes: 4,
666
+ },
667
+ },
668
+ ];
669
+ //# sourceMappingURL=scenarios.js.map