@pushchain/core 3.0.8 → 4.0.0
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 +1 -1
- package/src/lib/constants/abi/universalGatewayV0.evm.d.ts +26 -0
- package/src/lib/constants/abi/universalGatewayV0.evm.js +1830 -775
- package/src/lib/constants/abi/universalGatewayV0.evm.js.map +1 -1
- package/src/lib/constants/abi/universalGatewayV0.json +293 -903
- package/src/lib/index.d.ts +1 -0
- package/src/lib/index.js.map +1 -1
- package/src/lib/orchestrator/orchestrator.d.ts +39 -4
- package/src/lib/orchestrator/orchestrator.js +659 -318
- package/src/lib/orchestrator/orchestrator.js.map +1 -1
- package/src/lib/orchestrator/orchestrator.types.d.ts +26 -0
- package/src/lib/orchestrator/payload-builders.js +8 -8
- package/src/lib/orchestrator/payload-builders.js.map +1 -1
- package/src/lib/progress-hook/progress-hook.js +59 -51
- package/src/lib/progress-hook/progress-hook.js.map +1 -1
- package/src/lib/progress-hook/progress-hook.types.d.ts +11 -5
- package/src/lib/progress-hook/progress-hook.types.js +10 -7
- package/src/lib/progress-hook/progress-hook.types.js.map +1 -1
- package/src/lib/universal/signer/signer.js +16 -7
- package/src/lib/universal/signer/signer.js.map +1 -1
- package/src/lib/utils.d.ts +19 -5
- package/src/lib/utils.js +42 -16
- package/src/lib/utils.js.map +1 -1
- package/src/lib/vm-client/svm-client.d.ts +0 -14
- package/src/lib/vm-client/svm-client.js +16 -47
- package/src/lib/vm-client/svm-client.js.map +1 -1
|
@@ -2,24 +2,23 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Orchestrator = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
6
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
5
7
|
const viem_1 = require("viem");
|
|
6
|
-
const push_chain_1 = require("../push-chain/push-chain");
|
|
7
|
-
const enums_1 = require("../constants/enums");
|
|
8
|
-
const payload_builders_1 = require("./payload-builders");
|
|
9
|
-
const evm_client_1 = require("../vm-client/evm-client");
|
|
10
|
-
const chain_1 = require("../constants/chain");
|
|
11
8
|
const abi_1 = require("../constants/abi");
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
9
|
+
const uea_evm_1 = require("../constants/abi/uea.evm");
|
|
10
|
+
const chain_1 = require("../constants/chain");
|
|
11
|
+
const enums_1 = require("../constants/enums");
|
|
12
|
+
const tokens_1 = require("../constants/tokens");
|
|
16
13
|
const tx_1 = require("../generated/v1/tx");
|
|
17
14
|
const price_fetch_1 = require("../price-fetch/price-fetch");
|
|
18
|
-
const anchor_1 = require("@coral-xyz/anchor");
|
|
19
|
-
const progress_hook_types_1 = require("../progress-hook/progress-hook.types");
|
|
20
15
|
const progress_hook_1 = tslib_1.__importDefault(require("../progress-hook/progress-hook"));
|
|
21
|
-
const
|
|
22
|
-
const
|
|
16
|
+
const progress_hook_types_1 = require("../progress-hook/progress-hook.types");
|
|
17
|
+
const push_chain_1 = require("../push-chain/push-chain");
|
|
18
|
+
const push_client_1 = require("../push-client/push-client");
|
|
19
|
+
const evm_client_1 = require("../vm-client/evm-client");
|
|
20
|
+
const svm_client_1 = require("../vm-client/svm-client");
|
|
21
|
+
const payload_builders_1 = require("./payload-builders");
|
|
23
22
|
class Orchestrator {
|
|
24
23
|
constructor(universalSigner, pushNetwork, rpcUrls = {}, printTraces = false, progressHook) {
|
|
25
24
|
this.universalSigner = universalSigner;
|
|
@@ -66,26 +65,8 @@ class Orchestrator {
|
|
|
66
65
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
67
66
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
68
67
|
try {
|
|
69
|
-
// FUNDS_TX short-circuit: Bridge tokens from origin chain to Push Chain
|
|
70
|
-
// - EVM (Sepolia): UniversalGatewayV0
|
|
71
|
-
// - SVM (Solana Devnet): pushsolanagateway
|
|
72
68
|
if (execute.funds) {
|
|
73
69
|
if (!execute.data || execute.data === '0x') {
|
|
74
|
-
// @@@@@@@@@@@@@@@
|
|
75
|
-
// @@@@@@@@@@@@@@@
|
|
76
|
-
// @@@@@@@@@@@@@@@
|
|
77
|
-
// @@@@@@@@@@@@@@@
|
|
78
|
-
// @@@@@@@@@@@@@@@
|
|
79
|
-
// @@@@@@@@@@@@@@@
|
|
80
|
-
// // Disallow user-provided `value` for funds-only bridging. The SDK derives
|
|
81
|
-
// // origin-chain msg.value automatically from the funds input:
|
|
82
|
-
// // - Native path: msg.value = bridgeAmount
|
|
83
|
-
// // - ERC-20 path: msg.value = 0
|
|
84
|
-
// if (execute.value !== undefined && execute.value !== BigInt(0)) {
|
|
85
|
-
// throw new Error(
|
|
86
|
-
// 'Do not set `value` when using funds bridging; the SDK sets origin msg.value from `funds.amount` automatically'
|
|
87
|
-
// );
|
|
88
|
-
// }
|
|
89
70
|
const chain = this.universalSigner.account.chain;
|
|
90
71
|
const { vm } = chain_1.CHAIN_INFO[chain];
|
|
91
72
|
if (!(chain === enums_1.CHAIN.ETHEREUM_SEPOLIA ||
|
|
@@ -96,7 +77,7 @@ class Orchestrator {
|
|
|
96
77
|
throw new Error('Funds bridging is only supported on Ethereum Sepolia, Arbitrum Sepolia, Base Sepolia, BNB Testnet, and Solana Devnet for now');
|
|
97
78
|
}
|
|
98
79
|
// Progress: Origin chain detected
|
|
99
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_01, chain);
|
|
80
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_01, chain, this.universalSigner.account.address);
|
|
100
81
|
const { defaultRPC, lockerContract } = chain_1.CHAIN_INFO[chain];
|
|
101
82
|
const rpcUrls = this.rpcUrls[chain] || defaultRPC;
|
|
102
83
|
// Resolve token: default to native token based on VM (ETH for EVM, SOL for SVM)
|
|
@@ -114,23 +95,6 @@ class Orchestrator {
|
|
|
114
95
|
}
|
|
115
96
|
const amount = execute.funds.amount;
|
|
116
97
|
const symbol = execute.funds.token.symbol;
|
|
117
|
-
// Funds Flow: Preparing funds transfer
|
|
118
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_01, amount, execute.funds.token.decimals, symbol);
|
|
119
|
-
if (vm === enums_1.VM.EVM) {
|
|
120
|
-
const evmClient = new evm_client_1.EvmClient({ rpcUrls });
|
|
121
|
-
const gatewayAddress = lockerContract;
|
|
122
|
-
const tokenAddr = execute.funds.token.address;
|
|
123
|
-
// Approve gateway to pull tokens if ERC-20 (not native sentinel)
|
|
124
|
-
if (execute.funds.token.mechanism === 'approve') {
|
|
125
|
-
yield this.ensureErc20Allowance(evmClient, tokenAddr, gatewayAddress, amount);
|
|
126
|
-
}
|
|
127
|
-
else if (execute.funds.token.mechanism === 'permit2') {
|
|
128
|
-
throw new Error('Permit2 is not supported yet');
|
|
129
|
-
}
|
|
130
|
-
else if (execute.funds.token.mechanism === 'native') {
|
|
131
|
-
// Native flow uses msg.value == bridgeAmount and bridgeToken = address(0)
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
98
|
const bridgeAmount = amount;
|
|
135
99
|
const revertCFG = {
|
|
136
100
|
fundRecipient: this.universalSigner.account
|
|
@@ -141,48 +105,85 @@ class Orchestrator {
|
|
|
141
105
|
const evmClient = new evm_client_1.EvmClient({ rpcUrls });
|
|
142
106
|
const gatewayAddress = lockerContract;
|
|
143
107
|
const tokenAddr = execute.funds.token.address;
|
|
144
|
-
// Call UniversalGatewayV0.sendFunds(recipient, bridgeToken, bridgeAmount, revertCFG)
|
|
145
108
|
const recipient = execute.to; // funds to recipient on Push Chain
|
|
146
109
|
const isNative = execute.funds.token.mechanism === 'native';
|
|
147
110
|
const bridgeToken = execute.funds.token.mechanism === 'approve'
|
|
148
111
|
? tokenAddr
|
|
149
112
|
: '0x0000000000000000000000000000000000000000';
|
|
150
|
-
const { nonce } = yield this.getUeaStatusAndNonce();
|
|
151
|
-
const { payload: universalPayload } = yield this.buildGatewayPayloadAndGas(execute, nonce, 'sendFunds', bridgeAmount);
|
|
152
|
-
// Get UEA info
|
|
113
|
+
const { nonce, deployed } = yield this.getUeaStatusAndNonce();
|
|
114
|
+
const { payload: universalPayload, req } = yield this.buildGatewayPayloadAndGas(execute, nonce, 'sendFunds', bridgeAmount);
|
|
153
115
|
const ueaAddress = this.computeUEAOffchain();
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
const
|
|
116
|
+
// Compute minimal native amount to deposit for gas on Push Chain
|
|
117
|
+
const ueaBalanceForGas = yield this.pushClient.getBalance(ueaAddress);
|
|
118
|
+
const nativeAmount = yield this.calculateNativeAmountForDeposit(chain, BigInt(0), ueaBalanceForGas);
|
|
119
|
+
// We log the SEND_TX_03_01 here because the progress hook for gas estimation should arrive before the resolving of UEA.
|
|
120
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_03_01);
|
|
121
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_03_02, ueaAddress, deployed);
|
|
122
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_01, amount, execute.funds.token.decimals, symbol);
|
|
123
|
+
if (vm === enums_1.VM.EVM) {
|
|
124
|
+
const evmClient = new evm_client_1.EvmClient({ rpcUrls });
|
|
125
|
+
const gatewayAddress = lockerContract;
|
|
126
|
+
const tokenAddr = execute.funds.token.address;
|
|
127
|
+
// Approve gateway to pull tokens if ERC-20 (not native sentinel)
|
|
128
|
+
if (execute.funds.token.mechanism === 'approve') {
|
|
129
|
+
yield this.ensureErc20Allowance(evmClient, tokenAddr, gatewayAddress, amount);
|
|
130
|
+
}
|
|
131
|
+
else if (execute.funds.token.mechanism === 'permit2') {
|
|
132
|
+
throw new Error('Permit2 is not supported yet');
|
|
133
|
+
}
|
|
134
|
+
else if (execute.funds.token.mechanism === 'native') {
|
|
135
|
+
// Native flow uses msg.value == bridgeAmount and bridgeToken = address(0)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
157
138
|
let txHash;
|
|
158
139
|
try {
|
|
159
|
-
//
|
|
160
|
-
const ueaAddressForGas = this.computeUEAOffchain();
|
|
161
|
-
const ueaBalanceForGas = yield this.pushClient.getBalance(ueaAddressForGas);
|
|
162
|
-
const nativeAmount = yield this.calculateNativeAmountForDeposit(chain, BigInt(0), ueaBalanceForGas);
|
|
163
|
-
const ueaAddress = this.computeUEAOffchain();
|
|
140
|
+
// FUNDS ONLY SELF
|
|
164
141
|
if (execute.to.toLowerCase() === ueaAddress.toLowerCase()) {
|
|
142
|
+
// const payloadBytes = this.encodeUniversalPayload(
|
|
143
|
+
// universalPayload as unknown as UniversalPayload
|
|
144
|
+
// );
|
|
145
|
+
// const req = this._buildUniversalTxRequest({
|
|
146
|
+
// recipient: zeroAddress,
|
|
147
|
+
// token: bridgeToken,
|
|
148
|
+
// amount: bridgeAmount,
|
|
149
|
+
// payload: '0x',
|
|
150
|
+
// });
|
|
151
|
+
// const req: UniversalTxRequest = {
|
|
152
|
+
// recipient: zeroAddress,
|
|
153
|
+
// token: bridgeToken,
|
|
154
|
+
// amount: bridgeAmount,
|
|
155
|
+
// payload: '0x',
|
|
156
|
+
// // payload: payloadBytes,
|
|
157
|
+
// revertInstruction: revertCFG,
|
|
158
|
+
// signatureData: '0x',
|
|
159
|
+
// } as unknown as never;
|
|
165
160
|
txHash = yield evmClient.writeContract({
|
|
166
161
|
abi: abi_1.UNIVERSAL_GATEWAY_V0,
|
|
167
162
|
address: gatewayAddress,
|
|
168
|
-
functionName: '
|
|
169
|
-
args: [
|
|
163
|
+
functionName: 'sendUniversalTx',
|
|
164
|
+
args: [req],
|
|
170
165
|
signer: this.universalSigner,
|
|
171
166
|
value: isNative ? bridgeAmount : BigInt(0),
|
|
172
167
|
});
|
|
173
168
|
}
|
|
174
169
|
else {
|
|
170
|
+
// FUNDS ONLY OTHER
|
|
171
|
+
// const payloadBytes = this.encodeUniversalPayload(
|
|
172
|
+
// universalPayload as unknown as UniversalPayload
|
|
173
|
+
// );
|
|
174
|
+
// const req: UniversalTxRequest = {
|
|
175
|
+
// recipient,
|
|
176
|
+
// token: bridgeToken,
|
|
177
|
+
// amount: bridgeAmount,
|
|
178
|
+
// payload: payloadBytes,
|
|
179
|
+
// revertInstruction: revertCFG,
|
|
180
|
+
// signatureData: '0x',
|
|
181
|
+
// } as unknown as never;
|
|
175
182
|
txHash = yield evmClient.writeContract({
|
|
176
183
|
abi: abi_1.UNIVERSAL_GATEWAY_V0,
|
|
177
184
|
address: gatewayAddress,
|
|
178
|
-
functionName: '
|
|
179
|
-
args: [
|
|
180
|
-
tokenAddr,
|
|
181
|
-
bridgeAmount,
|
|
182
|
-
universalPayload,
|
|
183
|
-
revertCFG,
|
|
184
|
-
'0x',
|
|
185
|
-
],
|
|
185
|
+
functionName: 'sendUniversalTx',
|
|
186
|
+
args: [req],
|
|
186
187
|
signer: this.universalSigner,
|
|
187
188
|
value: nativeAmount,
|
|
188
189
|
});
|
|
@@ -192,13 +193,16 @@ class Orchestrator {
|
|
|
192
193
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_04_04);
|
|
193
194
|
throw err;
|
|
194
195
|
}
|
|
195
|
-
this.
|
|
196
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_02, txHash, bridgeAmount, execute.funds.token.decimals, symbol);
|
|
196
|
+
const originTx = yield this.fetchOriginChainTransactionForProgress(chain, txHash, txHash);
|
|
197
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_02, txHash, bridgeAmount, execute.funds.token.decimals, symbol, originTx);
|
|
197
198
|
yield this.waitForEvmConfirmationsWithCountdown(evmClient, txHash, 4, 210000);
|
|
198
199
|
const pushChainUniversalTx = yield this.queryUniversalTxStatusFromGatewayTx(evmClient, gatewayAddress, txHash, execute.to === ueaAddress ? 'sendFunds' : 'sendTxWithFunds');
|
|
200
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_04);
|
|
199
201
|
const lastPcTransaction = pushChainUniversalTx === null || pushChainUniversalTx === void 0 ? void 0 : pushChainUniversalTx.pcTx.at(-1);
|
|
200
202
|
const tx = yield this.pushClient.getTransaction(lastPcTransaction === null || lastPcTransaction === void 0 ? void 0 : lastPcTransaction.txHash);
|
|
201
203
|
const response = yield this.transformToUniversalTxResponse(tx);
|
|
204
|
+
// Funds Flow: Funds credited on Push Chain
|
|
205
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_05, bridgeAmount, execute.funds.token.decimals, symbol);
|
|
202
206
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01, [response]);
|
|
203
207
|
return response;
|
|
204
208
|
}
|
|
@@ -209,7 +213,9 @@ class Orchestrator {
|
|
|
209
213
|
const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
|
|
210
214
|
const [vaultPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('vault')], programId);
|
|
211
215
|
const [whitelistPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('whitelist')], programId);
|
|
216
|
+
const [rateLimitConfigPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit_config')], programId);
|
|
212
217
|
const userPk = new web3_js_1.PublicKey(this.universalSigner.account.address);
|
|
218
|
+
const priceUpdatePk = new web3_js_1.PublicKey('7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE');
|
|
213
219
|
// pay-with-token gas abstraction is not supported on Solana
|
|
214
220
|
if (execute.payGasWith !== undefined) {
|
|
215
221
|
throw new Error('Pay-with token is not supported on Solana');
|
|
@@ -222,59 +228,43 @@ class Orchestrator {
|
|
|
222
228
|
};
|
|
223
229
|
// New gateway expects EVM recipient as [u8; 20]
|
|
224
230
|
const recipientEvm20 = Array.from(Buffer.from(execute.to.slice(2).padStart(40, '0'), 'hex').subarray(0, 20));
|
|
231
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_03_01);
|
|
232
|
+
const ueaAddress = this.computeUEAOffchain();
|
|
233
|
+
const { nonce, deployed } = yield this.getUeaStatusAndNonce();
|
|
234
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_03_02, ueaAddress, deployed);
|
|
225
235
|
if (execute.funds.token.mechanism === 'native') {
|
|
226
236
|
// Native SOL funds-only
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
userTokenAccount: userPk,
|
|
259
|
-
gatewayTokenAccount: vaultPda,
|
|
260
|
-
bridgeToken: web3_js_1.PublicKey.default,
|
|
261
|
-
tokenProgram: new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),
|
|
262
|
-
systemProgram: web3_js_1.SystemProgram.programId,
|
|
263
|
-
},
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
const { nonce } = yield this.getUeaStatusAndNonce();
|
|
268
|
-
const { payload: universalPayload } = yield this.buildGatewayPayloadAndGas(execute, nonce, 'sendFunds', execute.funds.amount);
|
|
269
|
-
const ueaBalanceForGas = yield this.pushClient.getBalance(ueaAddress);
|
|
270
|
-
txSignature = yield this._sendSVMTxWithFunds({
|
|
271
|
-
execute,
|
|
272
|
-
mechanism: execute.funds.token.mechanism,
|
|
273
|
-
universalPayload,
|
|
274
|
-
bridgeAmount,
|
|
275
|
-
nativeAmount: yield this.calculateNativeAmountForDeposit(chain, BigInt(0), ueaBalanceForGas),
|
|
276
|
-
});
|
|
277
|
-
}
|
|
237
|
+
const [tokenRateLimitPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), web3_js_1.PublicKey.default.toBuffer()], programId);
|
|
238
|
+
const recipientNative = execute.to === ueaAddress
|
|
239
|
+
? Array.from(Buffer.alloc(20, 0))
|
|
240
|
+
: recipientEvm20;
|
|
241
|
+
const reqNative = this._buildSvmUniversalTxRequest({
|
|
242
|
+
recipient: recipientNative,
|
|
243
|
+
token: web3_js_1.PublicKey.default,
|
|
244
|
+
amount: bridgeAmount,
|
|
245
|
+
payload: '0x',
|
|
246
|
+
fundRecipient: userPk,
|
|
247
|
+
signatureData: '0x',
|
|
248
|
+
});
|
|
249
|
+
txSignature = yield svmClient.writeContract({
|
|
250
|
+
abi: abi_1.SVM_GATEWAY_IDL,
|
|
251
|
+
address: programId.toBase58(),
|
|
252
|
+
functionName: 'sendUniversalTx',
|
|
253
|
+
args: [reqNative, bridgeAmount],
|
|
254
|
+
signer: this.universalSigner,
|
|
255
|
+
accounts: {
|
|
256
|
+
config: configPda,
|
|
257
|
+
vault: vaultPda,
|
|
258
|
+
userTokenAccount: vaultPda,
|
|
259
|
+
gatewayTokenAccount: vaultPda,
|
|
260
|
+
user: userPk,
|
|
261
|
+
priceUpdate: priceUpdatePk,
|
|
262
|
+
rateLimitConfig: rateLimitConfigPda,
|
|
263
|
+
tokenRateLimit: tokenRateLimitPda,
|
|
264
|
+
tokenProgram: new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),
|
|
265
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
266
|
+
},
|
|
267
|
+
});
|
|
278
268
|
}
|
|
279
269
|
else if (execute.funds.token.mechanism === 'approve') {
|
|
280
270
|
// SPL token funds-only (requires pre-existing ATAs)
|
|
@@ -292,57 +282,83 @@ class Orchestrator {
|
|
|
292
282
|
TOKEN_PROGRAM_ID.toBuffer(),
|
|
293
283
|
mintPk.toBuffer(),
|
|
294
284
|
], ASSOCIATED_TOKEN_PROGRAM_ID)[0];
|
|
295
|
-
const
|
|
285
|
+
const [tokenRateLimitPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), mintPk.toBuffer()], programId);
|
|
296
286
|
if (execute.to === ueaAddress) {
|
|
297
|
-
|
|
287
|
+
const recipientSpl = Array.from(Buffer.alloc(20, 0));
|
|
288
|
+
const reqSpl = this._buildSvmUniversalTxRequest({
|
|
289
|
+
recipient: recipientSpl,
|
|
290
|
+
token: mintPk,
|
|
291
|
+
amount: bridgeAmount,
|
|
292
|
+
payload: '0x',
|
|
293
|
+
fundRecipient: userPk,
|
|
294
|
+
signatureData: '0x',
|
|
295
|
+
});
|
|
298
296
|
txSignature = yield svmClient.writeContract({
|
|
299
297
|
abi: abi_1.SVM_GATEWAY_IDL,
|
|
300
298
|
address: programId.toBase58(),
|
|
301
|
-
functionName: '
|
|
302
|
-
args: [
|
|
299
|
+
functionName: 'sendUniversalTx',
|
|
300
|
+
args: [reqSpl, BigInt(0)],
|
|
303
301
|
signer: this.universalSigner,
|
|
304
302
|
accounts: {
|
|
305
303
|
config: configPda,
|
|
306
304
|
vault: vaultPda,
|
|
307
|
-
tokenWhitelist: whitelistPda,
|
|
308
305
|
userTokenAccount: userAta,
|
|
309
306
|
gatewayTokenAccount: vaultAta,
|
|
310
307
|
user: userPk,
|
|
311
|
-
bridgeToken: mintPk,
|
|
312
308
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
309
|
+
priceUpdate: priceUpdatePk,
|
|
310
|
+
rateLimitConfig: rateLimitConfigPda,
|
|
311
|
+
tokenRateLimit: tokenRateLimitPda,
|
|
313
312
|
systemProgram: web3_js_1.SystemProgram.programId,
|
|
314
313
|
},
|
|
315
314
|
});
|
|
316
315
|
}
|
|
317
316
|
else {
|
|
318
|
-
const
|
|
319
|
-
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
317
|
+
const recipientSpl = recipientEvm20;
|
|
318
|
+
// vitalik
|
|
319
|
+
const reqSpl = this._buildSvmUniversalTxRequest({
|
|
320
|
+
recipient: recipientSpl,
|
|
321
|
+
token: mintPk,
|
|
322
|
+
amount: bridgeAmount,
|
|
323
|
+
payload: '0x',
|
|
324
|
+
fundRecipient: userPk,
|
|
325
|
+
signatureData: '0x',
|
|
326
|
+
});
|
|
327
|
+
txSignature = yield svmClient.writeContract({
|
|
328
|
+
abi: abi_1.SVM_GATEWAY_IDL,
|
|
329
|
+
address: programId.toBase58(),
|
|
330
|
+
functionName: 'sendUniversalTx',
|
|
331
|
+
args: [reqSpl, BigInt(0)],
|
|
332
|
+
signer: this.universalSigner,
|
|
333
|
+
accounts: {
|
|
334
|
+
config: configPda,
|
|
335
|
+
vault: vaultPda,
|
|
336
|
+
userTokenAccount: userAta,
|
|
337
|
+
gatewayTokenAccount: vaultAta,
|
|
338
|
+
user: userPk,
|
|
339
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
340
|
+
priceUpdate: priceUpdatePk,
|
|
341
|
+
rateLimitConfig: rateLimitConfigPda,
|
|
342
|
+
tokenRateLimit: tokenRateLimitPda,
|
|
343
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
344
|
+
},
|
|
327
345
|
});
|
|
328
346
|
}
|
|
329
347
|
}
|
|
330
348
|
else {
|
|
331
349
|
throw new Error('Unsupported token mechanism on Solana');
|
|
332
350
|
}
|
|
333
|
-
this.
|
|
334
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_02, txSignature, bridgeAmount, execute.funds.token.decimals, symbol);
|
|
335
|
-
yield
|
|
336
|
-
txSignature,
|
|
337
|
-
confirmations: 25,
|
|
338
|
-
timeoutMs: 300000,
|
|
339
|
-
});
|
|
351
|
+
const originTx = yield this.fetchOriginChainTransactionForProgress(chain, '0x', txSignature);
|
|
352
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_02, txSignature, bridgeAmount, execute.funds.token.decimals, symbol, originTx);
|
|
353
|
+
yield this.waitForSvmConfirmationsWithCountdown(svmClient, txSignature, 25, 300000);
|
|
340
354
|
// After origin confirmations, query Push Chain for UniversalTx status (SVM)
|
|
341
355
|
const pushChainUniversalTx = yield this.queryUniversalTxStatusFromGatewayTx(undefined, undefined, txSignature, 'sendFunds');
|
|
342
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.
|
|
356
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_04);
|
|
343
357
|
const lastPcTransaction = pushChainUniversalTx === null || pushChainUniversalTx === void 0 ? void 0 : pushChainUniversalTx.pcTx.at(-1);
|
|
344
358
|
const tx = yield this.pushClient.getTransaction(lastPcTransaction === null || lastPcTransaction === void 0 ? void 0 : lastPcTransaction.txHash);
|
|
345
359
|
const response = yield this.transformToUniversalTxResponse(tx);
|
|
360
|
+
// Funds Flow: Funds credited on Push Chain
|
|
361
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_05, bridgeAmount, execute.funds.token.decimals, symbol);
|
|
346
362
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01, [response]);
|
|
347
363
|
return response;
|
|
348
364
|
}
|
|
@@ -352,7 +368,7 @@ class Orchestrator {
|
|
|
352
368
|
// - EVM (Sepolia): ERC-20 approve path + native gas via msg.value
|
|
353
369
|
// - SVM (Solana Devnet): SPL or native SOL with gas_amount
|
|
354
370
|
const { chain, evmClient, gatewayAddress } = this.getOriginGatewayContext();
|
|
355
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_01, chain);
|
|
371
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_01, chain, this.universalSigner.account.address);
|
|
356
372
|
// Default token to native ETH if none provided
|
|
357
373
|
if (!execute.funds.token) {
|
|
358
374
|
const available = tokens_1.MOVEABLE_TOKENS[chain] || [];
|
|
@@ -368,7 +384,7 @@ class Orchestrator {
|
|
|
368
384
|
}
|
|
369
385
|
const mechanism = execute.funds.token.mechanism;
|
|
370
386
|
const { deployed, nonce } = yield this.getUeaStatusAndNonce();
|
|
371
|
-
const { payload: universalPayload } = yield this.buildGatewayPayloadAndGas(execute, nonce, 'sendTxWithFunds', execute.funds.amount);
|
|
387
|
+
const { payload: universalPayload, req } = yield this.buildGatewayPayloadAndGas(execute, nonce, 'sendTxWithFunds', execute.funds.amount);
|
|
372
388
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_01);
|
|
373
389
|
// Compute required gas funding on Push Chain and current UEA balance
|
|
374
390
|
const gasEstimate = execute.gasLimit || BigInt(1e7);
|
|
@@ -455,7 +471,6 @@ class Orchestrator {
|
|
|
455
471
|
try {
|
|
456
472
|
if (chain_1.CHAIN_INFO[this.universalSigner.account.chain].vm === enums_1.VM.EVM) {
|
|
457
473
|
const tokenAddr = execute.funds.token.address;
|
|
458
|
-
// Compute EIP-712 signature for the universal payload and hash to bytes32
|
|
459
474
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_03_01);
|
|
460
475
|
const ueaAddress = this.computeUEAOffchain();
|
|
461
476
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_03_02, ueaAddress, deployed);
|
|
@@ -464,21 +479,7 @@ class Orchestrator {
|
|
|
464
479
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_04_03);
|
|
465
480
|
const evmClientEvm = evmClient;
|
|
466
481
|
const gatewayAddressEvm = gatewayAddress;
|
|
467
|
-
|
|
468
|
-
// txHash = await evmClientEvm.writeContract({
|
|
469
|
-
// abi: UNIVERSAL_GATEWAY_V0 as unknown as Abi,
|
|
470
|
-
// address: gatewayAddressEvm,
|
|
471
|
-
// functionName: 'sendTxWithFunds',
|
|
472
|
-
// args: [
|
|
473
|
-
// tokenAddr,
|
|
474
|
-
// bridgeAmount,
|
|
475
|
-
// universalPayload,
|
|
476
|
-
// revertCFG,
|
|
477
|
-
// '0x',
|
|
478
|
-
// ],
|
|
479
|
-
// signer: this.universalSigner,
|
|
480
|
-
// value: nativeAmount,
|
|
481
|
-
// });
|
|
482
|
+
const payloadBytes = this.encodeUniversalPayload(universalPayload);
|
|
482
483
|
// New behavior: if user provided a gasTokenAddress, pay gas in that token via Uniswap quote
|
|
483
484
|
// Determine pay-with token address, min-out and slippage
|
|
484
485
|
const payWith = execute.payGasWith;
|
|
@@ -511,37 +512,51 @@ class Orchestrator {
|
|
|
511
512
|
// Approve gas token to gateway
|
|
512
513
|
yield this.ensureErc20Allowance(evmClientEvm, gasTokenAddress, gatewayAddressEvm, gasAmount);
|
|
513
514
|
// Approve bridge token already done above; now call new gateway signature (nonpayable)
|
|
515
|
+
// const reqToken: UniversalTokenTxRequest = {
|
|
516
|
+
// recipient: zeroAddress,
|
|
517
|
+
// token: tokenAddr,
|
|
518
|
+
// amount: bridgeAmount,
|
|
519
|
+
// gasToken: gasTokenAddress,
|
|
520
|
+
// gasAmount,
|
|
521
|
+
// payload: payloadBytes,
|
|
522
|
+
// revertInstruction: revertCFG,
|
|
523
|
+
// signatureData: '0x',
|
|
524
|
+
// amountOutMinETH,
|
|
525
|
+
// deadline,
|
|
526
|
+
// } as unknown as never;
|
|
527
|
+
const reqToken = Object.assign(Object.assign({}, req), { gasToken: gasTokenAddress, gasAmount,
|
|
528
|
+
amountOutMinETH,
|
|
529
|
+
deadline });
|
|
514
530
|
txHash = yield evmClientEvm.writeContract({
|
|
515
531
|
abi: abi_1.UNIVERSAL_GATEWAY_V0,
|
|
516
532
|
address: gatewayAddressEvm,
|
|
517
|
-
functionName: '
|
|
518
|
-
args: [
|
|
519
|
-
tokenAddr,
|
|
520
|
-
bridgeAmount,
|
|
521
|
-
gasTokenAddress,
|
|
522
|
-
gasAmount,
|
|
523
|
-
amountOutMinETH,
|
|
524
|
-
deadline,
|
|
525
|
-
universalPayload,
|
|
526
|
-
revertCFG,
|
|
527
|
-
'0x',
|
|
528
|
-
],
|
|
533
|
+
functionName: 'sendUniversalTx',
|
|
534
|
+
args: [reqToken],
|
|
529
535
|
signer: this.universalSigner,
|
|
530
536
|
});
|
|
531
537
|
}
|
|
532
538
|
else {
|
|
533
539
|
// Existing native-ETH value path
|
|
540
|
+
// const req: UniversalTxRequest = {
|
|
541
|
+
// recipient: zeroAddress,
|
|
542
|
+
// token: tokenAddr,
|
|
543
|
+
// amount: bridgeAmount,
|
|
544
|
+
// payload: payloadBytes,
|
|
545
|
+
// revertInstruction: revertCFG,
|
|
546
|
+
// signatureData: '0x',
|
|
547
|
+
// };
|
|
548
|
+
// const req = this._buildUniversalTxRequest({
|
|
549
|
+
// recipient: zeroAddress,
|
|
550
|
+
// token: tokenAddr,
|
|
551
|
+
// amount: bridgeAmount,
|
|
552
|
+
// payload: this.encodeUniversalPayload(universalPayload),
|
|
553
|
+
// });
|
|
554
|
+
// VALUE + PAYLOAD + FUNDS && PAYLOAD + FUNDS
|
|
534
555
|
txHash = yield evmClientEvm.writeContract({
|
|
535
556
|
abi: abi_1.UNIVERSAL_GATEWAY_V0,
|
|
536
557
|
address: gatewayAddressEvm,
|
|
537
|
-
functionName: '
|
|
538
|
-
args: [
|
|
539
|
-
tokenAddr,
|
|
540
|
-
bridgeAmount,
|
|
541
|
-
universalPayload,
|
|
542
|
-
revertCFG,
|
|
543
|
-
'0x',
|
|
544
|
-
],
|
|
558
|
+
functionName: 'sendUniversalTx',
|
|
559
|
+
args: [req],
|
|
545
560
|
signer: this.universalSigner,
|
|
546
561
|
value: nativeAmount,
|
|
547
562
|
});
|
|
@@ -554,6 +569,7 @@ class Orchestrator {
|
|
|
554
569
|
universalPayload,
|
|
555
570
|
bridgeAmount,
|
|
556
571
|
nativeAmount,
|
|
572
|
+
req,
|
|
557
573
|
});
|
|
558
574
|
}
|
|
559
575
|
}
|
|
@@ -575,11 +591,7 @@ class Orchestrator {
|
|
|
575
591
|
rpcUrls: this.rpcUrls[enums_1.CHAIN.SOLANA_DEVNET] ||
|
|
576
592
|
chain_1.CHAIN_INFO[enums_1.CHAIN.SOLANA_DEVNET].defaultRPC,
|
|
577
593
|
});
|
|
578
|
-
yield
|
|
579
|
-
txSignature: txHash,
|
|
580
|
-
confirmations: 25,
|
|
581
|
-
timeoutMs: 300000,
|
|
582
|
-
});
|
|
594
|
+
yield this.waitForSvmConfirmationsWithCountdown(svmClient, txHash, 25, 300000);
|
|
583
595
|
}
|
|
584
596
|
// Funds Flow: Confirmed on origin
|
|
585
597
|
let feeLockTxHash = txHash;
|
|
@@ -590,12 +602,14 @@ class Orchestrator {
|
|
|
590
602
|
feeLockTxHash = (0, viem_1.bytesToHex)(new Uint8Array(decoded));
|
|
591
603
|
}
|
|
592
604
|
}
|
|
593
|
-
if (
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
this.
|
|
605
|
+
// if (
|
|
606
|
+
// chain === CHAIN.SOLANA_DEVNET ||
|
|
607
|
+
// chain === CHAIN.SOLANA_TESTNET ||
|
|
608
|
+
// chain === CHAIN.SOLANA_MAINNET
|
|
609
|
+
// ) {
|
|
610
|
+
// await this.sendUniversalTx(deployed, feeLockTxHash);
|
|
611
|
+
// }
|
|
612
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_04);
|
|
599
613
|
// After sending Cosmos tx to Push Chain, query UniversalTx status
|
|
600
614
|
let pushChainUniversalTx;
|
|
601
615
|
if (chain_1.CHAIN_INFO[this.universalSigner.account.chain].vm === enums_1.VM.EVM) {
|
|
@@ -620,13 +634,13 @@ class Orchestrator {
|
|
|
620
634
|
execute.value = BigInt(0);
|
|
621
635
|
}
|
|
622
636
|
const chain = this.universalSigner.account.chain;
|
|
623
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_01, chain);
|
|
637
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_01, chain, this.universalSigner.account.address);
|
|
624
638
|
this.validateMainnetConnection(chain);
|
|
625
639
|
/**
|
|
626
640
|
* Push to Push Tx
|
|
627
641
|
*/
|
|
628
642
|
if (this.isPushChain(chain)) {
|
|
629
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.
|
|
643
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_07);
|
|
630
644
|
const tx = yield this.sendPushTx(execute);
|
|
631
645
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01, [tx]);
|
|
632
646
|
return tx;
|
|
@@ -667,6 +681,8 @@ class Orchestrator {
|
|
|
667
681
|
// Support multicall payload encoding when execute.data is an array
|
|
668
682
|
let payloadData;
|
|
669
683
|
let payloadTo;
|
|
684
|
+
let req;
|
|
685
|
+
// Here is only value and payload. No funds here
|
|
670
686
|
if (Array.isArray(execute.data)) {
|
|
671
687
|
// payloadData = this._buildMulticallPayloadData(execute.to, execute.data);
|
|
672
688
|
// Normal multicall. We replace the `to` to zeroAddress. Then console.warn to let user know that it should be
|
|
@@ -675,19 +691,54 @@ class Orchestrator {
|
|
|
675
691
|
payloadTo = viem_1.zeroAddress;
|
|
676
692
|
console.warn(`Multicalls should have execute.to as ${viem_1.zeroAddress}`);
|
|
677
693
|
payloadData = this._buildMulticallPayloadData(execute.to, (0, payload_builders_1.buildExecuteMulticall)({ execute, ueaAddress: UEA }));
|
|
694
|
+
req = this._buildUniversalTxRequest({
|
|
695
|
+
recipient: viem_1.zeroAddress,
|
|
696
|
+
token: viem_1.zeroAddress,
|
|
697
|
+
amount: BigInt(0),
|
|
698
|
+
payload: payloadData,
|
|
699
|
+
});
|
|
678
700
|
}
|
|
679
701
|
else {
|
|
680
702
|
if (execute.to.toLowerCase() !== UEA.toLowerCase()) {
|
|
681
703
|
// For Payload + Value we don't do multicall anymore.
|
|
682
704
|
// Multicall is only when Payload + Value;
|
|
683
705
|
// Payload + Value + Funds -> Multicall
|
|
706
|
+
// TODO: Check but I beleive this code section is never reached.
|
|
684
707
|
if (execute.funds) {
|
|
685
708
|
payloadTo = viem_1.zeroAddress;
|
|
686
709
|
payloadData = this._buildMulticallPayloadData(execute.to, (0, payload_builders_1.buildExecuteMulticall)({ execute, ueaAddress: UEA }));
|
|
710
|
+
req = this._buildUniversalTxRequest({
|
|
711
|
+
recipient: viem_1.zeroAddress,
|
|
712
|
+
token: viem_1.zeroAddress,
|
|
713
|
+
amount: BigInt(0),
|
|
714
|
+
payload: payloadData,
|
|
715
|
+
});
|
|
687
716
|
}
|
|
688
717
|
else {
|
|
718
|
+
// VALUE ONLY OTHER
|
|
719
|
+
// VALUE + PAYLOAD ONLY OTHER
|
|
689
720
|
payloadTo = execute.to;
|
|
690
721
|
payloadData = execute.data || '0x';
|
|
722
|
+
const reqData = this._buildMulticallPayloadData(execute.to, (0, payload_builders_1.buildExecuteMulticall)({ execute, ueaAddress: UEA }));
|
|
723
|
+
const universalPayload = JSON.parse(JSON.stringify({
|
|
724
|
+
to: viem_1.zeroAddress,
|
|
725
|
+
value: execute.value,
|
|
726
|
+
data: reqData,
|
|
727
|
+
gasLimit: execute.gasLimit || BigInt(5e7),
|
|
728
|
+
maxFeePerGas: execute.maxFeePerGas || BigInt(1e10),
|
|
729
|
+
maxPriorityFeePerGas: execute.maxPriorityFeePerGas || BigInt(0),
|
|
730
|
+
nonce,
|
|
731
|
+
deadline: execute.deadline || BigInt(9999999999),
|
|
732
|
+
vType: feeLockingRequired
|
|
733
|
+
? tx_1.VerificationType.universalTxVerification
|
|
734
|
+
: tx_1.VerificationType.signedVerification,
|
|
735
|
+
}, this.bigintReplacer));
|
|
736
|
+
req = this._buildUniversalTxRequest({
|
|
737
|
+
recipient: viem_1.zeroAddress,
|
|
738
|
+
token: viem_1.zeroAddress,
|
|
739
|
+
amount: BigInt(0),
|
|
740
|
+
payload: this.encodeUniversalPayload(universalPayload),
|
|
741
|
+
});
|
|
691
742
|
}
|
|
692
743
|
}
|
|
693
744
|
else {
|
|
@@ -695,8 +746,16 @@ class Orchestrator {
|
|
|
695
746
|
if (execute.data && execute.to.toLowerCase() === UEA.toLowerCase()) {
|
|
696
747
|
throw new Error(`You can't execute data on the UEA address`);
|
|
697
748
|
}
|
|
749
|
+
// VALUE ONLY SELF
|
|
698
750
|
payloadTo = execute.to;
|
|
699
751
|
payloadData = execute.data || '0x';
|
|
752
|
+
req = this._buildUniversalTxRequest({
|
|
753
|
+
// recipient: execute.to,
|
|
754
|
+
recipient: viem_1.zeroAddress,
|
|
755
|
+
token: viem_1.zeroAddress,
|
|
756
|
+
amount: BigInt(0),
|
|
757
|
+
payload: payloadData,
|
|
758
|
+
});
|
|
700
759
|
}
|
|
701
760
|
}
|
|
702
761
|
const universalPayload = JSON.parse(JSON.stringify({
|
|
@@ -712,12 +771,6 @@ class Orchestrator {
|
|
|
712
771
|
? tx_1.VerificationType.universalTxVerification
|
|
713
772
|
: tx_1.VerificationType.signedVerification,
|
|
714
773
|
}, this.bigintReplacer));
|
|
715
|
-
const ueaVersion = yield this.fetchUEAVersion();
|
|
716
|
-
const executionHash = this.computeExecutionHash({
|
|
717
|
-
verifyingContract: UEA,
|
|
718
|
-
payload: universalPayload,
|
|
719
|
-
version: ueaVersion,
|
|
720
|
-
});
|
|
721
774
|
/**
|
|
722
775
|
* Prepare verification data by either signature or fund locking
|
|
723
776
|
*/
|
|
@@ -729,13 +782,14 @@ class Orchestrator {
|
|
|
729
782
|
* 4. UEA not deployed + insufficient funds: Lock requiredFunds
|
|
730
783
|
*/
|
|
731
784
|
if (!feeLockingRequired) {
|
|
785
|
+
const ueaVersion = yield this.fetchUEAVersion();
|
|
732
786
|
/**
|
|
733
787
|
* Sign Universal Payload
|
|
734
788
|
*/
|
|
735
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.
|
|
789
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_04_02);
|
|
736
790
|
const signature = yield this.signUniversalPayload(universalPayload, UEA, ueaVersion);
|
|
737
791
|
verificationData = (0, viem_1.bytesToHex)(signature);
|
|
738
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.
|
|
792
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_04_03);
|
|
739
793
|
}
|
|
740
794
|
else {
|
|
741
795
|
/**
|
|
@@ -745,17 +799,20 @@ class Orchestrator {
|
|
|
745
799
|
const fixedPushAmount = push_chain_1.PushChain.utils.helpers.parseUnits('0.001', 18); // Minimum lock 0.001 Push tokens
|
|
746
800
|
const lockAmount = funds < requiredFunds ? fundDifference : fixedPushAmount;
|
|
747
801
|
const lockAmountInUSD = this.pushClient.pushToUSDC(lockAmount);
|
|
748
|
-
this.
|
|
749
|
-
const feeLockTxHashBytes = yield this.lockFee(lockAmountInUSD, universalPayload);
|
|
802
|
+
const feeLockTxHashBytes = yield this.lockFee(lockAmountInUSD, universalPayload, req);
|
|
750
803
|
feeLockTxHash = (0, viem_1.bytesToHex)(feeLockTxHashBytes);
|
|
751
804
|
verificationData = (0, viem_1.bytesToHex)(feeLockTxHashBytes);
|
|
752
805
|
const { vm } = chain_1.CHAIN_INFO[chain];
|
|
753
|
-
|
|
806
|
+
const feeLockTxHashDisplay = vm === enums_1.VM.SVM
|
|
754
807
|
? anchor_1.utils.bytes.bs58.encode(feeLockTxHashBytes)
|
|
755
|
-
: feeLockTxHash
|
|
808
|
+
: feeLockTxHash;
|
|
809
|
+
// Gas Flow: Gas funding in progress (with full origin tx when available)
|
|
810
|
+
const originTx = yield this.fetchOriginChainTransactionForProgress(chain, feeLockTxHash, feeLockTxHashDisplay);
|
|
811
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_05_01, feeLockTxHashDisplay, originTx);
|
|
756
812
|
// Waiting for blocks confirmations
|
|
757
813
|
yield this.waitForLockerFeeConfirmation(feeLockTxHashBytes);
|
|
758
|
-
|
|
814
|
+
// Gas Flow: Gas funding confirmed
|
|
815
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_05_02);
|
|
759
816
|
// Query nodes via gRPC for Push Chain transaction
|
|
760
817
|
const { defaultRPC, lockerContract } = chain_1.CHAIN_INFO[chain];
|
|
761
818
|
const pushChainUniversalTx = yield this.queryUniversalTxStatusFromGatewayTx(new evm_client_1.EvmClient({ rpcUrls: this.rpcUrls[chain] || defaultRPC }), lockerContract, feeLockTxHash, 'sendTxWithGas');
|
|
@@ -763,7 +820,6 @@ class Orchestrator {
|
|
|
763
820
|
* Return response directly (skip sendUniversalTx for sendTxWithGas flow)
|
|
764
821
|
* Note: queryTx may be undefined since validators don't recognize new UniversalTx event yet
|
|
765
822
|
*/
|
|
766
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06);
|
|
767
823
|
// Transform to UniversalTxResponse (follow sendFunds pattern)
|
|
768
824
|
const lastPcTransaction = pushChainUniversalTx === null || pushChainUniversalTx === void 0 ? void 0 : pushChainUniversalTx.pcTx.at(-1);
|
|
769
825
|
const tx = yield this.pushClient.getTransaction(lastPcTransaction === null || lastPcTransaction === void 0 ? void 0 : lastPcTransaction.txHash);
|
|
@@ -774,7 +830,7 @@ class Orchestrator {
|
|
|
774
830
|
/**
|
|
775
831
|
* Non-fee-locking path: Broadcasting Tx to PC via sendUniversalTx
|
|
776
832
|
*/
|
|
777
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.
|
|
833
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_07);
|
|
778
834
|
// We don't need to query via gRPC the PC transaction since it's getting returned it here already.
|
|
779
835
|
const transactions = yield this.sendUniversalTx(isUEADeployed, feeLockTxHash, universalPayload, verificationData);
|
|
780
836
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01, transactions);
|
|
@@ -806,7 +862,7 @@ class Orchestrator {
|
|
|
806
862
|
* @returns Transaction hash bytes
|
|
807
863
|
*/
|
|
808
864
|
lockFee(amount, // USD with 8 decimals
|
|
809
|
-
universalPayload) {
|
|
865
|
+
universalPayload, req) {
|
|
810
866
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
811
867
|
const chain = this.universalSigner.account.chain;
|
|
812
868
|
const { lockerContract, vm, defaultRPC } = chain_1.CHAIN_INFO[chain];
|
|
@@ -833,23 +889,19 @@ class Orchestrator {
|
|
|
833
889
|
(nativeTokenUsdPrice - BigInt(1))) /
|
|
834
890
|
nativeTokenUsdPrice;
|
|
835
891
|
nativeAmount = nativeAmount + BigInt(1);
|
|
836
|
-
//
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
//
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
const eip712Signature = yield this.signUniversalPayload(universalPayload, ueaAddress, ueaVersion);
|
|
845
|
-
const eip712SignatureHex = typeof eip712Signature === 'string'
|
|
846
|
-
? eip712Signature
|
|
847
|
-
: (0, viem_1.bytesToHex)(eip712Signature);
|
|
892
|
+
// const req: UniversalTxRequest = {
|
|
893
|
+
// recipient: zeroAddress,
|
|
894
|
+
// token: zeroAddress,
|
|
895
|
+
// amount: BigInt(0),
|
|
896
|
+
// payload: payloadBytes,
|
|
897
|
+
// revertInstruction: revertCFG,
|
|
898
|
+
// signatureData: '0x',
|
|
899
|
+
// } as unknown as never;
|
|
848
900
|
const txHash = yield evmClient.writeContract({
|
|
849
901
|
abi: abi_1.UNIVERSAL_GATEWAY_V0,
|
|
850
902
|
address: lockerContract,
|
|
851
|
-
functionName: '
|
|
852
|
-
args: [
|
|
903
|
+
functionName: 'sendUniversalTx',
|
|
904
|
+
args: [req],
|
|
853
905
|
signer: this.universalSigner,
|
|
854
906
|
value: nativeAmount,
|
|
855
907
|
});
|
|
@@ -877,44 +929,146 @@ class Orchestrator {
|
|
|
877
929
|
const programId = new web3_js_1.PublicKey(abi_1.SVM_GATEWAY_IDL.address);
|
|
878
930
|
const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
|
|
879
931
|
const [vaultPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('vault')], programId);
|
|
932
|
+
const [rateLimitConfigPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit_config')], programId);
|
|
933
|
+
const [tokenRateLimitPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), web3_js_1.PublicKey.default.toBuffer()], programId);
|
|
880
934
|
const userPk = new web3_js_1.PublicKey(this.universalSigner.account.address);
|
|
881
935
|
const revertSvm = {
|
|
882
936
|
fundRecipient: userPk,
|
|
883
937
|
revertMsg: Buffer.from([]),
|
|
884
938
|
};
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
939
|
+
const gasReq = this._buildSvmUniversalTxRequestFromReq(req, userPk);
|
|
940
|
+
try {
|
|
941
|
+
const txHash = yield svmClient.writeContract({
|
|
942
|
+
abi: abi_1.SVM_GATEWAY_IDL,
|
|
943
|
+
address: programId.toBase58(),
|
|
944
|
+
functionName: 'sendUniversalTx',
|
|
945
|
+
args: [gasReq, nativeAmount],
|
|
946
|
+
signer: this.universalSigner,
|
|
947
|
+
accounts: {
|
|
948
|
+
config: configPda,
|
|
949
|
+
vault: vaultPda,
|
|
950
|
+
userTokenAccount: vaultPda,
|
|
951
|
+
gatewayTokenAccount: vaultPda,
|
|
952
|
+
user: userPk,
|
|
953
|
+
priceUpdate: new web3_js_1.PublicKey('7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE'),
|
|
954
|
+
rateLimitConfig: rateLimitConfigPda,
|
|
955
|
+
tokenRateLimit: tokenRateLimitPda,
|
|
956
|
+
tokenProgram: new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),
|
|
957
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
958
|
+
},
|
|
959
|
+
});
|
|
960
|
+
return new Uint8Array(anchor_1.utils.bytes.bs58.decode(txHash));
|
|
961
|
+
}
|
|
962
|
+
catch (error) {
|
|
963
|
+
console.error('Error sending UniversalTx:', error);
|
|
964
|
+
throw error;
|
|
965
|
+
}
|
|
912
966
|
}
|
|
913
967
|
default:
|
|
914
968
|
throw new Error(`Unsupported VM type: ${vm}`);
|
|
915
969
|
}
|
|
916
970
|
});
|
|
917
971
|
}
|
|
972
|
+
_buildUniversalTxRequest({ recipient, token, amount, payload, }) {
|
|
973
|
+
const revertInstruction = {
|
|
974
|
+
fundRecipient: this.universalSigner.account.address,
|
|
975
|
+
revertMsg: '0x',
|
|
976
|
+
};
|
|
977
|
+
return {
|
|
978
|
+
recipient,
|
|
979
|
+
token,
|
|
980
|
+
amount,
|
|
981
|
+
payload,
|
|
982
|
+
revertInstruction,
|
|
983
|
+
signatureData: '0x',
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
/**
|
|
987
|
+
* Builds the SVM UniversalTxRequest object from an existing EVM-style UniversalTxRequest.
|
|
988
|
+
* This allows reusing the same request shape for both EVM and SVM while only translating
|
|
989
|
+
* field encodings (addresses, bytes) to the Solana program format.
|
|
990
|
+
*/
|
|
991
|
+
_buildSvmUniversalTxRequestFromReq(req, fundRecipient, signatureDataOverride) {
|
|
992
|
+
// recipient in EVM is a 20-byte address; the SVM gateway expects this as [u8; 20]
|
|
993
|
+
const recipientBytes = (0, viem_1.hexToBytes)(req.recipient);
|
|
994
|
+
const recipient = Array.from(recipientBytes.subarray(0, 20));
|
|
995
|
+
// token in EVM is a 20-byte address. For zeroAddress or the Solana-native sentinel we map to
|
|
996
|
+
// PublicKey.default (all zeros), which mirrors the existing behavior for native SOL paths.
|
|
997
|
+
// For non-zero addresses we embed the 20-byte value into a 32-byte buffer (left-padded with
|
|
998
|
+
// zeros) to obtain a deterministic PublicKey representation.
|
|
999
|
+
const tokenAddress = req.token;
|
|
1000
|
+
let token;
|
|
1001
|
+
if (tokenAddress === viem_1.zeroAddress || tokenAddress === 'solana-native') {
|
|
1002
|
+
// Native SOL on SVM is represented by a sentinel string `solana-native` in token metadata.
|
|
1003
|
+
// The SVM gateway expects the "native" token to be encoded as the default (all-zero) Pubkey.
|
|
1004
|
+
token = web3_js_1.PublicKey.default;
|
|
1005
|
+
}
|
|
1006
|
+
else {
|
|
1007
|
+
if (!tokenAddress.startsWith('0x')) {
|
|
1008
|
+
throw new Error('Unsupported token format for SVM UniversalTxRequest: ' + tokenAddress);
|
|
1009
|
+
}
|
|
1010
|
+
const token20 = (0, viem_1.hexToBytes)(tokenAddress);
|
|
1011
|
+
const token32 = new Uint8Array(32);
|
|
1012
|
+
token32.set(token20, 12);
|
|
1013
|
+
token = new web3_js_1.PublicKey(token32);
|
|
1014
|
+
}
|
|
1015
|
+
return this._buildSvmUniversalTxRequest({
|
|
1016
|
+
recipient,
|
|
1017
|
+
token,
|
|
1018
|
+
amount: req.amount,
|
|
1019
|
+
payload: req.payload,
|
|
1020
|
+
fundRecipient,
|
|
1021
|
+
signatureData: signatureDataOverride !== null && signatureDataOverride !== void 0 ? signatureDataOverride : req.signatureData,
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Builds the SVM UniversalTxRequest object expected by the Solana gateway program.
|
|
1026
|
+
* Shape mirrors the request used in `svm-gateway` tests.
|
|
1027
|
+
*/
|
|
1028
|
+
_buildSvmUniversalTxRequest({ recipient, token, amount, payload, fundRecipient, signatureData, }) {
|
|
1029
|
+
const payloadBuf = typeof payload === 'string' && payload.startsWith('0x')
|
|
1030
|
+
? (() => {
|
|
1031
|
+
const hex = payload.slice(2);
|
|
1032
|
+
if (!hex.length)
|
|
1033
|
+
return Buffer.alloc(0);
|
|
1034
|
+
const normalized = hex.length % 2 === 1 ? `0${hex}` : hex;
|
|
1035
|
+
return Buffer.from(normalized, 'hex');
|
|
1036
|
+
})()
|
|
1037
|
+
: Buffer.from(payload);
|
|
1038
|
+
let signatureBuf;
|
|
1039
|
+
if (!signatureData) {
|
|
1040
|
+
signatureBuf = Buffer.alloc(0);
|
|
1041
|
+
}
|
|
1042
|
+
else if (typeof signatureData === 'string' &&
|
|
1043
|
+
signatureData.startsWith('0x')) {
|
|
1044
|
+
const hex = signatureData.slice(2);
|
|
1045
|
+
if (!hex.length) {
|
|
1046
|
+
signatureBuf = Buffer.alloc(0);
|
|
1047
|
+
}
|
|
1048
|
+
else {
|
|
1049
|
+
const normalized = hex.length % 2 === 1 ? `0${hex}` : hex;
|
|
1050
|
+
signatureBuf = Buffer.from(normalized, 'hex');
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
else {
|
|
1054
|
+
// vitalik
|
|
1055
|
+
// I'm testing to see if it's possible to pass 0x as signature, the same way we did for EVM.
|
|
1056
|
+
// @@@@
|
|
1057
|
+
signatureBuf = Buffer.from(signatureData);
|
|
1058
|
+
// signatureBuf = Buffer.alloc(0);
|
|
1059
|
+
}
|
|
1060
|
+
return {
|
|
1061
|
+
recipient,
|
|
1062
|
+
token,
|
|
1063
|
+
amount,
|
|
1064
|
+
payload: payloadBuf,
|
|
1065
|
+
revertInstruction: {
|
|
1066
|
+
fundRecipient,
|
|
1067
|
+
revertMsg: Buffer.alloc(0),
|
|
1068
|
+
},
|
|
1069
|
+
signatureData: signatureBuf,
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
918
1072
|
signUniversalPayload(universalPayload, verifyingContract, version) {
|
|
919
1073
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
920
1074
|
const chain = this.universalSigner.account.chain;
|
|
@@ -1111,6 +1265,118 @@ class Orchestrator {
|
|
|
1111
1265
|
// 4. Final digest
|
|
1112
1266
|
return (0, viem_1.keccak256)((0, viem_1.encodePacked)(['string', 'bytes32', 'bytes32'], ['\x19\x01', domainSeparator, structHash]));
|
|
1113
1267
|
}
|
|
1268
|
+
/**
|
|
1269
|
+
* ABI-encodes a UniversalPayload struct to bytes, matching the Solidity layout.
|
|
1270
|
+
* This mirrors abi.encode(UniversalPayload) in the EVM contracts.
|
|
1271
|
+
*/
|
|
1272
|
+
encodeUniversalPayload(payload) {
|
|
1273
|
+
return (0, viem_1.encodeAbiParameters)([
|
|
1274
|
+
{ name: 'to', type: 'address' },
|
|
1275
|
+
{ name: 'value', type: 'uint256' },
|
|
1276
|
+
{ name: 'data', type: 'bytes' },
|
|
1277
|
+
{ name: 'gasLimit', type: 'uint256' },
|
|
1278
|
+
{ name: 'maxFeePerGas', type: 'uint256' },
|
|
1279
|
+
{ name: 'maxPriorityFeePerGas', type: 'uint256' },
|
|
1280
|
+
{ name: 'nonce', type: 'uint256' },
|
|
1281
|
+
{ name: 'deadline', type: 'uint256' },
|
|
1282
|
+
{ name: 'vType', type: 'uint8' },
|
|
1283
|
+
], [
|
|
1284
|
+
payload.to,
|
|
1285
|
+
BigInt(payload.value),
|
|
1286
|
+
payload.data,
|
|
1287
|
+
BigInt(payload.gasLimit),
|
|
1288
|
+
BigInt(payload.maxFeePerGas),
|
|
1289
|
+
BigInt(payload.maxPriorityFeePerGas),
|
|
1290
|
+
BigInt(payload.nonce),
|
|
1291
|
+
BigInt(payload.deadline),
|
|
1292
|
+
Number(payload.vType),
|
|
1293
|
+
]);
|
|
1294
|
+
}
|
|
1295
|
+
/**
|
|
1296
|
+
* Encodes a UniversalPayload into Borsh bytes for the SVM universal gateway.
|
|
1297
|
+
* Layout mirrors Rust `UniversalPayload`:
|
|
1298
|
+
* to: [u8; 20],
|
|
1299
|
+
* value: u64,
|
|
1300
|
+
* data: Vec<u8> (u32 LE len + bytes),
|
|
1301
|
+
* gas_limit: u64,
|
|
1302
|
+
* max_fee_per_gas: u64,
|
|
1303
|
+
* max_priority_fee_per_gas: u64,
|
|
1304
|
+
* nonce: u64,
|
|
1305
|
+
* deadline: i64,
|
|
1306
|
+
* v_type: u8 (0 = SignedVerification, 1 = UniversalTxVerification)
|
|
1307
|
+
*/
|
|
1308
|
+
encodeUniversalPayloadSvm(payload) {
|
|
1309
|
+
const writeU64 = (val) => {
|
|
1310
|
+
const b = Buffer.alloc(8);
|
|
1311
|
+
const big = BigInt(val);
|
|
1312
|
+
b.writeBigUInt64LE(big, 0);
|
|
1313
|
+
return b;
|
|
1314
|
+
};
|
|
1315
|
+
const writeI64 = (val) => {
|
|
1316
|
+
const b = Buffer.alloc(8);
|
|
1317
|
+
const big = BigInt(val);
|
|
1318
|
+
b.writeBigInt64LE(big, 0);
|
|
1319
|
+
return b;
|
|
1320
|
+
};
|
|
1321
|
+
const writeVecU8 = (val) => {
|
|
1322
|
+
const bytes = Buffer.isBuffer(val)
|
|
1323
|
+
? val
|
|
1324
|
+
: Buffer.from(val);
|
|
1325
|
+
const len = Buffer.alloc(4);
|
|
1326
|
+
len.writeUInt32LE(bytes.length, 0);
|
|
1327
|
+
return Buffer.concat([len, bytes]);
|
|
1328
|
+
};
|
|
1329
|
+
const writeU8 = (val) => Buffer.from([val]);
|
|
1330
|
+
// 1. to: address (20 bytes)
|
|
1331
|
+
const toBytes = (() => {
|
|
1332
|
+
// EVM-style 0x-address string
|
|
1333
|
+
const to = payload.to;
|
|
1334
|
+
const hex = to.slice(2).padStart(40, '0');
|
|
1335
|
+
return Buffer.from(hex, 'hex');
|
|
1336
|
+
})();
|
|
1337
|
+
// 2. value: u64
|
|
1338
|
+
const valueBytes = writeU64(payload.value);
|
|
1339
|
+
// 3. data: bytes -> Vec<u8>
|
|
1340
|
+
const dataBytes = (() => {
|
|
1341
|
+
const data = payload.data;
|
|
1342
|
+
const hex = data.slice(2);
|
|
1343
|
+
const buf = hex.length ? Buffer.from(hex, 'hex') : Buffer.alloc(0);
|
|
1344
|
+
return writeVecU8(buf);
|
|
1345
|
+
})();
|
|
1346
|
+
// 4. gasLimit: u64
|
|
1347
|
+
const gasLimitBytes = writeU64(payload.gasLimit);
|
|
1348
|
+
// 5. maxFeePerGas: u64
|
|
1349
|
+
const maxFeePerGasBytes = writeU64(payload.maxFeePerGas);
|
|
1350
|
+
// 6. maxPriorityFeePerGas: u64
|
|
1351
|
+
const maxPriorityFeePerGasBytes = writeU64(payload.maxPriorityFeePerGas);
|
|
1352
|
+
// 7. nonce: u64
|
|
1353
|
+
const nonceBytes = writeU64(payload.nonce);
|
|
1354
|
+
// 8. deadline: i64
|
|
1355
|
+
const deadlineBytes = writeI64(payload.deadline);
|
|
1356
|
+
// 9. vType: u8
|
|
1357
|
+
const vTypeVal = (() => {
|
|
1358
|
+
// When coming from EVM, vType is numeric (0/1) in most paths
|
|
1359
|
+
const v = payload.vType;
|
|
1360
|
+
if (typeof v === 'number')
|
|
1361
|
+
return v;
|
|
1362
|
+
if (typeof v === 'string')
|
|
1363
|
+
return Number(v);
|
|
1364
|
+
// Fallback: treat anything else as SignedVerification
|
|
1365
|
+
return 0;
|
|
1366
|
+
})();
|
|
1367
|
+
const vTypeBytes = writeU8(vTypeVal);
|
|
1368
|
+
return Buffer.concat([
|
|
1369
|
+
toBytes,
|
|
1370
|
+
valueBytes,
|
|
1371
|
+
dataBytes,
|
|
1372
|
+
gasLimitBytes,
|
|
1373
|
+
maxFeePerGasBytes,
|
|
1374
|
+
maxPriorityFeePerGasBytes,
|
|
1375
|
+
nonceBytes,
|
|
1376
|
+
deadlineBytes,
|
|
1377
|
+
vTypeBytes,
|
|
1378
|
+
]);
|
|
1379
|
+
}
|
|
1114
1380
|
/**
|
|
1115
1381
|
* Computes UEA for given UniversalAccount
|
|
1116
1382
|
* @dev - This fn calls a view fn of Factory Contract
|
|
@@ -1195,7 +1461,7 @@ class Orchestrator {
|
|
|
1195
1461
|
return (selector + encodedCalls.slice(2));
|
|
1196
1462
|
}
|
|
1197
1463
|
_sendSVMTxWithFunds(_a) {
|
|
1198
|
-
return tslib_1.__awaiter(this, arguments, void 0, function* ({ execute, mechanism, universalPayload, bridgeAmount, nativeAmount, }) {
|
|
1464
|
+
return tslib_1.__awaiter(this, arguments, void 0, function* ({ execute, mechanism, universalPayload, bridgeAmount, nativeAmount, req, }) {
|
|
1199
1465
|
var _b, _c, _d, _e;
|
|
1200
1466
|
// SVM funds+payload path
|
|
1201
1467
|
const svmClient = new svm_client_1.SvmClient({
|
|
@@ -1205,9 +1471,9 @@ class Orchestrator {
|
|
|
1205
1471
|
const programId = new web3_js_1.PublicKey(abi_1.SVM_GATEWAY_IDL.address);
|
|
1206
1472
|
const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
|
|
1207
1473
|
const [vaultPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('vault')], programId);
|
|
1208
|
-
// whitelistPda already computed above
|
|
1209
1474
|
const userPk = new web3_js_1.PublicKey(this.universalSigner.account.address);
|
|
1210
1475
|
const priceUpdatePk = new web3_js_1.PublicKey('7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE');
|
|
1476
|
+
const [rateLimitConfigPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit_config')], programId);
|
|
1211
1477
|
// pay-with-token gas abstraction is not supported on Solana
|
|
1212
1478
|
if (execute.payGasWith !== undefined) {
|
|
1213
1479
|
throw new Error('Pay-with token is not supported on Solana');
|
|
@@ -1227,29 +1493,32 @@ class Orchestrator {
|
|
|
1227
1493
|
if (isNative) {
|
|
1228
1494
|
// Native SOL as bridge + gas
|
|
1229
1495
|
const [whitelistPdaLocal] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('whitelist')], programId);
|
|
1496
|
+
const [tokenRateLimitPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), web3_js_1.PublicKey.default.toBuffer()], programId);
|
|
1497
|
+
const nativeReq = this._buildSvmUniversalTxRequest({
|
|
1498
|
+
recipient: Array.from(Buffer.alloc(20, 0)),
|
|
1499
|
+
token: web3_js_1.PublicKey.default,
|
|
1500
|
+
amount: bridgeAmount,
|
|
1501
|
+
payload: Uint8Array.from(this.encodeUniversalPayloadSvm(universalPayload)),
|
|
1502
|
+
fundRecipient: userPk,
|
|
1503
|
+
signatureData: svmSignature,
|
|
1504
|
+
});
|
|
1230
1505
|
return yield svmClient.writeContract({
|
|
1231
1506
|
abi: abi_1.SVM_GATEWAY_IDL,
|
|
1232
1507
|
address: programId.toBase58(),
|
|
1233
|
-
functionName: '
|
|
1234
|
-
args: [
|
|
1235
|
-
web3_js_1.PublicKey.default, // bridge_token = default for native SOL
|
|
1236
|
-
bridgeAmount,
|
|
1237
|
-
universalPayload,
|
|
1238
|
-
revertSvm2,
|
|
1239
|
-
nativeAmount,
|
|
1240
|
-
Buffer.from(svmSignature),
|
|
1241
|
-
],
|
|
1508
|
+
functionName: 'sendUniversalTx',
|
|
1509
|
+
args: [nativeReq, nativeAmount],
|
|
1242
1510
|
signer: this.universalSigner,
|
|
1243
1511
|
accounts: {
|
|
1244
1512
|
config: configPda,
|
|
1245
1513
|
vault: vaultPda,
|
|
1246
1514
|
tokenWhitelist: whitelistPdaLocal,
|
|
1247
|
-
userTokenAccount:
|
|
1248
|
-
gatewayTokenAccount: vaultPda, // for native SOL
|
|
1515
|
+
userTokenAccount: vaultPda, // dummy for native SOL
|
|
1516
|
+
gatewayTokenAccount: vaultPda, // dummy for native SOL
|
|
1249
1517
|
user: userPk,
|
|
1250
1518
|
priceUpdate: priceUpdatePk,
|
|
1251
|
-
bridgeToken: web3_js_1.PublicKey.default,
|
|
1252
1519
|
tokenProgram: new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),
|
|
1520
|
+
rateLimitConfig: rateLimitConfigPda,
|
|
1521
|
+
tokenRateLimit: tokenRateLimitPda,
|
|
1253
1522
|
systemProgram: web3_js_1.SystemProgram.programId,
|
|
1254
1523
|
},
|
|
1255
1524
|
});
|
|
@@ -1265,18 +1534,20 @@ class Orchestrator {
|
|
|
1265
1534
|
const userAta = web3_js_1.PublicKey.findProgramAddressSync([userPk.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mintPk.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID)[0];
|
|
1266
1535
|
const vaultAta = web3_js_1.PublicKey.findProgramAddressSync([vaultPda.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mintPk.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID)[0];
|
|
1267
1536
|
const [whitelistPdaLocal] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('whitelist')], programId);
|
|
1537
|
+
const [tokenRateLimitPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), mintPk.toBuffer()], programId);
|
|
1538
|
+
const splReq = this._buildSvmUniversalTxRequest({
|
|
1539
|
+
recipient: Array.from(Buffer.alloc(20, 0)),
|
|
1540
|
+
token: mintPk,
|
|
1541
|
+
amount: bridgeAmount,
|
|
1542
|
+
payload: Uint8Array.from(this.encodeUniversalPayloadSvm(universalPayload)),
|
|
1543
|
+
fundRecipient: userPk,
|
|
1544
|
+
signatureData: svmSignature,
|
|
1545
|
+
});
|
|
1268
1546
|
return yield svmClient.writeContract({
|
|
1269
1547
|
abi: abi_1.SVM_GATEWAY_IDL,
|
|
1270
1548
|
address: programId.toBase58(),
|
|
1271
|
-
functionName: '
|
|
1272
|
-
args: [
|
|
1273
|
-
mintPk,
|
|
1274
|
-
bridgeAmount,
|
|
1275
|
-
universalPayload,
|
|
1276
|
-
revertSvm2,
|
|
1277
|
-
nativeAmount,
|
|
1278
|
-
Buffer.from(svmSignature),
|
|
1279
|
-
],
|
|
1549
|
+
functionName: 'sendUniversalTx',
|
|
1550
|
+
args: [splReq, nativeAmount],
|
|
1280
1551
|
signer: this.universalSigner,
|
|
1281
1552
|
accounts: {
|
|
1282
1553
|
config: configPda,
|
|
@@ -1286,8 +1557,9 @@ class Orchestrator {
|
|
|
1286
1557
|
gatewayTokenAccount: vaultAta,
|
|
1287
1558
|
user: userPk,
|
|
1288
1559
|
priceUpdate: priceUpdatePk,
|
|
1289
|
-
bridgeToken: mintPk,
|
|
1290
1560
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1561
|
+
rateLimitConfig: rateLimitConfigPda,
|
|
1562
|
+
tokenRateLimit: tokenRateLimitPda,
|
|
1291
1563
|
systemProgram: web3_js_1.SystemProgram.programId,
|
|
1292
1564
|
},
|
|
1293
1565
|
});
|
|
@@ -1397,6 +1669,40 @@ class Orchestrator {
|
|
|
1397
1669
|
}
|
|
1398
1670
|
});
|
|
1399
1671
|
}
|
|
1672
|
+
/**
|
|
1673
|
+
* Internal helper: fetches the full origin-chain transaction for a given hash,
|
|
1674
|
+
* used only for progress-hook context (EVM or Solana).
|
|
1675
|
+
*/
|
|
1676
|
+
fetchOriginChainTransactionForProgress(chain, txHashHex, txHashDisplay) {
|
|
1677
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
1678
|
+
const { vm, defaultRPC } = chain_1.CHAIN_INFO[chain];
|
|
1679
|
+
const rpcUrls = this.rpcUrls[chain] || defaultRPC;
|
|
1680
|
+
try {
|
|
1681
|
+
if (vm === enums_1.VM.EVM) {
|
|
1682
|
+
if (!txHashHex.startsWith('0x')) {
|
|
1683
|
+
throw new Error('EVM transaction hash must be 0x-prefixed');
|
|
1684
|
+
}
|
|
1685
|
+
const evmClient = new evm_client_1.EvmClient({ rpcUrls });
|
|
1686
|
+
const tx = yield evmClient.publicClient.getTransaction({
|
|
1687
|
+
hash: txHashHex,
|
|
1688
|
+
});
|
|
1689
|
+
return tx !== null && tx !== void 0 ? tx : undefined;
|
|
1690
|
+
}
|
|
1691
|
+
if (vm === enums_1.VM.SVM) {
|
|
1692
|
+
const connection = new web3_js_1.Connection(rpcUrls[0], 'confirmed');
|
|
1693
|
+
const tx = yield connection.getTransaction(txHashDisplay, {
|
|
1694
|
+
maxSupportedTransactionVersion: 0,
|
|
1695
|
+
commitment: 'confirmed',
|
|
1696
|
+
});
|
|
1697
|
+
return tx !== null && tx !== void 0 ? tx : undefined;
|
|
1698
|
+
}
|
|
1699
|
+
return undefined;
|
|
1700
|
+
}
|
|
1701
|
+
catch (_a) {
|
|
1702
|
+
return undefined;
|
|
1703
|
+
}
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1400
1706
|
/**
|
|
1401
1707
|
* Quotes exact-output on Uniswap V3 for EVM origin chains using QuoterV2.
|
|
1402
1708
|
* Returns the minimum required input (amountIn) to receive the target amountOut.
|
|
@@ -1623,7 +1929,7 @@ class Orchestrator {
|
|
|
1623
1929
|
*/
|
|
1624
1930
|
buildGatewayPayloadAndGas(execute, nonce, type, fundsValue) {
|
|
1625
1931
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
1626
|
-
var _a, _b, _c, _d, _e;
|
|
1932
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
1627
1933
|
const gasEstimate = execute.gasLimit || BigInt(1e7);
|
|
1628
1934
|
const gasAmount = (_a = execute.value) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
1629
1935
|
if (type === 'sendTxWithFunds') {
|
|
@@ -1646,7 +1952,19 @@ class Orchestrator {
|
|
|
1646
1952
|
deadline: execute.deadline || BigInt(9999999999),
|
|
1647
1953
|
vType: tx_1.VerificationType.universalTxVerification,
|
|
1648
1954
|
};
|
|
1649
|
-
|
|
1955
|
+
// Temporary while we don't change the native address from 0xeee... to 0x0000...
|
|
1956
|
+
let tokenAddress = (_f = (_e = execute.funds) === null || _e === void 0 ? void 0 : _e.token) === null || _f === void 0 ? void 0 : _f.address;
|
|
1957
|
+
if (((_h = (_g = execute.funds) === null || _g === void 0 ? void 0 : _g.token) === null || _h === void 0 ? void 0 : _h.address) ===
|
|
1958
|
+
'0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee') {
|
|
1959
|
+
tokenAddress = viem_1.zeroAddress;
|
|
1960
|
+
}
|
|
1961
|
+
const req = this._buildUniversalTxRequest({
|
|
1962
|
+
recipient: viem_1.zeroAddress,
|
|
1963
|
+
token: tokenAddress,
|
|
1964
|
+
amount: (_j = execute.funds) === null || _j === void 0 ? void 0 : _j.amount,
|
|
1965
|
+
payload: this.encodeUniversalPayload(universalPayload),
|
|
1966
|
+
});
|
|
1967
|
+
return { payload: universalPayload, gasAmount, req };
|
|
1650
1968
|
}
|
|
1651
1969
|
else {
|
|
1652
1970
|
if (!fundsValue)
|
|
@@ -1662,12 +1980,12 @@ class Orchestrator {
|
|
|
1662
1980
|
// functionName: 'transfer',
|
|
1663
1981
|
// args: [execute.to, fundsValue],
|
|
1664
1982
|
// });
|
|
1665
|
-
// const pushChainTo = PushChain.utils.tokens.
|
|
1983
|
+
// const pushChainTo = PushChain.utils.tokens.getPRC20Address(
|
|
1666
1984
|
// execute.funds!.token as MoveableToken
|
|
1667
1985
|
// );
|
|
1668
1986
|
const universalPayload = {
|
|
1669
1987
|
to: viem_1.zeroAddress, // We can't simply do `0x` because we will get an error when eip712 signing the transaction.
|
|
1670
|
-
value: (
|
|
1988
|
+
value: (_k = execute.value) !== null && _k !== void 0 ? _k : BigInt(0),
|
|
1671
1989
|
data: this._buildMulticallPayloadData(execute.to, multicallData),
|
|
1672
1990
|
// data: this._buildMulticallPayloadData(execute.to, [
|
|
1673
1991
|
// { to: pushChainTo, value: execute.value ?? BigInt(0), data },
|
|
@@ -1679,7 +1997,19 @@ class Orchestrator {
|
|
|
1679
1997
|
deadline: execute.deadline || BigInt(9999999999),
|
|
1680
1998
|
vType: tx_1.VerificationType.universalTxVerification,
|
|
1681
1999
|
};
|
|
1682
|
-
|
|
2000
|
+
// Temporary while we don't change the native address from 0xeee... to 0x0000...
|
|
2001
|
+
let tokenAddress = (_m = (_l = execute.funds) === null || _l === void 0 ? void 0 : _l.token) === null || _m === void 0 ? void 0 : _m.address;
|
|
2002
|
+
if (((_p = (_o = execute.funds) === null || _o === void 0 ? void 0 : _o.token) === null || _p === void 0 ? void 0 : _p.address) ===
|
|
2003
|
+
'0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee') {
|
|
2004
|
+
tokenAddress = viem_1.zeroAddress;
|
|
2005
|
+
}
|
|
2006
|
+
const req = this._buildUniversalTxRequest({
|
|
2007
|
+
recipient: viem_1.zeroAddress,
|
|
2008
|
+
token: tokenAddress,
|
|
2009
|
+
amount: (_q = execute.funds) === null || _q === void 0 ? void 0 : _q.amount,
|
|
2010
|
+
payload: this.encodeUniversalPayload(universalPayload),
|
|
2011
|
+
});
|
|
2012
|
+
return { payload: universalPayload, gasAmount, req };
|
|
1683
2013
|
}
|
|
1684
2014
|
});
|
|
1685
2015
|
}
|
|
@@ -1910,6 +2240,8 @@ class Orchestrator {
|
|
|
1910
2240
|
if (!Array.isArray(logs) || logs.length === 0)
|
|
1911
2241
|
return 0;
|
|
1912
2242
|
const prefix = 'Program data: ';
|
|
2243
|
+
let matchCount = 0;
|
|
2244
|
+
let lastMatchIndex = -1;
|
|
1913
2245
|
for (let i = 0; i < logs.length; i++) {
|
|
1914
2246
|
const log = logs[i] || '';
|
|
1915
2247
|
if (!log.startsWith(prefix))
|
|
@@ -1925,12 +2257,19 @@ class Orchestrator {
|
|
|
1925
2257
|
if (!decoded || decoded.length < 8)
|
|
1926
2258
|
continue;
|
|
1927
2259
|
const discriminatorHex = (0, viem_1.bytesToHex)(decoded.slice(0, 8)).slice(2);
|
|
1928
|
-
// Skip add_funds discriminator; return the
|
|
2260
|
+
// Skip add_funds discriminator; return the second matching Program data event
|
|
1929
2261
|
// if (discriminatorHex === '7f1f6cffbb134644') continue;
|
|
1930
|
-
if (discriminatorHex === '6c9ad829b5ea1d7c')
|
|
1931
|
-
|
|
2262
|
+
if (discriminatorHex === '6c9ad829b5ea1d7c') {
|
|
2263
|
+
matchCount++;
|
|
2264
|
+
lastMatchIndex = i;
|
|
2265
|
+
if (matchCount === 2)
|
|
2266
|
+
return i;
|
|
2267
|
+
}
|
|
1932
2268
|
// return i;
|
|
1933
2269
|
}
|
|
2270
|
+
// If only one match was found, keep previous behavior and return that one.
|
|
2271
|
+
if (lastMatchIndex !== -1)
|
|
2272
|
+
return lastMatchIndex;
|
|
1934
2273
|
// Fallback to first log
|
|
1935
2274
|
return 0;
|
|
1936
2275
|
}
|
|
@@ -2013,25 +2352,9 @@ class Orchestrator {
|
|
|
2013
2352
|
}
|
|
2014
2353
|
yield new Promise((r) => setTimeout(r, 1500));
|
|
2015
2354
|
}
|
|
2016
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_06, (universalTxObj === null || universalTxObj === void 0 ? void 0 : universalTxObj.universalStatus) || (universalTxObj === null || universalTxObj === void 0 ? void 0 : universalTxObj.universal_status));
|
|
2017
|
-
// this.printLog(
|
|
2018
|
-
// `UniversalTx fetched via gRPC: ${JSON.stringify(
|
|
2019
|
-
// {
|
|
2020
|
-
// gatewayTx: txHashHex,
|
|
2021
|
-
// id: idHex,
|
|
2022
|
-
// status:
|
|
2023
|
-
// universalTxObj?.universalStatus ||
|
|
2024
|
-
// universalTxObj?.universal_status,
|
|
2025
|
-
// },
|
|
2026
|
-
// this.bigintReplacer,
|
|
2027
|
-
// 2
|
|
2028
|
-
// )}`
|
|
2029
|
-
// );
|
|
2030
2355
|
return universalTxObj;
|
|
2031
2356
|
}
|
|
2032
2357
|
catch (_d) {
|
|
2033
|
-
// Best-effort; do not fail flow if PC query is unavailable
|
|
2034
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_06);
|
|
2035
2358
|
return undefined;
|
|
2036
2359
|
}
|
|
2037
2360
|
});
|
|
@@ -2057,7 +2380,7 @@ class Orchestrator {
|
|
|
2057
2380
|
if (currentBlock >= targetBlock) {
|
|
2058
2381
|
// Only emit if we haven't already shown this confirmation
|
|
2059
2382
|
if (lastEmitted < confirmations) {
|
|
2060
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.
|
|
2383
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_03_02, confirmations, confirmations);
|
|
2061
2384
|
}
|
|
2062
2385
|
return;
|
|
2063
2386
|
}
|
|
@@ -2065,7 +2388,9 @@ class Orchestrator {
|
|
|
2065
2388
|
const completed = Math.max(1, confirmations - remaining + 1);
|
|
2066
2389
|
// Only emit if this is a new confirmation count
|
|
2067
2390
|
if (completed > lastEmitted) {
|
|
2068
|
-
this.executeProgressHook(
|
|
2391
|
+
this.executeProgressHook(completed >= confirmations
|
|
2392
|
+
? progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_03_02
|
|
2393
|
+
: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_03_01, completed, confirmations);
|
|
2069
2394
|
lastEmitted = completed;
|
|
2070
2395
|
// If we've reached required confirmations, we're done
|
|
2071
2396
|
if (completed >= confirmations) {
|
|
@@ -2082,7 +2407,6 @@ class Orchestrator {
|
|
|
2082
2407
|
// Emit countdown updates while waiting for SVM confirmations
|
|
2083
2408
|
waitForSvmConfirmationsWithCountdown(svmClient, txSignature, confirmations, timeoutMs) {
|
|
2084
2409
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
2085
|
-
var _a;
|
|
2086
2410
|
// initial emit
|
|
2087
2411
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_03, confirmations);
|
|
2088
2412
|
const start = Date.now();
|
|
@@ -2094,19 +2418,35 @@ class Orchestrator {
|
|
|
2094
2418
|
const { value } = yield connection.getSignatureStatuses([txSignature]);
|
|
2095
2419
|
const status = value[0];
|
|
2096
2420
|
if (status) {
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2421
|
+
// Surface transaction failures explicitly
|
|
2422
|
+
if (status.err) {
|
|
2423
|
+
throw new Error(`SVM transaction ${txSignature} failed: ${JSON.stringify(status.err)}`);
|
|
2424
|
+
}
|
|
2425
|
+
const rawConfirmations = status.confirmations;
|
|
2426
|
+
const hasNumericConfirmations = rawConfirmations != null;
|
|
2427
|
+
const currentConfirms = hasNumericConfirmations ? rawConfirmations : 0;
|
|
2428
|
+
// Align "finalized" semantics with SvmClient.waitForConfirmations:
|
|
2429
|
+
// treat either an explicit "finalized" status or a rooted tx
|
|
2430
|
+
// (confirmations === null) with no error as final.
|
|
2431
|
+
const isFinalized = status.err === null &&
|
|
2432
|
+
(status.confirmationStatus === 'finalized' ||
|
|
2433
|
+
status.confirmations === null);
|
|
2434
|
+
const hasEnoughConfirmations = hasNumericConfirmations && currentConfirms >= confirmations;
|
|
2435
|
+
// Emit progress only when the visible confirmation count increases.
|
|
2436
|
+
// We never "jump" straight to the requested confirmations unless
|
|
2437
|
+
// we're finalizing and haven't yet emitted a final step.
|
|
2438
|
+
if (currentConfirms > lastConfirmed) {
|
|
2439
|
+
const clamped = currentConfirms >= confirmations ? confirmations : currentConfirms;
|
|
2440
|
+
this.executeProgressHook(clamped >= confirmations
|
|
2441
|
+
? progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_03_02
|
|
2442
|
+
: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_03_01, Math.max(1, clamped), confirmations);
|
|
2107
2443
|
lastConfirmed = currentConfirms;
|
|
2108
2444
|
}
|
|
2109
|
-
if (hasEnoughConfirmations ||
|
|
2445
|
+
if (hasEnoughConfirmations || isFinalized) {
|
|
2446
|
+
// Ensure we emit a final "all confirmations" step if we haven't yet.
|
|
2447
|
+
if (lastConfirmed < confirmations) {
|
|
2448
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_03_02, confirmations, confirmations);
|
|
2449
|
+
}
|
|
2110
2450
|
return;
|
|
2111
2451
|
}
|
|
2112
2452
|
}
|
|
@@ -2185,6 +2525,7 @@ class Orchestrator {
|
|
|
2185
2525
|
calculateNativeAmountForDeposit(chain, requiredFunds, ueaBalance) {
|
|
2186
2526
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
2187
2527
|
var _a, _b;
|
|
2528
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_01);
|
|
2188
2529
|
// Determine USD to deposit via gateway (8 decimals) with caps: min=$1, max=$10
|
|
2189
2530
|
const oneUsd = push_chain_1.PushChain.utils.helpers.parseUnits('1', 8);
|
|
2190
2531
|
const tenUsd = push_chain_1.PushChain.utils.helpers.parseUnits('10', 8);
|
|
@@ -2194,7 +2535,6 @@ class Orchestrator {
|
|
|
2194
2535
|
depositUsd = oneUsd;
|
|
2195
2536
|
if (depositUsd > tenUsd)
|
|
2196
2537
|
throw new Error('Deposit value exceeds max $10 worth of native token');
|
|
2197
|
-
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_02, depositUsd);
|
|
2198
2538
|
// If SVM, clamp depositUsd to on-chain Config caps
|
|
2199
2539
|
if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM) {
|
|
2200
2540
|
const svmClient = new svm_client_1.SvmClient({
|
|
@@ -2236,6 +2576,7 @@ class Orchestrator {
|
|
|
2236
2576
|
nativeTokenUsdPrice;
|
|
2237
2577
|
// Add 1 unit safety to avoid BelowMinCap from rounding differences
|
|
2238
2578
|
nativeAmount = nativeAmount + BigInt(1);
|
|
2579
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_02, nativeAmount);
|
|
2239
2580
|
return nativeAmount;
|
|
2240
2581
|
});
|
|
2241
2582
|
}
|