@pushchain/core 6.0.0 → 6.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -1
- package/package.json +1 -1
- package/src/lib/constants/abi/universalGatewayPC.evm.d.ts +1 -1
- package/src/lib/constants/abi/universalGatewayPC.evm.js +1 -1
- package/src/lib/constants/chain.d.ts +4 -0
- package/src/lib/constants/chain.js +8 -0
- package/src/lib/constants/index.d.ts +1 -1
- package/src/lib/constants/tokens.d.ts +12 -1
- package/src/lib/constants/tokens.js +13 -9
- package/src/lib/orchestrator/internals/cascade.d.ts +3 -1
- package/src/lib/orchestrator/internals/cascade.js +50 -22
- package/src/lib/orchestrator/internals/helpers.js +1 -0
- package/src/lib/orchestrator/internals/pc-usd-oracle.d.ts +1 -1
- package/src/lib/orchestrator/internals/pc-usd-oracle.js +1 -1
- package/src/lib/orchestrator/internals/preflight.d.ts +8 -5
- package/src/lib/orchestrator/internals/preflight.js +35 -21
- package/src/lib/orchestrator/internals/route-handlers.js +25 -22
- package/src/lib/orchestrator/internals/svm-rent.js +13 -4
- package/src/lib/orchestrator/orchestrator.d.ts +5 -6
- package/src/lib/orchestrator/orchestrator.js +10 -3
- package/src/lib/orchestrator/orchestrator.types.d.ts +18 -2
- package/src/lib/orchestrator/payload-builders.d.ts +3 -3
- package/src/lib/orchestrator/payload-builders.js +4 -4
- package/src/lib/progress-hook/progress-hook.js +33 -9
- package/src/lib/progress-hook/progress-hook.types.d.ts +3 -3
- package/src/lib/progress-hook/progress-hook.types.js +4 -2
- package/src/lib/push-chain/push-chain.d.ts +10 -4
- package/src/lib/push-chain/push-chain.js +2 -2
- package/src/lib/utils.js +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,70 @@
|
|
|
1
|
-
@pushchain/core@
|
|
1
|
+
@pushchain/core@6.0.2 (unreleased)
|
|
2
|
+
|
|
3
|
+
- Token constants now expose the missing `USDT.bsc` chain-suffix accessor,
|
|
4
|
+
while keeping `USDT.bnb` as a deprecated alias for backward compatibility.
|
|
5
|
+
|
|
6
|
+
- Updated Donut testnet stable token metadata to match the current source of
|
|
7
|
+
truth: external moveable token addresses are kept separate from Push Chain
|
|
8
|
+
PRC20 addresses, and the WPC/stable pool address audit table now reflects the
|
|
9
|
+
documented PRC20/pool pairs.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
@pushchain/core@6.0.1 (2026-05-15)
|
|
14
|
+
|
|
15
|
+
- Pre-flight UEA balance checks now default to warning-only behavior and
|
|
16
|
+
proceed when short. `sendTransaction` and `prepareTransaction` accept
|
|
17
|
+
`options.enforceGasCheck: true` to restore fail-fast behavior with
|
|
18
|
+
`InsufficientUEABalanceError`; pre-flight progress hooks now report
|
|
19
|
+
`WARNING` vs `ERROR` with shortfall metadata.
|
|
20
|
+
|
|
21
|
+
- Token constants added the `USDC.bsc` BSC suffix accessor while retaining
|
|
22
|
+
`USDC.bnb` as a deprecated compatibility alias.
|
|
23
|
+
|
|
24
|
+
- Consolidated tests, renamed transaction `target` fields to `recipient`, and
|
|
25
|
+
fixed SVM test cases around the release.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
@pushchain/core@6.0.0 (2026-05-14)
|
|
30
|
+
|
|
31
|
+
- Updated audit-driven contract and pool configuration, including BNB CEA
|
|
32
|
+
address changes and refreshed pool addresses.
|
|
33
|
+
|
|
34
|
+
- Fixed cascade, SVM payload, and SVM execution flows, with additional test-case
|
|
35
|
+
coverage for the audited scenarios.
|
|
36
|
+
|
|
37
|
+
- Improved PC amount formatting in transaction output and diagnostics.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
@pushchain/core@5.1.18 (2026-05-12)
|
|
42
|
+
|
|
43
|
+
- Added `executeTransactions` progress-hook coverage and fixed cascade
|
|
44
|
+
scenarios, including fresh-UEA and six-hop flows.
|
|
45
|
+
|
|
46
|
+
- Removed the `allowUnderfundedSwap` parameter and tightened native PC
|
|
47
|
+
formatting.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
@pushchain/core@5.1.17 (2026-05-07)
|
|
52
|
+
|
|
53
|
+
- Fixed the R3 EVM path tag so progress hooks emit the `303` route family
|
|
54
|
+
instead of `203`.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
@pushchain/core@5.1.16 (2026-05-07)
|
|
59
|
+
|
|
60
|
+
- Added pre-flight balance-check progress hooks.
|
|
61
|
+
|
|
62
|
+
- Fixed SVM rent checks, SVM upward ceiling behavior, cascade progress-hook
|
|
63
|
+
handling, and shared PC formatting.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
@pushchain/core@5.1.5 (2026-04-20)
|
|
2
68
|
|
|
3
69
|
- Route 1 (UOA → Push) now applies Case A/B/C USD-bucket sizing to the
|
|
4
70
|
Push-chain gas cost. Case A pads deposits to the $1 floor; Case B passes
|
package/package.json
CHANGED
|
@@ -96,7 +96,7 @@ export declare const UNIVERSAL_GATEWAY_PC: readonly [{
|
|
|
96
96
|
readonly inputs: readonly [{
|
|
97
97
|
readonly components: readonly [{
|
|
98
98
|
readonly internalType: "bytes";
|
|
99
|
-
readonly name: "
|
|
99
|
+
readonly name: "recipient";
|
|
100
100
|
readonly type: "bytes";
|
|
101
101
|
}, {
|
|
102
102
|
readonly internalType: "address";
|
|
@@ -42,7 +42,7 @@ exports.UNIVERSAL_GATEWAY_PC = [
|
|
|
42
42
|
inputs: [
|
|
43
43
|
{
|
|
44
44
|
components: [
|
|
45
|
-
{ internalType: 'bytes', name: '
|
|
45
|
+
{ internalType: 'bytes', name: 'recipient', type: 'bytes' },
|
|
46
46
|
{ internalType: 'address', name: 'token', type: 'address' },
|
|
47
47
|
{ internalType: 'uint256', name: 'amount', type: 'uint256' },
|
|
48
48
|
{ internalType: 'uint256', name: 'gasLimit', type: 'uint256' },
|
|
@@ -36,7 +36,11 @@ export declare const SYNTHETIC_PUSH_ERC20: Record<PUSH_NETWORK, {
|
|
|
36
36
|
USDC_ARB: `0x${string}`;
|
|
37
37
|
USDT_SOL: `0x${string}`;
|
|
38
38
|
USDC_SOL: `0x${string}`;
|
|
39
|
+
USDT_BSC: `0x${string}`;
|
|
40
|
+
/** @deprecated Use USDT_BSC instead. */
|
|
39
41
|
USDT_BNB: `0x${string}`;
|
|
42
|
+
USDC_BSC: `0x${string}`;
|
|
43
|
+
/** @deprecated Use USDC_BSC instead. */
|
|
40
44
|
USDC_BNB: `0x${string}`;
|
|
41
45
|
USDT_BASE: `0x${string}`;
|
|
42
46
|
USDC_BASE: `0x${string}`;
|
|
@@ -62,7 +62,9 @@ exports.SYNTHETIC_PUSH_ERC20 = {
|
|
|
62
62
|
USDC_ARB: '0x1091cCBA2FF8d2A131AE4B35e34cf3308C48572C',
|
|
63
63
|
USDT_SOL: '0x4f1A3D22d170a2F4Bddb37845a962322e24f4e34',
|
|
64
64
|
USDC_SOL: '0x04B8F634ABC7C879763F623e0f0550a4b5c4426F',
|
|
65
|
+
USDT_BSC: '0x731aF1Da5365259d27528557EE4aFBA4baC90ef2',
|
|
65
66
|
USDT_BNB: '0x731aF1Da5365259d27528557EE4aFBA4baC90ef2',
|
|
67
|
+
USDC_BSC: '0x120EBf25Dad7D6a09Ad2316f23f9Be95DBb90639',
|
|
66
68
|
USDC_BNB: '0x120EBf25Dad7D6a09Ad2316f23f9Be95DBb90639',
|
|
67
69
|
USDT_BASE: '0x148823809B853e1db187BC09A9ac909BC42F971a',
|
|
68
70
|
USDC_BASE: '0xD7C6cA1e2c0CE260BE0c0AD39C1540de460e3Be1',
|
|
@@ -82,7 +84,9 @@ exports.SYNTHETIC_PUSH_ERC20 = {
|
|
|
82
84
|
USDC_ARB: '0x1091cCBA2FF8d2A131AE4B35e34cf3308C48572C',
|
|
83
85
|
USDT_SOL: '0x4f1A3D22d170a2F4Bddb37845a962322e24f4e34',
|
|
84
86
|
USDC_SOL: '0x04B8F634ABC7C879763F623e0f0550a4b5c4426F',
|
|
87
|
+
USDT_BSC: '0x731aF1Da5365259d27528557EE4aFBA4baC90ef2',
|
|
85
88
|
USDT_BNB: '0x731aF1Da5365259d27528557EE4aFBA4baC90ef2',
|
|
89
|
+
USDC_BSC: '0x120EBf25Dad7D6a09Ad2316f23f9Be95DBb90639',
|
|
86
90
|
USDC_BNB: '0x120EBf25Dad7D6a09Ad2316f23f9Be95DBb90639',
|
|
87
91
|
USDT_BASE: '0x148823809B853e1db187BC09A9ac909BC42F971a',
|
|
88
92
|
USDC_BASE: '0xD7C6cA1e2c0CE260BE0c0AD39C1540de460e3Be1',
|
|
@@ -102,7 +106,9 @@ exports.SYNTHETIC_PUSH_ERC20 = {
|
|
|
102
106
|
USDC_ARB: '0xTBD',
|
|
103
107
|
USDT_SOL: '0xTBD',
|
|
104
108
|
USDC_SOL: '0xTBD',
|
|
109
|
+
USDT_BSC: '0xTBD',
|
|
105
110
|
USDT_BNB: '0xTBD',
|
|
111
|
+
USDC_BSC: '0xTBD',
|
|
106
112
|
USDC_BNB: '0xTBD',
|
|
107
113
|
USDT_BASE: '0xTBD',
|
|
108
114
|
USDC_BASE: '0xTBD',
|
|
@@ -122,7 +128,9 @@ exports.SYNTHETIC_PUSH_ERC20 = {
|
|
|
122
128
|
USDC_ARB: '0xTBD',
|
|
123
129
|
USDT_SOL: '0xTBD',
|
|
124
130
|
USDC_SOL: '0xTBD',
|
|
131
|
+
USDT_BSC: '0xTBD',
|
|
125
132
|
USDT_BNB: '0xTBD',
|
|
133
|
+
USDC_BSC: '0xTBD',
|
|
126
134
|
USDC_BNB: '0xTBD',
|
|
127
135
|
USDT_BASE: '0xTBD',
|
|
128
136
|
USDC_BASE: '0xTBD',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CHAIN, LIBRARY, PUSH_NETWORK } from './enums';
|
|
2
2
|
import { TypedDataDomain, TypedData } from '../universal/signer/signer.types';
|
|
3
|
-
export type { MoveableToken, PayableToken, PushChainMoveableToken, ChainSuffixAccessor, PushChainMoveableTokenAccessor, MoveableTokenConstantsMap, PayableTokenConstantsMap, } from './tokens';
|
|
3
|
+
export type { MoveableToken, PayableToken, PushChainMoveableToken, ChainSuffixAccessor, UsdcChainSuffixAccessor, PushChainMoveableTokenAccessor, MoveableTokenConstantsMap, PayableTokenConstantsMap, } from './tokens';
|
|
4
4
|
export declare const CONSTANTS: {
|
|
5
5
|
PUSH_NETWORK: typeof PUSH_NETWORK;
|
|
6
6
|
CHAIN: typeof CHAIN;
|
|
@@ -73,6 +73,17 @@ export interface ChainSuffixAccessor {
|
|
|
73
73
|
readonly eth: PushChainMoveableToken;
|
|
74
74
|
readonly arb: PushChainMoveableToken;
|
|
75
75
|
readonly base: PushChainMoveableToken;
|
|
76
|
+
readonly bsc: PushChainMoveableToken;
|
|
77
|
+
/** @deprecated Use `bsc` instead. */
|
|
78
|
+
readonly bnb: PushChainMoveableToken;
|
|
79
|
+
readonly sol: PushChainMoveableToken;
|
|
80
|
+
}
|
|
81
|
+
export interface UsdcChainSuffixAccessor {
|
|
82
|
+
readonly eth: PushChainMoveableToken;
|
|
83
|
+
readonly arb: PushChainMoveableToken;
|
|
84
|
+
readonly base: PushChainMoveableToken;
|
|
85
|
+
readonly bsc: PushChainMoveableToken;
|
|
86
|
+
/** @deprecated Use `bsc` instead. */
|
|
76
87
|
readonly bnb: PushChainMoveableToken;
|
|
77
88
|
readonly sol: PushChainMoveableToken;
|
|
78
89
|
}
|
|
@@ -86,7 +97,7 @@ export interface PushChainMoveableTokenAccessor {
|
|
|
86
97
|
readonly pStEth: PushChainMoveableToken;
|
|
87
98
|
readonly pDai: PushChainMoveableToken;
|
|
88
99
|
readonly USDT: ChainSuffixAccessor;
|
|
89
|
-
readonly USDC:
|
|
100
|
+
readonly USDC: UsdcChainSuffixAccessor;
|
|
90
101
|
}
|
|
91
102
|
export type MoveableTokenConstantsMap = {
|
|
92
103
|
ETHEREUM_SEPOLIA: MoveableTokenAccessor;
|
|
@@ -85,7 +85,7 @@ const TOKEN_META = {
|
|
|
85
85
|
USDT: {
|
|
86
86
|
symbol: 'USDT',
|
|
87
87
|
decimals: 6,
|
|
88
|
-
address: '
|
|
88
|
+
address: '0xC4230aEaFcF6b8B49a7b4e53886420f00ff71876',
|
|
89
89
|
mechanism: 'approve',
|
|
90
90
|
},
|
|
91
91
|
WETH: {
|
|
@@ -139,7 +139,7 @@ const TOKEN_META = {
|
|
|
139
139
|
USDT: {
|
|
140
140
|
symbol: 'USDT',
|
|
141
141
|
decimals: 6,
|
|
142
|
-
address: '
|
|
142
|
+
address: '0xE30928528f52CAEeB75fB07837e22d77D47e9c07',
|
|
143
143
|
mechanism: 'approve',
|
|
144
144
|
},
|
|
145
145
|
USDC: {
|
|
@@ -166,7 +166,7 @@ const TOKEN_META = {
|
|
|
166
166
|
USDT: {
|
|
167
167
|
symbol: 'USDT',
|
|
168
168
|
decimals: 6,
|
|
169
|
-
address: '
|
|
169
|
+
address: '0x4D7646B9eE3D68F4b0F135B5cbc66B00819F6b61',
|
|
170
170
|
mechanism: 'approve',
|
|
171
171
|
},
|
|
172
172
|
USDC: {
|
|
@@ -193,13 +193,13 @@ const TOKEN_META = {
|
|
|
193
193
|
USDT: {
|
|
194
194
|
symbol: 'USDT',
|
|
195
195
|
decimals: 6,
|
|
196
|
-
address: '
|
|
196
|
+
address: '0xE935d9c9C24D02E61186c640cc01d713C876d40F',
|
|
197
197
|
mechanism: 'approve',
|
|
198
198
|
},
|
|
199
199
|
USDC: {
|
|
200
200
|
symbol: 'USDC',
|
|
201
201
|
decimals: 6,
|
|
202
|
-
address: '
|
|
202
|
+
address: '0xA8802F96cAd0d45343d9bc660B6f7d80050A660b',
|
|
203
203
|
mechanism: 'approve',
|
|
204
204
|
},
|
|
205
205
|
},
|
|
@@ -265,12 +265,12 @@ function buildPushChainMoveableTokenList() {
|
|
|
265
265
|
mk('USDT', 6, s.USDT_ETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
|
|
266
266
|
mk('USDT', 6, s.USDT_ARB, enums_1.CHAIN.ARBITRUM_SEPOLIA),
|
|
267
267
|
mk('USDT', 6, s.USDT_BASE, enums_1.CHAIN.BASE_SEPOLIA),
|
|
268
|
-
mk('USDT', 6, s.
|
|
268
|
+
mk('USDT', 6, s.USDT_BSC, enums_1.CHAIN.BNB_TESTNET),
|
|
269
269
|
mk('USDT', 6, s.USDT_SOL, enums_1.CHAIN.SOLANA_DEVNET),
|
|
270
270
|
mk('USDC', 6, s.USDC_ETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
|
|
271
271
|
mk('USDC', 6, s.USDC_ARB, enums_1.CHAIN.ARBITRUM_SEPOLIA),
|
|
272
272
|
mk('USDC', 6, s.USDC_BASE, enums_1.CHAIN.BASE_SEPOLIA),
|
|
273
|
-
mk('USDC', 6, s.
|
|
273
|
+
mk('USDC', 6, s.USDC_BSC, enums_1.CHAIN.BNB_TESTNET),
|
|
274
274
|
mk('USDC', 6, s.USDC_SOL, enums_1.CHAIN.SOLANA_DEVNET),
|
|
275
275
|
mk('WETH', 18, s.WETH_ETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
|
|
276
276
|
mk('stETH', 18, s.stETH_ETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
|
|
@@ -365,6 +365,8 @@ function buildPushChainMoveableTokenAccessor() {
|
|
|
365
365
|
sourceChain,
|
|
366
366
|
prc20Address: address,
|
|
367
367
|
});
|
|
368
|
+
const usdtBsc = mk('USDT', 6, s.USDT_BSC, enums_1.CHAIN.BNB_TESTNET);
|
|
369
|
+
const usdcBsc = mk('USDC', 6, s.USDC_BSC, enums_1.CHAIN.BNB_TESTNET);
|
|
368
370
|
return {
|
|
369
371
|
pEth: mk('pETH', 18, s.pETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
|
|
370
372
|
pEthArb: mk('pETH_ARB', 18, s.pETH_ARB, enums_1.CHAIN.ARBITRUM_SEPOLIA),
|
|
@@ -378,14 +380,16 @@ function buildPushChainMoveableTokenAccessor() {
|
|
|
378
380
|
eth: mk('USDT', 6, s.USDT_ETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
|
|
379
381
|
arb: mk('USDT', 6, s.USDT_ARB, enums_1.CHAIN.ARBITRUM_SEPOLIA),
|
|
380
382
|
base: mk('USDT', 6, s.USDT_BASE, enums_1.CHAIN.BASE_SEPOLIA),
|
|
381
|
-
|
|
383
|
+
bsc: usdtBsc,
|
|
384
|
+
bnb: usdtBsc,
|
|
382
385
|
sol: mk('USDT', 6, s.USDT_SOL, enums_1.CHAIN.SOLANA_DEVNET),
|
|
383
386
|
},
|
|
384
387
|
USDC: {
|
|
385
388
|
eth: mk('USDC', 6, s.USDC_ETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
|
|
386
389
|
arb: mk('USDC', 6, s.USDC_ARB, enums_1.CHAIN.ARBITRUM_SEPOLIA),
|
|
387
390
|
base: mk('USDC', 6, s.USDC_BASE, enums_1.CHAIN.BASE_SEPOLIA),
|
|
388
|
-
|
|
391
|
+
bsc: usdcBsc,
|
|
392
|
+
bnb: usdcBsc,
|
|
389
393
|
sol: mk('USDC', 6, s.USDC_SOL, enums_1.CHAIN.SOLANA_DEVNET),
|
|
390
394
|
},
|
|
391
395
|
};
|
|
@@ -41,7 +41,9 @@ export interface ComposeCascadeResult {
|
|
|
41
41
|
multicalls: MultiCall[];
|
|
42
42
|
requiredNativeValue: bigint;
|
|
43
43
|
}
|
|
44
|
-
export declare function composeCascadeDetailed(ctx: OrchestratorContext, segments: CascadeSegment[], ueaAddress: `0x${string}`, ueaBalance?: bigint, ueaNonce?: bigint
|
|
44
|
+
export declare function composeCascadeDetailed(ctx: OrchestratorContext, segments: CascadeSegment[], ueaAddress: `0x${string}`, ueaBalance?: bigint, ueaNonce?: bigint, options?: {
|
|
45
|
+
enforceGasCheck?: boolean;
|
|
46
|
+
}): Promise<ComposeCascadeResult>;
|
|
45
47
|
export declare function composeCascade(ctx: OrchestratorContext, segments: CascadeSegment[], ueaAddress: `0x${string}`, ueaBalance?: bigint, ueaNonce?: bigint): Promise<MultiCall[]>;
|
|
46
48
|
export declare function createCascadedBuilder(ctx: OrchestratorContext, preparedTxs: PreparedUniversalTx[], callbacks: CascadeCallbacks, defaultEventHook?: (event: import('../../progress-hook/progress-hook.types').ProgressEvent) => void): {
|
|
47
49
|
send: () => Promise<CascadedTxResponse>;
|
|
@@ -753,7 +753,7 @@ function getInboundFundingForBurnToken(segments, beforeSegmentIndex, burnToken,
|
|
|
753
753
|
}
|
|
754
754
|
return total;
|
|
755
755
|
}
|
|
756
|
-
function composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
|
|
756
|
+
function composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonce, options) {
|
|
757
757
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
758
758
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
759
759
|
let accumulatedPushMulticalls = [];
|
|
@@ -762,6 +762,8 @@ function composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonce)
|
|
|
762
762
|
const currentUeaBalance = ueaBalance !== null && ueaBalance !== void 0 ? ueaBalance : BigInt(0);
|
|
763
763
|
const cascadeNativeSeed = getCascadeNativeSeed(segments);
|
|
764
764
|
const effectiveUeaBalance = currentUeaBalance + cascadeNativeSeed;
|
|
765
|
+
const enforceGasCheck = (options === null || options === void 0 ? void 0 : options.enforceGasCheck) === true ||
|
|
766
|
+
segments.some((segment) => segment.hops.some((hop) => { var _a; return ((_a = hop.params.options) === null || _a === void 0 ? void 0 : _a.enforceGasCheck) === true; }));
|
|
765
767
|
if (cascadeNativeSeed > BigInt(0)) {
|
|
766
768
|
(0, context_1.printLog)(ctx, `composeCascade — counting cascade native seed ${cascadeNativeSeed.toString()} for cascade sizing (current UEA balance ${currentUeaBalance.toString()})`);
|
|
767
769
|
}
|
|
@@ -773,8 +775,8 @@ function composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonce)
|
|
|
773
775
|
// Cascade pre-flight: catches the zero-balance silent-segment-zero failure
|
|
774
776
|
// mode. When `ueaBalance <= CASCADE_GAS_RESERVE`, `perOutboundNativeValue`
|
|
775
777
|
// is left undefined and downstream segments silently allocate value=0,
|
|
776
|
-
// producing under-funded swaps that revert inside Uniswap.
|
|
777
|
-
//
|
|
778
|
+
// producing under-funded swaps that revert inside Uniswap. Warn by default
|
|
779
|
+
// and throw only when enforceGasCheck=true.
|
|
778
780
|
if (numOutbounds > 0) {
|
|
779
781
|
(0, preflight_1.runPreflight)({
|
|
780
782
|
ctx,
|
|
@@ -785,6 +787,7 @@ function composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonce)
|
|
|
785
787
|
requiredValue: BigInt(1),
|
|
786
788
|
gasReserve: CASCADE_GAS_RESERVE,
|
|
787
789
|
pathTag: 'CASCADE',
|
|
790
|
+
enforceGasCheck,
|
|
788
791
|
});
|
|
789
792
|
}
|
|
790
793
|
let perOutboundNativeValue;
|
|
@@ -867,6 +870,17 @@ function composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonce)
|
|
|
867
870
|
// knows which hop's pool is misbehaving.
|
|
868
871
|
if (estimated > BigInt(0) && value < estimated) {
|
|
869
872
|
const shortfall = estimated - value;
|
|
873
|
+
(0, context_2.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_003_03, estimated, value, false, ueaAddress, 'CASCADE', {
|
|
874
|
+
kind: 'NATIVE',
|
|
875
|
+
segmentIndex: cascadeIdx,
|
|
876
|
+
enforceGasCheck,
|
|
877
|
+
shortfall,
|
|
878
|
+
});
|
|
879
|
+
if (!enforceGasCheck) {
|
|
880
|
+
(0, context_1.printLog)(ctx, `composeCascade — SVM outbound segment ${cascadeIdx} has native shortfall ${shortfall.toString()}; proceeding because enforceGasCheck=false`);
|
|
881
|
+
svmNativeValueBySegment.set(seg, value);
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
870
884
|
(0, context_2.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_003_04, estimated, value, shortfall, ueaAddress, 'CASCADE', { kind: 'NATIVE', segmentIndex: cascadeIdx });
|
|
871
885
|
throw new errors_1.InsufficientUEABalanceError({
|
|
872
886
|
required: estimated,
|
|
@@ -940,7 +954,13 @@ function composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonce)
|
|
|
940
954
|
args: [ueaAddress],
|
|
941
955
|
});
|
|
942
956
|
const sufficient = onHand >= segBurnAmount;
|
|
943
|
-
(0, context_2.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_003_03, segBurnAmount, onHand, sufficient, ueaAddress, 'CASCADE', {
|
|
957
|
+
(0, context_2.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_003_03, segBurnAmount, onHand, sufficient, ueaAddress, 'CASCADE', {
|
|
958
|
+
kind: 'PRC20',
|
|
959
|
+
burnToken: segBurnToken,
|
|
960
|
+
segmentIndex: segIdxLoop,
|
|
961
|
+
enforceGasCheck,
|
|
962
|
+
shortfall: sufficient ? BigInt(0) : segBurnAmount - onHand,
|
|
963
|
+
});
|
|
944
964
|
const priorPushExecutionMayFundBurn = segments
|
|
945
965
|
.slice(0, segIdxLoop)
|
|
946
966
|
.some((s) => s.type === 'PUSH_EXECUTION');
|
|
@@ -951,21 +971,26 @@ function composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonce)
|
|
|
951
971
|
!priorInboundMayFundBurn) {
|
|
952
972
|
const projectedOnHand = onHand + priorInboundFundingForBurn;
|
|
953
973
|
const shortfall = segBurnAmount - projectedOnHand;
|
|
954
|
-
(
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
974
|
+
if (!enforceGasCheck) {
|
|
975
|
+
(0, context_1.printLog)(ctx, `composeCascade — PRC-20 shortfall ${shortfall.toString()} for segment ${segIdxLoop}; proceeding because enforceGasCheck=false`);
|
|
976
|
+
}
|
|
977
|
+
else {
|
|
978
|
+
(0, context_2.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_003_04, segBurnAmount, projectedOnHand, shortfall, ueaAddress, 'CASCADE', {
|
|
979
|
+
kind: 'PRC20',
|
|
980
|
+
burnToken: segBurnToken,
|
|
981
|
+
segmentIndex: segIdxLoop,
|
|
982
|
+
});
|
|
983
|
+
throw new errors_1.InsufficientUEABalanceError({
|
|
984
|
+
required: segBurnAmount,
|
|
985
|
+
available: projectedOnHand,
|
|
986
|
+
shortfall,
|
|
987
|
+
ueaAddress,
|
|
988
|
+
pathTag: 'CASCADE',
|
|
989
|
+
reason: 'PRC20',
|
|
990
|
+
burnToken: segBurnToken,
|
|
991
|
+
segmentIndex: segIdxLoop,
|
|
992
|
+
});
|
|
993
|
+
}
|
|
969
994
|
}
|
|
970
995
|
else if (!sufficient && priorPushExecutionMayFundBurn) {
|
|
971
996
|
(0, context_1.printLog)(ctx, `composeCascade — skipping PRC-20 preflight failure for segment ${segIdxLoop}; earlier Push execution may fund ${segBurnToken} before this outbound runs`);
|
|
@@ -1252,11 +1277,14 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
|
|
|
1252
1277
|
const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
|
|
1253
1278
|
// Extract HopDescriptors
|
|
1254
1279
|
const hops = preparedTxs.map((tx) => tx._hop);
|
|
1280
|
+
const enforceGasCheck = hops.some((hop) => { var _a; return ((_a = hop.params.options) === null || _a === void 0 ? void 0 : _a.enforceGasCheck) === true; });
|
|
1281
|
+
const withCascadeOptions = (params) => enforceGasCheck
|
|
1282
|
+
? Object.assign(Object.assign({}, params), { options: Object.assign(Object.assign({}, params.options), { enforceGasCheck: true }) }) : params;
|
|
1255
1283
|
// Classify into segments
|
|
1256
1284
|
const segments = classifyIntoSegments(hops);
|
|
1257
1285
|
// Check if this is a single-hop Route 1 (no composition needed)
|
|
1258
1286
|
if (preparedTxs.length === 1 && preparedTxs[0].route === 'UOA_TO_PUSH') {
|
|
1259
|
-
const response = yield callbacks.executeFn(hops[0].params);
|
|
1287
|
+
const response = yield callbacks.executeFn(withCascadeOptions(hops[0].params));
|
|
1260
1288
|
const singleRoute1Result = {
|
|
1261
1289
|
initialTxHash: response.hash,
|
|
1262
1290
|
initialTxResponse: response,
|
|
@@ -1290,7 +1318,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
|
|
|
1290
1318
|
}
|
|
1291
1319
|
// Check if single-hop Route 2 (just execute directly)
|
|
1292
1320
|
if (preparedTxs.length === 1 && preparedTxs[0].route === 'UOA_TO_CEA') {
|
|
1293
|
-
const response = yield callbacks.executeFn(hops[0].params);
|
|
1321
|
+
const response = yield callbacks.executeFn(withCascadeOptions(hops[0].params));
|
|
1294
1322
|
const targetChain = hops[0].targetChain || (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
|
|
1295
1323
|
const singleRoute2Result = {
|
|
1296
1324
|
initialTxHash: response.hash,
|
|
@@ -1335,7 +1363,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
|
|
|
1335
1363
|
let composedMulticalls;
|
|
1336
1364
|
let cascadeRequiredNativeValue = BigInt(0);
|
|
1337
1365
|
try {
|
|
1338
|
-
const composed = yield composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonceCascade);
|
|
1366
|
+
const composed = yield composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonceCascade, { enforceGasCheck });
|
|
1339
1367
|
composedMulticalls = composed.multicalls;
|
|
1340
1368
|
cascadeRequiredNativeValue = composed.requiredNativeValue;
|
|
1341
1369
|
}
|
|
@@ -146,6 +146,7 @@ function toExecuteParams(params) {
|
|
|
146
146
|
maxFeePerGas: params.maxFeePerGas,
|
|
147
147
|
maxPriorityFeePerGas: params.maxPriorityFeePerGas,
|
|
148
148
|
deadline: params.deadline,
|
|
149
|
+
options: params.options,
|
|
149
150
|
payGasWith: params.payGasWith,
|
|
150
151
|
feeLockTxHash: params.feeLockTxHash,
|
|
151
152
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CHAIN } from '../../constants/enums';
|
|
2
2
|
import type { OrchestratorContext } from './context';
|
|
3
|
-
type StableKey = 'USDT_ETH' | 'USDT_ARB' | 'USDT_BASE' | '
|
|
3
|
+
type StableKey = 'USDT_ETH' | 'USDT_ARB' | 'USDT_BASE' | 'USDT_BSC' | 'USDC_BSC' | 'USDT_SOL';
|
|
4
4
|
/**
|
|
5
5
|
* Get $PC/USD price (8 decimals) for the given origin chain's route.
|
|
6
6
|
* Returns 0 on any failure — caller is expected to fall back to
|
|
@@ -37,7 +37,7 @@ const ORIGIN_TO_STABLE = {
|
|
|
37
37
|
[enums_1.CHAIN.ETHEREUM_SEPOLIA]: 'USDT_ETH',
|
|
38
38
|
[enums_1.CHAIN.ARBITRUM_SEPOLIA]: 'USDT_ARB',
|
|
39
39
|
[enums_1.CHAIN.BASE_SEPOLIA]: 'USDT_BASE',
|
|
40
|
-
[enums_1.CHAIN.BNB_TESTNET]: '
|
|
40
|
+
[enums_1.CHAIN.BNB_TESTNET]: 'USDT_BSC',
|
|
41
41
|
[enums_1.CHAIN.SOLANA_DEVNET]: 'USDT_SOL',
|
|
42
42
|
};
|
|
43
43
|
/** Default decimals for stable PRC-20s on Push Chain. */
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
* with `Error("STF")`, fees are burned, and the user sees an opaque
|
|
9
9
|
* library string with no balance signal.
|
|
10
10
|
*
|
|
11
|
-
* `runPreflight`
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* - emits `SEND-TX-203-03` (
|
|
11
|
+
* `runPreflight` checks the **pre-clamp** buffered pool quote against UEA
|
|
12
|
+
* balance (and optionally a PRC-20 burn balance) and either:
|
|
13
|
+
* - emits `SEND-TX-203-03` (INFO, sufficient) and lets the caller proceed;
|
|
14
|
+
* - emits `SEND-TX-203-03` (WARNING, insufficient) and proceeds when
|
|
15
|
+
* enforceGasCheck is false/omitted; or
|
|
15
16
|
* - emits `SEND-TX-203-03` (ERROR, insufficient) + `SEND-TX-203-04` and
|
|
16
|
-
* throws `InsufficientUEABalanceError
|
|
17
|
+
* throws `InsufficientUEABalanceError` when enforceGasCheck is true.
|
|
17
18
|
*
|
|
18
19
|
* The helper is intentionally not "pure" — it emits hooks and may throw.
|
|
19
20
|
* Callers fetch all balances (so the helper itself does no I/O).
|
|
@@ -34,6 +35,8 @@ export interface RunPreflightOpts {
|
|
|
34
35
|
burnToken?: `0x${string}`;
|
|
35
36
|
burnAmount?: bigint;
|
|
36
37
|
prc20Balance?: bigint;
|
|
38
|
+
/** Defaults to false: warn on shortfall and proceed. */
|
|
39
|
+
enforceGasCheck?: boolean;
|
|
37
40
|
/** Cascade-only: identifies which segment failed. */
|
|
38
41
|
segmentIndex?: number;
|
|
39
42
|
}
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
* with `Error("STF")`, fees are burned, and the user sees an opaque
|
|
10
10
|
* library string with no balance signal.
|
|
11
11
|
*
|
|
12
|
-
* `runPreflight`
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* - emits `SEND-TX-203-03` (
|
|
12
|
+
* `runPreflight` checks the **pre-clamp** buffered pool quote against UEA
|
|
13
|
+
* balance (and optionally a PRC-20 burn balance) and either:
|
|
14
|
+
* - emits `SEND-TX-203-03` (INFO, sufficient) and lets the caller proceed;
|
|
15
|
+
* - emits `SEND-TX-203-03` (WARNING, insufficient) and proceeds when
|
|
16
|
+
* enforceGasCheck is false/omitted; or
|
|
16
17
|
* - emits `SEND-TX-203-03` (ERROR, insufficient) + `SEND-TX-203-04` and
|
|
17
|
-
* throws `InsufficientUEABalanceError
|
|
18
|
+
* throws `InsufficientUEABalanceError` when enforceGasCheck is true.
|
|
18
19
|
*
|
|
19
20
|
* The helper is intentionally not "pure" — it emits hooks and may throw.
|
|
20
21
|
* Callers fetch all balances (so the helper itself does no I/O).
|
|
@@ -32,7 +33,7 @@ const errors_1 = require("./errors");
|
|
|
32
33
|
* sees the actionable PRC-20 shortfall instead of a stale native PC error.
|
|
33
34
|
*/
|
|
34
35
|
function runPreflight(opts) {
|
|
35
|
-
const { ctx, ueaAddress, ueaBalance, requiredValue, gasReserve, pathTag, burnToken, burnAmount, prc20Balance, segmentIndex, } = opts;
|
|
36
|
+
const { ctx, ueaAddress, ueaBalance, requiredValue, gasReserve, pathTag, burnToken, burnAmount, prc20Balance, enforceGasCheck = false, segmentIndex, } = opts;
|
|
36
37
|
// Each route bucket gets its own preflight IDs so hook streams stay
|
|
37
38
|
// self-consistent within their convention (R2 → 203-xx, R3 → 303-xx,
|
|
38
39
|
// cascade → 003-xx). The three hook formatters share an identical
|
|
@@ -54,9 +55,15 @@ function runPreflight(opts) {
|
|
|
54
55
|
if (burnAmount && burnAmount > BigInt(0) && burnToken) {
|
|
55
56
|
const onHand = prc20Balance !== null && prc20Balance !== void 0 ? prc20Balance : BigInt(0);
|
|
56
57
|
const sufficient = onHand >= burnAmount;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
const shortfall = sufficient ? BigInt(0) : burnAmount - onHand;
|
|
59
|
+
(0, context_1.fireProgressHook)(ctx, HOOK_PRE_INFO, burnAmount, onHand, sufficient, ueaAddress, pathTag, {
|
|
60
|
+
kind: 'PRC20',
|
|
61
|
+
burnToken,
|
|
62
|
+
segmentIndex,
|
|
63
|
+
enforceGasCheck,
|
|
64
|
+
shortfall,
|
|
65
|
+
});
|
|
66
|
+
if (!sufficient && enforceGasCheck) {
|
|
60
67
|
(0, context_1.fireProgressHook)(ctx, HOOK_PRE_FAIL, burnAmount, onHand, shortfall, ueaAddress, pathTag, { kind: 'PRC20', burnToken, segmentIndex });
|
|
61
68
|
throw new errors_1.InsufficientUEABalanceError({
|
|
62
69
|
required: burnAmount,
|
|
@@ -69,25 +76,32 @@ function runPreflight(opts) {
|
|
|
69
76
|
segmentIndex,
|
|
70
77
|
});
|
|
71
78
|
}
|
|
79
|
+
else if (!sufficient) {
|
|
80
|
+
(0, context_1.printLog)(ctx, `[preflight ${pathTag}] PRC-20 shortfall ${shortfall.toString()} for ${burnToken}; proceeding because enforceGasCheck=false`);
|
|
81
|
+
}
|
|
72
82
|
}
|
|
73
83
|
// 2. Native (UPC) balance check.
|
|
74
84
|
const totalRequired = requiredValue + gasReserve;
|
|
75
85
|
const sufficient = ueaBalance >= totalRequired;
|
|
76
|
-
|
|
86
|
+
const shortfall = sufficient ? BigInt(0) : totalRequired - ueaBalance;
|
|
87
|
+
(0, context_1.fireProgressHook)(ctx, HOOK_PRE_INFO, totalRequired, ueaBalance, sufficient, ueaAddress, pathTag, { kind: 'NATIVE', segmentIndex, enforceGasCheck, shortfall });
|
|
77
88
|
if (sufficient) {
|
|
78
89
|
return { ok: true, adjustedValue: requiredValue };
|
|
79
90
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
if (enforceGasCheck) {
|
|
92
|
+
(0, context_1.fireProgressHook)(ctx, HOOK_PRE_FAIL, totalRequired, ueaBalance, shortfall, ueaAddress, pathTag, { kind: 'NATIVE', segmentIndex });
|
|
93
|
+
throw new errors_1.InsufficientUEABalanceError({
|
|
94
|
+
required: totalRequired,
|
|
95
|
+
available: ueaBalance,
|
|
96
|
+
shortfall,
|
|
97
|
+
ueaAddress,
|
|
98
|
+
pathTag,
|
|
99
|
+
reason: 'NATIVE',
|
|
100
|
+
segmentIndex,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
(0, context_1.printLog)(ctx, `[preflight ${pathTag}] native shortfall ${shortfall.toString()}; proceeding because enforceGasCheck=false`);
|
|
104
|
+
return { ok: true, adjustedValue: requiredValue };
|
|
91
105
|
}
|
|
92
106
|
/**
|
|
93
107
|
* SVM-only telemetry threshold. Buffered pool quotes above this value
|
|
@@ -312,7 +312,7 @@ function executeMultiChain(ctx, params, executeFn) {
|
|
|
312
312
|
*/
|
|
313
313
|
function executeUoaToCea(ctx, params, executeFn) {
|
|
314
314
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
315
|
-
var _a, _b, _c, _d;
|
|
315
|
+
var _a, _b, _c, _d, _e;
|
|
316
316
|
const target = params.to;
|
|
317
317
|
const targetChain = target.chain;
|
|
318
318
|
const targetAddress = target.address;
|
|
@@ -418,7 +418,7 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
418
418
|
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, gasLimitForQuery, ceaPayload, ueaAddress, // revert recipient is the UEA
|
|
419
419
|
(_d = params.maxPCForGas) !== null && _d !== void 0 ? _d : BigInt(0), outboundGasPrice);
|
|
420
420
|
(0, context_1.printLog)(ctx, `executeUoaToCea — outbound request: ${JSON.stringify({
|
|
421
|
-
|
|
421
|
+
recipient: outboundReq.recipient,
|
|
422
422
|
token: outboundReq.token,
|
|
423
423
|
amount: outboundReq.amount.toString(),
|
|
424
424
|
gasLimit: outboundReq.gasLimit.toString(),
|
|
@@ -480,10 +480,9 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
480
480
|
(0, context_1.printLog)(ctx, `executeUoaToCea — capping nativeValueForGas at 200 UPC ceiling (was ${nativeValueForGas.toString()})`);
|
|
481
481
|
nativeValueForGas = EVM_NATIVE_VALUE_SAFETY_CAP;
|
|
482
482
|
}
|
|
483
|
-
// Pre-flight:
|
|
484
|
-
//
|
|
485
|
-
//
|
|
486
|
-
// bubbled up as Uniswap STF reverts. PRC-20 check fires whenever
|
|
483
|
+
// Pre-flight: warns by default when UEA cannot cover (nativeValueForGas +
|
|
484
|
+
// gasReserve) or the PRC-20 burn amount; throws only when
|
|
485
|
+
// options.enforceGasCheck=true. PRC-20 check fires whenever
|
|
487
486
|
// burnAmount > 0 — user must pre-hold the burn token, even when it equals
|
|
488
487
|
// the gas token (the gateway does transferFrom BEFORE the gas swap).
|
|
489
488
|
let prc20BalanceR2Evm;
|
|
@@ -505,6 +504,7 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
505
504
|
burnToken: prc20Token,
|
|
506
505
|
burnAmount,
|
|
507
506
|
prc20Balance: prc20BalanceR2Evm,
|
|
507
|
+
enforceGasCheck: ((_e = params.options) === null || _e === void 0 ? void 0 : _e.enforceGasCheck) === true,
|
|
508
508
|
});
|
|
509
509
|
// Preflight success means nativeValueForGas already covers required + reserve; no adjust needed.
|
|
510
510
|
// Build outbound multicalls (approve burn + sendUniversalTxOutbound with native value)
|
|
@@ -568,7 +568,7 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
568
568
|
*/
|
|
569
569
|
function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
570
570
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
571
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
571
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
572
572
|
const targetChain = target.chain;
|
|
573
573
|
const targetAddress = target.address; // 0x-prefixed, 32 bytes
|
|
574
574
|
const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
|
|
@@ -656,7 +656,7 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
656
656
|
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, effectiveGasLimit, svmPayload, ueaAddress, // revert recipient is the UEA
|
|
657
657
|
(_f = params.maxPCForGas) !== null && _f !== void 0 ? _f : BigInt(0), outboundGasPriceSvm);
|
|
658
658
|
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — outbound request: ${JSON.stringify({
|
|
659
|
-
|
|
659
|
+
recipient: outboundReq.recipient,
|
|
660
660
|
token: outboundReq.token,
|
|
661
661
|
amount: outboundReq.amount.toString(),
|
|
662
662
|
gasLimit: outboundReq.gasLimit.toString(),
|
|
@@ -710,10 +710,9 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
710
710
|
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — nativeValueForGas=${nativeValueForGas.toString()} (includes 2.2x buffer)`);
|
|
711
711
|
(0, preflight_1.maybeFireSvmWarnThreshold)(ctx, nativeValueForGas, gasToken, 'R2_SVM');
|
|
712
712
|
}
|
|
713
|
-
// Pre-flight:
|
|
714
|
-
//
|
|
715
|
-
//
|
|
716
|
-
// swaps and bubbled up as Uniswap STF reverts.
|
|
713
|
+
// Pre-flight: warns by default when UEA cannot cover (nativeValueForGas +
|
|
714
|
+
// SVM_GAS_RESERVE) or the PRC-20 burn amount; throws only when
|
|
715
|
+
// options.enforceGasCheck=true.
|
|
717
716
|
// PRC-20 burn-balance pre-check fires whenever `burnAmount > 0`, regardless
|
|
718
717
|
// of whether `prc20Token` happens to equal `gasToken`. The gateway's
|
|
719
718
|
// `sendUniversalTxOutbound` does `transferFrom(user, gateway, burnAmount)`
|
|
@@ -739,6 +738,7 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
739
738
|
burnToken: prc20Token,
|
|
740
739
|
burnAmount,
|
|
741
740
|
prc20Balance: prc20BalanceR2Svm,
|
|
741
|
+
enforceGasCheck: ((_j = params.options) === null || _j === void 0 ? void 0 : _j.enforceGasCheck) === true,
|
|
742
742
|
});
|
|
743
743
|
// --- Build Push Chain multicalls (approve + sendUniversalTxOutbound) ---
|
|
744
744
|
// Reuse the same builder as EVM — this part is identical
|
|
@@ -804,7 +804,7 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
804
804
|
*/
|
|
805
805
|
function executeCeaToPush(ctx, params, executeFn) {
|
|
806
806
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
807
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
807
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
808
808
|
// 1. Validate and extract source chain
|
|
809
809
|
if (!((_a = params.from) === null || _a === void 0 ? void 0 : _a.chain)) {
|
|
810
810
|
throw new Error('Route 3 (CEA -> Push) requires from.chain to specify the source CEA chain');
|
|
@@ -936,15 +936,15 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
936
936
|
const outboundGasLimit = (_f = params.gasLimit) !== null && _f !== void 0 ? _f : selectors_1.DEFAULT_CEA_TO_PUSH_GAS_LIMIT;
|
|
937
937
|
(0, context_1.printLog)(ctx, `executeCeaToPush — prc20Token: ${prc20Token}, burnAmount: ${burnAmount.toString()}`);
|
|
938
938
|
// 9. Build outbound request (same structure as Route 2)
|
|
939
|
-
//
|
|
940
|
-
let outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, //
|
|
939
|
+
// recipient = CEA address (for self-execution), value = 0 in payload
|
|
940
|
+
let outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, // recipient: CEA address (to=CEA for self-execution)
|
|
941
941
|
prc20Token, // token: native PRC-20 for source chain (for namespace lookup)
|
|
942
942
|
burnAmount, // amount: 0 (payload-only, CEA uses its own balance)
|
|
943
943
|
outboundGasLimit, ceaPayload, // payload: ABI-encoded CEA multicall
|
|
944
944
|
ueaAddress, // revertRecipient: UEA
|
|
945
945
|
(_g = params.maxPCForGas) !== null && _g !== void 0 ? _g : BigInt(0));
|
|
946
946
|
(0, context_1.printLog)(ctx, `executeCeaToPush — outbound request: ${JSON.stringify({
|
|
947
|
-
|
|
947
|
+
recipient: outboundReq.recipient,
|
|
948
948
|
token: outboundReq.token,
|
|
949
949
|
amount: outboundReq.amount.toString(),
|
|
950
950
|
gasLimit: outboundReq.gasLimit.toString(),
|
|
@@ -1047,7 +1047,8 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
1047
1047
|
}
|
|
1048
1048
|
// Pre-flight (R3 EVM): no PRC-20 burn check — `burnAmount = 0` makes this
|
|
1049
1049
|
// payload-only (UEA never holds the source-chain PRC-20; see plan §9 #4).
|
|
1050
|
-
// Native UPC check still applies for the gas swap.
|
|
1050
|
+
// Native UPC check still applies for the gas swap. It warns by default and
|
|
1051
|
+
// throws only when options.enforceGasCheck=true.
|
|
1051
1052
|
(0, preflight_1.runPreflight)({
|
|
1052
1053
|
ctx,
|
|
1053
1054
|
ueaAddress,
|
|
@@ -1055,6 +1056,7 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
1055
1056
|
requiredValue: nativeValueForGas,
|
|
1056
1057
|
gasReserve: OUTBOUND_GAS_RESERVE_R3,
|
|
1057
1058
|
pathTag: 'R3_EVM',
|
|
1059
|
+
enforceGasCheck: ((_l = params.options) === null || _l === void 0 ? void 0 : _l.enforceGasCheck) === true,
|
|
1058
1060
|
});
|
|
1059
1061
|
// 12. Build Push Chain multicalls (approvals + sendUniversalTxOutbound)
|
|
1060
1062
|
const pushChainMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
|
|
@@ -1120,7 +1122,7 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
1120
1122
|
*/
|
|
1121
1123
|
function executeCeaToPushSvm(ctx, params, sourceChain, executeFn) {
|
|
1122
1124
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
1123
|
-
var _a, _b, _c, _d, _e;
|
|
1125
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1124
1126
|
if (typeof params.to !== 'string') {
|
|
1125
1127
|
throw new Error('Route 3 SVM (CEA -> Push): to must be a Push Chain address (string), not a ChainTarget');
|
|
1126
1128
|
}
|
|
@@ -1170,9 +1172,9 @@ function executeCeaToPushSvm(ctx, params, sourceChain, executeFn) {
|
|
|
1170
1172
|
// on the cascade path, and the same precompile is used here.
|
|
1171
1173
|
const burnAmount = BigInt(0);
|
|
1172
1174
|
let effectiveGasLimit = (_a = params.gasLimit) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
1173
|
-
// Build outbound request:
|
|
1175
|
+
// Build outbound request: recipient = gateway program (self-call)
|
|
1174
1176
|
let outboundReq = (0, payload_builders_1.buildOutboundRequest)(gatewayProgramHex, prc20Token, burnAmount, effectiveGasLimit, svmPayload, ueaAddress, (_b = params.maxPCForGas) !== null && _b !== void 0 ? _b : BigInt(0));
|
|
1175
|
-
(0, context_1.printLog)(ctx, `executeCeaToPushSvm — outbound request:
|
|
1177
|
+
(0, context_1.printLog)(ctx, `executeCeaToPushSvm — outbound request: recipient=${outboundReq.recipient.slice(0, 20)}..., token=${outboundReq.token}, maxPCForGas=${outboundReq.maxPCForGas}`);
|
|
1176
1178
|
// Query gas fees
|
|
1177
1179
|
let gasFee = BigInt(0);
|
|
1178
1180
|
let protocolFeeR3Svm = BigInt(0);
|
|
@@ -1245,13 +1247,13 @@ function executeCeaToPushSvm(ctx, params, sourceChain, executeFn) {
|
|
|
1245
1247
|
: UPWARD_BASE_CEILING_R3_SVM;
|
|
1246
1248
|
// Upward-only allocation: when balance has headroom over the calibrated
|
|
1247
1249
|
// value, consume more of it (up to the ceiling above). Down-clamp +
|
|
1248
|
-
// zero-balance
|
|
1250
|
+
// zero-balance handling lives in pre-flight.
|
|
1249
1251
|
// Ordering note: pre-flight runs AFTER the upward adjust below; the
|
|
1250
1252
|
// semantics are equivalent to running it before — when upward adjust
|
|
1251
1253
|
// applies it sets nativeValueForGas to balance-reserve (capped), and the
|
|
1252
1254
|
// post-adjust pre-flight check is always satisfied. When upward adjust is
|
|
1253
1255
|
// skipped (balance too low), pre-flight runs against the calibrated value
|
|
1254
|
-
// and throws
|
|
1256
|
+
// and either warns or throws based on options.enforceGasCheck.
|
|
1255
1257
|
if (currentBalance > OUTBOUND_GAS_RESERVE_R3_SVM &&
|
|
1256
1258
|
currentBalance - OUTBOUND_GAS_RESERVE_R3_SVM > nativeValueForGas) {
|
|
1257
1259
|
const balanceDriven = currentBalance - OUTBOUND_GAS_RESERVE_R3_SVM;
|
|
@@ -1273,6 +1275,7 @@ function executeCeaToPushSvm(ctx, params, sourceChain, executeFn) {
|
|
|
1273
1275
|
requiredValue: nativeValueForGas,
|
|
1274
1276
|
gasReserve: OUTBOUND_GAS_RESERVE_R3_SVM,
|
|
1275
1277
|
pathTag: 'R3_SVM',
|
|
1278
|
+
enforceGasCheck: ((_f = params.options) === null || _f === void 0 ? void 0 : _f.enforceGasCheck) === true,
|
|
1276
1279
|
});
|
|
1277
1280
|
// Build Push Chain multicalls (approvals + sendUniversalTxOutbound)
|
|
1278
1281
|
const pushChainMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
|
|
@@ -97,6 +97,14 @@ function gasLimitForSvmGasFeeBudget(gasFeeBudget, gasPrice) {
|
|
|
97
97
|
}
|
|
98
98
|
return (gasFeeBudget + gasPrice - BigInt(1)) / gasPrice;
|
|
99
99
|
}
|
|
100
|
+
function resolveSvmGasLimitUsed(quote) {
|
|
101
|
+
if (quote.gasLimitUsed > BigInt(0) ||
|
|
102
|
+
quote.gasFee <= BigInt(0) ||
|
|
103
|
+
quote.gasPrice <= BigInt(0)) {
|
|
104
|
+
return quote;
|
|
105
|
+
}
|
|
106
|
+
return Object.assign(Object.assign({}, quote), { gasLimitUsed: gasLimitForSvmGasFeeBudget(quote.gasFee, quote.gasPrice) });
|
|
107
|
+
}
|
|
100
108
|
function ensureSvmFinalizeGasBudgetQuote(_a) {
|
|
101
109
|
return tslib_1.__awaiter(this, arguments, void 0, function* ({ ctx, ueaAddress, targetChain, prc20Token, quote, splMintBase58, burnAmount, pathTag, }) {
|
|
102
110
|
const minGasFee = yield getSvmFinalizeGasBudget({
|
|
@@ -107,9 +115,10 @@ function ensureSvmFinalizeGasBudgetQuote(_a) {
|
|
|
107
115
|
burnAmount,
|
|
108
116
|
});
|
|
109
117
|
if (quote.gasFee >= minGasFee) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
const resolvedQuote = resolveSvmGasLimitUsed(quote);
|
|
119
|
+
(0, context_1.printLog)(ctx, `${pathTag} — SVM finalize gas budget ok: gasFee=${resolvedQuote.gasFee.toString()}, ` +
|
|
120
|
+
`minimum=${minGasFee.toString()}, gasLimit=${resolvedQuote.gasLimitUsed.toString()}`);
|
|
121
|
+
return resolvedQuote;
|
|
113
122
|
}
|
|
114
123
|
const bumpedGasLimit = gasLimitForSvmGasFeeBudget(minGasFee, quote.gasPrice);
|
|
115
124
|
(0, context_1.printLog)(ctx, `${pathTag} — bumping SVM gasLimit ${quote.gasLimitUsed.toString()} → ${bumpedGasLimit.toString()}; ` +
|
|
@@ -119,7 +128,7 @@ function ensureSvmFinalizeGasBudgetQuote(_a) {
|
|
|
119
128
|
(0, context_1.printLog)(ctx, `${pathTag} — WARNING: bumped SVM gasFee=${bumpedQuote.gasFee.toString()} ` +
|
|
120
129
|
`still below finalize minimum=${minGasFee.toString()}`);
|
|
121
130
|
}
|
|
122
|
-
return bumpedQuote;
|
|
131
|
+
return resolveSvmGasLimitUsed(bumpedQuote);
|
|
123
132
|
});
|
|
124
133
|
}
|
|
125
134
|
/**
|
|
@@ -4,7 +4,7 @@ import type { AccountStatus, UniversalTxResponse } from './orchestrator.types';
|
|
|
4
4
|
import { ProgressEvent } from '../progress-hook/progress-hook.types';
|
|
5
5
|
import { PushClient } from '../push-client/push-client';
|
|
6
6
|
import type { UniversalAccount, UniversalSigner } from '../universal/universal.types';
|
|
7
|
-
import { ExecuteParams, UniversalExecuteParams, PreparedUniversalTx, CascadedTxResponse, RescueFundsParams } from './orchestrator.types';
|
|
7
|
+
import { ExecuteParams, UniversalExecuteParams, PreparedUniversalTx, CascadedTxResponse, CascadeExecutionOptions, TransactionExecutionOptions, RescueFundsParams } from './orchestrator.types';
|
|
8
8
|
import { TransactionRoute } from './route-detector';
|
|
9
9
|
export declare class Orchestrator {
|
|
10
10
|
private readonly universalSigner;
|
|
@@ -71,15 +71,16 @@ export declare class Orchestrator {
|
|
|
71
71
|
* Routes 2-4 (multi-chain) delegate to prepareTransaction().send().
|
|
72
72
|
* Route 1 (Push Chain) dispatches to extracted sub-flow modules.
|
|
73
73
|
*/
|
|
74
|
-
execute(params: ExecuteParams | UniversalExecuteParams): Promise<UniversalTxResponse>;
|
|
74
|
+
execute(params: ExecuteParams | UniversalExecuteParams, options?: TransactionExecutionOptions): Promise<UniversalTxResponse>;
|
|
75
75
|
/**
|
|
76
76
|
* Prepare a universal transaction without executing it.
|
|
77
77
|
* Returns a PreparedUniversalTx that can be chained with thenOn() or sent with send().
|
|
78
78
|
*
|
|
79
79
|
* @param params - Universal execution parameters
|
|
80
|
+
* @param options - Optional transaction behavior switches.
|
|
80
81
|
* @returns PreparedUniversalTx with chaining capabilities
|
|
81
82
|
*/
|
|
82
|
-
prepareTransaction(params: UniversalExecuteParams): Promise<PreparedUniversalTx>;
|
|
83
|
+
prepareTransaction(params: UniversalExecuteParams, options?: TransactionExecutionOptions): Promise<PreparedUniversalTx>;
|
|
83
84
|
/**
|
|
84
85
|
* Creates a cascaded transaction builder for nested multi-chain execution.
|
|
85
86
|
* The cascade composes all hops bottom-to-top into a single Push Chain tx.
|
|
@@ -91,9 +92,7 @@ export declare class Orchestrator {
|
|
|
91
92
|
* tracking). Dedups by reference if it matches the init-time hook.
|
|
92
93
|
* @returns Object with send() method
|
|
93
94
|
*/
|
|
94
|
-
createCascadedBuilder(preparedTxs: PreparedUniversalTx[], options?: {
|
|
95
|
-
progressHook?: (event: ProgressEvent) => void;
|
|
96
|
-
}): {
|
|
95
|
+
createCascadedBuilder(preparedTxs: PreparedUniversalTx[], options?: CascadeExecutionOptions): {
|
|
97
96
|
send: () => Promise<CascadedTxResponse>;
|
|
98
97
|
};
|
|
99
98
|
/**
|
|
@@ -129,9 +129,12 @@ class Orchestrator {
|
|
|
129
129
|
* Routes 2-4 (multi-chain) delegate to prepareTransaction().send().
|
|
130
130
|
* Route 1 (Push Chain) dispatches to extracted sub-flow modules.
|
|
131
131
|
*/
|
|
132
|
-
execute(params) {
|
|
132
|
+
execute(params, options) {
|
|
133
133
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
134
134
|
var _a, _b, _c, _d;
|
|
135
|
+
if (options) {
|
|
136
|
+
params = Object.assign(Object.assign({}, params), { options: Object.assign(Object.assign({}, params.options), options) });
|
|
137
|
+
}
|
|
135
138
|
// Snapshot the caller's active route — `executeMultiChain` recurses into
|
|
136
139
|
// this same method for R2/R3's inner Push-side execution, and without
|
|
137
140
|
// snapshot/restore the recursive `detectRoute(params)` would clobber the
|
|
@@ -285,10 +288,14 @@ class Orchestrator {
|
|
|
285
288
|
* Returns a PreparedUniversalTx that can be chained with thenOn() or sent with send().
|
|
286
289
|
*
|
|
287
290
|
* @param params - Universal execution parameters
|
|
291
|
+
* @param options - Optional transaction behavior switches.
|
|
288
292
|
* @returns PreparedUniversalTx with chaining capabilities
|
|
289
293
|
*/
|
|
290
|
-
prepareTransaction(params) {
|
|
294
|
+
prepareTransaction(params, options) {
|
|
291
295
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
296
|
+
if (options) {
|
|
297
|
+
params = Object.assign(Object.assign({}, params), { options: Object.assign(Object.assign({}, params.options), options) });
|
|
298
|
+
}
|
|
292
299
|
return (0, internals_1.prepareTransaction)(this.ctx, params, this._getCascadeCallbacks());
|
|
293
300
|
});
|
|
294
301
|
}
|
|
@@ -306,7 +313,7 @@ class Orchestrator {
|
|
|
306
313
|
createCascadedBuilder(preparedTxs, options) {
|
|
307
314
|
const perCallHook = options === null || options === void 0 ? void 0 : options.progressHook;
|
|
308
315
|
if (!perCallHook) {
|
|
309
|
-
return (0, internals_1.createCascadedBuilder)(this.ctx, preparedTxs, this._getCascadeCallbacks());
|
|
316
|
+
return (0, internals_1.createCascadedBuilder)(this.ctx, preparedTxs, this._getCascadeCallbacks(), undefined);
|
|
310
317
|
}
|
|
311
318
|
// Wrap ctx.progressHook for the synchronous send() phase — captures every
|
|
312
319
|
// fireProgressHook(ctx, ...) call during pre-flight, composeCascade, and
|
|
@@ -31,6 +31,14 @@ export type UniversalTo = `0x${string}` | ChainTarget;
|
|
|
31
31
|
* Transaction route identifiers
|
|
32
32
|
*/
|
|
33
33
|
export type TransactionRouteType = 'UOA_TO_PUSH' | 'UOA_TO_CEA' | 'CEA_TO_PUSH' | 'CEA_TO_CEA';
|
|
34
|
+
export interface TransactionExecutionOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Enforce the SDK pre-flight gas/balance check.
|
|
37
|
+
* - false/omitted: emit a warning on shortfall and continue
|
|
38
|
+
* - true: emit the failure hook, throw InsufficientUEABalanceError, and stop
|
|
39
|
+
*/
|
|
40
|
+
enforceGasCheck?: boolean;
|
|
41
|
+
}
|
|
34
42
|
export type ExecuteParams = {
|
|
35
43
|
/**
|
|
36
44
|
* The target contract or account on Push Chain.
|
|
@@ -80,6 +88,10 @@ export type ExecuteParams = {
|
|
|
80
88
|
* Optional for signature expiry
|
|
81
89
|
*/
|
|
82
90
|
deadline?: bigint;
|
|
91
|
+
/**
|
|
92
|
+
* Optional transaction behavior switches.
|
|
93
|
+
*/
|
|
94
|
+
options?: TransactionExecutionOptions;
|
|
83
95
|
/**
|
|
84
96
|
* Optional: pay gas in a specific token. If not provided, use `token` (bridge token) when present; otherwise, native token.
|
|
85
97
|
*/
|
|
@@ -432,7 +444,7 @@ export interface SvmExecutePayloadFields {
|
|
|
432
444
|
* Request structure for sendUniversalTxOutbound on Push Chain
|
|
433
445
|
* Used for Routes 2, 3, 4 (outbound from Push)
|
|
434
446
|
*
|
|
435
|
-
* NOTE: The `
|
|
447
|
+
* NOTE: The `recipient` field is raw recipient bytes for the destination chain.
|
|
436
448
|
* For EVM CEA funds-parking, use the zero recipient when `payload` is empty.
|
|
437
449
|
*/
|
|
438
450
|
export interface UniversalOutboundTxRequest {
|
|
@@ -440,7 +452,7 @@ export interface UniversalOutboundTxRequest {
|
|
|
440
452
|
* Raw destination recipient bytes. EVM routes usually pass a 20-byte address;
|
|
441
453
|
* SVM routes pass a 32-byte program/account address.
|
|
442
454
|
*/
|
|
443
|
-
|
|
455
|
+
recipient: `0x${string}`;
|
|
444
456
|
/** PRC20 token address on Push Chain to burn */
|
|
445
457
|
token: `0x${string}`;
|
|
446
458
|
/** Amount to burn (0 for no-burn, use existing CEA balance) */
|
|
@@ -662,6 +674,10 @@ export interface CascadeTrackOptions {
|
|
|
662
674
|
*/
|
|
663
675
|
eventHook?: (event: import('../progress-hook/progress-hook.types').ProgressEvent) => void;
|
|
664
676
|
}
|
|
677
|
+
export interface CascadeExecutionOptions {
|
|
678
|
+
/** Per-call progress callback. */
|
|
679
|
+
progressHook?: (event: import('../progress-hook/progress-hook.types').ProgressEvent) => void;
|
|
680
|
+
}
|
|
665
681
|
/**
|
|
666
682
|
* Progress event emitted during cascade tracking
|
|
667
683
|
*/
|
|
@@ -70,8 +70,8 @@ export declare function buildSendUniversalTxToUEA(ceaAddress: `0x${string}`, tok
|
|
|
70
70
|
/**
|
|
71
71
|
* Build UniversalOutboundTxRequest for Push Chain outbound
|
|
72
72
|
*
|
|
73
|
-
* @param
|
|
74
|
-
*
|
|
73
|
+
* @param recipient - Raw recipient bytes for the destination chain. For EVM CEA
|
|
74
|
+
* funds-parking, use the zero recipient when payload is empty.
|
|
75
75
|
* @param prc20Token - PRC20 token address to burn (or address(0) for native)
|
|
76
76
|
* @param amount - Amount to burn
|
|
77
77
|
* @param gasLimit - Gas limit for fee calculation
|
|
@@ -81,7 +81,7 @@ export declare function buildSendUniversalTxToUEA(ceaAddress: `0x${string}`, tok
|
|
|
81
81
|
* @param gasPrice - Destination-chain gas price override (0 = UniversalCore default)
|
|
82
82
|
* @returns UniversalOutboundTxRequest object
|
|
83
83
|
*/
|
|
84
|
-
export declare function buildOutboundRequest(
|
|
84
|
+
export declare function buildOutboundRequest(recipient: `0x${string}`, prc20Token: `0x${string}`, amount: bigint, gasLimit: bigint, payload: `0x${string}`, revertRecipient: `0x${string}`, maxPCForGas?: bigint, gasPrice?: bigint): UniversalOutboundTxRequest;
|
|
85
85
|
export declare function assertCeaFundsParkingInvariant(recipient: `0x${string}`, payload: `0x${string}`): void;
|
|
86
86
|
/**
|
|
87
87
|
* Build ERC20 transfer multicall
|
|
@@ -226,8 +226,8 @@ function buildSendUniversalTxToUEA(ceaAddress, token, amount, payload, revertRec
|
|
|
226
226
|
/**
|
|
227
227
|
* Build UniversalOutboundTxRequest for Push Chain outbound
|
|
228
228
|
*
|
|
229
|
-
* @param
|
|
230
|
-
*
|
|
229
|
+
* @param recipient - Raw recipient bytes for the destination chain. For EVM CEA
|
|
230
|
+
* funds-parking, use the zero recipient when payload is empty.
|
|
231
231
|
* @param prc20Token - PRC20 token address to burn (or address(0) for native)
|
|
232
232
|
* @param amount - Amount to burn
|
|
233
233
|
* @param gasLimit - Gas limit for fee calculation
|
|
@@ -237,9 +237,9 @@ function buildSendUniversalTxToUEA(ceaAddress, token, amount, payload, revertRec
|
|
|
237
237
|
* @param gasPrice - Destination-chain gas price override (0 = UniversalCore default)
|
|
238
238
|
* @returns UniversalOutboundTxRequest object
|
|
239
239
|
*/
|
|
240
|
-
function buildOutboundRequest(
|
|
240
|
+
function buildOutboundRequest(recipient, prc20Token, amount, gasLimit, payload, revertRecipient, maxPCForGas = BigInt(0), gasPrice = BigInt(0)) {
|
|
241
241
|
return {
|
|
242
|
-
|
|
242
|
+
recipient,
|
|
243
243
|
token: prc20Token,
|
|
244
244
|
amount,
|
|
245
245
|
gasLimit,
|
|
@@ -23,6 +23,18 @@ const friendlyChain = (chainOrNs) => {
|
|
|
23
23
|
const key = utils_1.Utils.chains.getChainName(asString);
|
|
24
24
|
return key ? toTitleCase(key) : asString;
|
|
25
25
|
};
|
|
26
|
+
function preflightLevel(sufficient, enforceGasCheck) {
|
|
27
|
+
if (sufficient)
|
|
28
|
+
return 'INFO';
|
|
29
|
+
return enforceGasCheck === false ? 'WARNING' : 'ERROR';
|
|
30
|
+
}
|
|
31
|
+
function preflightSuffix(sufficient, pathTag, enforceGasCheck) {
|
|
32
|
+
if (sufficient)
|
|
33
|
+
return `sufficient (${pathTag})`;
|
|
34
|
+
return enforceGasCheck === false
|
|
35
|
+
? `INSUFFICIENT (${pathTag}); warning only, proceeding`
|
|
36
|
+
: `INSUFFICIENT (${pathTag})`;
|
|
37
|
+
}
|
|
26
38
|
/**
|
|
27
39
|
* Classify a sign-time error as either a true wallet user-decline
|
|
28
40
|
* (viem `UserRejectedRequestError`, ethers `ACTION_REJECTED`, EIP-1193 4001,
|
|
@@ -307,15 +319,16 @@ const RAW_HOOKS_R2 = {
|
|
|
307
319
|
level: 'SUCCESS',
|
|
308
320
|
}),
|
|
309
321
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_203_03]: (required, available, sufficient, ueaAddress, pathTag, extra) => {
|
|
310
|
-
var _a, _b, _c;
|
|
322
|
+
var _a, _b, _c, _d;
|
|
311
323
|
const kind = (_a = extra === null || extra === void 0 ? void 0 : extra.kind) !== null && _a !== void 0 ? _a : 'NATIVE';
|
|
312
324
|
const availableStr = kind === 'PRC20' ? `${available} units` : (0, formatters_1.formatPc)(available, 4);
|
|
313
325
|
const requiredStr = kind === 'PRC20' ? `${required} units` : (0, formatters_1.formatPc)(required, 4);
|
|
326
|
+
const enforceGasCheck = extra === null || extra === void 0 ? void 0 : extra.enforceGasCheck;
|
|
314
327
|
return {
|
|
315
328
|
id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_203_03,
|
|
316
329
|
title: 'Pre-flight Balance Check',
|
|
317
330
|
message: `UEA balance: ${availableStr}; required: ${requiredStr}; ` +
|
|
318
|
-
|
|
331
|
+
preflightSuffix(sufficient, pathTag, enforceGasCheck),
|
|
319
332
|
response: {
|
|
320
333
|
required,
|
|
321
334
|
available,
|
|
@@ -325,8 +338,11 @@ const RAW_HOOKS_R2 = {
|
|
|
325
338
|
kind,
|
|
326
339
|
burnToken: (_b = extra === null || extra === void 0 ? void 0 : extra.burnToken) !== null && _b !== void 0 ? _b : null,
|
|
327
340
|
segmentIndex: (_c = extra === null || extra === void 0 ? void 0 : extra.segmentIndex) !== null && _c !== void 0 ? _c : null,
|
|
341
|
+
enforceGasCheck: enforceGasCheck !== null && enforceGasCheck !== void 0 ? enforceGasCheck : null,
|
|
342
|
+
warningOnly: !sufficient && enforceGasCheck === false,
|
|
343
|
+
shortfall: (_d = extra === null || extra === void 0 ? void 0 : extra.shortfall) !== null && _d !== void 0 ? _d : null,
|
|
328
344
|
},
|
|
329
|
-
level: sufficient
|
|
345
|
+
level: preflightLevel(sufficient, enforceGasCheck),
|
|
330
346
|
};
|
|
331
347
|
},
|
|
332
348
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_203_04]: (required, available, shortfall, ueaAddress, pathTag, extra) => {
|
|
@@ -521,15 +537,16 @@ const RAW_HOOKS_R3 = {
|
|
|
521
537
|
}),
|
|
522
538
|
// R3 single-route pre-flight balance check. Same payload shape as 203-03/04/05.
|
|
523
539
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_303_04]: (required, available, sufficient, ueaAddress, pathTag, extra) => {
|
|
524
|
-
var _a, _b, _c;
|
|
540
|
+
var _a, _b, _c, _d;
|
|
525
541
|
const kind = (_a = extra === null || extra === void 0 ? void 0 : extra.kind) !== null && _a !== void 0 ? _a : 'NATIVE';
|
|
526
542
|
const availableStr = kind === 'PRC20' ? `${available} units` : (0, formatters_1.formatPc)(available, 4);
|
|
527
543
|
const requiredStr = kind === 'PRC20' ? `${required} units` : (0, formatters_1.formatPc)(required, 4);
|
|
544
|
+
const enforceGasCheck = extra === null || extra === void 0 ? void 0 : extra.enforceGasCheck;
|
|
528
545
|
return {
|
|
529
546
|
id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_303_04,
|
|
530
547
|
title: 'Pre-flight Balance Check',
|
|
531
548
|
message: `UEA balance: ${availableStr}; required: ${requiredStr}; ` +
|
|
532
|
-
|
|
549
|
+
preflightSuffix(sufficient, pathTag, enforceGasCheck),
|
|
533
550
|
response: {
|
|
534
551
|
required,
|
|
535
552
|
available,
|
|
@@ -539,8 +556,11 @@ const RAW_HOOKS_R3 = {
|
|
|
539
556
|
kind,
|
|
540
557
|
burnToken: (_b = extra === null || extra === void 0 ? void 0 : extra.burnToken) !== null && _b !== void 0 ? _b : null,
|
|
541
558
|
segmentIndex: (_c = extra === null || extra === void 0 ? void 0 : extra.segmentIndex) !== null && _c !== void 0 ? _c : null,
|
|
559
|
+
enforceGasCheck: enforceGasCheck !== null && enforceGasCheck !== void 0 ? enforceGasCheck : null,
|
|
560
|
+
warningOnly: !sufficient && enforceGasCheck === false,
|
|
561
|
+
shortfall: (_d = extra === null || extra === void 0 ? void 0 : extra.shortfall) !== null && _d !== void 0 ? _d : null,
|
|
542
562
|
},
|
|
543
|
-
level: sufficient
|
|
563
|
+
level: preflightLevel(sufficient, enforceGasCheck),
|
|
544
564
|
};
|
|
545
565
|
},
|
|
546
566
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_303_05]: (required, available, shortfall, ueaAddress, pathTag, extra) => {
|
|
@@ -785,15 +805,16 @@ const RAW_HOOKS_MULTICHAIN = {
|
|
|
785
805
|
// streams remain self-consistent. `runPreflight` switches between
|
|
786
806
|
// 203-xx and 003-xx based on pathTag === 'CASCADE'.
|
|
787
807
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_003_03]: (required, available, sufficient, ueaAddress, pathTag, extra) => {
|
|
788
|
-
var _a, _b, _c;
|
|
808
|
+
var _a, _b, _c, _d;
|
|
789
809
|
const kind = (_a = extra === null || extra === void 0 ? void 0 : extra.kind) !== null && _a !== void 0 ? _a : 'NATIVE';
|
|
790
810
|
const availableStr = kind === 'PRC20' ? `${available} units` : (0, formatters_1.formatPc)(available, 4);
|
|
791
811
|
const requiredStr = kind === 'PRC20' ? `${required} units` : (0, formatters_1.formatPc)(required, 4);
|
|
812
|
+
const enforceGasCheck = extra === null || extra === void 0 ? void 0 : extra.enforceGasCheck;
|
|
792
813
|
return {
|
|
793
814
|
id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_003_03,
|
|
794
815
|
title: 'Cascade Pre-flight Balance Check',
|
|
795
816
|
message: `UEA balance: ${availableStr}; required: ${requiredStr}; ` +
|
|
796
|
-
|
|
817
|
+
preflightSuffix(sufficient, pathTag, enforceGasCheck),
|
|
797
818
|
response: {
|
|
798
819
|
required,
|
|
799
820
|
available,
|
|
@@ -803,8 +824,11 @@ const RAW_HOOKS_MULTICHAIN = {
|
|
|
803
824
|
kind,
|
|
804
825
|
burnToken: (_b = extra === null || extra === void 0 ? void 0 : extra.burnToken) !== null && _b !== void 0 ? _b : null,
|
|
805
826
|
segmentIndex: (_c = extra === null || extra === void 0 ? void 0 : extra.segmentIndex) !== null && _c !== void 0 ? _c : null,
|
|
827
|
+
enforceGasCheck: enforceGasCheck !== null && enforceGasCheck !== void 0 ? enforceGasCheck : null,
|
|
828
|
+
warningOnly: !sufficient && enforceGasCheck === false,
|
|
829
|
+
shortfall: (_d = extra === null || extra === void 0 ? void 0 : extra.shortfall) !== null && _d !== void 0 ? _d : null,
|
|
806
830
|
},
|
|
807
|
-
level: sufficient
|
|
831
|
+
level: preflightLevel(sufficient, enforceGasCheck),
|
|
808
832
|
};
|
|
809
833
|
},
|
|
810
834
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_003_04]: (required, available, shortfall, ueaAddress, pathTag, extra) => {
|
|
@@ -7,7 +7,7 @@ export type ProgressEvent = {
|
|
|
7
7
|
id: string;
|
|
8
8
|
title: string;
|
|
9
9
|
message: string;
|
|
10
|
-
level: 'INFO' | 'SUCCESS' | 'ERROR';
|
|
10
|
+
level: 'INFO' | 'SUCCESS' | 'WARNING' | 'ERROR';
|
|
11
11
|
response: object | null;
|
|
12
12
|
timestamp: string;
|
|
13
13
|
};
|
|
@@ -68,7 +68,7 @@ export declare enum PROGRESS_HOOK {
|
|
|
68
68
|
SEND_TX_303_03_01 = "SEND-TX-303-03-01",// Sizer: Case A (< $1, padded)
|
|
69
69
|
SEND_TX_303_03_02 = "SEND-TX-303-03-02",// Sizer: Case B ($1–$10, happy path)
|
|
70
70
|
SEND_TX_303_03_03 = "SEND-TX-303-03-03",// Sizer: Case C (> $10, split + overflow bridge)
|
|
71
|
-
SEND_TX_303_04 = "SEND-TX-303-04",// R3 pre-flight balance check (INFO
|
|
71
|
+
SEND_TX_303_04 = "SEND-TX-303-04",// R3 pre-flight balance check (INFO/WARNING/ERROR per enforceGasCheck)
|
|
72
72
|
SEND_TX_303_05 = "SEND-TX-303-05",// R3 pre-flight FAILED (ERROR, terminal precursor before 399-02)
|
|
73
73
|
SEND_TX_303_06 = "SEND-TX-303-06",// R3 SVM warn-threshold tripped (INFO, no action)
|
|
74
74
|
SEND_TX_304_01 = "SEND-TX-304-01",
|
|
@@ -87,7 +87,7 @@ export declare enum PROGRESS_HOOK {
|
|
|
87
87
|
SEND_TX_001 = "SEND-TX-001",
|
|
88
88
|
SEND_TX_002_01 = "SEND-TX-002-01",
|
|
89
89
|
SEND_TX_002_99_99 = "SEND-TX-002-99-99",
|
|
90
|
-
SEND_TX_003_03 = "SEND-TX-003-03",// Cascade pre-flight balance check (INFO
|
|
90
|
+
SEND_TX_003_03 = "SEND-TX-003-03",// Cascade pre-flight balance check (INFO/WARNING/ERROR per enforceGasCheck)
|
|
91
91
|
SEND_TX_003_04 = "SEND-TX-003-04",// Cascade pre-flight FAILED (ERROR, terminal precursor before 999-02)
|
|
92
92
|
SEND_TX_003_05 = "SEND-TX-003-05",// Cascade SVM warn-threshold tripped (INFO, no action)
|
|
93
93
|
SEND_TX_999_01 = "SEND-TX-999-01",
|
|
@@ -37,8 +37,10 @@ var PROGRESS_HOOK;
|
|
|
37
37
|
PROGRESS_HOOK["SEND_TX_202_02"] = "SEND-TX-202-02";
|
|
38
38
|
PROGRESS_HOOK["SEND_TX_203_01"] = "SEND-TX-203-01";
|
|
39
39
|
PROGRESS_HOOK["SEND_TX_203_02"] = "SEND-TX-203-02";
|
|
40
|
-
// Pre-flight balance check (203-03 INFO when sufficient
|
|
41
|
-
//
|
|
40
|
+
// Pre-flight balance check (203-03 INFO when sufficient, WARNING when
|
|
41
|
+
// short but enforceGasCheck=false, ERROR when enforceGasCheck=true;
|
|
42
|
+
// 203-04 ERROR terminal precursor on enforced shortfall;
|
|
43
|
+
// 203-05 INFO SVM warn-threshold tripped).
|
|
42
44
|
// 203 bucket choice is temporal (sits between 203-02 CEA-resolved and 204-01 sign),
|
|
43
45
|
// not strictly semantic — UEA balance is on Push Chain, not the destination CEA.
|
|
44
46
|
PROGRESS_HOOK["SEND_TX_203_03"] = "SEND-TX-203-03";
|
|
@@ -6,7 +6,7 @@ import { TypedData, TypedDataDomain } from 'viem';
|
|
|
6
6
|
import { ProgressEvent } from '../progress-hook/progress-hook.types';
|
|
7
7
|
import type { AccountStatus } from '../orchestrator/orchestrator.types';
|
|
8
8
|
import { MoveableToken, PayableToken, ConversionQuote, MoveableTokenAccessor, PayableTokenAccessor } from '../constants/tokens';
|
|
9
|
-
import type { PreparedUniversalTx, CascadedTxResponse } from '../orchestrator/orchestrator.types';
|
|
9
|
+
import type { PreparedUniversalTx, CascadedTxResponse, CascadeExecutionOptions } from '../orchestrator/orchestrator.types';
|
|
10
10
|
/**
|
|
11
11
|
* @class PushChain
|
|
12
12
|
*
|
|
@@ -67,11 +67,19 @@ export declare class PushChain {
|
|
|
67
67
|
* to: { address: '0x...', chain: CHAIN.BNB_TESTNET },
|
|
68
68
|
* value: parseEther('0.001')
|
|
69
69
|
* });
|
|
70
|
+
*
|
|
71
|
+
* @param options.enforceGasCheck - Defaults to false. When true, the
|
|
72
|
+
* SDK stops on pre-flight gas/balance shortfall instead of warning
|
|
73
|
+
* and proceeding.
|
|
70
74
|
*/
|
|
71
75
|
sendTransaction: Orchestrator['execute'];
|
|
72
76
|
/**
|
|
73
77
|
* Prepare a universal transaction without executing it.
|
|
74
78
|
* Returns a PreparedUniversalTx that can be passed to executeTransactions.
|
|
79
|
+
*
|
|
80
|
+
* @param options.enforceGasCheck - Defaults to false. When true, the
|
|
81
|
+
* prepared transaction carries strict pre-flight gas/balance enforcement
|
|
82
|
+
* into executeTransactions.
|
|
75
83
|
*/
|
|
76
84
|
prepareTransaction: Orchestrator['prepareTransaction'];
|
|
77
85
|
/**
|
|
@@ -86,9 +94,7 @@ export declare class PushChain {
|
|
|
86
94
|
* if it matches the init-time hook. Note: concurrent calls on the
|
|
87
95
|
* same instance share the hook channel during the broadcast phase.
|
|
88
96
|
*/
|
|
89
|
-
executeTransactions: (txs: PreparedUniversalTx[], options?:
|
|
90
|
-
progressHook?: (event: ProgressEvent) => void;
|
|
91
|
-
}) => Promise<CascadedTxResponse>;
|
|
97
|
+
executeTransactions: (txs: PreparedUniversalTx[], options?: CascadeExecutionOptions) => Promise<CascadedTxResponse>;
|
|
92
98
|
/**
|
|
93
99
|
* Tracks a transaction by hash on Push Chain
|
|
94
100
|
*/
|
|
@@ -81,8 +81,8 @@ class PushChain {
|
|
|
81
81
|
}
|
|
82
82
|
return orchestrator.execute.bind(orchestrator)(...args);
|
|
83
83
|
},
|
|
84
|
-
prepareTransaction: (params) => {
|
|
85
|
-
return orchestrator.prepareTransaction.bind(orchestrator)(params);
|
|
84
|
+
prepareTransaction: (params, options) => {
|
|
85
|
+
return orchestrator.prepareTransaction.bind(orchestrator)(params, options);
|
|
86
86
|
},
|
|
87
87
|
executeTransactions: (txs, options) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
88
88
|
if (this.isReadMode) {
|
package/src/lib/utils.js
CHANGED
|
@@ -696,7 +696,7 @@ Utils.tokens = {
|
|
|
696
696
|
else if (isBaseFamily)
|
|
697
697
|
key = 'USDT_BASE';
|
|
698
698
|
else if (isBnbFamily)
|
|
699
|
-
key = '
|
|
699
|
+
key = 'USDT_BSC';
|
|
700
700
|
else if (isSolFamily)
|
|
701
701
|
key = 'USDT_SOL';
|
|
702
702
|
else
|
|
@@ -711,7 +711,7 @@ Utils.tokens = {
|
|
|
711
711
|
else if (isBaseFamily)
|
|
712
712
|
key = 'USDC_BASE';
|
|
713
713
|
else if (isBnbFamily)
|
|
714
|
-
key = '
|
|
714
|
+
key = 'USDC_BSC';
|
|
715
715
|
else if (isSolFamily)
|
|
716
716
|
key = 'USDC_SOL';
|
|
717
717
|
else
|