@pushchain/core 2.1.6 → 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.
@@ -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: 'sendFunds',
147
- args: [recipient, bridgeToken, bridgeAmount, revertCFG],
164
+ functionName: 'sendTxWithFunds',
165
+ args: [
166
+ tokenAddr,
167
+ bridgeAmount,
168
+ universalPayload,
169
+ revertCFG,
170
+ '0x',
171
+ ],
148
172
  signer: this.universalSigner,
149
- value: isNative ? bridgeAmount : BigInt(0),
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
- eip712SignatureHex,
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
- eip712SignatureHex,
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(1e7),
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, executionHash);
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 of the locking transaction
970
+ * @returns Transaction hash bytes
851
971
  */
852
- lockFee(amount_1) {
853
- return tslib_1.__awaiter(this, arguments, void 0, function* (amount, // USD with 8 decimals
854
- executionHash = viem_1.zeroHash) {
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
- const nativeAmount = (amount * BigInt(Math.pow(10, nativeDecimals))) / nativeTokenUsdPrice;
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.FEE_LOCKER_EVM,
1013
+ abi: abi_1.UNIVERSAL_GATEWAY_V0,
872
1014
  address: lockerContract,
873
- functionName: 'addFunds',
874
- args: [executionHash],
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, client creation, and PDA computation in parallel
882
- const [nativeTokenUsdPrice, svmClient, [lockerPda]] = yield Promise.all([
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 nativeAmount = (amount * BigInt(Math.pow(10, nativeDecimals))) / nativeTokenUsdPrice;
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.FEE_LOCKER_SVM,
891
- address: lockerContract,
892
- functionName: 'addFunds',
893
- args: [nativeAmount, (0, viem_1.toBytes)(executionHash)],
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
- locker: lockerPda,
897
- user: new web3_js_1.PublicKey(this.universalSigner.account.address),
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.waitForConfirmations({
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.waitForConfirmations({
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
- * Builds UniversalPayload for the gateway and computes the native gas deposit.
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
- const universalPayload = {
1488
- to: execute.to,
1489
- value: payloadValue,
1490
- data: execute.data || '0x',
1491
- gasLimit: gasEstimate,
1492
- maxFeePerGas: execute.maxFeePerGas || BigInt(1e10),
1493
- maxPriorityFeePerGas: execute.maxPriorityFeePerGas || BigInt(0),
1494
- nonce,
1495
- deadline: execute.deadline || BigInt(9999999999),
1496
- vType: tx_1.VerificationType.signedVerification,
1497
- };
1498
- return { payload: universalPayload, gasAmount };
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
- continue;
1746
- return i;
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, fromBranch) {
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
- const receipt = yield evmClient.publicClient.getTransactionReceipt({
1764
- hash: txHash,
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 = fromBranch === 'sendTxWithFunds' ? 1 : 0;
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 (_c) {
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
- if (currentBlock >= targetBlock)
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.executeProgressHook(progress_hook_types_1.PROGRESS_HOOK.SEND_TX_06_04, completed, confirmations);
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