@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
@@ -10,7 +10,6 @@ exports.PushChainExecutionError = void 0;
10
10
  exports.sendPushTx = sendPushTx;
11
11
  exports.sendUniversalTx = sendUniversalTx;
12
12
  exports.extractPcTxAndTransform = extractPcTxAndTransform;
13
- const tslib_1 = require("tslib");
14
13
  const bs58_1 = require("../../internal/bs58");
15
14
  const viem_1 = require("viem");
16
15
  const chain_1 = require("../../constants/chain");
@@ -25,36 +24,34 @@ const formatters_1 = require("../../formatters");
25
24
  const PUSH_TX_INDEX_TIMEOUT_MS = 30000;
26
25
  const PUSH_TX_INDEX_POLL_MS = 1000;
27
26
  const TX_NOT_INDEXED_RE = /not found|TransactionNotFound|TransactionReceiptNotFound|could not be found|No transaction found/i;
28
- function getIndexedPushTransaction(ctx, txHash, label) {
29
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
30
- const startedAt = Date.now();
31
- let receiptWaited = false;
32
- let retryLogged = false;
33
- // eslint-disable-next-line no-constant-condition
34
- while (true) {
35
- try {
36
- if (!receiptWaited) {
37
- yield ctx.pushClient.publicClient.waitForTransactionReceipt({
38
- hash: txHash,
39
- });
40
- receiptWaited = true;
41
- }
42
- return yield ctx.pushClient.getTransaction(txHash);
27
+ async function getIndexedPushTransaction(ctx, txHash, label) {
28
+ const startedAt = Date.now();
29
+ let receiptWaited = false;
30
+ let retryLogged = false;
31
+ // eslint-disable-next-line no-constant-condition
32
+ while (true) {
33
+ try {
34
+ if (!receiptWaited) {
35
+ await ctx.pushClient.publicClient.waitForTransactionReceipt({
36
+ hash: txHash,
37
+ });
38
+ receiptWaited = true;
43
39
  }
44
- catch (err) {
45
- const msg = (err === null || err === void 0 ? void 0 : err.shortMessage) || (err === null || err === void 0 ? void 0 : err.message) || String(err);
46
- const retryable = TX_NOT_INDEXED_RE.test(msg);
47
- if (!retryable || Date.now() - startedAt >= PUSH_TX_INDEX_TIMEOUT_MS) {
48
- throw err;
49
- }
50
- if (!retryLogged) {
51
- (0, context_1.printLog)(ctx, `${label} — Push tx ${txHash} has a receipt but is not indexed yet; retrying transaction lookup`);
52
- retryLogged = true;
53
- }
54
- yield new Promise((r) => setTimeout(r, PUSH_TX_INDEX_POLL_MS));
40
+ return await ctx.pushClient.getTransaction(txHash);
41
+ }
42
+ catch (err) {
43
+ const msg = err?.shortMessage || err?.message || String(err);
44
+ const retryable = TX_NOT_INDEXED_RE.test(msg);
45
+ if (!retryable || Date.now() - startedAt >= PUSH_TX_INDEX_TIMEOUT_MS) {
46
+ throw err;
55
47
  }
48
+ if (!retryLogged) {
49
+ (0, context_1.printLog)(ctx, `${label} — Push tx ${txHash} has a receipt but is not indexed yet; retrying transaction lookup`);
50
+ retryLogged = true;
51
+ }
52
+ await new Promise((r) => setTimeout(r, PUSH_TX_INDEX_POLL_MS));
56
53
  }
57
- });
54
+ }
58
55
  }
59
56
  // ============================================================================
60
57
  // sendPushTx
@@ -66,142 +63,137 @@ function getIndexedPushTransaction(ctx, txHash, label) {
66
63
  * For multicall arrays: executes each call as a separate transaction with
67
64
  * local nonce management and per-tx receipt confirmation.
68
65
  */
69
- function sendPushTx(ctx, execute, eventBuffer, transformFn) {
70
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
71
- var _a, _b, _c;
72
- if (Array.isArray(execute.data)) {
73
- const calls = execute.data;
74
- // Reject a zero `to` BEFORE route selection so behaviour is identical
75
- // regardless of signer capability: ERC-7821 (the 7702 path) reinterprets
76
- // `target == 0` as the account itself, whereas the legacy loop would send to
77
- // the zero address. A zero target is almost always a bug — disallow it.
78
- if (calls.some((c) => /^0x0{40}$/i.test(c.to))) {
79
- throw new errors_1.PushChainExecutionError('A multicall entry has a zero `to` address. Use an explicit target ' +
80
- '(the EIP-7702 executor reinterprets a zero target as the account itself).');
66
+ async function sendPushTx(ctx, execute, eventBuffer, transformFn) {
67
+ if (Array.isArray(execute.data)) {
68
+ const calls = execute.data;
69
+ // Reject a zero `to` BEFORE route selection so behaviour is identical
70
+ // regardless of signer capability: ERC-7821 (the 7702 path) reinterprets
71
+ // `target == 0` as the account itself, whereas the legacy loop would send to
72
+ // the zero address. A zero target is almost always a bug — disallow it.
73
+ if (calls.some((c) => /^0x0{40}$/i.test(c.to))) {
74
+ throw new errors_1.PushChainExecutionError('A multicall entry has a zero `to` address. Use an explicit target ' +
75
+ '(the EIP-7702 executor reinterprets a zero target as the account itself).');
76
+ }
77
+ // Preferred path: execute the batch atomically in a single EIP-7702 type-4
78
+ // transaction. Requires (a) a deployed PushBatchExecutor on this chain and
79
+ // (b) a wallet that can sign a 7702 authorization. When either is missing we
80
+ // fall back to the legacy non-atomic per-call loop below.
81
+ const executor = (0, chain_1.getBatchExecutorAddress)(ctx.universalSigner.account.chain);
82
+ if (executor && ctx.universalSigner.signAuthorization) {
83
+ try {
84
+ (0, context_1.printLog)(ctx, `sendPushTx — executing ${calls.length} call(s) atomically via EIP-7702 (executor: ${executor})`);
85
+ const txHash = await ctx.pushClient.sendBatch7702({
86
+ executor,
87
+ calls,
88
+ signer: ctx.universalSigner,
89
+ });
90
+ const txResponse = await getIndexedPushTransaction(ctx, txHash, 'sendPushTx');
91
+ return await transformFn(txResponse, eventBuffer);
92
+ }
93
+ catch (err) {
94
+ // Only fall back when the wallet genuinely can't sign a 7702
95
+ // authorization. This is raised before any broadcast, so falling back
96
+ // to sequential execution cannot double-execute. Any other error
97
+ // (e.g. a real revert) must surface.
98
+ if (!(err instanceof evm_client_1.EIP7702NotSupportedError))
99
+ throw err;
100
+ (0, context_1.printLog)(ctx, `sendPushTx — wallet cannot sign EIP-7702 authorization; falling back to sequential execution`);
101
+ // eslint-disable-next-line no-console
102
+ console.warn('[push-chain] Wallet cannot produce an EIP-7702 authorization — batch ' +
103
+ 'will execute as separate, non-atomic transactions (if one call reverts, ' +
104
+ 'earlier calls remain committed).');
81
105
  }
82
- // Preferred path: execute the batch atomically in a single EIP-7702 type-4
83
- // transaction. Requires (a) a deployed PushBatchExecutor on this chain and
84
- // (b) a wallet that can sign a 7702 authorization. When either is missing we
85
- // fall back to the legacy non-atomic per-call loop below.
86
- const executor = (0, chain_1.getBatchExecutorAddress)(ctx.universalSigner.account.chain);
87
- if (executor && ctx.universalSigner.signAuthorization) {
106
+ }
107
+ else if (!ctx.universalSigner.signAuthorization) {
108
+ // eslint-disable-next-line no-console
109
+ console.warn('[push-chain] Signer does not support EIP-7702 — batch will execute as ' +
110
+ 'separate, non-atomic transactions (if one call reverts, earlier calls ' +
111
+ 'remain committed).');
112
+ }
113
+ const MAX_NONCE_RETRIES = 3;
114
+ let nonce = await ctx.pushClient.publicClient.getTransactionCount({
115
+ address: ctx.universalSigner.account.address,
116
+ blockTag: 'pending',
117
+ });
118
+ let lastTxHash = '0x';
119
+ for (let i = 0; i < calls.length; i++) {
120
+ const call = calls[i];
121
+ let txSent = false;
122
+ for (let retry = 0; retry < MAX_NONCE_RETRIES && !txSent; retry++) {
88
123
  try {
89
- (0, context_1.printLog)(ctx, `sendPushTx — executing ${calls.length} call(s) atomically via EIP-7702 (executor: ${executor})`);
90
- const txHash = yield ctx.pushClient.sendBatch7702({
91
- executor,
92
- calls,
124
+ (0, context_1.printLog)(ctx, `sendPushTx — executing multicall operation ${i + 1}/${calls.length} to: ${call.to} (nonce: ${nonce})`);
125
+ lastTxHash = await ctx.pushClient.sendTransaction({
126
+ to: call.to,
127
+ data: (call.data || '0x'),
128
+ value: call.value,
93
129
  signer: ctx.universalSigner,
130
+ nonce,
94
131
  });
95
- const txResponse = yield getIndexedPushTransaction(ctx, txHash, 'sendPushTx');
96
- return yield transformFn(txResponse, eventBuffer);
132
+ txSent = true;
97
133
  }
98
134
  catch (err) {
99
- // Only fall back when the wallet genuinely can't sign a 7702
100
- // authorization. This is raised before any broadcast, so falling back
101
- // to sequential execution cannot double-execute. Any other error
102
- // (e.g. a real revert) must surface.
103
- if (!(err instanceof evm_client_1.EIP7702NotSupportedError))
135
+ const msg = err?.message || err?.details || '';
136
+ if (msg.includes('invalid nonce') || msg.includes('invalid sequence')) {
137
+ (0, context_1.printLog)(ctx, `sendPushTx — nonce mismatch on operation ${i + 1}/${calls.length} (retry ${retry + 1}/${MAX_NONCE_RETRIES}), re-fetching nonce`);
138
+ nonce = await ctx.pushClient.publicClient.getTransactionCount({
139
+ address: ctx.universalSigner.account.address,
140
+ blockTag: 'pending',
141
+ });
142
+ }
143
+ else {
104
144
  throw err;
105
- (0, context_1.printLog)(ctx, `sendPushTx — wallet cannot sign EIP-7702 authorization; falling back to sequential execution`);
106
- // eslint-disable-next-line no-console
107
- console.warn('[push-chain] Wallet cannot produce an EIP-7702 authorization — batch ' +
108
- 'will execute as separate, non-atomic transactions (if one call reverts, ' +
109
- 'earlier calls remain committed).');
145
+ }
110
146
  }
111
147
  }
112
- else if (!ctx.universalSigner.signAuthorization) {
113
- // eslint-disable-next-line no-console
114
- console.warn('[push-chain] Signer does not support EIP-7702 — batch will execute as ' +
115
- 'separate, non-atomic transactions (if one call reverts, earlier calls ' +
116
- 'remain committed).');
148
+ if (!txSent) {
149
+ throw new Error(`sendPushTx — multicall operation ${i + 1}/${calls.length} failed after ${MAX_NONCE_RETRIES} nonce retries`);
117
150
  }
118
- const PUSH_CHAIN_GAS_LIMIT = BigInt(500000);
119
- const MAX_NONCE_RETRIES = 3;
120
- let nonce = yield ctx.pushClient.publicClient.getTransactionCount({
121
- address: ctx.universalSigner.account.address,
122
- blockTag: 'pending',
151
+ const receipt = await ctx.pushClient.publicClient.waitForTransactionReceipt({
152
+ hash: lastTxHash,
123
153
  });
124
- let lastTxHash = '0x';
125
- for (let i = 0; i < calls.length; i++) {
126
- const call = calls[i];
127
- let txSent = false;
128
- for (let retry = 0; retry < MAX_NONCE_RETRIES && !txSent; retry++) {
129
- try {
130
- (0, context_1.printLog)(ctx, `sendPushTx — executing multicall operation ${i + 1}/${calls.length} to: ${call.to} (nonce: ${nonce})`);
131
- lastTxHash = yield ctx.pushClient.sendTransaction({
132
- to: call.to,
133
- data: (call.data || '0x'),
134
- value: call.value,
135
- signer: ctx.universalSigner,
136
- nonce,
137
- gas: PUSH_CHAIN_GAS_LIMIT,
138
- });
139
- txSent = true;
140
- }
141
- catch (err) {
142
- const msg = (err === null || err === void 0 ? void 0 : err.message) || (err === null || err === void 0 ? void 0 : err.details) || '';
143
- if (msg.includes('invalid nonce') || msg.includes('invalid sequence')) {
144
- (0, context_1.printLog)(ctx, `sendPushTx — nonce mismatch on operation ${i + 1}/${calls.length} (retry ${retry + 1}/${MAX_NONCE_RETRIES}), re-fetching nonce`);
145
- nonce = yield ctx.pushClient.publicClient.getTransactionCount({
146
- address: ctx.universalSigner.account.address,
147
- blockTag: 'pending',
148
- });
149
- }
150
- else {
151
- throw err;
152
- }
153
- }
154
- }
155
- if (!txSent) {
156
- throw new Error(`sendPushTx — multicall operation ${i + 1}/${calls.length} failed after ${MAX_NONCE_RETRIES} nonce retries`);
154
+ if (receipt.status === 'reverted') {
155
+ // Simulate the failed call to extract the revert reason
156
+ let revertReason = 'unknown';
157
+ try {
158
+ await ctx.pushClient.publicClient.call({
159
+ to: call.to,
160
+ data: (call.data || '0x'),
161
+ value: call.value,
162
+ account: ctx.universalSigner.account.address,
163
+ blockNumber: receipt.blockNumber,
164
+ });
157
165
  }
158
- const receipt = yield ctx.pushClient.publicClient.waitForTransactionReceipt({
159
- hash: lastTxHash,
160
- });
161
- if (receipt.status === 'reverted') {
162
- // Simulate the failed call to extract the revert reason
163
- let revertReason = 'unknown';
164
- try {
165
- yield ctx.pushClient.publicClient.call({
166
- to: call.to,
167
- data: (call.data || '0x'),
168
- value: call.value,
169
- account: ctx.universalSigner.account.address,
170
- blockNumber: receipt.blockNumber,
171
- });
166
+ catch (simErr) {
167
+ // viem decodes common revert reasons into shortMessage
168
+ revertReason =
169
+ simErr?.shortMessage || simErr?.cause?.reason || simErr?.cause?.message || simErr?.message || String(simErr);
170
+ // Also log the raw revert data if available
171
+ const revertData = simErr?.cause?.data || simErr?.data;
172
+ if (revertData) {
173
+ revertReason += ` [data: ${revertData}]`;
172
174
  }
173
- catch (simErr) {
174
- // viem decodes common revert reasons into shortMessage
175
- revertReason =
176
- (simErr === null || simErr === void 0 ? void 0 : simErr.shortMessage) || ((_a = simErr === null || simErr === void 0 ? void 0 : simErr.cause) === null || _a === void 0 ? void 0 : _a.reason) || ((_b = simErr === null || simErr === void 0 ? void 0 : simErr.cause) === null || _b === void 0 ? void 0 : _b.message) || (simErr === null || simErr === void 0 ? void 0 : simErr.message) || String(simErr);
177
- // Also log the raw revert data if available
178
- const revertData = ((_c = simErr === null || simErr === void 0 ? void 0 : simErr.cause) === null || _c === void 0 ? void 0 : _c.data) || (simErr === null || simErr === void 0 ? void 0 : simErr.data);
179
- if (revertData) {
180
- revertReason += ` [data: ${revertData}]`;
181
- }
182
- }
183
- (0, context_1.printLog)(ctx, `sendPushTx — multicall operation ${i + 1}/${calls.length} reverted (to: ${call.to}, txHash: ${lastTxHash}, revertReason: ${revertReason})`);
184
- throw new Error(`sendPushTx — multicall operation ${i + 1}/${calls.length} reverted (to: ${call.to}, txHash: ${lastTxHash}, revertReason: ${revertReason})`);
185
175
  }
186
- (0, context_1.printLog)(ctx, `sendPushTx — operation ${i + 1}/${calls.length} confirmed in block ${receipt.blockNumber}`);
187
- nonce++;
176
+ (0, context_1.printLog)(ctx, `sendPushTx — multicall operation ${i + 1}/${calls.length} reverted (to: ${call.to}, txHash: ${lastTxHash}, revertReason: ${revertReason})`);
177
+ throw new Error(`sendPushTx — multicall operation ${i + 1}/${calls.length} reverted (to: ${call.to}, txHash: ${lastTxHash}, revertReason: ${revertReason})`);
188
178
  }
189
- const txResponse = yield getIndexedPushTransaction(ctx, lastTxHash, 'sendPushTx');
190
- // Sequential fallback: each call was a separate tx, so the batch is NOT
191
- // atomic (an earlier call can be committed while a later one reverts).
192
- const resp = yield transformFn(txResponse, eventBuffer);
193
- resp.atomic = false;
194
- return resp;
179
+ (0, context_1.printLog)(ctx, `sendPushTx — operation ${i + 1}/${calls.length} confirmed in block ${receipt.blockNumber}`);
180
+ nonce++;
195
181
  }
196
- const txHash = yield ctx.pushClient.sendTransaction({
197
- to: execute.to,
198
- data: (execute.data || '0x'),
199
- value: execute.value,
200
- signer: ctx.universalSigner,
201
- });
202
- const txResponse = yield getIndexedPushTransaction(ctx, txHash, 'sendPushTx');
203
- return yield transformFn(txResponse, eventBuffer);
182
+ const txResponse = await getIndexedPushTransaction(ctx, lastTxHash, 'sendPushTx');
183
+ // Sequential fallback: each call was a separate tx, so the batch is NOT
184
+ // atomic (an earlier call can be committed while a later one reverts).
185
+ const resp = await transformFn(txResponse, eventBuffer);
186
+ resp.atomic = false;
187
+ return resp;
188
+ }
189
+ const txHash = await ctx.pushClient.sendTransaction({
190
+ to: execute.to,
191
+ data: (execute.data || '0x'),
192
+ value: execute.value,
193
+ signer: ctx.universalSigner,
204
194
  });
195
+ const txResponse = await getIndexedPushTransaction(ctx, txHash, 'sendPushTx');
196
+ return await transformFn(txResponse, eventBuffer);
205
197
  }
206
198
  // ============================================================================
207
199
  // sendUniversalTx
@@ -230,139 +222,138 @@ const SEQ_RETRY_BASE_DELAY_MS = 400;
230
222
  * `InvalidEVMSignature()` selector. Each retry calls `resignFn` to obtain
231
223
  * a payload re-signed against the UEA's current on-chain nonce.
232
224
  */
233
- function sendUniversalTx(ctx, isUEADeployed, feeLockTxHash, universalPayload, verificationData, eventBuffer, transformFn, resignFn) {
234
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
235
- var _a, _b, _c, _d, _e;
236
- const { chain, address } = ctx.universalSigner.account;
237
- const { vm, chainId } = chain_1.CHAIN_INFO[chain];
238
- const universalAccountId = {
239
- chainNamespace: chain_1.VM_NAMESPACE[vm],
240
- chainId: chainId,
241
- owner: vm === enums_1.VM.EVM
242
- ? address
243
- : vm === enums_1.VM.SVM
244
- ? (0, viem_1.bytesToHex)(new Uint8Array(bs58_1.bs58.decode(address)))
245
- : address,
246
- };
247
- const { cosmosAddress: signer } = ctx.pushClient.getSignerAddress();
248
- let currentPayload = universalPayload;
249
- let currentVerificationData = verificationData;
250
- let tx;
251
- let seqRetryCount = 0;
252
- for (let attempt = 0; attempt <= MAX_SIG_RETRIES; attempt++) {
253
- const msgs = [];
254
- if (currentPayload && currentVerificationData) {
255
- msgs.push(ctx.pushClient.createMsgExecutePayload({
256
- signer,
257
- universalAccountId,
258
- universalPayload: currentPayload,
259
- verificationData: currentVerificationData,
260
- }));
261
- }
262
- const txBody = yield ctx.pushClient.createCosmosTxBody(msgs);
263
- const txRaw = yield ctx.pushClient.signCosmosTx(txBody);
264
- try {
265
- tx = yield ctx.pushClient.broadcastCosmosTx(txRaw);
266
- }
267
- catch (err) {
268
- const msg = (err === null || err === void 0 ? void 0 : err.message) || String(err);
269
- if (COSMOS_SEQUENCE_MISMATCH_RE.test(msg) &&
270
- seqRetryCount < MAX_SEQ_RETRIES) {
271
- seqRetryCount++;
272
- const delay = Math.round(SEQ_RETRY_BASE_DELAY_MS * seqRetryCount * (1 + Math.random() * 0.2));
273
- (0, context_1.printLog)(ctx, `sendUniversalTx — Cosmos sequence mismatch on broadcast (retry ${seqRetryCount}/${MAX_SEQ_RETRIES}), sleeping ${delay}ms: ${msg}`);
274
- yield new Promise((r) => setTimeout(r, delay));
275
- attempt--; // don't consume EVM-signature retry budget
276
- continue;
277
- }
278
- throw err;
279
- }
280
- if (tx.code === 0)
281
- break;
282
- // Cosmos sequence race: returned via tx.rawLog rather than thrown
283
- const isSeqMismatch = typeof tx.rawLog === 'string' &&
284
- COSMOS_SEQUENCE_MISMATCH_RE.test(tx.rawLog);
285
- if (isSeqMismatch && seqRetryCount < MAX_SEQ_RETRIES) {
225
+ async function sendUniversalTx(ctx, isUEADeployed, feeLockTxHash, universalPayload, verificationData, eventBuffer, transformFn, resignFn) {
226
+ const { chain, address } = ctx.universalSigner.account;
227
+ const { vm, chainId } = chain_1.CHAIN_INFO[chain];
228
+ const universalAccountId = {
229
+ chainNamespace: chain_1.VM_NAMESPACE[vm],
230
+ chainId: chainId,
231
+ owner: vm === enums_1.VM.EVM
232
+ ? address
233
+ : vm === enums_1.VM.SVM
234
+ ? (0, viem_1.bytesToHex)(new Uint8Array(bs58_1.bs58.decode(address)))
235
+ : address,
236
+ };
237
+ const { cosmosAddress: signer } = ctx.pushClient.getSignerAddress();
238
+ let currentPayload = universalPayload;
239
+ let currentVerificationData = verificationData;
240
+ let tx;
241
+ let seqRetryCount = 0;
242
+ for (let attempt = 0; attempt <= MAX_SIG_RETRIES; attempt++) {
243
+ const msgs = [];
244
+ if (currentPayload && currentVerificationData) {
245
+ msgs.push(ctx.pushClient.createMsgExecutePayload({
246
+ signer,
247
+ universalAccountId,
248
+ universalPayload: currentPayload,
249
+ verificationData: currentVerificationData,
250
+ }));
251
+ }
252
+ const txBody = await ctx.pushClient.createCosmosTxBody(msgs);
253
+ const txRaw = await ctx.pushClient.signCosmosTx(txBody);
254
+ try {
255
+ tx = await ctx.pushClient.broadcastCosmosTx(txRaw);
256
+ }
257
+ catch (err) {
258
+ const msg = err?.message || String(err);
259
+ if (COSMOS_SEQUENCE_MISMATCH_RE.test(msg) &&
260
+ seqRetryCount < MAX_SEQ_RETRIES) {
286
261
  seqRetryCount++;
287
262
  const delay = Math.round(SEQ_RETRY_BASE_DELAY_MS * seqRetryCount * (1 + Math.random() * 0.2));
288
- (0, context_1.printLog)(ctx, `sendUniversalTx — Cosmos sequence mismatch in tx.rawLog (retry ${seqRetryCount}/${MAX_SEQ_RETRIES}), sleeping ${delay}ms: ${tx.rawLog}`);
289
- yield new Promise((r) => setTimeout(r, delay));
263
+ (0, context_1.printLog)(ctx, `sendUniversalTx — Cosmos sequence mismatch on broadcast (retry ${seqRetryCount}/${MAX_SEQ_RETRIES}), sleeping ${delay}ms: ${msg}`);
264
+ await new Promise((r) => setTimeout(r, delay));
290
265
  attempt--; // don't consume EVM-signature retry budget
291
266
  continue;
292
267
  }
293
- // Nonce-race retry: UEA storage nonce advanced between our read and
294
- // tx inclusion. Re-sign with the fresh nonce and rebroadcast.
295
- const isSigMismatch = typeof tx.rawLog === 'string' &&
296
- tx.rawLog.includes(INVALID_EVM_SIGNATURE_SELECTOR);
297
- if (attempt < MAX_SIG_RETRIES && isSigMismatch && resignFn) {
298
- (0, context_1.printLog)(ctx, `sendUniversalTx — InvalidEVMSignature on attempt ${attempt + 1} (${tx.rawLog}); re-signing with fresh UEA nonce (retry ${attempt + 1}/${MAX_SIG_RETRIES})`);
299
- const fresh = yield resignFn();
300
- currentPayload = fresh.universalPayload;
301
- currentVerificationData = fresh.verificationData;
302
- continue;
303
- }
304
- // Terminal failure
305
- const failedEthTxHashes = (_b = (_a = tx.events) === null || _a === void 0 ? void 0 : _a.filter((e) => e.type === 'ethereum_tx').flatMap((e) => {
306
- var _a;
307
- return (_a = e.attributes) === null || _a === void 0 ? void 0 : _a.filter((attr) => attr.key === 'ethereumTxHash').map((attr) => attr.value);
308
- })) !== null && _b !== void 0 ? _b : [];
309
- // Decode known revert selectors (e.g. `ret 0xacfdb444`) from the cosmos
310
- // rawLog so the consumer-facing error AND the diagnostic failureSummary
311
- // log carry an actionable hint instead of raw 4-byte hex. Mirrors the
312
- // wiring in `extractPcTxAndTransform` for the post-success `pcTx FAILED`
313
- // path. Also feeds the structured `decodedError` payload through to the
314
- // terminal hook (199-02 / 299-02 / 399-02 / 999-02).
315
- const rawMessage = (_c = tx.rawLog) !== null && _c !== void 0 ? _c : '';
316
- let publicMessage = (0, formatters_1.normalizePublicErrorMessage)(rawMessage);
317
- let decodedForPayload;
318
- const decoded = (0, error_decoder_1.decodeRevert)(rawMessage);
319
- if ((decoded === null || decoded === void 0 ? void 0 : decoded.kind) === 'custom') {
320
- publicMessage = (0, error_decoder_1.formatDecodedRevertForUser)(decoded);
321
- decodedForPayload = {
322
- name: decoded.name,
323
- hint: decoded.hint,
324
- selector: decoded.selector,
325
- };
326
- }
327
- else if ((decoded === null || decoded === void 0 ? void 0 : decoded.kind) === 'string') {
328
- publicMessage = (0, error_decoder_1.formatDecodedRevertForUser)(decoded);
329
- decodedForPayload = {
330
- decoded: decoded.decoded,
331
- selector: decoded.selector,
332
- };
333
- }
334
- else if ((decoded === null || decoded === void 0 ? void 0 : decoded.kind) === 'unknown') {
335
- (0, context_1.printLog)(ctx, `[error-decoder] unknown selector ${decoded.selector} — consider adding to KNOWN_ERROR_SELECTORS`);
336
- }
337
- const failureSummary = [
338
- `PUSH CHAIN TRANSACTION FAILED`,
339
- `Cosmos TX Hash: ${tx.transactionHash}`,
340
- `Block Height: ${tx.height}, TX Code: ${tx.code} (error)`,
341
- `Gas Used: ${tx.gasUsed}, Gas Wanted: ${tx.gasWanted}`,
342
- ...(failedEthTxHashes.length > 0 ? [`Ethereum TX Hash(es): ${failedEthTxHashes.join(', ')}`] : []),
343
- `Error: ${publicMessage}`,
344
- ].join(' | ');
345
- (0, context_1.printLog)(ctx, failureSummary);
346
- // Throw a typed error so the orchestrator's outer catch can lift the
347
- // structured `decodedError` straight onto the terminal-hook payload.
348
- throw new errors_1.PushChainExecutionError(publicMessage, {
349
- decodedError: decodedForPayload,
350
- });
268
+ throw err;
351
269
  }
352
- if (!tx || tx.code !== 0) {
353
- throw new Error(`sendUniversalTx — unreachable: loop exited without success or throw`);
270
+ if (tx.code === 0)
271
+ break;
272
+ // Cosmos sequence race: returned via tx.rawLog rather than thrown
273
+ const isSeqMismatch = typeof tx.rawLog === 'string' &&
274
+ COSMOS_SEQUENCE_MISMATCH_RE.test(tx.rawLog);
275
+ if (isSeqMismatch && seqRetryCount < MAX_SEQ_RETRIES) {
276
+ seqRetryCount++;
277
+ const delay = Math.round(SEQ_RETRY_BASE_DELAY_MS * seqRetryCount * (1 + Math.random() * 0.2));
278
+ (0, context_1.printLog)(ctx, `sendUniversalTx — Cosmos sequence mismatch in tx.rawLog (retry ${seqRetryCount}/${MAX_SEQ_RETRIES}), sleeping ${delay}ms: ${tx.rawLog}`);
279
+ await new Promise((r) => setTimeout(r, delay));
280
+ attempt--; // don't consume EVM-signature retry budget
281
+ continue;
354
282
  }
355
- const ethTxHashes = (_e = (_d = tx.events) === null || _d === void 0 ? void 0 : _d.filter((e) => e.type === 'ethereum_tx').flatMap((e) => {
356
- var _a;
357
- return (_a = e.attributes) === null || _a === void 0 ? void 0 : _a.filter((attr) => attr.key === 'ethereumTxHash').map((attr) => attr.value);
358
- })) !== null && _e !== void 0 ? _e : [];
359
- if (ethTxHashes.length === 0) {
360
- throw new Error('No ethereumTxHash found in transaction events');
283
+ // Nonce-race retry: UEA storage nonce advanced between our read and
284
+ // tx inclusion. Re-sign with the fresh nonce and rebroadcast.
285
+ const isSigMismatch = typeof tx.rawLog === 'string' &&
286
+ tx.rawLog.includes(INVALID_EVM_SIGNATURE_SELECTOR);
287
+ if (attempt < MAX_SIG_RETRIES && isSigMismatch && resignFn) {
288
+ (0, context_1.printLog)(ctx, `sendUniversalTx — InvalidEVMSignature on attempt ${attempt + 1} (${tx.rawLog}); re-signing with fresh UEA nonce (retry ${attempt + 1}/${MAX_SIG_RETRIES})`);
289
+ const fresh = await resignFn();
290
+ currentPayload = fresh.universalPayload;
291
+ currentVerificationData = fresh.verificationData;
292
+ continue;
361
293
  }
362
- const evmTxs = yield Promise.all(ethTxHashes.map((hash) => tslib_1.__awaiter(this, void 0, void 0, function* () { return getIndexedPushTransaction(ctx, hash, 'sendUniversalTx'); })));
363
- const responses = yield Promise.all(evmTxs.map((tx, index) => transformFn(tx, index === evmTxs.length - 1 ? eventBuffer : [])));
364
- return responses;
365
- });
294
+ // Terminal failure
295
+ const failedEthTxHashes = tx.events
296
+ ?.filter((e) => e.type === 'ethereum_tx')
297
+ .flatMap((e) => e.attributes
298
+ ?.filter((attr) => attr.key === 'ethereumTxHash')
299
+ .map((attr) => attr.value)) ?? [];
300
+ // Decode known revert selectors (e.g. `ret 0xacfdb444`) from the cosmos
301
+ // rawLog so the consumer-facing error AND the diagnostic failureSummary
302
+ // log carry an actionable hint instead of raw 4-byte hex. Mirrors the
303
+ // wiring in `extractPcTxAndTransform` for the post-success `pcTx FAILED`
304
+ // path. Also feeds the structured `decodedError` payload through to the
305
+ // terminal hook (199-02 / 299-02 / 399-02 / 999-02).
306
+ const rawMessage = tx.rawLog ?? '';
307
+ let publicMessage = (0, formatters_1.normalizePublicErrorMessage)(rawMessage);
308
+ let decodedForPayload;
309
+ const decoded = (0, error_decoder_1.decodeRevert)(rawMessage);
310
+ if (decoded?.kind === 'custom') {
311
+ publicMessage = (0, error_decoder_1.formatDecodedRevertForUser)(decoded);
312
+ decodedForPayload = {
313
+ name: decoded.name,
314
+ hint: decoded.hint,
315
+ selector: decoded.selector,
316
+ };
317
+ }
318
+ else if (decoded?.kind === 'string') {
319
+ publicMessage = (0, error_decoder_1.formatDecodedRevertForUser)(decoded);
320
+ decodedForPayload = {
321
+ decoded: decoded.decoded,
322
+ selector: decoded.selector,
323
+ };
324
+ }
325
+ else if (decoded?.kind === 'unknown') {
326
+ (0, context_1.printLog)(ctx, `[error-decoder] unknown selector ${decoded.selector} — consider adding to KNOWN_ERROR_SELECTORS`);
327
+ }
328
+ const failureSummary = [
329
+ `PUSH CHAIN TRANSACTION FAILED`,
330
+ `Cosmos TX Hash: ${tx.transactionHash}`,
331
+ `Block Height: ${tx.height}, TX Code: ${tx.code} (error)`,
332
+ `Gas Used: ${tx.gasUsed}, Gas Wanted: ${tx.gasWanted}`,
333
+ ...(failedEthTxHashes.length > 0 ? [`Ethereum TX Hash(es): ${failedEthTxHashes.join(', ')}`] : []),
334
+ `Error: ${publicMessage}`,
335
+ ].join(' | ');
336
+ (0, context_1.printLog)(ctx, failureSummary);
337
+ // Throw a typed error so the orchestrator's outer catch can lift the
338
+ // structured `decodedError` straight onto the terminal-hook payload.
339
+ throw new errors_1.PushChainExecutionError(publicMessage, {
340
+ decodedError: decodedForPayload,
341
+ });
342
+ }
343
+ if (!tx || tx.code !== 0) {
344
+ throw new Error(`sendUniversalTx — unreachable: loop exited without success or throw`);
345
+ }
346
+ const ethTxHashes = tx.events
347
+ ?.filter((e) => e.type === 'ethereum_tx')
348
+ .flatMap((e) => e.attributes
349
+ ?.filter((attr) => attr.key === 'ethereumTxHash')
350
+ .map((attr) => attr.value)) ?? [];
351
+ if (ethTxHashes.length === 0) {
352
+ throw new Error('No ethereumTxHash found in transaction events');
353
+ }
354
+ const evmTxs = await Promise.all(ethTxHashes.map(async (hash) => getIndexedPushTransaction(ctx, hash, 'sendUniversalTx')));
355
+ const responses = await Promise.all(evmTxs.map((tx, index) => transformFn(tx, index === evmTxs.length - 1 ? eventBuffer : [])));
356
+ return responses;
366
357
  }
367
358
  // ============================================================================
368
359
  // extractPcTxAndTransform
@@ -371,66 +362,63 @@ function sendUniversalTx(ctx, isUEADeployed, feeLockTxHash, universalPayload, ve
371
362
  * Validates Push Chain tx response, extracts last pcTx, fetches EVM tx,
372
363
  * and transforms to UniversalTxResponse.
373
364
  */
374
- function extractPcTxAndTransform(ctx, pushChainUniversalTx, gatewayTxHash, eventBuffer, label, transformFn) {
375
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
376
- var _a, _b;
377
- if (!((_a = pushChainUniversalTx === null || pushChainUniversalTx === void 0 ? void 0 : pushChainUniversalTx.pcTx) === null || _a === void 0 ? void 0 : _a.length)) {
378
- throw new Error(`Failed to retrieve Push Chain transaction status for gateway tx: ${gatewayTxHash}. ` +
379
- `The transaction may have failed on Push Chain or not been indexed yet.`);
365
+ async function extractPcTxAndTransform(ctx, pushChainUniversalTx, gatewayTxHash, eventBuffer, label, transformFn) {
366
+ if (!pushChainUniversalTx?.pcTx?.length) {
367
+ throw new Error(`Failed to retrieve Push Chain transaction status for gateway tx: ${gatewayTxHash}. ` +
368
+ `The transaction may have failed on Push Chain or not been indexed yet.`);
369
+ }
370
+ const lastPcTransaction = pushChainUniversalTx.pcTx.at(-1);
371
+ (0, context_1.printLog)(ctx, `${label} — pcTx: ` + JSON.stringify(pushChainUniversalTx.pcTx.map((p) => ({ txHash: p.txHash, status: p.status, errorMsg: p.errorMsg })), null, 2));
372
+ (0, context_1.printLog)(ctx, `${label} — using lastPcTransaction: ` + JSON.stringify(lastPcTransaction, null, 2));
373
+ if (!lastPcTransaction?.txHash || lastPcTransaction.status === 'FAILED') {
374
+ const failedPcTx = lastPcTransaction?.status === 'FAILED'
375
+ ? lastPcTransaction
376
+ : pushChainUniversalTx.pcTx.find((pcTx) => pcTx.status === 'FAILED' && pcTx.errorMsg);
377
+ const rawFailedPcTxErrorMsg = failedPcTx?.errorMsg ?? '';
378
+ let failedPcTxErrorMsg = rawFailedPcTxErrorMsg
379
+ ? (0, formatters_1.normalizePublicErrorMessage)(rawFailedPcTxErrorMsg)
380
+ : '';
381
+ const errorDetails = failedPcTxErrorMsg ? `: ${failedPcTxErrorMsg}` : '';
382
+ // Decode known revert selectors and ABI-encoded `Error(string)` reverts
383
+ // into actionable hints. Unknown selectors are logged at INFO so the
384
+ // table can grow from real reverts.
385
+ let hint = '';
386
+ let decodedForPayload;
387
+ const decoded = (0, error_decoder_1.decodeRevert)(rawFailedPcTxErrorMsg);
388
+ if (decoded?.kind === 'custom') {
389
+ failedPcTxErrorMsg = (0, error_decoder_1.formatDecodedRevertForUser)(decoded);
390
+ hint = '';
391
+ decodedForPayload = {
392
+ name: decoded.name,
393
+ hint: decoded.hint,
394
+ selector: decoded.selector,
395
+ };
380
396
  }
381
- const lastPcTransaction = pushChainUniversalTx.pcTx.at(-1);
382
- (0, context_1.printLog)(ctx, `${label} — pcTx: ` + JSON.stringify(pushChainUniversalTx.pcTx.map((p) => ({ txHash: p.txHash, status: p.status, errorMsg: p.errorMsg })), null, 2));
383
- (0, context_1.printLog)(ctx, `${label} — using lastPcTransaction: ` + JSON.stringify(lastPcTransaction, null, 2));
384
- if (!(lastPcTransaction === null || lastPcTransaction === void 0 ? void 0 : lastPcTransaction.txHash) || lastPcTransaction.status === 'FAILED') {
385
- const failedPcTx = (lastPcTransaction === null || lastPcTransaction === void 0 ? void 0 : lastPcTransaction.status) === 'FAILED'
386
- ? lastPcTransaction
387
- : pushChainUniversalTx.pcTx.find((pcTx) => pcTx.status === 'FAILED' && pcTx.errorMsg);
388
- const rawFailedPcTxErrorMsg = (_b = failedPcTx === null || failedPcTx === void 0 ? void 0 : failedPcTx.errorMsg) !== null && _b !== void 0 ? _b : '';
389
- let failedPcTxErrorMsg = rawFailedPcTxErrorMsg
390
- ? (0, formatters_1.normalizePublicErrorMessage)(rawFailedPcTxErrorMsg)
391
- : '';
392
- const errorDetails = failedPcTxErrorMsg ? `: ${failedPcTxErrorMsg}` : '';
393
- // Decode known revert selectors and ABI-encoded `Error(string)` reverts
394
- // into actionable hints. Unknown selectors are logged at INFO so the
395
- // table can grow from real reverts.
396
- let hint = '';
397
- let decodedForPayload;
398
- const decoded = (0, error_decoder_1.decodeRevert)(rawFailedPcTxErrorMsg);
399
- if ((decoded === null || decoded === void 0 ? void 0 : decoded.kind) === 'custom') {
400
- failedPcTxErrorMsg = (0, error_decoder_1.formatDecodedRevertForUser)(decoded);
401
- hint = '';
402
- decodedForPayload = {
403
- name: decoded.name,
404
- hint: decoded.hint,
405
- selector: decoded.selector,
406
- };
407
- }
408
- else if ((decoded === null || decoded === void 0 ? void 0 : decoded.kind) === 'string') {
409
- failedPcTxErrorMsg = (0, error_decoder_1.formatDecodedRevertForUser)(decoded);
410
- hint = '';
411
- decodedForPayload = {
412
- decoded: decoded.decoded,
413
- selector: decoded.selector,
414
- };
415
- }
416
- else if ((decoded === null || decoded === void 0 ? void 0 : decoded.kind) === 'unknown') {
417
- (0, context_1.printLog)(ctx, `[error-decoder] unknown selector ${decoded.selector} — consider adding to KNOWN_ERROR_SELECTORS`);
418
- }
419
- const decodedErrorDetails = failedPcTxErrorMsg
420
- ? `: ${failedPcTxErrorMsg}`
421
- : errorDetails;
422
- const fullMessage = `Push Chain transaction failed for gateway tx: ${gatewayTxHash}${decodedErrorDetails}${hint}`;
423
- // Live-emit 199-02 before throwing so the terminal failure hook reaches
424
- // any caller-registered progress stream (parity with reconstructProgressEvents
425
- // which emits 199-02 on replay).
426
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, fullMessage, decodedForPayload, failedPcTx === null || failedPcTx === void 0 ? void 0 : failedPcTx.txHash);
427
- throw new errors_1.PushChainExecutionError(fullMessage, {
428
- gatewayTxHash,
429
- decodedError: decodedForPayload,
430
- });
397
+ else if (decoded?.kind === 'string') {
398
+ failedPcTxErrorMsg = (0, error_decoder_1.formatDecodedRevertForUser)(decoded);
399
+ hint = '';
400
+ decodedForPayload = {
401
+ decoded: decoded.decoded,
402
+ selector: decoded.selector,
403
+ };
431
404
  }
432
- const tx = yield getIndexedPushTransaction(ctx, lastPcTransaction.txHash, label);
433
- return transformFn(tx, eventBuffer);
434
- });
405
+ else if (decoded?.kind === 'unknown') {
406
+ (0, context_1.printLog)(ctx, `[error-decoder] unknown selector ${decoded.selector} — consider adding to KNOWN_ERROR_SELECTORS`);
407
+ }
408
+ const decodedErrorDetails = failedPcTxErrorMsg
409
+ ? `: ${failedPcTxErrorMsg}`
410
+ : errorDetails;
411
+ const fullMessage = `Push Chain transaction failed for gateway tx: ${gatewayTxHash}${decodedErrorDetails}${hint}`;
412
+ // Live-emit 199-02 before throwing so the terminal failure hook reaches
413
+ // any caller-registered progress stream (parity with reconstructProgressEvents
414
+ // which emits 199-02 on replay).
415
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, fullMessage, decodedForPayload, failedPcTx?.txHash);
416
+ throw new errors_1.PushChainExecutionError(fullMessage, {
417
+ gatewayTxHash,
418
+ decodedError: decodedForPayload,
419
+ });
420
+ }
421
+ const tx = await getIndexedPushTransaction(ctx, lastPcTransaction.txHash, label);
422
+ return transformFn(tx, eventBuffer);
435
423
  }
436
424
  //# sourceMappingURL=push-chain-tx.js.map