@pushchain/core 5.1.3 → 5.1.4-alpha.1
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/package.json +29 -6
- package/src/lib/constants/abi/prc20.evm.d.ts +22 -2
- package/src/lib/constants/abi/prc20.evm.js +11 -3
- package/src/lib/constants/abi/universalGatewayPC.evm.d.ts +59 -0
- package/src/lib/constants/abi/universalGatewayPC.evm.js +26 -0
- package/src/lib/constants/chain.d.ts +4 -0
- package/src/lib/constants/chain.js +6 -2
- package/src/lib/index.d.ts +2 -2
- package/src/lib/internal/bs58.d.ts +2 -0
- package/src/lib/internal/bs58.js +7 -0
- package/src/lib/orchestrator/cea-utils.d.ts +0 -9
- package/src/lib/orchestrator/cea-utils.js +15 -4
- package/src/lib/orchestrator/internals/account-manager.d.ts +16 -0
- package/src/lib/orchestrator/internals/account-manager.js +191 -0
- package/src/lib/orchestrator/internals/cascade.d.ts +23 -0
- package/src/lib/orchestrator/internals/cascade.js +945 -0
- package/src/lib/orchestrator/internals/confirmation.d.ts +9 -0
- package/src/lib/orchestrator/internals/confirmation.js +123 -0
- package/src/lib/orchestrator/internals/context.d.ts +38 -0
- package/src/lib/orchestrator/internals/context.js +49 -0
- package/src/lib/orchestrator/internals/execute-funds-only.d.ts +11 -0
- package/src/lib/orchestrator/internals/execute-funds-only.js +219 -0
- package/src/lib/orchestrator/internals/execute-funds-payload.d.ts +11 -0
- package/src/lib/orchestrator/internals/execute-funds-payload.js +222 -0
- package/src/lib/orchestrator/internals/execute-standard.d.ts +13 -0
- package/src/lib/orchestrator/internals/execute-standard.js +225 -0
- package/src/lib/orchestrator/internals/gas-calculator.d.ts +38 -0
- package/src/lib/orchestrator/internals/gas-calculator.js +424 -0
- package/src/lib/orchestrator/internals/gateway-client.d.ts +24 -0
- package/src/lib/orchestrator/internals/gateway-client.js +191 -0
- package/src/lib/orchestrator/internals/helpers.d.ts +26 -0
- package/src/lib/orchestrator/internals/helpers.js +181 -0
- package/src/lib/orchestrator/internals/index.d.ts +24 -0
- package/src/lib/orchestrator/internals/index.js +132 -0
- package/src/lib/orchestrator/internals/outbound-sync.d.ts +49 -0
- package/src/lib/orchestrator/internals/outbound-sync.js +357 -0
- package/src/lib/orchestrator/internals/outbound-tracker.d.ts +8 -0
- package/src/lib/orchestrator/internals/outbound-tracker.js +64 -0
- package/src/lib/orchestrator/internals/payload-builder.d.ts +24 -0
- package/src/lib/orchestrator/internals/payload-builder.js +178 -0
- package/src/lib/orchestrator/internals/push-chain-tx.d.ts +32 -0
- package/src/lib/orchestrator/internals/push-chain-tx.js +207 -0
- package/src/lib/orchestrator/internals/quote.d.ts +9 -0
- package/src/lib/orchestrator/internals/quote.js +114 -0
- package/src/lib/orchestrator/internals/rescue.d.ts +20 -0
- package/src/lib/orchestrator/internals/rescue.js +112 -0
- package/src/lib/orchestrator/internals/response-builder.d.ts +26 -0
- package/src/lib/orchestrator/internals/response-builder.js +504 -0
- package/src/lib/orchestrator/internals/route-handlers.d.ts +77 -0
- package/src/lib/orchestrator/internals/route-handlers.js +1192 -0
- package/src/lib/orchestrator/internals/signing.d.ts +27 -0
- package/src/lib/orchestrator/internals/signing.js +258 -0
- package/src/lib/orchestrator/internals/svm-bridge.d.ts +21 -0
- package/src/lib/orchestrator/internals/svm-bridge.js +122 -0
- package/src/lib/orchestrator/internals/svm-helpers.d.ts +35 -0
- package/src/lib/orchestrator/internals/svm-helpers.js +143 -0
- package/src/lib/orchestrator/internals/tx-transformer.d.ts +12 -0
- package/src/lib/orchestrator/internals/tx-transformer.js +120 -0
- package/src/lib/orchestrator/internals/uea-manager.d.ts +17 -0
- package/src/lib/orchestrator/internals/uea-manager.js +164 -0
- package/src/lib/orchestrator/orchestrator.d.ts +33 -431
- package/src/lib/orchestrator/orchestrator.js +124 -6125
- package/src/lib/orchestrator/orchestrator.types.d.ts +11 -10
- package/src/lib/orchestrator/payload-builders.js +34 -8
- package/src/lib/price-fetch/price-fetch.js +19 -7
- package/src/lib/push-chain/push-chain.d.ts +6 -0
- package/src/lib/push-chain/push-chain.js +10 -2
- package/src/lib/push-client/push-client.d.ts +3 -0
- package/src/lib/push-client/push-client.js +21 -31
- package/src/lib/universal/account/account.d.ts +35 -16
- package/src/lib/universal/account/account.js +298 -16
- package/src/lib/universal/signer/signer.d.ts +2 -3
- package/src/lib/universal/signer/signer.js +65 -115
- package/src/lib/universal/universal.types.d.ts +41 -0
- package/src/lib/utils.d.ts +7 -2
- package/src/lib/utils.js +65 -34
- package/src/lib/vm-client/evm-client.js +3 -11
- package/src/lib/vm-client/svm-client.d.ts +0 -4
- package/src/lib/vm-client/svm-client.js +2 -8
- package/src/index.js.map +0 -1
- package/src/lib/cache/cache.js.map +0 -1
- package/src/lib/constants/abi/cea.evm.js.map +0 -1
- package/src/lib/constants/abi/ceaFactory.evm.js.map +0 -1
- package/src/lib/constants/abi/erc20.evm.js.map +0 -1
- package/src/lib/constants/abi/factoryV1.js.map +0 -1
- package/src/lib/constants/abi/feeLocker.evm.js.map +0 -1
- package/src/lib/constants/abi/index.js.map +0 -1
- package/src/lib/constants/abi/prc20.evm.js.map +0 -1
- package/src/lib/constants/abi/uea-factory.js.map +0 -1
- package/src/lib/constants/abi/uea.evm.js.map +0 -1
- package/src/lib/constants/abi/uea.svm.js.map +0 -1
- package/src/lib/constants/abi/universalGateway.evm.js.map +0 -1
- package/src/lib/constants/abi/universalGatewayPC.evm.js.map +0 -1
- package/src/lib/constants/abi/universalGatewayV0.evm.js.map +0 -1
- package/src/lib/constants/chain.js.map +0 -1
- package/src/lib/constants/enums.js.map +0 -1
- package/src/lib/constants/index.js.map +0 -1
- package/src/lib/constants/selectors.js.map +0 -1
- package/src/lib/constants/tokens.js.map +0 -1
- package/src/lib/generated/uexecutor/v1/query.js.map +0 -1
- package/src/lib/generated/uexecutor/v1/types.js.map +0 -1
- package/src/lib/generated/uexecutor/v2/index.js.map +0 -1
- package/src/lib/generated/uexecutor/v2/query.js.map +0 -1
- package/src/lib/generated/uexecutor/v2/types.js.map +0 -1
- package/src/lib/generated/v1/tx.js.map +0 -1
- package/src/lib/index.js.map +0 -1
- package/src/lib/internal/buffer.js.map +0 -1
- package/src/lib/internal/global-buffer-polyfill.js.map +0 -1
- package/src/lib/orchestrator/cea-utils.js.map +0 -1
- package/src/lib/orchestrator/orchestrator.js.map +0 -1
- package/src/lib/orchestrator/orchestrator.types.js.map +0 -1
- package/src/lib/orchestrator/payload-builders.js.map +0 -1
- package/src/lib/orchestrator/route-detector.js.map +0 -1
- package/src/lib/price-fetch/price-fetch.js.map +0 -1
- package/src/lib/progress-hook/progress-hook.js.map +0 -1
- package/src/lib/progress-hook/progress-hook.types.js.map +0 -1
- package/src/lib/push-chain/helpers/abis.js.map +0 -1
- package/src/lib/push-chain/helpers/addresses.js.map +0 -1
- package/src/lib/push-chain/push-chain.js.map +0 -1
- package/src/lib/push-client/push-client.js.map +0 -1
- package/src/lib/push-client/push-client.types.js.map +0 -1
- package/src/lib/universal/account/account.js.map +0 -1
- package/src/lib/universal/account/index.js.map +0 -1
- package/src/lib/universal/signer/index.js.map +0 -1
- package/src/lib/universal/signer/signer.js.map +0 -1
- package/src/lib/universal/signer/signer.types.js.map +0 -1
- package/src/lib/universal/universal.types.js.map +0 -1
- package/src/lib/utils.js.map +0 -1
- package/src/lib/vm-client/evm-client.js.map +0 -1
- package/src/lib/vm-client/svm-client.js.map +0 -1
- package/src/lib/vm-client/vm-client.types.js.map +0 -1
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gas fee queries, native amount calculations, ERC-20 allowance,
|
|
4
|
+
* and Uniswap V3 quoting — extracted from Orchestrator.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.ensureErc20Allowance = ensureErc20Allowance;
|
|
8
|
+
exports.queryOutboundGasFee = queryOutboundGasFee;
|
|
9
|
+
exports.estimateNativeValueForSwap = estimateNativeValueForSwap;
|
|
10
|
+
exports.queryRescueGasFee = queryRescueGasFee;
|
|
11
|
+
exports.calculateNativeAmountForDeposit = calculateNativeAmountForDeposit;
|
|
12
|
+
exports.calculateGasAmountFromAmountOutMinETH = calculateGasAmountFromAmountOutMinETH;
|
|
13
|
+
const tslib_1 = require("tslib");
|
|
14
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
15
|
+
const viem_1 = require("viem");
|
|
16
|
+
const abi_1 = require("../../constants/abi");
|
|
17
|
+
const chain_1 = require("../../constants/chain");
|
|
18
|
+
const enums_1 = require("../../constants/enums");
|
|
19
|
+
const tokens_1 = require("../../constants/tokens");
|
|
20
|
+
const progress_hook_types_1 = require("../../progress-hook/progress-hook.types");
|
|
21
|
+
const price_fetch_1 = require("../../price-fetch/price-fetch");
|
|
22
|
+
const utils_1 = require("../../utils");
|
|
23
|
+
const svm_client_1 = require("../../vm-client/svm-client");
|
|
24
|
+
const context_1 = require("./context");
|
|
25
|
+
const helpers_1 = require("./helpers");
|
|
26
|
+
/** Buffer multiplier for nativeValueForGas. Excess is refunded by swapAndBurnGas to the UEA. */
|
|
27
|
+
const GAS_FEE_BUFFER_MULTIPLIER = BigInt(1000000);
|
|
28
|
+
// Minimal ABIs for Uniswap V3 pool price estimation
|
|
29
|
+
const UNISWAP_V3_POOL_SLOT0_ABI = [
|
|
30
|
+
{
|
|
31
|
+
type: 'function',
|
|
32
|
+
name: 'slot0',
|
|
33
|
+
inputs: [],
|
|
34
|
+
outputs: [
|
|
35
|
+
{ name: 'sqrtPriceX96', type: 'uint160', internalType: 'uint160' },
|
|
36
|
+
{ name: 'tick', type: 'int24', internalType: 'int24' },
|
|
37
|
+
{ name: 'observationIndex', type: 'uint16', internalType: 'uint16' },
|
|
38
|
+
{ name: 'observationCardinality', type: 'uint16', internalType: 'uint16' },
|
|
39
|
+
{ name: 'observationCardinalityNext', type: 'uint16', internalType: 'uint16' },
|
|
40
|
+
{ name: 'feeProtocol', type: 'uint8', internalType: 'uint8' },
|
|
41
|
+
{ name: 'unlocked', type: 'bool', internalType: 'bool' },
|
|
42
|
+
],
|
|
43
|
+
stateMutability: 'view',
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
const UNISWAP_V3_FACTORY_ABI = [
|
|
47
|
+
{
|
|
48
|
+
type: 'function',
|
|
49
|
+
name: 'getPool',
|
|
50
|
+
inputs: [
|
|
51
|
+
{ name: 'tokenA', type: 'address', internalType: 'address' },
|
|
52
|
+
{ name: 'tokenB', type: 'address', internalType: 'address' },
|
|
53
|
+
{ name: 'fee', type: 'uint24', internalType: 'uint24' },
|
|
54
|
+
],
|
|
55
|
+
outputs: [{ name: 'pool', type: 'address', internalType: 'address' }],
|
|
56
|
+
stateMutability: 'view',
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
const UNIVERSAL_CORE_SWAP_HELPERS_ABI = [
|
|
60
|
+
{ type: 'function', name: 'WPC', inputs: [], outputs: [{ name: '', type: 'address', internalType: 'address' }], stateMutability: 'view' },
|
|
61
|
+
{ type: 'function', name: 'uniswapV3Factory', inputs: [], outputs: [{ name: '', type: 'address', internalType: 'address' }], stateMutability: 'view' },
|
|
62
|
+
{ type: 'function', name: 'defaultFeeTier', inputs: [{ name: '', type: 'address', internalType: 'address' }], outputs: [{ name: '', type: 'uint24', internalType: 'uint24' }], stateMutability: 'view' },
|
|
63
|
+
];
|
|
64
|
+
const ZERO_ADDR = '0x0000000000000000000000000000000000000000';
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// ERC-20 Allowance
|
|
67
|
+
// ============================================================================
|
|
68
|
+
function ensureErc20Allowance(ctx, evmClient, tokenAddress, spender, requiredAmount) {
|
|
69
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
const chain = ctx.universalSigner.account.chain;
|
|
71
|
+
const owner = ctx.universalSigner.account.address;
|
|
72
|
+
const currentAllowance = yield evmClient.readContract({
|
|
73
|
+
abi: abi_1.ERC20_EVM,
|
|
74
|
+
address: tokenAddress,
|
|
75
|
+
functionName: 'allowance',
|
|
76
|
+
args: [owner, spender],
|
|
77
|
+
});
|
|
78
|
+
if (currentAllowance >= requiredAmount)
|
|
79
|
+
return;
|
|
80
|
+
if (currentAllowance > BigInt(0)) {
|
|
81
|
+
(0, context_1.printLog)(ctx, `Resetting existing allowance from ${currentAllowance.toString()} to 0 for spender ${spender}`);
|
|
82
|
+
const resetTxHash = yield evmClient.writeContract({
|
|
83
|
+
abi: abi_1.ERC20_EVM,
|
|
84
|
+
address: tokenAddress,
|
|
85
|
+
functionName: 'approve',
|
|
86
|
+
args: [spender, BigInt(0)],
|
|
87
|
+
signer: ctx.universalSigner,
|
|
88
|
+
});
|
|
89
|
+
yield evmClient.waitForConfirmations({
|
|
90
|
+
txHash: resetTxHash,
|
|
91
|
+
confirmations: 1,
|
|
92
|
+
timeoutMs: chain_1.CHAIN_INFO[chain].timeout,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const setTxHash = yield evmClient.writeContract({
|
|
96
|
+
abi: abi_1.ERC20_EVM,
|
|
97
|
+
address: tokenAddress,
|
|
98
|
+
functionName: 'approve',
|
|
99
|
+
args: [spender, requiredAmount],
|
|
100
|
+
signer: ctx.universalSigner,
|
|
101
|
+
});
|
|
102
|
+
yield evmClient.waitForConfirmations({
|
|
103
|
+
txHash: setTxHash,
|
|
104
|
+
confirmations: 1,
|
|
105
|
+
timeoutMs: chain_1.CHAIN_INFO[chain].timeout,
|
|
106
|
+
});
|
|
107
|
+
try {
|
|
108
|
+
const updated = yield evmClient.readContract({
|
|
109
|
+
abi: abi_1.ERC20_EVM,
|
|
110
|
+
address: tokenAddress,
|
|
111
|
+
functionName: 'allowance',
|
|
112
|
+
args: [owner, spender],
|
|
113
|
+
});
|
|
114
|
+
if (updated < requiredAmount) {
|
|
115
|
+
(0, context_1.printLog)(ctx, 'Warning: allowance not updated yet; proceeding');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch (_a) {
|
|
119
|
+
// ignore
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
// ============================================================================
|
|
124
|
+
// Outbound Gas Fee Query
|
|
125
|
+
// ============================================================================
|
|
126
|
+
function queryOutboundGasFee(ctx, prc20Token, gasLimit) {
|
|
127
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
var _a, _b;
|
|
129
|
+
const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
|
|
130
|
+
const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
|
|
131
|
+
const rpcUrl = ((_b = (_a = chain_1.CHAIN_INFO[pushChain]) === null || _a === void 0 ? void 0 : _a.defaultRPC) === null || _b === void 0 ? void 0 : _b[0]) || 'unknown';
|
|
132
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 1] inputs: gateway=${gatewayPcAddress}, prc20Token=${prc20Token}, gasLimit=${gasLimit}, rpcUrl=${rpcUrl}`);
|
|
133
|
+
let universalCoreAddress;
|
|
134
|
+
try {
|
|
135
|
+
universalCoreAddress = yield ctx.pushClient.readContract({
|
|
136
|
+
address: gatewayPcAddress,
|
|
137
|
+
abi: abi_1.UNIVERSAL_GATEWAY_PC,
|
|
138
|
+
functionName: 'UNIVERSAL_CORE',
|
|
139
|
+
args: [],
|
|
140
|
+
});
|
|
141
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 2] UNIVERSAL_CORE resolved to: ${universalCoreAddress}`);
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 2] FAILED to read UNIVERSAL_CORE: ${err instanceof Error ? err.message : String(err)}`);
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
const callData = (0, viem_1.encodeFunctionData)({
|
|
148
|
+
abi: abi_1.UNIVERSAL_CORE_EVM,
|
|
149
|
+
functionName: 'getOutboundTxGasAndFees',
|
|
150
|
+
args: [prc20Token, gasLimit],
|
|
151
|
+
});
|
|
152
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] calling getOutboundTxGasAndFees on ${universalCoreAddress}`);
|
|
153
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] eth_call: {"method":"eth_call","params":[{"to":"${universalCoreAddress}","data":"${callData}"},"latest"]}`);
|
|
154
|
+
let gasToken;
|
|
155
|
+
let gasFee;
|
|
156
|
+
let protocolFee;
|
|
157
|
+
let gasPrice = BigInt(0);
|
|
158
|
+
try {
|
|
159
|
+
const result = yield ctx.pushClient.readContract({
|
|
160
|
+
address: universalCoreAddress,
|
|
161
|
+
abi: abi_1.UNIVERSAL_CORE_EVM,
|
|
162
|
+
functionName: 'getOutboundTxGasAndFees',
|
|
163
|
+
args: [prc20Token, gasLimit],
|
|
164
|
+
});
|
|
165
|
+
gasToken = result[0];
|
|
166
|
+
gasFee = result[1];
|
|
167
|
+
protocolFee = result[2];
|
|
168
|
+
gasPrice = result[3];
|
|
169
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 4] success: gasToken=${gasToken}, gasFee=${gasFee}, protocolFee=${protocolFee}, gasPrice=${gasPrice}`);
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] FAILED: ${err instanceof Error ? err.message : String(err)}`);
|
|
173
|
+
throw err;
|
|
174
|
+
}
|
|
175
|
+
const nativeValueForGas = protocolFee + gasFee * GAS_FEE_BUFFER_MULTIPLIER;
|
|
176
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] using 1000000x buffer: nativeValueForGas=${nativeValueForGas}`);
|
|
177
|
+
return { gasToken, gasFee, protocolFee, nativeValueForGas, gasPrice, universalCoreAddress };
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
// ============================================================================
|
|
181
|
+
// Uniswap V3 Pool Price Estimation
|
|
182
|
+
// ============================================================================
|
|
183
|
+
/**
|
|
184
|
+
* Estimate the native WPC amount needed to swap for `gasFee` of `gasToken`
|
|
185
|
+
* by reading the Uniswap V3 pool price on Push Chain.
|
|
186
|
+
* Returns the estimated amount with a 2x safety buffer (excess is refunded by the contract).
|
|
187
|
+
* Falls back to a percentage of accountBalance if any on-chain query fails.
|
|
188
|
+
*/
|
|
189
|
+
function estimateNativeValueForSwap(ctx, universalCoreAddress, gasToken, gasFee, accountBalance) {
|
|
190
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
191
|
+
const SWAP_BUFFER = BigInt(2); // 2x safety buffer; excess is refunded by swapAndBurnGas
|
|
192
|
+
const BALANCE_FALLBACK_DIVISOR = BigInt(10); // 10% of balance as fallback
|
|
193
|
+
const GAS_RESERVE = BigInt(3e18); // 3 UPC reserve for tx overhead
|
|
194
|
+
try {
|
|
195
|
+
// Read WPC, factory, and defaultFeeTier in parallel
|
|
196
|
+
const [wpcAddress, factoryAddress, feeTier] = yield Promise.all([
|
|
197
|
+
ctx.pushClient.readContract({
|
|
198
|
+
address: universalCoreAddress,
|
|
199
|
+
abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
|
|
200
|
+
functionName: 'WPC',
|
|
201
|
+
args: [],
|
|
202
|
+
}),
|
|
203
|
+
ctx.pushClient.readContract({
|
|
204
|
+
address: universalCoreAddress,
|
|
205
|
+
abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
|
|
206
|
+
functionName: 'uniswapV3Factory',
|
|
207
|
+
args: [],
|
|
208
|
+
}),
|
|
209
|
+
ctx.pushClient.readContract({
|
|
210
|
+
address: universalCoreAddress,
|
|
211
|
+
abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
|
|
212
|
+
functionName: 'defaultFeeTier',
|
|
213
|
+
args: [gasToken],
|
|
214
|
+
}),
|
|
215
|
+
]);
|
|
216
|
+
if (!feeTier) {
|
|
217
|
+
(0, context_1.printLog)(ctx, `estimateNativeValueForSwap — no fee tier for gasToken, using balance fallback`);
|
|
218
|
+
return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
|
|
219
|
+
}
|
|
220
|
+
// Get pool address from factory
|
|
221
|
+
const poolAddress = yield ctx.pushClient.readContract({
|
|
222
|
+
address: factoryAddress,
|
|
223
|
+
abi: UNISWAP_V3_FACTORY_ABI,
|
|
224
|
+
functionName: 'getPool',
|
|
225
|
+
args: [wpcAddress, gasToken, feeTier],
|
|
226
|
+
});
|
|
227
|
+
if (poolAddress === ZERO_ADDR) {
|
|
228
|
+
(0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool not found, using balance fallback`);
|
|
229
|
+
return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
|
|
230
|
+
}
|
|
231
|
+
// Read slot0 for current price
|
|
232
|
+
const slot0 = yield ctx.pushClient.readContract({
|
|
233
|
+
address: poolAddress,
|
|
234
|
+
abi: UNISWAP_V3_POOL_SLOT0_ABI,
|
|
235
|
+
functionName: 'slot0',
|
|
236
|
+
args: [],
|
|
237
|
+
});
|
|
238
|
+
const sqrtPriceX96 = slot0[0];
|
|
239
|
+
if (!sqrtPriceX96 || sqrtPriceX96 === BigInt(0)) {
|
|
240
|
+
(0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool not initialized, using balance fallback`);
|
|
241
|
+
return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
|
|
242
|
+
}
|
|
243
|
+
// price (token1/token0 in raw units) = (sqrtPriceX96)² / 2¹⁹²
|
|
244
|
+
const Q192 = BigInt(1) << BigInt(192);
|
|
245
|
+
const priceNum = sqrtPriceX96 * sqrtPriceX96; // sqrtPrice² in Q192
|
|
246
|
+
// Uniswap V3 sorts tokens: token0 < token1 by address
|
|
247
|
+
const isGasTokenToken0 = gasToken.toLowerCase() < wpcAddress.toLowerCase();
|
|
248
|
+
let wpcNeeded;
|
|
249
|
+
if (isGasTokenToken0) {
|
|
250
|
+
// price = WPC_per_gasToken → wpcNeeded = gasFee * price
|
|
251
|
+
wpcNeeded = (gasFee * priceNum) / Q192;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
// price = gasToken_per_WPC → wpcNeeded = gasFee / price
|
|
255
|
+
wpcNeeded = (gasFee * Q192) / priceNum;
|
|
256
|
+
}
|
|
257
|
+
const result = wpcNeeded * SWAP_BUFFER;
|
|
258
|
+
(0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool=${poolAddress}, sqrtPriceX96=${sqrtPriceX96}, ` +
|
|
259
|
+
`wpcNeeded=${wpcNeeded}, withBuffer(2x)=${result}`);
|
|
260
|
+
// Cap at (balance - reserve)
|
|
261
|
+
if (accountBalance > result + GAS_RESERVE) {
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
else if (accountBalance > GAS_RESERVE) {
|
|
265
|
+
return accountBalance - GAS_RESERVE;
|
|
266
|
+
}
|
|
267
|
+
return result; // let caller decide if balance is too low
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
(0, context_1.printLog)(ctx, `estimateNativeValueForSwap — failed: ${err instanceof Error ? err.message : String(err)}, using balance fallback`);
|
|
271
|
+
return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
function balanceFallback(balance, divisor, reserve) {
|
|
276
|
+
const fraction = balance / divisor;
|
|
277
|
+
if (balance > fraction + reserve)
|
|
278
|
+
return fraction;
|
|
279
|
+
if (balance > reserve)
|
|
280
|
+
return balance - reserve;
|
|
281
|
+
return fraction;
|
|
282
|
+
}
|
|
283
|
+
// ============================================================================
|
|
284
|
+
// Rescue Gas Fee Query
|
|
285
|
+
// ============================================================================
|
|
286
|
+
function queryRescueGasFee(ctx, prc20Token) {
|
|
287
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
288
|
+
const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
|
|
289
|
+
(0, context_1.printLog)(ctx, `queryRescueGasFee — inputs: gateway=${gatewayPcAddress}, prc20Token=${prc20Token}`);
|
|
290
|
+
let universalCoreAddress;
|
|
291
|
+
try {
|
|
292
|
+
universalCoreAddress = yield ctx.pushClient.readContract({
|
|
293
|
+
address: gatewayPcAddress,
|
|
294
|
+
abi: abi_1.UNIVERSAL_GATEWAY_PC,
|
|
295
|
+
functionName: 'UNIVERSAL_CORE',
|
|
296
|
+
args: [],
|
|
297
|
+
});
|
|
298
|
+
(0, context_1.printLog)(ctx, `queryRescueGasFee — UNIVERSAL_CORE resolved to: ${universalCoreAddress}`);
|
|
299
|
+
}
|
|
300
|
+
catch (err) {
|
|
301
|
+
(0, context_1.printLog)(ctx, `queryRescueGasFee — FAILED to read UNIVERSAL_CORE: ${err instanceof Error ? err.message : String(err)}`);
|
|
302
|
+
throw err;
|
|
303
|
+
}
|
|
304
|
+
let gasToken;
|
|
305
|
+
let gasFee;
|
|
306
|
+
let rescueGasLimit;
|
|
307
|
+
let gasPrice;
|
|
308
|
+
try {
|
|
309
|
+
const result = yield ctx.pushClient.readContract({
|
|
310
|
+
address: universalCoreAddress,
|
|
311
|
+
abi: abi_1.UNIVERSAL_CORE_EVM,
|
|
312
|
+
functionName: 'getRescueFundsGasLimit',
|
|
313
|
+
args: [prc20Token],
|
|
314
|
+
});
|
|
315
|
+
gasToken = result[0];
|
|
316
|
+
gasFee = result[1];
|
|
317
|
+
rescueGasLimit = result[2];
|
|
318
|
+
gasPrice = result[3];
|
|
319
|
+
(0, context_1.printLog)(ctx, `queryRescueGasFee — success: gasToken=${gasToken}, gasFee=${gasFee}, rescueGasLimit=${rescueGasLimit}, gasPrice=${gasPrice}`);
|
|
320
|
+
}
|
|
321
|
+
catch (err) {
|
|
322
|
+
(0, context_1.printLog)(ctx, `queryRescueGasFee — FAILED: ${err instanceof Error ? err.message : String(err)}`);
|
|
323
|
+
throw err;
|
|
324
|
+
}
|
|
325
|
+
const nativeValueForGas = gasFee * GAS_FEE_BUFFER_MULTIPLIER;
|
|
326
|
+
(0, context_1.printLog)(ctx, `queryRescueGasFee — using 1000000x buffer: nativeValueForGas=${nativeValueForGas}`);
|
|
327
|
+
return { gasToken, gasFee, rescueGasLimit, gasPrice, nativeValueForGas };
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
// ============================================================================
|
|
331
|
+
// Native Amount Calculation for Deposit
|
|
332
|
+
// ============================================================================
|
|
333
|
+
function calculateNativeAmountForDeposit(ctx, chain, requiredFunds, ueaBalance) {
|
|
334
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
335
|
+
var _a, _b;
|
|
336
|
+
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_01);
|
|
337
|
+
const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
|
|
338
|
+
const tenUsd = utils_1.Utils.helpers.parseUnits('10', 8);
|
|
339
|
+
const deficit = requiredFunds > ueaBalance ? requiredFunds - ueaBalance : BigInt(0);
|
|
340
|
+
let depositUsd = deficit > BigInt(0) ? ctx.pushClient.pushToUSDC(deficit) : oneUsd;
|
|
341
|
+
if (depositUsd < oneUsd)
|
|
342
|
+
depositUsd = oneUsd;
|
|
343
|
+
if (depositUsd > tenUsd)
|
|
344
|
+
throw new Error('Deposit value exceeds max $10 worth of native token');
|
|
345
|
+
if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM) {
|
|
346
|
+
const svmClient = new svm_client_1.SvmClient({
|
|
347
|
+
rpcUrls: ctx.rpcUrls[enums_1.CHAIN.SOLANA_DEVNET] ||
|
|
348
|
+
chain_1.CHAIN_INFO[enums_1.CHAIN.SOLANA_DEVNET].defaultRPC,
|
|
349
|
+
});
|
|
350
|
+
const programId = new web3_js_1.PublicKey(abi_1.SVM_GATEWAY_IDL.address);
|
|
351
|
+
const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
|
|
352
|
+
try {
|
|
353
|
+
const cfg = yield svmClient.readContract({
|
|
354
|
+
abi: abi_1.SVM_GATEWAY_IDL,
|
|
355
|
+
address: abi_1.SVM_GATEWAY_IDL.address,
|
|
356
|
+
functionName: 'config',
|
|
357
|
+
args: [configPda.toBase58()],
|
|
358
|
+
});
|
|
359
|
+
const minField = (_a = cfg.minCapUniversalTxUsd) !== null && _a !== void 0 ? _a : cfg.min_cap_universal_tx_usd;
|
|
360
|
+
const maxField = (_b = cfg.maxCapUniversalTxUsd) !== null && _b !== void 0 ? _b : cfg.max_cap_universal_tx_usd;
|
|
361
|
+
const minCapUsd = BigInt(minField.toString());
|
|
362
|
+
const maxCapUsd = BigInt(maxField.toString());
|
|
363
|
+
if (depositUsd < minCapUsd)
|
|
364
|
+
depositUsd = minCapUsd;
|
|
365
|
+
const withMargin = (minCapUsd * BigInt(12)) / BigInt(10);
|
|
366
|
+
if (depositUsd < withMargin)
|
|
367
|
+
depositUsd = withMargin;
|
|
368
|
+
if (depositUsd > maxCapUsd)
|
|
369
|
+
depositUsd = maxCapUsd;
|
|
370
|
+
}
|
|
371
|
+
catch (_c) {
|
|
372
|
+
// best-effort
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const nativeTokenUsdPrice = yield new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(chain);
|
|
376
|
+
const nativeDecimals = chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM ? 9 : 18;
|
|
377
|
+
const oneNativeUnit = utils_1.Utils.helpers.parseUnits('1', nativeDecimals);
|
|
378
|
+
let nativeAmount = (depositUsd * oneNativeUnit + (nativeTokenUsdPrice - BigInt(1))) /
|
|
379
|
+
nativeTokenUsdPrice;
|
|
380
|
+
nativeAmount = nativeAmount + BigInt(1);
|
|
381
|
+
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_02, nativeAmount);
|
|
382
|
+
return nativeAmount;
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
// ============================================================================
|
|
386
|
+
// ERC-20 Gas Amount from Exact Output Quote
|
|
387
|
+
// ============================================================================
|
|
388
|
+
function calculateGasAmountFromAmountOutMinETH(ctx, gasTokenAddress, amountOutMinETH, quoteExactOutputFn) {
|
|
389
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
390
|
+
var _a, _b, _c;
|
|
391
|
+
const originChain = ctx.universalSigner.account.chain;
|
|
392
|
+
if (originChain !== enums_1.CHAIN.ETHEREUM_SEPOLIA &&
|
|
393
|
+
originChain !== enums_1.CHAIN.ARBITRUM_SEPOLIA &&
|
|
394
|
+
originChain !== enums_1.CHAIN.BASE_SEPOLIA) {
|
|
395
|
+
throw new Error('Gas payment in ERC-20 is supported only on Ethereum Sepolia, Arbitrum Sepolia, and Base Sepolia for now');
|
|
396
|
+
}
|
|
397
|
+
const WETH = (_a = chain_1.CHAIN_INFO[originChain].dex) === null || _a === void 0 ? void 0 : _a.weth;
|
|
398
|
+
if (!WETH)
|
|
399
|
+
throw new Error('WETH address not configured for this chain');
|
|
400
|
+
let gasAmount;
|
|
401
|
+
if (gasTokenAddress.toLowerCase() === WETH.toLowerCase()) {
|
|
402
|
+
gasAmount = BigInt(amountOutMinETH);
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
const fromList = (_b = tokens_1.PAYABLE_TOKENS[originChain]) !== null && _b !== void 0 ? _b : [];
|
|
406
|
+
const fromToken = fromList.find((t) => (t.address || '').toLowerCase() === gasTokenAddress.toLowerCase());
|
|
407
|
+
const toList = ((_c = tokens_1.MOVEABLE_TOKENS[originChain]) !== null && _c !== void 0 ? _c : []);
|
|
408
|
+
const toToken = toList.find((t) => t.symbol === 'WETH' ||
|
|
409
|
+
(t.address || '').toLowerCase() === (WETH || '').toLowerCase());
|
|
410
|
+
if (!fromToken || !toToken) {
|
|
411
|
+
throw new Error('Token not supported for quoting');
|
|
412
|
+
}
|
|
413
|
+
const targetOut = BigInt(amountOutMinETH);
|
|
414
|
+
const exactOutQuote = yield quoteExactOutputFn(targetOut, {
|
|
415
|
+
from: fromToken,
|
|
416
|
+
to: toToken,
|
|
417
|
+
});
|
|
418
|
+
const requiredIn = BigInt(exactOutQuote.amountIn);
|
|
419
|
+
gasAmount = (requiredIn * BigInt(101)) / BigInt(100);
|
|
420
|
+
}
|
|
421
|
+
return { gasAmount };
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
//# sourceMappingURL=gas-calculator.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway interaction: request conversion, tx sending, and fee locking.
|
|
3
|
+
* All chains use V1 gateway ABI.
|
|
4
|
+
*/
|
|
5
|
+
import { CHAIN } from '../../constants/enums';
|
|
6
|
+
import { EvmClient } from '../../vm-client/evm-client';
|
|
7
|
+
import type { UniversalPayload } from '../../generated/v1/tx';
|
|
8
|
+
import type { UniversalTxRequest, UniversalTxRequestV1, UniversalTokenTxRequest, UniversalTokenTxRequestV1 } from '../orchestrator.types';
|
|
9
|
+
import type { UniversalSigner } from '../../universal/universal.types';
|
|
10
|
+
import type { OrchestratorContext } from './context';
|
|
11
|
+
export declare function toGatewayRequestV1(req: UniversalTxRequest): UniversalTxRequestV1;
|
|
12
|
+
export declare function toGatewayTokenRequestV1(req: UniversalTokenTxRequest): UniversalTokenTxRequestV1;
|
|
13
|
+
export declare function sendGatewayTxWithFallback(ctx: OrchestratorContext, evmClient: EvmClient, address: `0x${string}`, req: UniversalTxRequest, signer: UniversalSigner, value: bigint): Promise<`0x${string}`>;
|
|
14
|
+
export declare function sendGatewayTokenTxWithFallback(ctx: OrchestratorContext, evmClient: EvmClient, address: `0x${string}`, req: UniversalTokenTxRequest, signer: UniversalSigner, value?: bigint): Promise<`0x${string}`>;
|
|
15
|
+
export declare function lockFee(ctx: OrchestratorContext, amount: bigint, universalPayload: UniversalPayload, req: UniversalTxRequest): Promise<Uint8Array>;
|
|
16
|
+
/**
|
|
17
|
+
* Creates an EVM client for the origin chain's gateway.
|
|
18
|
+
* Validates that the chain supports gateway operations.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getOriginGatewayContext(ctx: OrchestratorContext): {
|
|
21
|
+
chain: CHAIN;
|
|
22
|
+
evmClient?: EvmClient;
|
|
23
|
+
gatewayAddress?: `0x${string}`;
|
|
24
|
+
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gateway interaction: request conversion, tx sending, and fee locking.
|
|
4
|
+
* All chains use V1 gateway ABI.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.toGatewayRequestV1 = toGatewayRequestV1;
|
|
8
|
+
exports.toGatewayTokenRequestV1 = toGatewayTokenRequestV1;
|
|
9
|
+
exports.sendGatewayTxWithFallback = sendGatewayTxWithFallback;
|
|
10
|
+
exports.sendGatewayTokenTxWithFallback = sendGatewayTokenTxWithFallback;
|
|
11
|
+
exports.lockFee = lockFee;
|
|
12
|
+
exports.getOriginGatewayContext = getOriginGatewayContext;
|
|
13
|
+
const tslib_1 = require("tslib");
|
|
14
|
+
const bs58_1 = require("../../internal/bs58");
|
|
15
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
16
|
+
const viem_1 = require("viem");
|
|
17
|
+
const context_1 = require("./context");
|
|
18
|
+
const abi_1 = require("../../constants/abi");
|
|
19
|
+
const chain_1 = require("../../constants/chain");
|
|
20
|
+
const enums_1 = require("../../constants/enums");
|
|
21
|
+
const price_fetch_1 = require("../../price-fetch/price-fetch");
|
|
22
|
+
const utils_1 = require("../../utils");
|
|
23
|
+
const evm_client_1 = require("../../vm-client/evm-client");
|
|
24
|
+
const helpers_1 = require("./helpers");
|
|
25
|
+
const svm_client_1 = require("../../vm-client/svm-client");
|
|
26
|
+
const context_2 = require("./context");
|
|
27
|
+
const svm_helpers_1 = require("./svm-helpers");
|
|
28
|
+
const svm_helpers_2 = require("./svm-helpers");
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// ABI
|
|
31
|
+
// ============================================================================
|
|
32
|
+
const GATEWAY_ABI = abi_1.UNIVERSAL_GATEWAY_V1_SEND;
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Request Conversion (V0 struct → V1 flat format)
|
|
35
|
+
// ============================================================================
|
|
36
|
+
function toGatewayRequestV1(req) {
|
|
37
|
+
return {
|
|
38
|
+
recipient: req.recipient,
|
|
39
|
+
token: req.token,
|
|
40
|
+
amount: req.amount,
|
|
41
|
+
payload: req.payload,
|
|
42
|
+
revertRecipient: req.revertInstruction.fundRecipient,
|
|
43
|
+
signatureData: req.signatureData,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function toGatewayTokenRequestV1(req) {
|
|
47
|
+
return {
|
|
48
|
+
recipient: req.recipient,
|
|
49
|
+
token: req.token,
|
|
50
|
+
amount: req.amount,
|
|
51
|
+
gasToken: req.gasToken,
|
|
52
|
+
gasAmount: req.gasAmount,
|
|
53
|
+
payload: req.payload,
|
|
54
|
+
revertRecipient: req.revertInstruction.fundRecipient,
|
|
55
|
+
signatureData: req.signatureData,
|
|
56
|
+
amountOutMinETH: req.amountOutMinETH,
|
|
57
|
+
deadline: req.deadline,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Send Gateway Tx (V1 only)
|
|
62
|
+
// ============================================================================
|
|
63
|
+
function sendGatewayTxWithFallback(ctx, evmClient, address, req, signer, value) {
|
|
64
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
return evmClient.writeContract({
|
|
66
|
+
abi: GATEWAY_ABI,
|
|
67
|
+
address,
|
|
68
|
+
functionName: 'sendUniversalTx',
|
|
69
|
+
args: [toGatewayRequestV1(req)],
|
|
70
|
+
signer,
|
|
71
|
+
value,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function sendGatewayTokenTxWithFallback(ctx, evmClient, address, req, signer, value) {
|
|
76
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
return evmClient.writeContract(Object.assign({ abi: GATEWAY_ABI, address, functionName: 'sendUniversalTx', args: [toGatewayTokenRequestV1(req)], signer }, (value !== undefined && { value })));
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// Fee Locking
|
|
82
|
+
// ============================================================================
|
|
83
|
+
function lockFee(ctx, amount, universalPayload,
|
|
84
|
+
// DEBUG: lockFee entry
|
|
85
|
+
req) {
|
|
86
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
const chain = ctx.universalSigner.account.chain;
|
|
88
|
+
const { lockerContract, vm, defaultRPC } = chain_1.CHAIN_INFO[chain];
|
|
89
|
+
if (!lockerContract) {
|
|
90
|
+
throw new Error(`Locker contract not configured for chain: ${chain}`);
|
|
91
|
+
}
|
|
92
|
+
const rpcUrls = ctx.rpcUrls[chain] || defaultRPC;
|
|
93
|
+
switch (vm) {
|
|
94
|
+
case enums_1.VM.EVM: {
|
|
95
|
+
const evmClient = (0, context_1.getOriginEvmClient)(ctx);
|
|
96
|
+
const nativeTokenUsdPrice = yield new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(chain);
|
|
97
|
+
const nativeDecimals = 18;
|
|
98
|
+
const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
|
|
99
|
+
const tenUsd = utils_1.Utils.helpers.parseUnits('10', 8);
|
|
100
|
+
let depositUsd = amount < oneUsd ? oneUsd : amount;
|
|
101
|
+
if (depositUsd > tenUsd)
|
|
102
|
+
depositUsd = tenUsd;
|
|
103
|
+
let nativeAmount = (depositUsd * BigInt(Math.pow(10, nativeDecimals)) +
|
|
104
|
+
(nativeTokenUsdPrice - BigInt(1))) /
|
|
105
|
+
nativeTokenUsdPrice;
|
|
106
|
+
nativeAmount = nativeAmount + BigInt(1);
|
|
107
|
+
const txHash = yield sendGatewayTxWithFallback(ctx, evmClient, lockerContract, req, ctx.universalSigner, nativeAmount);
|
|
108
|
+
return (0, viem_1.hexToBytes)(txHash);
|
|
109
|
+
}
|
|
110
|
+
case enums_1.VM.SVM: {
|
|
111
|
+
const [nativeTokenUsdPrice, svmClient] = yield Promise.all([
|
|
112
|
+
new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(chain),
|
|
113
|
+
Promise.resolve(new svm_client_1.SvmClient({ rpcUrls })),
|
|
114
|
+
]);
|
|
115
|
+
const nativeDecimals = 9;
|
|
116
|
+
const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
|
|
117
|
+
const tenUsd = utils_1.Utils.helpers.parseUnits('10', 8);
|
|
118
|
+
let depositUsd = amount < oneUsd ? oneUsd : amount;
|
|
119
|
+
if (depositUsd > tenUsd)
|
|
120
|
+
depositUsd = tenUsd;
|
|
121
|
+
let nativeAmount = (depositUsd * BigInt(Math.pow(10, nativeDecimals)) +
|
|
122
|
+
(nativeTokenUsdPrice - BigInt(1))) /
|
|
123
|
+
nativeTokenUsdPrice;
|
|
124
|
+
nativeAmount = nativeAmount + BigInt(1);
|
|
125
|
+
const programId = new web3_js_1.PublicKey(abi_1.SVM_GATEWAY_IDL.address);
|
|
126
|
+
const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
|
|
127
|
+
const [vaultPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('vault')], programId);
|
|
128
|
+
const [rateLimitConfigPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit_config')], programId);
|
|
129
|
+
const [tokenRateLimitPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), web3_js_1.PublicKey.default.toBuffer()], programId);
|
|
130
|
+
const userPk = new web3_js_1.PublicKey(ctx.universalSigner.account.address);
|
|
131
|
+
const { feeVaultPda, protocolFeeLamports } = yield (0, svm_helpers_2.getSvmProtocolFee)(svmClient, programId);
|
|
132
|
+
const gasReq = (0, svm_helpers_1.buildSvmUniversalTxRequestFromReq)(req, userPk);
|
|
133
|
+
try {
|
|
134
|
+
const txHash = yield svmClient.writeContract({
|
|
135
|
+
abi: abi_1.SVM_GATEWAY_IDL,
|
|
136
|
+
address: programId.toBase58(),
|
|
137
|
+
functionName: 'sendUniversalTx',
|
|
138
|
+
args: [gasReq, nativeAmount + protocolFeeLamports],
|
|
139
|
+
signer: ctx.universalSigner,
|
|
140
|
+
accounts: {
|
|
141
|
+
config: configPda,
|
|
142
|
+
vault: vaultPda,
|
|
143
|
+
feeVault: feeVaultPda,
|
|
144
|
+
userTokenAccount: vaultPda,
|
|
145
|
+
gatewayTokenAccount: vaultPda,
|
|
146
|
+
user: userPk,
|
|
147
|
+
priceUpdate: new web3_js_1.PublicKey(chain_1.SVM_PYTH_PRICE_FEED),
|
|
148
|
+
rateLimitConfig: rateLimitConfigPda,
|
|
149
|
+
tokenRateLimit: tokenRateLimitPda,
|
|
150
|
+
tokenProgram: new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),
|
|
151
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
return new Uint8Array(bs58_1.bs58.decode(txHash));
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
(0, context_2.printLog)(ctx, `Error sending UniversalTx: ${error instanceof Error ? error.message : String(error)}`);
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
default:
|
|
162
|
+
throw new Error(`Unsupported VM type: ${vm}`);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// ============================================================================
|
|
167
|
+
// Origin Gateway Context
|
|
168
|
+
// ============================================================================
|
|
169
|
+
/**
|
|
170
|
+
* Creates an EVM client for the origin chain's gateway.
|
|
171
|
+
* Validates that the chain supports gateway operations.
|
|
172
|
+
*/
|
|
173
|
+
function getOriginGatewayContext(ctx) {
|
|
174
|
+
const chain = ctx.universalSigner.account.chain;
|
|
175
|
+
if (!helpers_1.SUPPORTED_GATEWAY_CHAINS.includes(chain)) {
|
|
176
|
+
throw new Error('Funds + payload bridging is only supported on Ethereum Sepolia, Arbitrum Sepolia, Base Sepolia, BNB Testnet, and Solana Devnet for now');
|
|
177
|
+
}
|
|
178
|
+
if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.EVM) {
|
|
179
|
+
const { defaultRPC, lockerContract } = chain_1.CHAIN_INFO[chain];
|
|
180
|
+
const rpcUrls = ctx.rpcUrls[chain] || defaultRPC;
|
|
181
|
+
const evmClient = new evm_client_1.EvmClient({ rpcUrls });
|
|
182
|
+
const gatewayAddress = lockerContract;
|
|
183
|
+
if (!gatewayAddress) {
|
|
184
|
+
throw new Error('Universal Gateway address not configured');
|
|
185
|
+
}
|
|
186
|
+
return { chain, evmClient, gatewayAddress };
|
|
187
|
+
}
|
|
188
|
+
// SVM path does not require evmClient/gatewayAddress
|
|
189
|
+
return { chain };
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=gateway-client.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure utility functions extracted from Orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* These have minimal dependencies and are used across multiple submodules.
|
|
5
|
+
*/
|
|
6
|
+
import { CHAIN, PUSH_NETWORK } from '../../constants/enums';
|
|
7
|
+
import type { ExecuteParams, UniversalExecuteParams } from '../orchestrator.types';
|
|
8
|
+
import type { OrchestratorContext } from './context';
|
|
9
|
+
/** Chains that support gateway operations (multicall, funds bridging, etc.) */
|
|
10
|
+
export declare const SUPPORTED_GATEWAY_CHAINS: CHAIN[];
|
|
11
|
+
export declare function isPushChain(chain: CHAIN): boolean;
|
|
12
|
+
export declare function getPushChainForNetwork(pushNetwork: PUSH_NETWORK): CHAIN;
|
|
13
|
+
export declare function getChainNamespace(chain: CHAIN): string;
|
|
14
|
+
export declare function chainFromNamespace(namespace: string): CHAIN | null;
|
|
15
|
+
export declare function getNativePRC20ForChain(targetChain: CHAIN, pushNetwork: PUSH_NETWORK): `0x${string}`;
|
|
16
|
+
export declare function getUniversalGatewayPCAddress(): `0x${string}`;
|
|
17
|
+
/**
|
|
18
|
+
* Validates that a feeLockTxHash is a well-formed transaction hash.
|
|
19
|
+
* EVM: must be 0x-prefixed 64-hex-char string (66 chars total).
|
|
20
|
+
* SVM (Base58): must be at least 32 chars.
|
|
21
|
+
*/
|
|
22
|
+
export declare function validateFeeLockTxHash(feeLockTxHash: string): void;
|
|
23
|
+
export declare function validateMainnetConnection(chain: CHAIN, pushChainId: string): void;
|
|
24
|
+
export declare function bigintReplacer(_key: string, value: any): any;
|
|
25
|
+
export declare function toExecuteParams(params: UniversalExecuteParams): ExecuteParams;
|
|
26
|
+
export declare function fetchOriginChainTransactionForProgress(ctx: OrchestratorContext, chain: CHAIN, txHashHex: string, txHashDisplay: string): Promise<object | undefined>;
|