@pushchain/core 5.1.5-alpha.0 → 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 +556 -225
  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 +252 -53
  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 +120 -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 +555 -101
  57. package/src/lib/progress-hook/progress-hook.types.d.ts +76 -24
  58. package/src/lib/progress-hook/progress-hook.types.js +74 -29
  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
@@ -23,6 +23,7 @@ const context_1 = require("./context");
23
23
  const helpers_1 = require("./helpers");
24
24
  const payload_builder_1 = require("./payload-builder");
25
25
  const signing_1 = require("./signing");
26
+ const progress_hook_1 = require("../../progress-hook/progress-hook");
26
27
  const uea_manager_1 = require("./uea-manager");
27
28
  const confirmation_1 = require("./confirmation");
28
29
  const gateway_client_1 = require("./gateway-client");
@@ -31,37 +32,81 @@ const push_chain_tx_1 = require("./push-chain-tx");
31
32
  const gas_calculator_1 = require("./gas-calculator");
32
33
  const helpers_2 = require("./helpers");
33
34
  const price_fetch_1 = require("../../price-fetch/price-fetch");
35
+ /**
36
+ * Encode a UniversalPayload for transport over the origin chain's gateway.
37
+ * - EVM origin → ABI encoding (chain decodes via DecodeUniversalPayloadEVM).
38
+ * - SVM origin → Borsh encoding (chain decodes via DecodeUniversalPayloadSolana).
39
+ *
40
+ * The encoded bytes are placed in the Solana gateway's UniversalTx event
41
+ * (or the EVM UniversalGateway's SendUniversalTx event) payload field. Push
42
+ * Chain's uexecutor module decodes from that same field using the source
43
+ * chain's namespace (see push-chain/x/uexecutor/types/decode_payload.go).
44
+ * Using the wrong encoder for SVM origin results in garbage fields — in
45
+ * particular gasLimit=0 — which surfaces as "intrinsic gas too low" when
46
+ * the chain calls executeUniversalTx on the (possibly lazy-deployed) UEA.
47
+ */
48
+ function encodePayloadForOrigin(ctx, payload) {
49
+ const { vm } = chain_1.CHAIN_INFO[ctx.universalSigner.account.chain];
50
+ if (vm === enums_1.VM.SVM) {
51
+ const buf = (0, signing_1.encodeUniversalPayloadSvm)(payload);
52
+ return ('0x' + buf.toString('hex'));
53
+ }
54
+ return (0, signing_1.encodeUniversalPayload)(payload);
55
+ }
34
56
  function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks) {
35
57
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
36
- var _a, _b;
58
+ var _a, _b, _c;
37
59
  const transformFn = (tx, buf = []) => (0, response_builder_1.transformToUniversalTxResponse)(ctx, tx, buf, getResponseCallbacks());
38
60
  // Set default value for value if undefined
39
61
  if (execute.value === undefined) {
40
62
  execute.value = BigInt(0);
41
63
  }
42
64
  const chain = ctx.universalSigner.account.chain;
43
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_01, chain, ctx.universalSigner.account.address);
65
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_101, chain, ctx.universalSigner.account.address);
44
66
  (0, helpers_1.validateMainnetConnection)(chain, ctx.pushClient.pushChainInfo.chainId);
67
+ // Gas estimation fires for both Push-to-Push and external-origin flows so
68
+ // reconstructProgressEvents (which always emits 102-01/02) and live execute
69
+ // stay in lockstep. For the Push-to-Push shortcut we have no origin-chain
70
+ // gas to estimate; surface the tx gas limit as the "cost" to match what
71
+ // the reconstruction path does (it reads universalTxResponse.gasLimit).
72
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_102_01);
45
73
  // Push to Push Tx
46
74
  if ((0, helpers_1.isPushChain)(chain)) {
47
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_07);
48
- const tx = yield (0, push_chain_tx_1.sendPushTx)(ctx, execute, eventBuffer, transformFn);
49
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01, [tx]);
75
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_102_02, (_a = execute.gasLimit) !== null && _a !== void 0 ? _a : BigInt(21000));
76
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_107);
77
+ let tx;
78
+ try {
79
+ tx = yield (0, push_chain_tx_1.sendPushTx)(ctx, execute, eventBuffer, transformFn);
80
+ }
81
+ catch (err) {
82
+ // Push Chain broadcast failed. Wallet rejection surfaces as 104-04;
83
+ // everything else (RPC fail, on-chain revert) as 199-02.
84
+ const errMsg = err instanceof Error ? err.message : String(err);
85
+ const { isUserDecline } = (0, progress_hook_1.classifyDeclineError)(errMsg);
86
+ (0, context_1.fireProgressHook)(ctx, isUserDecline ? progress_hook_types_1.PROGRESS_HOOK.SEND_TX_104_04 : progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, errMsg);
87
+ // Mark that a terminal-ish error hook has already fired so the
88
+ // outer orchestrator catch doesn't emit a second 199-02 on top.
89
+ ctx._routeTerminalEmitted = true;
90
+ if (!isUserDecline && !(err instanceof push_chain_tx_1.PushChainExecutionError)) {
91
+ throw new push_chain_tx_1.PushChainExecutionError(errMsg);
92
+ }
93
+ throw err;
94
+ }
95
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_01, [tx]);
50
96
  return tx;
51
97
  }
52
98
  // Fetch Gas details and estimate cost of execution
53
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_01);
54
99
  const gasEstimate = execute.gasLimit || BigInt(1e7);
55
100
  const gasPrice = yield ctx.pushClient.getGasPrice();
56
101
  const requiredGasFee = gasEstimate * gasPrice;
57
102
  const requiredFunds = requiredGasFee + execute.value;
58
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_02, requiredFunds);
103
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_102_02, requiredFunds);
59
104
  // Fetch UEA Details (or use pre-fetched status if available)
60
105
  const UEA = (0, uea_manager_1.computeUEAOffchain)(ctx);
61
106
  let isUEADeployed;
62
107
  let nonce;
63
108
  let funds;
64
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_03_01);
109
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_103_01);
65
110
  if (execute._ueaStatus) {
66
111
  isUEADeployed = execute._ueaStatus.isDeployed;
67
112
  nonce = execute._ueaStatus.nonce;
@@ -69,7 +114,7 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
69
114
  }
70
115
  else {
71
116
  // Skip getCode if accountStatusCache already confirmed deployment
72
- const deployedHint = (_b = (_a = ctx.accountStatusCache) === null || _a === void 0 ? void 0 : _a.uea) === null || _b === void 0 ? void 0 : _b.deployed;
117
+ const deployedHint = (_c = (_b = ctx.accountStatusCache) === null || _b === void 0 ? void 0 : _b.uea) === null || _c === void 0 ? void 0 : _c.deployed;
73
118
  if (deployedHint) {
74
119
  const [balance, ueaNonce] = yield Promise.all([
75
120
  ctx.pushClient.getBalance(UEA),
@@ -89,7 +134,7 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
89
134
  funds = balance;
90
135
  }
91
136
  }
92
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_03_02, UEA, isUEADeployed);
137
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_103_02, UEA, isUEADeployed);
93
138
  // Validate and decode feeLockTxHash
94
139
  let feeLockTxHash = execute.feeLockTxHash;
95
140
  if (feeLockTxHash) {
@@ -122,7 +167,7 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
122
167
  }, helpers_1.bigintReplacer));
123
168
  req = (0, payload_builder_1.buildUniversalTxRequest)(ctx.universalSigner.account.address, {
124
169
  recipient: viem_1.zeroAddress, token: viem_1.zeroAddress, amount: BigInt(0),
125
- payload: (0, signing_1.encodeUniversalPayload)(universalPayloadForReq),
170
+ payload: encodePayloadForOrigin(ctx, universalPayloadForReq),
126
171
  });
127
172
  }
128
173
  else {
@@ -151,7 +196,7 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
151
196
  }, helpers_1.bigintReplacer));
152
197
  req = (0, payload_builder_1.buildUniversalTxRequest)(ctx.universalSigner.account.address, {
153
198
  recipient: viem_1.zeroAddress, token: viem_1.zeroAddress, amount: BigInt(0),
154
- payload: (0, signing_1.encodeUniversalPayload)(universalPayloadOther),
199
+ payload: encodePayloadForOrigin(ctx, universalPayloadOther),
155
200
  });
156
201
  }
157
202
  }
@@ -172,7 +217,7 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
172
217
  }, helpers_1.bigintReplacer));
173
218
  req = (0, payload_builder_1.buildUniversalTxRequest)(ctx.universalSigner.account.address, {
174
219
  recipient: viem_1.zeroAddress, token: viem_1.zeroAddress, amount: BigInt(0),
175
- payload: (0, signing_1.encodeUniversalPayload)(universalPayloadSelf),
220
+ payload: encodePayloadForOrigin(ctx, universalPayloadSelf),
176
221
  });
177
222
  }
178
223
  }
@@ -190,10 +235,21 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
190
235
  let verificationData;
191
236
  if (!feeLockingRequired) {
192
237
  const ueaVersion = yield (0, uea_manager_1.fetchUEAVersion)(ctx);
193
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_04_02);
194
- const signature = yield (0, signing_1.signUniversalPayload)(ctx, universalPayload, UEA, ueaVersion);
238
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_104_02);
239
+ let signature;
240
+ try {
241
+ signature = yield (0, signing_1.signUniversalPayload)(ctx, universalPayload, UEA, ueaVersion);
242
+ }
243
+ catch (err) {
244
+ // Wallet decline, contract revert during sign, or RPC failure — the
245
+ // 104-04 builder's classifyDeclineError heuristic picks the right
246
+ // copy (real decline → "Verification Declined"; else "Signature Failed").
247
+ const errMsg = err instanceof Error ? err.message : String(err);
248
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_104_04, errMsg);
249
+ throw err;
250
+ }
195
251
  verificationData = (0, viem_1.bytesToHex)(signature);
196
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_04_03);
252
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_104_03);
197
253
  }
198
254
  else {
199
255
  // Fee Locking
@@ -299,7 +355,18 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
299
355
  (0, context_1.printLog)(ctx, `Fee-lock pre-flight quote failed, proceeding without validation: ${err instanceof Error ? err.message : String(err)}`);
300
356
  }
301
357
  }
302
- const feeLockTxHashBytes = yield (0, gateway_client_1.lockFee)(ctx, effectiveLockAmountInUSD, universalPayload, req);
358
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_104_01);
359
+ let feeLockTxHashBytes;
360
+ try {
361
+ feeLockTxHashBytes = yield (0, gateway_client_1.lockFee)(ctx, effectiveLockAmountInUSD, universalPayload, req);
362
+ }
363
+ catch (err) {
364
+ // User declined the fee-lock tx submission or the origin-chain RPC
365
+ // rejected it — classifier picks decline vs generic signature failure.
366
+ const errMsg = err instanceof Error ? err.message : String(err);
367
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_104_04, errMsg);
368
+ throw err;
369
+ }
303
370
  feeLockTxHash = (0, viem_1.bytesToHex)(feeLockTxHashBytes);
304
371
  verificationData = (0, viem_1.bytesToHex)(feeLockTxHashBytes);
305
372
  const { vm } = chain_1.CHAIN_INFO[chain];
@@ -307,19 +374,63 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
307
374
  ? bs58_1.bs58.encode(Buffer.from(feeLockTxHashBytes))
308
375
  : feeLockTxHash;
309
376
  const originTx = yield (0, helpers_1.fetchOriginChainTransactionForProgress)(ctx, chain, feeLockTxHash, feeLockTxHashDisplay);
310
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_05_01, feeLockTxHashDisplay, originTx);
377
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_105_01, feeLockTxHashDisplay, originTx);
311
378
  yield (0, confirmation_1.waitForLockerFeeConfirmation)(ctx, feeLockTxHashBytes);
312
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_05_02);
379
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_105_02);
313
380
  const { defaultRPC, lockerContract } = chain_1.CHAIN_INFO[chain];
314
- const pushChainUniversalTx = yield (0, response_builder_1.queryUniversalTxStatusFromGatewayTx)(ctx, new evm_client_1.EvmClient({ rpcUrls: ctx.rpcUrls[chain] || defaultRPC }), lockerContract, feeLockTxHash, 'sendTxWithGas');
315
- const response = yield (0, push_chain_tx_1.extractPcTxAndTransform)(ctx, pushChainUniversalTx, feeLockTxHash, eventBuffer, 'sendTxWithGas', transformFn);
316
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01, [response]);
381
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_107);
382
+ let response;
383
+ try {
384
+ const pushChainUniversalTx = yield (0, response_builder_1.queryUniversalTxStatusFromGatewayTx)(ctx, new evm_client_1.EvmClient({ rpcUrls: ctx.rpcUrls[chain] || defaultRPC }), lockerContract, feeLockTxHash, 'sendTxWithGas');
385
+ // extractPcTxAndTransform fires 199-02 itself on pcTx FAILED and throws
386
+ // PushChainExecutionError — don't double-emit. Anything else thrown
387
+ // here (gateway-tx lookup failure, RPC error) hasn't emitted 199-02
388
+ // yet, so the catch below surfaces it.
389
+ response = yield (0, push_chain_tx_1.extractPcTxAndTransform)(ctx, pushChainUniversalTx, feeLockTxHash, eventBuffer, 'sendTxWithGas', transformFn);
390
+ }
391
+ catch (err) {
392
+ if (!(err instanceof push_chain_tx_1.PushChainExecutionError)) {
393
+ const errMsg = err instanceof Error ? err.message : String(err);
394
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, errMsg);
395
+ throw new push_chain_tx_1.PushChainExecutionError(errMsg, { gatewayTxHash: feeLockTxHash });
396
+ }
397
+ throw err;
398
+ }
399
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_01, [response]);
317
400
  return response;
318
401
  }
319
- // Non-fee-locking path: Broadcasting Tx to PC via sendUniversalTx
320
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_07);
321
- const transactions = yield (0, push_chain_tx_1.sendUniversalTx)(ctx, isUEADeployed, feeLockTxHash, universalPayload, verificationData, eventBuffer, transformFn);
322
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01, transactions);
402
+ // Non-fee-locking path: Broadcasting Tx to PC via sendUniversalTx.
403
+ // Provide a resign callback so sendUniversalTx can recover from the
404
+ // UEA-nonce race: the EIP-712 hash uses the UEA's live storage nonce
405
+ // (not payload.nonce), so if anything advances it between our read and
406
+ // Cosmos inclusion the tx reverts with InvalidEVMSignature(0xc7dbd31d).
407
+ const resignOnSigMismatch = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
408
+ const freshNonce = yield (0, uea_manager_1.getUEANonce)(ctx, UEA);
409
+ const freshUeaVersion = yield (0, uea_manager_1.fetchUEAVersion)(ctx);
410
+ const freshPayload = JSON.parse(JSON.stringify(Object.assign(Object.assign({}, universalPayload), { nonce: freshNonce }), helpers_1.bigintReplacer));
411
+ const freshSig = yield (0, signing_1.signUniversalPayload)(ctx, freshPayload, UEA, freshUeaVersion);
412
+ return {
413
+ universalPayload: freshPayload,
414
+ verificationData: (0, viem_1.bytesToHex)(freshSig),
415
+ };
416
+ });
417
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_107);
418
+ let transactions;
419
+ try {
420
+ transactions = yield (0, push_chain_tx_1.sendUniversalTx)(ctx, isUEADeployed, feeLockTxHash, universalPayload, verificationData, eventBuffer, transformFn, resignOnSigMismatch);
421
+ }
422
+ catch (err) {
423
+ // Push Chain broadcast failed (Cosmos reject, UEA revert, nonce race
424
+ // exhaustion). Surface terminal 199-02 before re-throwing so the stream
425
+ // ends with the spec'd error hook. Typed PushChainExecutionError lets
426
+ // callers classify via instanceof without message sniffing.
427
+ const errMsg = err instanceof Error ? err.message : String(err);
428
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, errMsg);
429
+ if (err instanceof push_chain_tx_1.PushChainExecutionError)
430
+ throw err;
431
+ throw new push_chain_tx_1.PushChainExecutionError(errMsg);
432
+ }
433
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_01, transactions);
323
434
  return transactions[transactions.length - 1];
324
435
  });
325
436
  }
@@ -6,14 +6,16 @@ import { CHAIN } from '../../constants/enums';
6
6
  import { ConversionQuote, MoveableToken, PayableToken } from '../../constants/tokens';
7
7
  import { EvmClient } from '../../vm-client/evm-client';
8
8
  import type { OrchestratorContext } from './context';
9
+ import { type GasSizingDecision } from './gas-usd-sizer';
9
10
  export declare function ensureErc20Allowance(ctx: OrchestratorContext, evmClient: EvmClient, tokenAddress: `0x${string}`, spender: `0x${string}`, requiredAmount: bigint): Promise<void>;
10
- export declare function queryOutboundGasFee(ctx: OrchestratorContext, prc20Token: `0x${string}`, gasLimit: bigint): Promise<{
11
+ export declare function queryOutboundGasFee(ctx: OrchestratorContext, prc20Token: `0x${string}`, gasLimit: bigint, destinationChain?: CHAIN): Promise<{
11
12
  gasToken: `0x${string}`;
12
13
  gasFee: bigint;
13
14
  protocolFee: bigint;
14
15
  nativeValueForGas: bigint;
15
16
  gasPrice: bigint;
16
17
  universalCoreAddress: `0x${string}`;
18
+ sizing?: GasSizingDecision;
17
19
  }>;
18
20
  /**
19
21
  * Estimate the native WPC amount needed to swap for `gasFee` of `gasToken`
@@ -22,12 +24,13 @@ export declare function queryOutboundGasFee(ctx: OrchestratorContext, prc20Token
22
24
  * Falls back to a percentage of accountBalance if any on-chain query fails.
23
25
  */
24
26
  export declare function estimateNativeValueForSwap(ctx: OrchestratorContext, universalCoreAddress: `0x${string}`, gasToken: `0x${string}`, gasFee: bigint, accountBalance: bigint): Promise<bigint>;
25
- export declare function queryRescueGasFee(ctx: OrchestratorContext, prc20Token: `0x${string}`): Promise<{
27
+ export declare function queryRescueGasFee(ctx: OrchestratorContext, prc20Token: `0x${string}`, destinationChain?: CHAIN): Promise<{
26
28
  gasToken: `0x${string}`;
27
29
  gasFee: bigint;
28
30
  rescueGasLimit: bigint;
29
31
  gasPrice: bigint;
30
32
  nativeValueForGas: bigint;
33
+ sizing?: GasSizingDecision;
31
34
  }>;
32
35
  export declare function calculateNativeAmountForDeposit(ctx: OrchestratorContext, chain: CHAIN, requiredFunds: bigint, ueaBalance: bigint): Promise<bigint>;
33
36
  export declare function calculateGasAmountFromAmountOutMinETH(ctx: OrchestratorContext, gasTokenAddress: `0x${string}`, amountOutMinETH: bigint | string, quoteExactOutputFn: (amountOut: bigint, opts: {
@@ -25,7 +25,13 @@ const utils_1 = require("../../utils");
25
25
  const svm_client_1 = require("../../vm-client/svm-client");
26
26
  const context_1 = require("./context");
27
27
  const helpers_1 = require("./helpers");
28
- /** Buffer multiplier for nativeValueForGas. Excess is refunded by swapAndBurnGas to the UEA. */
28
+ const gas_usd_sizer_1 = require("./gas-usd-sizer");
29
+ /**
30
+ * Legacy fallback buffer used ONLY when the caller does not supply a
31
+ * `destinationChain` and the USD sizer cannot be invoked. New code paths
32
+ * should always pass `destinationChain` so gas is sized against the real
33
+ * dollar cost (SDK 5.2). Excess is refunded by swapAndBurnGas to the UEA.
34
+ */
29
35
  const GAS_FEE_BUFFER_MULTIPLIER = BigInt(1000000);
30
36
  // Minimal ABIs for Uniswap V3 pool price estimation
31
37
  const UNISWAP_V3_POOL_SLOT0_ABI = [
@@ -125,7 +131,7 @@ function ensureErc20Allowance(ctx, evmClient, tokenAddress, spender, requiredAmo
125
131
  // ============================================================================
126
132
  // Outbound Gas Fee Query
127
133
  // ============================================================================
128
- function queryOutboundGasFee(ctx, prc20Token, gasLimit) {
134
+ function queryOutboundGasFee(ctx, prc20Token, gasLimit, destinationChain) {
129
135
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
130
136
  var _a, _b;
131
137
  const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
@@ -174,9 +180,32 @@ function queryOutboundGasFee(ctx, prc20Token, gasLimit) {
174
180
  (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] FAILED: ${err instanceof Error ? err.message : String(err)}`);
175
181
  throw err;
176
182
  }
177
- const nativeValueForGas = protocolFee + gasFee * GAS_FEE_BUFFER_MULTIPLIER;
178
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] using 1000000x buffer: nativeValueForGas=${nativeValueForGas}`);
179
- return { gasToken, gasFee, protocolFee, nativeValueForGas, gasPrice, universalCoreAddress };
183
+ let nativeValueForGas;
184
+ let sizing;
185
+ if (destinationChain !== undefined) {
186
+ try {
187
+ sizing = yield (0, gas_usd_sizer_1.sizeOutboundGas)(ctx, {
188
+ gasFee,
189
+ originChain: ctx.universalSigner.account.chain,
190
+ destinationChain,
191
+ });
192
+ // All categories — A, B, and C — return the sizer's calibrated gas leg.
193
+ // R3 consumers additionally bump `nativeValueForGas` by `overflowNativePc`
194
+ // when category === 'C' (see route-handlers.executeCeaToPush).
195
+ nativeValueForGas = sizing.gasLegNativePc + protocolFee;
196
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] sizer: category=${sizing.category}, gasUsd=${sizing.gasUsd}, ` +
197
+ `gasLegNativePc=${sizing.gasLegNativePc}, overflowNativePc=${sizing.overflowNativePc}, nativeValueForGas=${nativeValueForGas}`);
198
+ }
199
+ catch (err) {
200
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] sizer failed (${err instanceof Error ? err.message : String(err)}); falling back to 1M buffer`);
201
+ nativeValueForGas = protocolFee + gasFee * GAS_FEE_BUFFER_MULTIPLIER;
202
+ }
203
+ }
204
+ else {
205
+ nativeValueForGas = protocolFee + gasFee * GAS_FEE_BUFFER_MULTIPLIER;
206
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] no destinationChain provided; legacy 1M buffer: nativeValueForGas=${nativeValueForGas}`);
207
+ }
208
+ return { gasToken, gasFee, protocolFee, nativeValueForGas, gasPrice, universalCoreAddress, sizing };
180
209
  });
181
210
  }
182
211
  // ============================================================================
@@ -285,7 +314,7 @@ function balanceFallback(balance, divisor, reserve) {
285
314
  // ============================================================================
286
315
  // Rescue Gas Fee Query
287
316
  // ============================================================================
288
- function queryRescueGasFee(ctx, prc20Token) {
317
+ function queryRescueGasFee(ctx, prc20Token, destinationChain) {
289
318
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
290
319
  const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
291
320
  (0, context_1.printLog)(ctx, `queryRescueGasFee — inputs: gateway=${gatewayPcAddress}, prc20Token=${prc20Token}`);
@@ -324,9 +353,28 @@ function queryRescueGasFee(ctx, prc20Token) {
324
353
  (0, context_1.printLog)(ctx, `queryRescueGasFee — FAILED: ${err instanceof Error ? err.message : String(err)}`);
325
354
  throw err;
326
355
  }
327
- const nativeValueForGas = gasFee * GAS_FEE_BUFFER_MULTIPLIER;
328
- (0, context_1.printLog)(ctx, `queryRescueGasFee — using 1000000x buffer: nativeValueForGas=${nativeValueForGas}`);
329
- return { gasToken, gasFee, rescueGasLimit, gasPrice, nativeValueForGas };
356
+ let nativeValueForGas;
357
+ let sizing;
358
+ if (destinationChain !== undefined) {
359
+ try {
360
+ sizing = yield (0, gas_usd_sizer_1.sizeOutboundGas)(ctx, {
361
+ gasFee,
362
+ originChain: ctx.universalSigner.account.chain,
363
+ destinationChain,
364
+ });
365
+ nativeValueForGas = sizing.gasLegNativePc;
366
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — sizer: category=${sizing.category}, gasUsd=${sizing.gasUsd}, nativeValueForGas=${nativeValueForGas}`);
367
+ }
368
+ catch (err) {
369
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — sizer failed (${err instanceof Error ? err.message : String(err)}); falling back to 1M buffer`);
370
+ nativeValueForGas = gasFee * GAS_FEE_BUFFER_MULTIPLIER;
371
+ }
372
+ }
373
+ else {
374
+ nativeValueForGas = gasFee * GAS_FEE_BUFFER_MULTIPLIER;
375
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — no destinationChain provided; legacy 1M buffer: nativeValueForGas=${nativeValueForGas}`);
376
+ }
377
+ return { gasToken, gasFee, rescueGasLimit, gasPrice, nativeValueForGas, sizing };
330
378
  });
331
379
  }
332
380
  // ============================================================================
@@ -335,7 +383,7 @@ function queryRescueGasFee(ctx, prc20Token) {
335
383
  function calculateNativeAmountForDeposit(ctx, chain, requiredFunds, ueaBalance) {
336
384
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
337
385
  var _a, _b;
338
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_01);
386
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_102_01);
339
387
  const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
340
388
  const maxUsd = utils_1.Utils.helpers.parseUnits('1000', 8);
341
389
  const deficit = requiredFunds > ueaBalance ? requiredFunds - ueaBalance : BigInt(0);
@@ -380,7 +428,7 @@ function calculateNativeAmountForDeposit(ctx, chain, requiredFunds, ueaBalance)
380
428
  let nativeAmount = (depositUsd * oneNativeUnit + (nativeTokenUsdPrice - BigInt(1))) /
381
429
  nativeTokenUsdPrice;
382
430
  nativeAmount = nativeAmount + BigInt(1);
383
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_02, nativeAmount);
431
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_102_02, nativeAmount);
384
432
  return nativeAmount;
385
433
  });
386
434
  }
@@ -0,0 +1,53 @@
1
+ import { CHAIN } from '../../constants/enums';
2
+ import type { OrchestratorContext } from './context';
3
+ export type GasSizingCategory = 'A' | 'B' | 'C';
4
+ export interface GasSizingInput {
5
+ /** Raw gasFee from getOutboundTxGasAndFees (in gasToken units, e.g., pETH 18d) */
6
+ gasFee: bigint;
7
+ /** Origin chain the user signed from — picks the PC/USD oracle pool */
8
+ originChain: CHAIN;
9
+ /**
10
+ * Destination chain whose native asset is represented by gasToken on PC.
11
+ * Used to price gasFee in USD via PriceFetch (Chainlink ETH/USD, Pyth SOL/USD).
12
+ */
13
+ destinationChain: CHAIN;
14
+ }
15
+ export interface GasSizingDecision {
16
+ category: GasSizingCategory;
17
+ /** Native PC to send as msg.value for the sendUniversalTxOutbound leg */
18
+ gasLegNativePc: bigint;
19
+ /** Native PC to bridge as funds alongside (only > 0 when category === 'C') */
20
+ overflowNativePc: bigint;
21
+ /** Diagnostic — raw gas cost in USD (1e8) */
22
+ gasUsd: bigint;
23
+ /** Diagnostic — portion to bridge in USD (1e8) */
24
+ overflowUsd: bigint;
25
+ }
26
+ export declare function sizeOutboundGas(ctx: OrchestratorContext, input: GasSizingInput): Promise<GasSizingDecision>;
27
+ export interface R1SizingInput {
28
+ /** Push-chain gas cost in UPC wei (18 decimals) */
29
+ pushGasFeeWei: bigint;
30
+ /** Origin chain — picks the WPC/USD oracle pool */
31
+ originChain: CHAIN;
32
+ }
33
+ export interface R1SizingDecision {
34
+ category: GasSizingCategory;
35
+ /** Push-gas cost in USD (8 decimals) */
36
+ pushGasUsd: bigint;
37
+ /** USD the SDK should request on the origin gateway (8 decimals) */
38
+ paddedDepositUsd: bigint;
39
+ }
40
+ export declare function sizeR1PushGas(ctx: OrchestratorContext, input: R1SizingInput): Promise<R1SizingDecision>;
41
+ /**
42
+ * Given gasFee (in gasToken units) and destination VM, return gasFee in USD
43
+ * (8 decimals). Exposed for direct use in places that already have the
44
+ * destUsdPrice cached (e.g., rescue flows).
45
+ */
46
+ export declare function computeGasUsd(ctx: OrchestratorContext, gasFee: bigint, destinationChain: CHAIN): Promise<bigint>;
47
+ /** Test-only export of thresholds. @internal */
48
+ export declare const __THRESHOLDS: {
49
+ ONE_USD_8D: bigint;
50
+ TEN_USD_8D: bigint;
51
+ };
52
+ /** Alias for backward-compat at call sites. */
53
+ export { getPcUsdPrice } from './pc-usd-oracle';
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPcUsdPrice = exports.__THRESHOLDS = void 0;
4
+ exports.sizeOutboundGas = sizeOutboundGas;
5
+ exports.sizeR1PushGas = sizeR1PushGas;
6
+ exports.computeGasUsd = computeGasUsd;
7
+ const tslib_1 = require("tslib");
8
+ /**
9
+ * Gas sizing for outbound transactions (Routes 2/3/4).
10
+ *
11
+ * Categorizes destination gas cost into three buckets per the SDK 5.2 spec:
12
+ * - A: gasUsd < $1 → floor to $1 worth of native PC
13
+ * - B: $1 ≤ gasUsd ≤ $10 → happy path, use gasFee as sized
14
+ * - C: gasUsd > $10 → split: $10 gas leg + overflow bridged as funds
15
+ *
16
+ * Output amounts are in native PC (nPUSH, 18 decimals) because that's what
17
+ * `sendUniversalTxOutbound` consumes as `msg.value` before swapAndBurnGas
18
+ * swaps it into the destination gas token (pETH, pSOL, …).
19
+ */
20
+ const viem_1 = require("viem");
21
+ const enums_1 = require("../../constants/enums");
22
+ const chain_1 = require("../../constants/chain");
23
+ const price_fetch_1 = require("../../price-fetch/price-fetch");
24
+ const context_1 = require("./context");
25
+ const pc_usd_oracle_1 = require("./pc-usd-oracle");
26
+ // ============================================================================
27
+ // Thresholds (USD, 8 decimals)
28
+ // ============================================================================
29
+ const ONE_USD_8D = (0, viem_1.parseUnits)('1', 8); // 100_000_000
30
+ const TEN_USD_8D = (0, viem_1.parseUnits)('10', 8); // 1_000_000_000
31
+ // ============================================================================
32
+ // Public API
33
+ // ============================================================================
34
+ function sizeOutboundGas(ctx, input) {
35
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
36
+ const { gasFee, originChain, destinationChain } = input;
37
+ // 1) Price gasFee in USD (8 decimals). gasFee is denominated in the
38
+ // destination native (pETH = ETH value, pSOL = SOL value). The price
39
+ // feed lives on the *origin* side (origin gateway's Chainlink/Pyth),
40
+ // but we reuse the same feed via PriceFetch — the asset being priced
41
+ // is ETH or SOL, not the route.
42
+ const destVm = chain_1.CHAIN_INFO[destinationChain].vm;
43
+ const priceSourceChain = destVm === enums_1.VM.SVM ? enums_1.CHAIN.SOLANA_DEVNET : enums_1.CHAIN.ETHEREUM_SEPOLIA;
44
+ const destDecimals = destVm === enums_1.VM.SVM ? 9 : 18;
45
+ let destUsdPrice;
46
+ try {
47
+ destUsdPrice = yield new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(priceSourceChain);
48
+ }
49
+ catch (err) {
50
+ (0, context_1.printLog)(ctx, `sizeOutboundGas — PriceFetch.getPrice failed (${err instanceof Error ? err.message : String(err)}); treating as Case B passthrough`);
51
+ // Degrade gracefully: assume the raw gasFee is already a sane size and
52
+ // convert 1:1 to native PC. Callers keep their existing fallback logic.
53
+ return passthroughAsCaseB(ctx, gasFee, originChain);
54
+ }
55
+ const oneDestNativeUnit = (0, viem_1.parseUnits)('1', destDecimals);
56
+ const gasUsd = (gasFee * destUsdPrice) / oneDestNativeUnit;
57
+ (0, context_1.printLog)(ctx, `sizeOutboundGas — gasFee=${gasFee.toString()} ${destVm === enums_1.VM.SVM ? 'pSOL' : 'pETH'} (${destDecimals}d), ` +
58
+ `destUsdPrice=${destUsdPrice.toString()} (1e8), gasUsd=${gasUsd.toString()} (1e8)`);
59
+ // 2) Categorize and compute target USD for each leg.
60
+ let category;
61
+ let gasLegUsd;
62
+ let overflowUsd;
63
+ if (gasUsd < ONE_USD_8D) {
64
+ category = 'A';
65
+ gasLegUsd = ONE_USD_8D;
66
+ overflowUsd = BigInt(0);
67
+ }
68
+ else if (gasUsd <= TEN_USD_8D) {
69
+ category = 'B';
70
+ gasLegUsd = gasUsd;
71
+ overflowUsd = BigInt(0);
72
+ }
73
+ else {
74
+ category = 'C';
75
+ gasLegUsd = TEN_USD_8D;
76
+ overflowUsd = gasUsd - TEN_USD_8D;
77
+ }
78
+ // 3) Convert USD targets back to native PC via the per-route WPC/stable oracle.
79
+ const gasLegNativePc = yield (0, pc_usd_oracle_1.usdToPc)(ctx, gasLegUsd, originChain);
80
+ const overflowNativePc = overflowUsd > BigInt(0)
81
+ ? yield (0, pc_usd_oracle_1.usdToPc)(ctx, overflowUsd, originChain)
82
+ : BigInt(0);
83
+ (0, context_1.printLog)(ctx, `sizeOutboundGas — category=${category}, gasLegUsd=${gasLegUsd.toString()}, ` +
84
+ `overflowUsd=${overflowUsd.toString()}, gasLegNativePc=${gasLegNativePc.toString()}, ` +
85
+ `overflowNativePc=${overflowNativePc.toString()}`);
86
+ return {
87
+ category,
88
+ gasLegNativePc,
89
+ overflowNativePc,
90
+ gasUsd,
91
+ overflowUsd,
92
+ };
93
+ });
94
+ }
95
+ // ============================================================================
96
+ // Internal helpers
97
+ // ============================================================================
98
+ /**
99
+ * When the USD price feed fails, fall back to a pass-through that keeps the
100
+ * Orchestrator alive: return the raw gasFee as a Case B result, converting
101
+ * through the existing PC/USD oracle (or its hardcoded fallback).
102
+ */
103
+ function passthroughAsCaseB(ctx, gasFee, originChain) {
104
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
105
+ const oneUsd = ONE_USD_8D;
106
+ const gasLegNativePc = yield (0, pc_usd_oracle_1.usdToPc)(ctx, oneUsd, originChain);
107
+ void gasFee;
108
+ return {
109
+ category: 'B',
110
+ gasLegNativePc,
111
+ overflowNativePc: BigInt(0),
112
+ gasUsd: oneUsd,
113
+ overflowUsd: BigInt(0),
114
+ };
115
+ });
116
+ }
117
+ function sizeR1PushGas(ctx, input) {
118
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
119
+ const { pushGasFeeWei, originChain } = input;
120
+ // 1) Convert pushGasFeeWei (UPC wei, 18d) → USD (8d) via per-route oracle.
121
+ const pcUsdPrice = yield (0, pc_usd_oracle_1.getPcUsdPrice)(ctx, originChain);
122
+ const onePcUnit = (0, viem_1.parseUnits)('1', 18);
123
+ const pushGasUsd = (pushGasFeeWei * pcUsdPrice) / onePcUnit;
124
+ (0, context_1.printLog)(ctx, `sizeR1PushGas — pushGasFeeWei=${pushGasFeeWei.toString()} UPC (18d), ` +
125
+ `pcUsdPrice=${pcUsdPrice.toString()} (1e8), pushGasUsd=${pushGasUsd.toString()} (1e8)`);
126
+ // 2) Bucket.
127
+ let category;
128
+ let paddedDepositUsd;
129
+ if (pushGasUsd < ONE_USD_8D) {
130
+ category = 'A';
131
+ paddedDepositUsd = ONE_USD_8D;
132
+ }
133
+ else if (pushGasUsd <= TEN_USD_8D) {
134
+ category = 'B';
135
+ paddedDepositUsd = pushGasUsd;
136
+ }
137
+ else {
138
+ category = 'C';
139
+ paddedDepositUsd = pushGasUsd;
140
+ }
141
+ (0, context_1.printLog)(ctx, `sizeR1PushGas — category=${category}, paddedDepositUsd=${paddedDepositUsd.toString()} (1e8)`);
142
+ return { category, pushGasUsd, paddedDepositUsd };
143
+ });
144
+ }
145
+ /**
146
+ * Given gasFee (in gasToken units) and destination VM, return gasFee in USD
147
+ * (8 decimals). Exposed for direct use in places that already have the
148
+ * destUsdPrice cached (e.g., rescue flows).
149
+ */
150
+ function computeGasUsd(ctx, gasFee, destinationChain) {
151
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
152
+ const destVm = chain_1.CHAIN_INFO[destinationChain].vm;
153
+ const priceSourceChain = destVm === enums_1.VM.SVM ? enums_1.CHAIN.SOLANA_DEVNET : enums_1.CHAIN.ETHEREUM_SEPOLIA;
154
+ const destDecimals = destVm === enums_1.VM.SVM ? 9 : 18;
155
+ const destUsdPrice = yield new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(priceSourceChain);
156
+ const oneUnit = (0, viem_1.parseUnits)('1', destDecimals);
157
+ return (gasFee * destUsdPrice) / oneUnit;
158
+ });
159
+ }
160
+ /** Test-only export of thresholds. @internal */
161
+ exports.__THRESHOLDS = { ONE_USD_8D, TEN_USD_8D };
162
+ /** Alias for backward-compat at call sites. */
163
+ var pc_usd_oracle_2 = require("./pc-usd-oracle");
164
+ Object.defineProperty(exports, "getPcUsdPrice", { enumerable: true, get: function () { return pc_usd_oracle_2.getPcUsdPrice; } });
165
+ //# sourceMappingURL=gas-usd-sizer.js.map
@@ -129,6 +129,8 @@ function bigintReplacer(_key, value) {
129
129
  // Params Conversion
130
130
  // ============================================================================
131
131
  function toExecuteParams(params) {
132
+ // Post-route-detector, ChainTarget.address has already been normalized to
133
+ // 0x-prefixed hex for SVM targets (see route-detector.ts), so the cast is safe.
132
134
  const to = typeof params.to === 'string'
133
135
  ? params.to
134
136
  : params.to.address;