@pushchain/core 2.1.5 → 2.1.7-alpha-v0
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 +4 -3
- package/src/lib/constants/abi/erc20.evm.d.ts +33 -0
- package/src/lib/constants/abi/erc20.evm.js +19 -0
- package/src/lib/constants/abi/erc20.evm.js.map +1 -1
- package/src/lib/constants/abi/universalGatewayV0.evm.d.ts +48 -1
- package/src/lib/constants/abi/universalGatewayV0.evm.js +1061 -29
- package/src/lib/constants/abi/universalGatewayV0.evm.js.map +1 -1
- package/src/lib/constants/abi/universalGatewayV0.json +1223 -206
- package/src/lib/constants/chain.d.ts +0 -2
- package/src/lib/constants/chain.js +2 -10
- package/src/lib/constants/chain.js.map +1 -1
- package/src/lib/constants/tokens.d.ts +1 -2
- package/src/lib/constants/tokens.js +119 -103
- package/src/lib/constants/tokens.js.map +1 -1
- package/src/lib/generated/v1/tx.d.ts +1 -2
- package/src/lib/generated/v1/tx.js +2 -1
- package/src/lib/generated/v1/tx.js.map +1 -1
- package/src/lib/orchestrator/orchestrator.d.ts +4 -2
- package/src/lib/orchestrator/orchestrator.js +393 -66
- package/src/lib/orchestrator/orchestrator.js.map +1 -1
- package/src/lib/vm-client/svm-client.js +24 -3
- package/src/lib/vm-client/svm-client.js.map +1 -1
|
@@ -138,16 +138,48 @@ class Orchestrator {
|
|
|
138
138
|
const bridgeToken = execute.funds.token.mechanism === 'approve'
|
|
139
139
|
? tokenAddr
|
|
140
140
|
: '0x0000000000000000000000000000000000000000';
|
|
141
|
+
const { nonce } = yield this.getUeaStatusAndNonce();
|
|
142
|
+
const { payload: universalPayload } = yield this.buildGatewayPayloadAndGas(execute, nonce, 'sendFunds', bridgeAmount);
|
|
143
|
+
// Get UEA info
|
|
144
|
+
const ueaAddress = this.computeUEAOffchain();
|
|
145
|
+
const ueaVersion = yield this.fetchUEAVersion();
|
|
146
|
+
const eip712Signature = yield this.signUniversalPayload(universalPayload, ueaAddress, ueaVersion);
|
|
147
|
+
const eip712SignatureHex = (0, viem_1.bytesToHex)(eip712Signature);
|
|
141
148
|
let txHash;
|
|
142
149
|
try {
|
|
150
|
+
// Compute minimal native amount to deposit for gas on Push Chain
|
|
151
|
+
const ueaAddressForGas = this.computeUEAOffchain();
|
|
152
|
+
const ueaBalanceForGas = yield this.pushClient.getBalance(ueaAddressForGas);
|
|
153
|
+
const nativeAmount = yield this.calculateNativeAmountForDeposit(chain, BigInt(0), ueaBalanceForGas);
|
|
154
|
+
console.log([
|
|
155
|
+
tokenAddr,
|
|
156
|
+
bridgeAmount,
|
|
157
|
+
universalPayload,
|
|
158
|
+
revertCFG,
|
|
159
|
+
'0x',
|
|
160
|
+
]);
|
|
143
161
|
txHash = yield evmClient.writeContract({
|
|
144
162
|
abi: abi_1.UNIVERSAL_GATEWAY_V0,
|
|
145
163
|
address: gatewayAddress,
|
|
146
|
-
functionName: '
|
|
147
|
-
args: [
|
|
164
|
+
functionName: 'sendTxWithFunds',
|
|
165
|
+
args: [
|
|
166
|
+
tokenAddr,
|
|
167
|
+
bridgeAmount,
|
|
168
|
+
universalPayload,
|
|
169
|
+
revertCFG,
|
|
170
|
+
'0x',
|
|
171
|
+
],
|
|
148
172
|
signer: this.universalSigner,
|
|
149
|
-
value:
|
|
173
|
+
value: nativeAmount,
|
|
150
174
|
});
|
|
175
|
+
// txHash = await evmClient.writeContract({
|
|
176
|
+
// abi: UNIVERSAL_GATEWAY_V0 as unknown as Abi,
|
|
177
|
+
// address: gatewayAddress,
|
|
178
|
+
// functionName: 'sendFunds',
|
|
179
|
+
// args: [recipient, bridgeToken, bridgeAmount, revertCFG],
|
|
180
|
+
// signer: this.universalSigner,
|
|
181
|
+
// value: isNative ? bridgeAmount : BigInt(0),
|
|
182
|
+
// });
|
|
151
183
|
}
|
|
152
184
|
catch (err) {
|
|
153
185
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_04_04);
|
|
@@ -333,7 +365,7 @@ class Orchestrator {
|
|
|
333
365
|
}
|
|
334
366
|
const mechanism = execute.funds.token.mechanism;
|
|
335
367
|
const { deployed, nonce } = yield this.getUeaStatusAndNonce();
|
|
336
|
-
const { payload: universalPayload } = yield this.buildGatewayPayloadAndGas(execute, nonce);
|
|
368
|
+
const { payload: universalPayload } = yield this.buildGatewayPayloadAndGas(execute, nonce, 'sendTxWithFunds');
|
|
337
369
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_01);
|
|
338
370
|
// Compute required gas funding on Push Chain and current UEA balance
|
|
339
371
|
const gasEstimate = execute.gasLimit || BigInt(1e7);
|
|
@@ -434,6 +466,21 @@ class Orchestrator {
|
|
|
434
466
|
: (0, viem_1.bytesToHex)(eip712Signature);
|
|
435
467
|
const evmClientEvm = evmClient;
|
|
436
468
|
const gatewayAddressEvm = gatewayAddress;
|
|
469
|
+
// @@@@@@@@@@@@
|
|
470
|
+
// txHash = await evmClientEvm.writeContract({
|
|
471
|
+
// abi: UNIVERSAL_GATEWAY_V0 as unknown as Abi,
|
|
472
|
+
// address: gatewayAddressEvm,
|
|
473
|
+
// functionName: 'sendTxWithFunds',
|
|
474
|
+
// args: [
|
|
475
|
+
// tokenAddr,
|
|
476
|
+
// bridgeAmount,
|
|
477
|
+
// universalPayload,
|
|
478
|
+
// revertCFG,
|
|
479
|
+
// '0x',
|
|
480
|
+
// ],
|
|
481
|
+
// signer: this.universalSigner,
|
|
482
|
+
// value: nativeAmount,
|
|
483
|
+
// });
|
|
437
484
|
// New behavior: if user provided a gasTokenAddress, pay gas in that token via Uniswap quote
|
|
438
485
|
// Determine pay-with token address, min-out and slippage
|
|
439
486
|
const payWith = execute.funds.payWith;
|
|
@@ -479,7 +526,7 @@ class Orchestrator {
|
|
|
479
526
|
deadline,
|
|
480
527
|
universalPayload,
|
|
481
528
|
revertCFG,
|
|
482
|
-
|
|
529
|
+
'0x',
|
|
483
530
|
],
|
|
484
531
|
signer: this.universalSigner,
|
|
485
532
|
});
|
|
@@ -495,7 +542,7 @@ class Orchestrator {
|
|
|
495
542
|
bridgeAmount,
|
|
496
543
|
universalPayload,
|
|
497
544
|
revertCFG,
|
|
498
|
-
|
|
545
|
+
'0x',
|
|
499
546
|
],
|
|
500
547
|
signer: this.universalSigner,
|
|
501
548
|
value: nativeAmount,
|
|
@@ -760,7 +807,7 @@ class Orchestrator {
|
|
|
760
807
|
to: payloadTo,
|
|
761
808
|
value: execute.value,
|
|
762
809
|
data: payloadData,
|
|
763
|
-
gasLimit: execute.gasLimit || BigInt(
|
|
810
|
+
gasLimit: execute.gasLimit || BigInt(5e7),
|
|
764
811
|
maxFeePerGas: execute.maxFeePerGas || BigInt(1e10),
|
|
765
812
|
maxPriorityFeePerGas: execute.maxPriorityFeePerGas || BigInt(0),
|
|
766
813
|
nonce,
|
|
@@ -796,28 +843,101 @@ class Orchestrator {
|
|
|
796
843
|
}
|
|
797
844
|
else {
|
|
798
845
|
/**
|
|
799
|
-
* Fee Locking
|
|
846
|
+
* Fee Locking - For all chains, EVM and Solana
|
|
800
847
|
*/
|
|
801
848
|
const fundDifference = requiredFunds - funds;
|
|
802
849
|
const fixedPushAmount = push_chain_1.PushChain.utils.helpers.parseUnits('0.001', 18); // Minimum lock 0.001 Push tokens
|
|
803
850
|
const lockAmount = funds < requiredFunds ? fundDifference : fixedPushAmount;
|
|
804
851
|
const lockAmountInUSD = this.pushClient.pushToUSDC(lockAmount);
|
|
805
852
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_05_01, lockAmount);
|
|
806
|
-
const feeLockTxHashBytes = yield this.lockFee(lockAmountInUSD,
|
|
853
|
+
const feeLockTxHashBytes = yield this.lockFee(lockAmountInUSD, universalPayload);
|
|
807
854
|
feeLockTxHash = (0, viem_1.bytesToHex)(feeLockTxHashBytes);
|
|
808
855
|
verificationData = (0, viem_1.bytesToHex)(feeLockTxHashBytes);
|
|
809
|
-
/**
|
|
810
|
-
* Waiting for Confirmations
|
|
811
|
-
*/
|
|
812
856
|
const { vm } = chain_1.CHAIN_INFO[chain];
|
|
813
857
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_05_02, vm === enums_1.VM.SVM
|
|
814
858
|
? anchor_1.utils.bytes.bs58.encode(feeLockTxHashBytes)
|
|
815
859
|
: feeLockTxHash, chain_1.CHAIN_INFO[chain].confirmations);
|
|
860
|
+
// Waiting for blocks confirmations
|
|
816
861
|
yield this.waitForLockerFeeConfirmation(feeLockTxHashBytes);
|
|
817
862
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_05_03);
|
|
863
|
+
// Query nodes via gRPC for Push Chain transaction
|
|
864
|
+
const { defaultRPC, lockerContract } = chain_1.CHAIN_INFO[chain];
|
|
865
|
+
yield this.queryUniversalTxStatusFromGatewayTx(new evm_client_1.EvmClient({ rpcUrls: this.rpcUrls[chain] || defaultRPC }), lockerContract, feeLockTxHash, 'sendTxWithGas');
|
|
866
|
+
/**
|
|
867
|
+
* Return response directly (skip sendUniversalTx for sendTxWithGas flow)
|
|
868
|
+
* Note: queryTx may be undefined since validators don't recognize new UniversalTx event yet
|
|
869
|
+
*/
|
|
870
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06);
|
|
871
|
+
// Transform to UniversalTxResponse (follow sendFunds pattern)
|
|
872
|
+
if (vm === enums_1.VM.EVM) {
|
|
873
|
+
// Get EVM transaction for full response
|
|
874
|
+
const evmClient = new evm_client_1.EvmClient({
|
|
875
|
+
rpcUrls: this.rpcUrls[chain] || chain_1.CHAIN_INFO[chain].defaultRPC,
|
|
876
|
+
});
|
|
877
|
+
const tx = yield evmClient.getTransaction(feeLockTxHash);
|
|
878
|
+
const response = yield this.transformToUniversalTxResponse(tx);
|
|
879
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01, [response]);
|
|
880
|
+
return response;
|
|
881
|
+
}
|
|
882
|
+
else {
|
|
883
|
+
// SVM: build minimal response (follow sendFunds SVM pattern)
|
|
884
|
+
const chainId = chain_1.CHAIN_INFO[chain].chainId;
|
|
885
|
+
const origin = `${chain_1.VM_NAMESPACE[vm]}:${chainId}:${this.universalSigner.account.address}`;
|
|
886
|
+
const response = {
|
|
887
|
+
hash: anchor_1.utils.bytes.bs58.encode(feeLockTxHashBytes),
|
|
888
|
+
origin,
|
|
889
|
+
blockNumber: BigInt(0),
|
|
890
|
+
blockHash: '',
|
|
891
|
+
transactionIndex: 0,
|
|
892
|
+
chainId,
|
|
893
|
+
from: this.universalSigner.account.address,
|
|
894
|
+
to: '0x0000000000000000000000000000000000000000',
|
|
895
|
+
nonce: 0,
|
|
896
|
+
data: '0x',
|
|
897
|
+
value: BigInt(0),
|
|
898
|
+
gasLimit: BigInt(0),
|
|
899
|
+
gasPrice: undefined,
|
|
900
|
+
maxFeePerGas: undefined,
|
|
901
|
+
maxPriorityFeePerGas: undefined,
|
|
902
|
+
accessList: [],
|
|
903
|
+
wait: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
904
|
+
return ({
|
|
905
|
+
hash: anchor_1.utils.bytes.bs58.encode(feeLockTxHashBytes),
|
|
906
|
+
blockNumber: BigInt(0),
|
|
907
|
+
blockHash: '',
|
|
908
|
+
transactionIndex: 0,
|
|
909
|
+
from: this.universalSigner.account.address,
|
|
910
|
+
to: '0x0000000000000000000000000000000000000000',
|
|
911
|
+
contractAddress: null,
|
|
912
|
+
gasPrice: BigInt(0),
|
|
913
|
+
gasUsed: BigInt(0),
|
|
914
|
+
cumulativeGasUsed: BigInt(0),
|
|
915
|
+
logs: [],
|
|
916
|
+
logsBloom: '0x',
|
|
917
|
+
status: 1,
|
|
918
|
+
raw: {
|
|
919
|
+
from: this.universalSigner.account.address,
|
|
920
|
+
to: '0x0000000000000000000000000000000000000000',
|
|
921
|
+
},
|
|
922
|
+
});
|
|
923
|
+
}),
|
|
924
|
+
type: '99',
|
|
925
|
+
typeVerbose: 'universal',
|
|
926
|
+
signature: { r: '0x0', s: '0x0', v: 0 },
|
|
927
|
+
raw: {
|
|
928
|
+
from: this.universalSigner.account.address,
|
|
929
|
+
to: '0x0000000000000000000000000000000000000000',
|
|
930
|
+
nonce: 0,
|
|
931
|
+
data: '0x',
|
|
932
|
+
value: BigInt(0),
|
|
933
|
+
},
|
|
934
|
+
};
|
|
935
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01, [response]);
|
|
936
|
+
return response;
|
|
937
|
+
}
|
|
818
938
|
}
|
|
819
939
|
/**
|
|
820
|
-
* Broadcasting Tx to PC
|
|
940
|
+
* Non-fee-locking path: Broadcasting Tx to PC via sendUniversalTx
|
|
821
941
|
*/
|
|
822
942
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06);
|
|
823
943
|
const transactions = yield this.sendUniversalTx(isUEADeployed, feeLockTxHash, universalPayload, verificationData);
|
|
@@ -847,11 +967,11 @@ class Orchestrator {
|
|
|
847
967
|
*
|
|
848
968
|
* @param amount - Fee amount in USDC (8 Decimals)
|
|
849
969
|
* @param executionHash - Optional execution payload hash (default: zeroHash)
|
|
850
|
-
* @returns Transaction hash
|
|
970
|
+
* @returns Transaction hash bytes
|
|
851
971
|
*/
|
|
852
|
-
lockFee(
|
|
853
|
-
|
|
854
|
-
|
|
972
|
+
lockFee(amount, // USD with 8 decimals
|
|
973
|
+
universalPayload) {
|
|
974
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
855
975
|
const chain = this.universalSigner.account.chain;
|
|
856
976
|
const { lockerContract, vm, defaultRPC } = chain_1.CHAIN_INFO[chain];
|
|
857
977
|
if (!lockerContract) {
|
|
@@ -866,35 +986,88 @@ class Orchestrator {
|
|
|
866
986
|
Promise.resolve(new evm_client_1.EvmClient({ rpcUrls })),
|
|
867
987
|
]);
|
|
868
988
|
const nativeDecimals = 18; // ETH, MATIC, etc.
|
|
869
|
-
|
|
989
|
+
// Ensure deposit respects gateway USD caps (min $1, max $10) and avoid rounding below min
|
|
990
|
+
const oneUsd = push_chain_1.PushChain.utils.helpers.parseUnits('1', 8);
|
|
991
|
+
const tenUsd = push_chain_1.PushChain.utils.helpers.parseUnits('10', 8);
|
|
992
|
+
let depositUsd = amount < oneUsd ? oneUsd : amount;
|
|
993
|
+
if (depositUsd > tenUsd)
|
|
994
|
+
depositUsd = tenUsd;
|
|
995
|
+
// Ceil division to avoid falling below on-chain min due to rounding, then add 1 wei safety
|
|
996
|
+
let nativeAmount = (depositUsd * BigInt(Math.pow(10, nativeDecimals)) +
|
|
997
|
+
(nativeTokenUsdPrice - BigInt(1))) /
|
|
998
|
+
nativeTokenUsdPrice;
|
|
999
|
+
nativeAmount = nativeAmount + BigInt(1);
|
|
1000
|
+
// Deposit-only funding via UniversalGatewayV0 (no payload execution)
|
|
1001
|
+
const revertCFG = {
|
|
1002
|
+
fundRecipient: this.universalSigner.account.address,
|
|
1003
|
+
revertMsg: '0x',
|
|
1004
|
+
};
|
|
1005
|
+
// Sign the universal payload
|
|
1006
|
+
const ueaAddress = this.computeUEAOffchain();
|
|
1007
|
+
const ueaVersion = yield this.fetchUEAVersion();
|
|
1008
|
+
const eip712Signature = yield this.signUniversalPayload(universalPayload, ueaAddress, ueaVersion);
|
|
1009
|
+
const eip712SignatureHex = typeof eip712Signature === 'string'
|
|
1010
|
+
? eip712Signature
|
|
1011
|
+
: (0, viem_1.bytesToHex)(eip712Signature);
|
|
870
1012
|
const txHash = yield evmClient.writeContract({
|
|
871
|
-
abi: abi_1.
|
|
1013
|
+
abi: abi_1.UNIVERSAL_GATEWAY_V0,
|
|
872
1014
|
address: lockerContract,
|
|
873
|
-
functionName: '
|
|
874
|
-
args: [
|
|
1015
|
+
functionName: 'sendTxWithGas',
|
|
1016
|
+
args: [universalPayload, revertCFG, '0x'],
|
|
875
1017
|
signer: this.universalSigner,
|
|
876
1018
|
value: nativeAmount,
|
|
877
1019
|
});
|
|
878
1020
|
return (0, viem_1.hexToBytes)(txHash);
|
|
879
1021
|
}
|
|
880
1022
|
case enums_1.VM.SVM: {
|
|
881
|
-
// Run price fetching
|
|
882
|
-
const [nativeTokenUsdPrice, svmClient
|
|
1023
|
+
// Run price fetching and client creation in parallel
|
|
1024
|
+
const [nativeTokenUsdPrice, svmClient] = yield Promise.all([
|
|
883
1025
|
new price_fetch_1.PriceFetch(this.rpcUrls).getPrice(chain), // 8 decimals
|
|
884
1026
|
Promise.resolve(new svm_client_1.SvmClient({ rpcUrls })),
|
|
885
|
-
Promise.resolve(anchor.web3.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('locker')], new web3_js_1.PublicKey(lockerContract))),
|
|
886
1027
|
]);
|
|
1028
|
+
// Ensure deposit respects gateway USD caps (min $1, max $10) and avoid rounding below min
|
|
887
1029
|
const nativeDecimals = 9; // SOL lamports
|
|
888
|
-
const
|
|
1030
|
+
const oneUsd = push_chain_1.PushChain.utils.helpers.parseUnits('1', 8);
|
|
1031
|
+
const tenUsd = push_chain_1.PushChain.utils.helpers.parseUnits('10', 8);
|
|
1032
|
+
let depositUsd = amount < oneUsd ? oneUsd : amount;
|
|
1033
|
+
if (depositUsd > tenUsd)
|
|
1034
|
+
depositUsd = tenUsd;
|
|
1035
|
+
// Ceil division to avoid falling below on-chain min due to rounding, then add 1 lamport safety
|
|
1036
|
+
let nativeAmount = (depositUsd * BigInt(Math.pow(10, nativeDecimals)) +
|
|
1037
|
+
(nativeTokenUsdPrice - BigInt(1))) /
|
|
1038
|
+
nativeTokenUsdPrice;
|
|
1039
|
+
nativeAmount = nativeAmount + BigInt(1);
|
|
1040
|
+
// Program & PDAs
|
|
1041
|
+
const programId = new web3_js_1.PublicKey(abi_1.SVM_GATEWAY_IDL.address);
|
|
1042
|
+
const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
|
|
1043
|
+
const [vaultPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('vault')], programId);
|
|
1044
|
+
const userPk = new web3_js_1.PublicKey(this.universalSigner.account.address);
|
|
1045
|
+
const revertSvm = {
|
|
1046
|
+
fundRecipient: userPk,
|
|
1047
|
+
revertMsg: Buffer.from([]),
|
|
1048
|
+
};
|
|
1049
|
+
// const ueaAddressSvm = this.computeUEAOffchain();
|
|
1050
|
+
// const ueaVersion = await this.fetchUEAVersion();
|
|
1051
|
+
// const svmSignature = await this.signUniversalPayload(
|
|
1052
|
+
// universalPayload,
|
|
1053
|
+
// ueaAddressSvm,
|
|
1054
|
+
// ueaVersion
|
|
1055
|
+
// );
|
|
889
1056
|
const txHash = yield svmClient.writeContract({
|
|
890
|
-
abi: abi_1.
|
|
891
|
-
address:
|
|
892
|
-
functionName: '
|
|
893
|
-
args: [
|
|
1057
|
+
abi: abi_1.SVM_GATEWAY_IDL,
|
|
1058
|
+
address: programId.toBase58(),
|
|
1059
|
+
functionName: 'sendTxWithGas',
|
|
1060
|
+
args: [
|
|
1061
|
+
universalPayload,
|
|
1062
|
+
revertSvm,
|
|
1063
|
+
new anchor.BN(nativeAmount.toString()),
|
|
1064
|
+
'0x',
|
|
1065
|
+
],
|
|
894
1066
|
signer: this.universalSigner,
|
|
895
1067
|
accounts: {
|
|
896
|
-
|
|
897
|
-
|
|
1068
|
+
config: configPda,
|
|
1069
|
+
vault: vaultPda,
|
|
1070
|
+
user: userPk,
|
|
898
1071
|
priceUpdate: new web3_js_1.PublicKey('7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE'),
|
|
899
1072
|
systemProgram: web3_js_1.SystemProgram.programId,
|
|
900
1073
|
},
|
|
@@ -1233,20 +1406,12 @@ class Orchestrator {
|
|
|
1233
1406
|
switch (vm) {
|
|
1234
1407
|
case enums_1.VM.EVM: {
|
|
1235
1408
|
const evmClient = new evm_client_1.EvmClient({ rpcUrls });
|
|
1236
|
-
yield evmClient.
|
|
1237
|
-
txHash: (0, viem_1.bytesToHex)(txHashBytes),
|
|
1238
|
-
confirmations,
|
|
1239
|
-
timeoutMs: timeout,
|
|
1240
|
-
});
|
|
1409
|
+
yield this.waitForEvmConfirmationsWithCountdown(evmClient, (0, viem_1.bytesToHex)(txHashBytes), confirmations, timeout);
|
|
1241
1410
|
return;
|
|
1242
1411
|
}
|
|
1243
1412
|
case enums_1.VM.SVM: {
|
|
1244
1413
|
const svmClient = new svm_client_1.SvmClient({ rpcUrls });
|
|
1245
|
-
yield svmClient.
|
|
1246
|
-
txSignature: anchor_1.utils.bytes.bs58.encode(txHashBytes),
|
|
1247
|
-
confirmations,
|
|
1248
|
-
timeoutMs: timeout,
|
|
1249
|
-
});
|
|
1414
|
+
yield this.waitForSvmConfirmationsWithCountdown(svmClient, anchor_1.utils.bytes.bs58.encode(txHashBytes), confirmations, timeout);
|
|
1250
1415
|
return;
|
|
1251
1416
|
}
|
|
1252
1417
|
default:
|
|
@@ -1476,26 +1641,65 @@ class Orchestrator {
|
|
|
1476
1641
|
});
|
|
1477
1642
|
}
|
|
1478
1643
|
/**
|
|
1479
|
-
*
|
|
1644
|
+
* For sendFunds, we will call internally the sendTxWithFunds.
|
|
1480
1645
|
*/
|
|
1481
|
-
buildGatewayPayloadAndGas(execute, nonce) {
|
|
1646
|
+
buildGatewayPayloadAndGas(execute, nonce, type, fundsValue) {
|
|
1482
1647
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
1483
1648
|
var _a, _b;
|
|
1484
1649
|
const gasEstimate = execute.gasLimit || BigInt(1e7);
|
|
1485
1650
|
const payloadValue = (_a = execute.value) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
1486
1651
|
const gasAmount = (_b = execute.value) !== null && _b !== void 0 ? _b : BigInt(0);
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1652
|
+
// @@@@@@@@@@@@
|
|
1653
|
+
// const universalPayload = {
|
|
1654
|
+
// to: execute.to,
|
|
1655
|
+
// value: payloadValue,
|
|
1656
|
+
// data: execute.data || '0x',
|
|
1657
|
+
// gasLimit: gasEstimate,
|
|
1658
|
+
// maxFeePerGas: execute.maxFeePerGas || BigInt(1e10),
|
|
1659
|
+
// maxPriorityFeePerGas: execute.maxPriorityFeePerGas || BigInt(0),
|
|
1660
|
+
// nonce,
|
|
1661
|
+
// deadline: execute.deadline || BigInt(9999999999),
|
|
1662
|
+
// vType: VerificationType.universalTxVerification,
|
|
1663
|
+
// } as unknown as never;
|
|
1664
|
+
if (type === 'sendTxWithFunds') {
|
|
1665
|
+
if (fundsValue)
|
|
1666
|
+
throw new Error('fundsValue property must be empty');
|
|
1667
|
+
const universalPayload = {
|
|
1668
|
+
to: execute.to,
|
|
1669
|
+
value: payloadValue,
|
|
1670
|
+
data: execute.data || '0x',
|
|
1671
|
+
gasLimit: gasEstimate,
|
|
1672
|
+
maxFeePerGas: execute.maxFeePerGas || BigInt(1e10),
|
|
1673
|
+
maxPriorityFeePerGas: execute.maxPriorityFeePerGas || BigInt(0),
|
|
1674
|
+
nonce,
|
|
1675
|
+
deadline: execute.deadline || BigInt(9999999999),
|
|
1676
|
+
vType: tx_1.VerificationType.universalTxVerification,
|
|
1677
|
+
};
|
|
1678
|
+
return { payload: universalPayload, gasAmount };
|
|
1679
|
+
}
|
|
1680
|
+
else {
|
|
1681
|
+
if (!fundsValue)
|
|
1682
|
+
throw new Error('fundsValue property must not be empty');
|
|
1683
|
+
// The data will be the abi-encoded transfer function from erc-20 function. The recipient will be `execute.to`, the value
|
|
1684
|
+
// will be the fundsValue property.
|
|
1685
|
+
const data = (0, viem_1.encodeFunctionData)({
|
|
1686
|
+
abi: abi_1.ERC20_EVM,
|
|
1687
|
+
functionName: 'transfer',
|
|
1688
|
+
args: [execute.to, fundsValue],
|
|
1689
|
+
});
|
|
1690
|
+
const universalPayload = {
|
|
1691
|
+
to: viem_1.zeroAddress, // We can't simply do `0x` because we will get an error when eip712 signing the transaction.
|
|
1692
|
+
value: payloadValue,
|
|
1693
|
+
data,
|
|
1694
|
+
gasLimit: gasEstimate,
|
|
1695
|
+
maxFeePerGas: execute.maxFeePerGas || BigInt(1e10),
|
|
1696
|
+
maxPriorityFeePerGas: execute.maxPriorityFeePerGas || BigInt(0),
|
|
1697
|
+
nonce,
|
|
1698
|
+
deadline: execute.deadline || BigInt(9999999999),
|
|
1699
|
+
vType: tx_1.VerificationType.universalTxVerification,
|
|
1700
|
+
};
|
|
1701
|
+
return { payload: universalPayload, gasAmount };
|
|
1702
|
+
}
|
|
1499
1703
|
});
|
|
1500
1704
|
}
|
|
1501
1705
|
/********************************** HELPER FUNCTIONS **************************************************/
|
|
@@ -1741,15 +1945,16 @@ class Orchestrator {
|
|
|
1741
1945
|
continue;
|
|
1742
1946
|
const discriminatorHex = (0, viem_1.bytesToHex)(decoded.slice(0, 8)).slice(2);
|
|
1743
1947
|
// Skip add_funds discriminator; return the first other Program data event
|
|
1744
|
-
if (discriminatorHex === '7f1f6cffbb134644')
|
|
1745
|
-
|
|
1746
|
-
|
|
1948
|
+
// if (discriminatorHex === '7f1f6cffbb134644') continue;
|
|
1949
|
+
if (discriminatorHex === '6c9ad829b5ea1d7c')
|
|
1950
|
+
return i;
|
|
1951
|
+
// return i;
|
|
1747
1952
|
}
|
|
1748
1953
|
// Fallback to first log
|
|
1749
1954
|
return 0;
|
|
1750
1955
|
}
|
|
1751
1956
|
// Query Push Chain for UniversalTx status given an origin gateway tx (EVM or SVM)
|
|
1752
|
-
queryUniversalTxStatusFromGatewayTx(evmClient, gatewayAddress, txHash,
|
|
1957
|
+
queryUniversalTxStatusFromGatewayTx(evmClient, gatewayAddress, txHash, evmGatewayMethod) {
|
|
1753
1958
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
1754
1959
|
var _a, _b;
|
|
1755
1960
|
try {
|
|
@@ -1760,11 +1965,22 @@ class Orchestrator {
|
|
|
1760
1965
|
if (vm === enums_1.VM.EVM) {
|
|
1761
1966
|
if (!evmClient || !gatewayAddress)
|
|
1762
1967
|
throw new Error('Missing EVM context');
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1968
|
+
let receipt;
|
|
1969
|
+
try {
|
|
1970
|
+
receipt = yield evmClient.publicClient.getTransactionReceipt({
|
|
1971
|
+
hash: txHash,
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
catch (_c) {
|
|
1975
|
+
// Receipt might not be indexed yet on this RPC; wait briefly for it
|
|
1976
|
+
receipt = yield evmClient.publicClient.waitForTransactionReceipt({
|
|
1977
|
+
hash: txHash,
|
|
1978
|
+
confirmations: 0,
|
|
1979
|
+
timeout: chain_1.CHAIN_INFO[chain].timeout,
|
|
1980
|
+
});
|
|
1981
|
+
}
|
|
1766
1982
|
const gatewayLogs = (receipt.logs || []).filter((l) => (l.address || '').toLowerCase() === gatewayAddress.toLowerCase());
|
|
1767
|
-
const logIndexToUse =
|
|
1983
|
+
const logIndexToUse = evmGatewayMethod === 'sendTxWithFunds' ? 1 : 0;
|
|
1768
1984
|
const firstLog = (gatewayLogs[logIndexToUse] ||
|
|
1769
1985
|
((_a = receipt.logs) === null || _a === void 0 ? void 0 : _a[logIndexToUse]));
|
|
1770
1986
|
const logIndexVal = (_b = firstLog === null || firstLog === void 0 ? void 0 : firstLog.logIndex) !== null && _b !== void 0 ? _b : 0;
|
|
@@ -1832,7 +2048,7 @@ class Orchestrator {
|
|
|
1832
2048
|
// );
|
|
1833
2049
|
return universalTxObj;
|
|
1834
2050
|
}
|
|
1835
|
-
catch (
|
|
2051
|
+
catch (_d) {
|
|
1836
2052
|
// Best-effort; do not fail flow if PC query is unavailable
|
|
1837
2053
|
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_06);
|
|
1838
2054
|
return undefined;
|
|
@@ -1850,15 +2066,31 @@ class Orchestrator {
|
|
|
1850
2066
|
hash: txHash,
|
|
1851
2067
|
});
|
|
1852
2068
|
const targetBlock = receipt.blockNumber + BigInt(confirmations);
|
|
2069
|
+
// Track last emitted confirmation to avoid duplicates
|
|
2070
|
+
let lastEmitted = 0;
|
|
1853
2071
|
// Poll blocks and emit remaining confirmations
|
|
1854
2072
|
// eslint-disable-next-line no-constant-condition
|
|
1855
2073
|
while (true) {
|
|
1856
2074
|
const currentBlock = yield evmClient.publicClient.getBlockNumber();
|
|
1857
|
-
|
|
2075
|
+
// If already confirmed, emit progress for final confirmation
|
|
2076
|
+
if (currentBlock >= targetBlock) {
|
|
2077
|
+
// Only emit if we haven't already shown this confirmation
|
|
2078
|
+
if (lastEmitted < confirmations) {
|
|
2079
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_04, confirmations, confirmations);
|
|
2080
|
+
}
|
|
1858
2081
|
return;
|
|
2082
|
+
}
|
|
1859
2083
|
const remaining = Number(targetBlock - currentBlock);
|
|
1860
2084
|
const completed = Math.max(1, confirmations - remaining + 1);
|
|
1861
|
-
this
|
|
2085
|
+
// Only emit if this is a new confirmation count
|
|
2086
|
+
if (completed > lastEmitted) {
|
|
2087
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_04, completed, confirmations);
|
|
2088
|
+
lastEmitted = completed;
|
|
2089
|
+
// If we've reached required confirmations, we're done
|
|
2090
|
+
if (completed >= confirmations) {
|
|
2091
|
+
return;
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
1862
2094
|
if (Date.now() - start > timeoutMs) {
|
|
1863
2095
|
throw new Error(`Timeout: transaction ${txHash} not confirmed with ${confirmations} confirmations within ${timeoutMs} ms`);
|
|
1864
2096
|
}
|
|
@@ -1866,6 +2098,44 @@ class Orchestrator {
|
|
|
1866
2098
|
}
|
|
1867
2099
|
});
|
|
1868
2100
|
}
|
|
2101
|
+
// Emit countdown updates while waiting for SVM confirmations
|
|
2102
|
+
waitForSvmConfirmationsWithCountdown(svmClient, txSignature, confirmations, timeoutMs) {
|
|
2103
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
2104
|
+
var _a;
|
|
2105
|
+
// initial emit
|
|
2106
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_03, confirmations);
|
|
2107
|
+
const start = Date.now();
|
|
2108
|
+
// Poll for confirmations and emit progress
|
|
2109
|
+
let lastConfirmed = 0;
|
|
2110
|
+
// eslint-disable-next-line no-constant-condition
|
|
2111
|
+
while (true) {
|
|
2112
|
+
const connection = svmClient.connections[svmClient.currentConnectionIndex];
|
|
2113
|
+
const { value } = yield connection.getSignatureStatuses([txSignature]);
|
|
2114
|
+
const status = value[0];
|
|
2115
|
+
if (status) {
|
|
2116
|
+
const currentConfirms = (_a = status.confirmations) !== null && _a !== void 0 ? _a : 0;
|
|
2117
|
+
const hasEnoughConfirmations = currentConfirms >= confirmations;
|
|
2118
|
+
const isSuccessfullyFinalized = status.err === null && status.confirmationStatus !== null;
|
|
2119
|
+
// Emit progress if we have more confirmations than before OR if finalized
|
|
2120
|
+
if (currentConfirms > lastConfirmed ||
|
|
2121
|
+
(isSuccessfullyFinalized && lastConfirmed === 0)) {
|
|
2122
|
+
const confirmCount = isSuccessfullyFinalized && currentConfirms === 0
|
|
2123
|
+
? confirmations
|
|
2124
|
+
: currentConfirms;
|
|
2125
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_04, Math.max(1, confirmCount), confirmations);
|
|
2126
|
+
lastConfirmed = currentConfirms;
|
|
2127
|
+
}
|
|
2128
|
+
if (hasEnoughConfirmations || isSuccessfullyFinalized) {
|
|
2129
|
+
return;
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
if (Date.now() - start > timeoutMs) {
|
|
2133
|
+
throw new Error(`Timeout: transaction ${txSignature} not confirmed with ${confirmations} confirmations within ${timeoutMs} ms`);
|
|
2134
|
+
}
|
|
2135
|
+
yield new Promise((r) => setTimeout(r, 500));
|
|
2136
|
+
}
|
|
2137
|
+
});
|
|
2138
|
+
}
|
|
1869
2139
|
// Fetch and cache UEA version from the contract on Push Chain
|
|
1870
2140
|
fetchUEAVersion() {
|
|
1871
2141
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -1931,6 +2201,63 @@ class Orchestrator {
|
|
|
1931
2201
|
return { gasAmount };
|
|
1932
2202
|
});
|
|
1933
2203
|
}
|
|
2204
|
+
calculateNativeAmountForDeposit(chain, requiredFunds, ueaBalance) {
|
|
2205
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
2206
|
+
var _a, _b;
|
|
2207
|
+
// Determine USD to deposit via gateway (8 decimals) with caps: min=$1, max=$10
|
|
2208
|
+
const oneUsd = push_chain_1.PushChain.utils.helpers.parseUnits('1', 8);
|
|
2209
|
+
const tenUsd = push_chain_1.PushChain.utils.helpers.parseUnits('10', 8);
|
|
2210
|
+
const deficit = requiredFunds > ueaBalance ? requiredFunds - ueaBalance : BigInt(0);
|
|
2211
|
+
let depositUsd = deficit > BigInt(0) ? this.pushClient.pushToUSDC(deficit) : oneUsd;
|
|
2212
|
+
if (depositUsd < oneUsd)
|
|
2213
|
+
depositUsd = oneUsd;
|
|
2214
|
+
if (depositUsd > tenUsd)
|
|
2215
|
+
throw new Error('Deposit value exceeds max $10 worth of native token');
|
|
2216
|
+
this.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_02, depositUsd);
|
|
2217
|
+
// If SVM, clamp depositUsd to on-chain Config caps
|
|
2218
|
+
if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM) {
|
|
2219
|
+
const svmClient = new svm_client_1.SvmClient({
|
|
2220
|
+
rpcUrls: this.rpcUrls[enums_1.CHAIN.SOLANA_DEVNET] ||
|
|
2221
|
+
chain_1.CHAIN_INFO[enums_1.CHAIN.SOLANA_DEVNET].defaultRPC,
|
|
2222
|
+
});
|
|
2223
|
+
const programId = new web3_js_1.PublicKey(abi_1.SVM_GATEWAY_IDL.address);
|
|
2224
|
+
const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
|
|
2225
|
+
try {
|
|
2226
|
+
const cfg = yield svmClient.readContract({
|
|
2227
|
+
abi: abi_1.SVM_GATEWAY_IDL,
|
|
2228
|
+
address: abi_1.SVM_GATEWAY_IDL.address,
|
|
2229
|
+
functionName: 'config',
|
|
2230
|
+
args: [configPda.toBase58()],
|
|
2231
|
+
});
|
|
2232
|
+
const minField = (_a = cfg.minCapUniversalTxUsd) !== null && _a !== void 0 ? _a : cfg.min_cap_universal_tx_usd;
|
|
2233
|
+
const maxField = (_b = cfg.maxCapUniversalTxUsd) !== null && _b !== void 0 ? _b : cfg.max_cap_universal_tx_usd;
|
|
2234
|
+
const minCapUsd = BigInt(minField.toString());
|
|
2235
|
+
const maxCapUsd = BigInt(maxField.toString());
|
|
2236
|
+
if (depositUsd < minCapUsd)
|
|
2237
|
+
depositUsd = minCapUsd;
|
|
2238
|
+
// Add 20% safety margin to avoid BelowMinCap due to price drift
|
|
2239
|
+
const withMargin = (minCapUsd * BigInt(12)) / BigInt(10);
|
|
2240
|
+
if (depositUsd < withMargin)
|
|
2241
|
+
depositUsd = withMargin;
|
|
2242
|
+
if (depositUsd > maxCapUsd)
|
|
2243
|
+
depositUsd = maxCapUsd;
|
|
2244
|
+
}
|
|
2245
|
+
catch (_c) {
|
|
2246
|
+
// best-effort; fallback to previous bounds if read fails
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
// Convert USD(8) -> native units using pricing path
|
|
2250
|
+
const nativeTokenUsdPrice = yield new price_fetch_1.PriceFetch(this.rpcUrls).getPrice(chain); // 8 decimals
|
|
2251
|
+
const nativeDecimals = chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM ? 9 : 18;
|
|
2252
|
+
const oneNativeUnit = push_chain_1.PushChain.utils.helpers.parseUnits('1', nativeDecimals);
|
|
2253
|
+
// Ceil division to avoid rounding below min USD on-chain
|
|
2254
|
+
let nativeAmount = (depositUsd * oneNativeUnit + (nativeTokenUsdPrice - BigInt(1))) /
|
|
2255
|
+
nativeTokenUsdPrice;
|
|
2256
|
+
// Add 1 unit safety to avoid BelowMinCap from rounding differences
|
|
2257
|
+
nativeAmount = nativeAmount + BigInt(1);
|
|
2258
|
+
return nativeAmount;
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
1934
2261
|
}
|
|
1935
2262
|
exports.Orchestrator = Orchestrator;
|
|
1936
2263
|
//# sourceMappingURL=orchestrator.js.map
|