@sodax/sdk 0.0.1-rc.13 → 0.0.1-rc.15

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/README.md CHANGED
@@ -225,8 +225,8 @@ As part of Sodax suite, xWagmi SDK is also going to be provided as one example w
225
225
  - `ISuiWalletProvider`: Sui ✅
226
226
  - `IIconWalletProvider`: ICON ✅
227
227
  - `IStellarWalletProvider`: Stellar ✅
228
- - Solana ❌ Coming soon
229
- - Injective ❌ Coming soon
228
+ - Solana
229
+ - Injective
230
230
  - Havah ❌ Coming soon
231
231
 
232
232
  ### Initialising Spoke Provider
@@ -251,6 +251,86 @@ const bscSpokeProvider: EvmSpokeProvider = new EvmSpokeProvider(
251
251
  );
252
252
  ```
253
253
 
254
+ ### Estimate Gas for Raw Transactions
255
+
256
+ The `estimateGas` function allows you to estimate the gas cost for raw transactions before executing them. This is particularly useful for all Sodax operations (swaps, money market operations, approvals) to provide users with accurate gas estimates.
257
+
258
+ The function is available on all service classes:
259
+ - `SolverService.estimateGas()` - for solver/intent operations
260
+ - `MoneyMarketService.estimateGas()` - for money market operations
261
+ - `SpokeService.estimateGas()` - for general spoke chain operations
262
+
263
+ ```typescript
264
+ import {
265
+ SolverService,
266
+ MoneyMarketService,
267
+ SpokeService,
268
+ MoneyMarketSupplyParams
269
+ } from "@sodax/sdk";
270
+
271
+ // Example: Estimate gas for a solver swap transaction
272
+ const createIntentResult = await sodax.solver.createIntent(
273
+ createIntentParams,
274
+ bscSpokeProvider,
275
+ partnerFeeAmount,
276
+ true, // true = get raw transaction
277
+ );
278
+
279
+ if (createIntentResult.ok) {
280
+ const [rawTx, intent] = createIntentResult.value;
281
+
282
+ // Estimate gas for the raw transaction
283
+ const gasEstimate = await SolverService.estimateGas(rawTx, bscSpokeProvider);
284
+
285
+ if (gasEstimate.ok) {
286
+ console.log('Estimated gas for swap:', gasEstimate.value);
287
+ } else {
288
+ console.error('Failed to estimate gas for swap:', gasEstimate.error);
289
+ }
290
+ }
291
+
292
+ // Example: Estimate gas for a money market supply transaction
293
+ const supplyResult = await sodax.moneyMarket.createSupplyIntent(
294
+ supplyParams,
295
+ bscSpokeProvider,
296
+ true, // true = get raw transaction
297
+ );
298
+
299
+ if (supplyResult.ok) {
300
+ const rawTx = supplyResult.value;
301
+
302
+ // Estimate gas for the raw transaction
303
+ const gasEstimate = await MoneyMarketService.estimateGas(rawTx, bscSpokeProvider);
304
+
305
+ if (gasEstimate.ok) {
306
+ console.log('Estimated gas for supply:', gasEstimate.value);
307
+ } else {
308
+ console.error('Failed to estimate gas for supply:', gasEstimate.error);
309
+ }
310
+ }
311
+
312
+ // Example: Estimate gas for an approval transaction
313
+ const approveResult = await sodax.solver.approve(
314
+ tokenAddress,
315
+ amount,
316
+ bscSpokeProvider,
317
+ true // true = get raw transaction
318
+ );
319
+
320
+ if (approveResult.ok) {
321
+ const rawTx = approveResult.value;
322
+
323
+ // Estimate gas for the approval transaction
324
+ const gasEstimate = await SpokeService.estimateGas(rawTx, bscSpokeProvider);
325
+
326
+ if (gasEstimate.ok) {
327
+ console.log('Estimated gas for approval:', gasEstimate.value);
328
+ } else {
329
+ console.error('Failed to estimate gas for approval:', gasEstimate.error);
330
+ }
331
+ }
332
+ ```
333
+
254
334
  ### Accessing Sodax Features
255
335
 
256
336
  Sodax feature set currently contain:
package/dist/index.cjs CHANGED
@@ -4,12 +4,16 @@ var viem = require('viem');
4
4
  var chains = require('viem/chains');
5
5
  var types = require('@sodax/types');
6
6
  var stargate = require('@cosmjs/stargate');
7
+ var networks = require('@injectivelabs/networks');
8
+ var sdkTs = require('@injectivelabs/sdk-ts');
7
9
  var IconSdkRaw = require('icon-sdk-js');
8
10
  var stellarSdk = require('@stellar/stellar-sdk');
9
11
  var bcs = require('@mysten/sui/bcs');
12
+ var client = require('@mysten/sui/client');
10
13
  var transactions = require('@mysten/sui/transactions');
11
14
  var web3_js = require('@solana/web3.js');
12
15
  var invariant2 = require('tiny-invariant');
16
+ var tx_js = require('cosmjs-types/cosmos/tx/v1beta1/tx.js');
13
17
  var rlp = require('rlp');
14
18
  var splToken = require('@solana/spl-token');
15
19
  var anchor = require('@coral-xyz/anchor');
@@ -5282,8 +5286,7 @@ var spokeChainConfig = {
5282
5286
  }
5283
5287
  },
5284
5288
  gasPrice: "500000",
5285
- rpcUrl: "https://solana-mainnet.g.alchemy.com/v2/i3q5fE3cYSFBE4Lcg1kS5",
5286
- wsUrl: "https://solana-mainnet.g.alchemy.com/v2/i3q5fE3cYSFBE4Lcg1kS5",
5289
+ rpcUrl: "https://api.mainnet-beta.solana.com",
5287
5290
  walletAddress: ""
5288
5291
  },
5289
5292
  [types.AVALANCHE_MAINNET_CHAIN_ID]: {
@@ -6772,14 +6775,16 @@ var Injective20Token = class {
6772
6775
  return await this.client.execute(senderAddress, this.contractAddress, msg, "auto");
6773
6776
  }
6774
6777
  };
6775
-
6776
- // src/entities/injective/InjectiveSpokeProvider.ts
6777
6778
  var InjectiveSpokeProvider = class {
6778
6779
  walletProvider;
6779
6780
  chainConfig;
6781
+ txClient;
6780
6782
  constructor(conf, walletProvider) {
6781
6783
  this.chainConfig = conf;
6782
6784
  this.walletProvider = walletProvider;
6785
+ this.txClient = new sdkTs.TxGrpcClient(
6786
+ networks.getNetworkEndpoints(this.chainConfig.network === "Mainnet" ? networks.Network.Mainnet : networks.Network.Testnet).grpc
6787
+ );
6783
6788
  }
6784
6789
  // Query Methods
6785
6790
  async getState() {
@@ -6840,16 +6845,7 @@ var InjectiveSpokeProvider = class {
6840
6845
  return this.transfer(sender, token, to, amount, data, funds, raw);
6841
6846
  }
6842
6847
  async isNative(token) {
6843
- let isNative2 = true;
6844
- const injective20Token = new Injective20Token(this.walletProvider, token);
6845
- try {
6846
- await injective20Token.getTokenInfo();
6847
- isNative2 = false;
6848
- } catch (err) {
6849
- console.log("[InjectiveSpokeProvider] isNative error", err);
6850
- throw err;
6851
- }
6852
- return isNative2;
6848
+ return token === "inj";
6853
6849
  }
6854
6850
  async receiveMessage(senderAddress, srcChainId, srcAddress, connSn, payload, signatures) {
6855
6851
  const msg = {
@@ -6923,10 +6919,12 @@ var IconSpokeProvider = class {
6923
6919
  walletProvider;
6924
6920
  chainConfig;
6925
6921
  iconService;
6926
- constructor(walletProvider, chainConfig, rpcUrl = "https://ctz.solidwallet.io/api/v3") {
6922
+ debugRpcUrl;
6923
+ constructor(walletProvider, chainConfig, rpcUrl = "https://ctz.solidwallet.io/api/v3", debugRpcUrl = "https://ctz.solidwallet.io/api/v3d") {
6927
6924
  this.walletProvider = walletProvider;
6928
6925
  this.chainConfig = chainConfig;
6929
6926
  this.iconService = new IconSdk.IconService(new IconSdk.IconService.HttpProvider(rpcUrl));
6927
+ this.debugRpcUrl = debugRpcUrl;
6930
6928
  }
6931
6929
  };
6932
6930
 
@@ -7177,7 +7175,7 @@ var StellarSpokeProvider = class {
7177
7175
  networkPassphrase: network.passphrase
7178
7176
  }).addOperation(operation).setTimeout(STELLAR_DEFAULT_TX_TIMEOUT_SECONDS).build();
7179
7177
  const simulation = await this.sorobanServer.simulateTransaction(priorityTransaction);
7180
- return [stellarSdk.SorobanRpc.assembleTransaction(priorityTransaction, simulation).build(), simulation];
7178
+ return [priorityTransaction, simulation];
7181
7179
  }
7182
7180
  handleSendTransactionError(response) {
7183
7181
  if (response.status === "ERROR") {
@@ -7265,9 +7263,14 @@ var StellarSpokeProvider = class {
7265
7263
  const accountResponse = await this.server.loadAccount(walletAddress);
7266
7264
  const stellarAccount = new CustomStellarAccount(accountResponse);
7267
7265
  const depositCall = this.buildDepositCall(walletAddress, token, amount, recipient, data);
7268
- const [priorityTx, simulation] = await this.buildPriorityStellarTransaction(stellarAccount, network, depositCall);
7266
+ const [rawPriorityTx, simulation] = await this.buildPriorityStellarTransaction(
7267
+ stellarAccount,
7268
+ network,
7269
+ depositCall
7270
+ );
7271
+ const assembledPriorityTx = stellarSdk.SorobanRpc.assembleTransaction(rawPriorityTx, simulation).build();
7269
7272
  if (raw) {
7270
- const transactionXdr = priorityTx.toXDR();
7273
+ const transactionXdr = rawPriorityTx.toXDR();
7271
7274
  return {
7272
7275
  from: walletAddress,
7273
7276
  to: this.chainConfig.addresses.assetManager,
@@ -7275,7 +7278,13 @@ var StellarSpokeProvider = class {
7275
7278
  data: transactionXdr
7276
7279
  };
7277
7280
  }
7278
- const hash = await this.submitOrRestoreAndRetry(stellarAccount, network, priorityTx, depositCall, simulation);
7281
+ const hash = await this.submitOrRestoreAndRetry(
7282
+ stellarAccount,
7283
+ network,
7284
+ assembledPriorityTx,
7285
+ depositCall,
7286
+ simulation
7287
+ );
7279
7288
  return `${hash}`;
7280
7289
  } catch (error) {
7281
7290
  console.error("Error during deposit:", error);
@@ -7344,9 +7353,11 @@ var StellarSpokeProvider = class {
7344
7353
  var SuiSpokeProvider = class _SuiSpokeProvider {
7345
7354
  walletProvider;
7346
7355
  chainConfig;
7356
+ publicClient;
7347
7357
  constructor(config, wallet_provider) {
7348
7358
  this.chainConfig = config;
7349
7359
  this.walletProvider = wallet_provider;
7360
+ this.publicClient = new client.SuiClient({ url: client.getFullnodeUrl("mainnet") });
7350
7361
  }
7351
7362
  async getBalance(token) {
7352
7363
  const assetmanager = this.splitAddress(this.chainConfig.addresses.assetManager);
@@ -7386,7 +7397,11 @@ var SuiSpokeProvider = class _SuiSpokeProvider {
7386
7397
  ]
7387
7398
  });
7388
7399
  if (raw) {
7389
- const transactionRaw = await tx.build();
7400
+ tx.setSender(walletAddress);
7401
+ const transactionRaw = await tx.build({
7402
+ client: this.publicClient,
7403
+ onlyTransactionKind: true
7404
+ });
7390
7405
  const transactionRawBase64String = Buffer.from(transactionRaw).toString("base64");
7391
7406
  return {
7392
7407
  from: walletAddress,
@@ -7449,10 +7464,14 @@ var SuiSpokeProvider = class _SuiSpokeProvider {
7449
7464
  txb.pure(bcs.bcs.vector(bcs.bcs.u8()).serialize(data))
7450
7465
  ]
7451
7466
  });
7467
+ const walletAddress = await this.walletProvider.getWalletAddress();
7452
7468
  if (raw) {
7453
- const transactionRaw = await txb.build();
7469
+ txb.setSender(walletAddress);
7470
+ const transactionRaw = await txb.build({
7471
+ client: this.publicClient,
7472
+ onlyTransactionKind: true
7473
+ });
7454
7474
  const transactionRawBase64String = Buffer.from(transactionRaw).toString("base64");
7455
- const walletAddress = await this.walletProvider.getWalletAddressBytes();
7456
7475
  return {
7457
7476
  from: walletAddress,
7458
7477
  to: `${connection.packageId}::${connection.moduleId}::send_message_ua`,
@@ -8115,6 +8134,15 @@ function encodeAddress(spokeChainId, address) {
8115
8134
  return address;
8116
8135
  }
8117
8136
  }
8137
+ function hexToBigInt(hex) {
8138
+ const trimmed = hex.trim().toLowerCase();
8139
+ const isValid = /^(0x)?[0-9a-f]+$/.test(trimmed);
8140
+ if (!isValid) {
8141
+ throw new Error(`Invalid hex string: "${hex}"`);
8142
+ }
8143
+ const normalized = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
8144
+ return BigInt(normalized);
8145
+ }
8118
8146
  var MoneyMarketService = class _MoneyMarketService {
8119
8147
  config;
8120
8148
  hubProvider;
@@ -8142,6 +8170,15 @@ var MoneyMarketService = class _MoneyMarketService {
8142
8170
  }
8143
8171
  this.hubProvider = hubProvider;
8144
8172
  }
8173
+ /**
8174
+ * Estimate the gas for a raw transaction.
8175
+ * @param {TxReturnType<T, true>} params - The parameters for the raw transaction.
8176
+ * @param {SpokeProvider} spokeProvider - The provider for the spoke chain.
8177
+ * @returns {Promise<GetEstimateGasReturnType<T>>} A promise that resolves to the gas.
8178
+ */
8179
+ static async estimateGas(params, spokeProvider) {
8180
+ return SpokeService.estimateGas(params, spokeProvider);
8181
+ }
8145
8182
  /**
8146
8183
  * Check if allowance is sufficient for actions on the money market pool
8147
8184
  * @param {MoneyMarketParams} params - Money market params containing token address and amount
@@ -9305,6 +9342,37 @@ var MoneyMarketService = class _MoneyMarketService {
9305
9342
  var EvmSpokeService = class _EvmSpokeService {
9306
9343
  constructor() {
9307
9344
  }
9345
+ /**
9346
+ * Estimates the gas necessary to complete a transaction without submitting it to the network.
9347
+ *
9348
+ * - Docs: https://viem.sh/docs/actions/public/estimateGas
9349
+ * - JSON-RPC Methods: [`eth_estimateGas`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_estimategas)
9350
+ *
9351
+ * @param {EvmRawTransaction} rawTx - The raw transaction to estimate the gas for.
9352
+ * @param {EvmSpokeProvider} spokeProvider - The EVM spoke provider.
9353
+ * @returns {Promise<bigint>} Estimated gas for the transaction.
9354
+ *
9355
+ * @example
9356
+ *
9357
+ * const rawTx: EvmRawTransaction = {
9358
+ * from: '0x1234...abcd', // sender address
9359
+ * to: '0xabcd...1234', // recipient address
9360
+ * value: 1000000000000000000n, // 1 ETH in wei
9361
+ * data: '0x', // no calldata
9362
+ * };
9363
+ *
9364
+ * // Assume spokeProvider is an initialized EvmSpokeProvider
9365
+ * const estimatedGas = await EvmSpokeService.estimateGas(rawTx, spokeProvider);
9366
+ * console.log(`Estimated gas: ${estimatedGas}`);
9367
+ */
9368
+ static async estimateGas(rawTx, spokeProvider) {
9369
+ return spokeProvider.publicClient.estimateGas({
9370
+ account: rawTx.from,
9371
+ to: rawTx.to,
9372
+ value: rawTx.value,
9373
+ data: rawTx.data
9374
+ });
9375
+ }
9308
9376
  /**
9309
9377
  * Deposit tokens to the spoke chain.
9310
9378
  * @param {EvmSpokeDepositParams} params - The parameters for the deposit, including the user's address, token address, amount, and additional data.
@@ -9421,6 +9489,25 @@ var EvmSpokeService = class _EvmSpokeService {
9421
9489
  var InjectiveSpokeService = class _InjectiveSpokeService {
9422
9490
  constructor() {
9423
9491
  }
9492
+ /**
9493
+ * Estimate the gas for a transaction.
9494
+ * @param {InjectiveRawTransaction} rawTx - The raw transaction to estimate the gas for.
9495
+ * @param {InjectiveSpokeProvider} spokeProvider - The provider for the spoke chain.
9496
+ * @returns {Promise<InjectiveGasEstimate>} The estimated gas for the transaction.
9497
+ */
9498
+ static async estimateGas(rawTx, spokeProvider) {
9499
+ const txRaw = tx_js.TxRaw.fromPartial({
9500
+ bodyBytes: rawTx.signedDoc.bodyBytes,
9501
+ authInfoBytes: rawTx.signedDoc.authInfoBytes,
9502
+ signatures: []
9503
+ // not required for simulation
9504
+ });
9505
+ const { gasInfo } = await spokeProvider.txClient.simulate(txRaw);
9506
+ return {
9507
+ gasWanted: gasInfo.gasWanted,
9508
+ gasUsed: gasInfo.gasUsed
9509
+ };
9510
+ }
9424
9511
  /**
9425
9512
  * Deposit tokens to the spoke chain.
9426
9513
  * @param {InjectiveSpokeDepositParams} params - The parameters for the deposit, including the user's address, token address, amount, and additional data.
@@ -9496,11 +9583,44 @@ var InjectiveSpokeService = class _InjectiveSpokeService {
9496
9583
  return spokeProvider.send_message(sender, dstChainId.toString(), dstAddress, payload, raw);
9497
9584
  }
9498
9585
  };
9586
+
9587
+ // src/utils/icon-utils.ts
9588
+ async function estimateStepCost(rawTx, debugRpcUrl) {
9589
+ try {
9590
+ const tmpRawTx = { ...rawTx };
9591
+ delete tmpRawTx["stepLimit"];
9592
+ const response = await fetch(debugRpcUrl, {
9593
+ method: "POST",
9594
+ headers: {
9595
+ "Content-Type": "application/json"
9596
+ },
9597
+ body: JSON.stringify({
9598
+ jsonrpc: "2.0",
9599
+ method: "debug_estimateStep",
9600
+ id: 1234,
9601
+ params: tmpRawTx
9602
+ })
9603
+ });
9604
+ if (!response.ok) {
9605
+ throw new Error(`Failed to fetch step cost: ${response.statusText}`);
9606
+ }
9607
+ const data = await response.json();
9608
+ return hexToBigInt(data.result);
9609
+ } catch (e) {
9610
+ console.error("estimateStepCost error:", e);
9611
+ throw e;
9612
+ }
9613
+ }
9614
+
9615
+ // src/services/spoke/IconSpokeService.ts
9499
9616
  var IconSdk2 = "default" in IconSdkRaw__namespace.default ? IconSdkRaw__namespace.default : IconSdkRaw__namespace;
9500
9617
  var { Converter, CallTransactionBuilder, CallBuilder } = IconSdk2;
9501
9618
  var IconSpokeService = class _IconSpokeService {
9502
9619
  constructor() {
9503
9620
  }
9621
+ static async estimateGas(rawTx, spokeProvider) {
9622
+ return estimateStepCost(rawTx, spokeProvider.debugRpcUrl);
9623
+ }
9504
9624
  /**
9505
9625
  * Deposit tokens to the spoke chain.
9506
9626
  * @param {IconSpokeDepositParams} params - The parameters for the deposit
@@ -9564,15 +9684,16 @@ var IconSpokeService = class _IconSpokeService {
9564
9684
  };
9565
9685
  const value = isNativeToken(spokeProvider.chainConfig.chain.id, token) ? BigIntToHex(amount) : "0x0";
9566
9686
  const walletAddress = await spokeProvider.walletProvider.getWalletAddress();
9687
+ const to = isNativeToken(spokeProvider.chainConfig.chain.id, token) ? spokeProvider.chainConfig.addresses.wICX : token;
9567
9688
  const rawTransaction = Converter.toRawTransaction(
9568
- new CallTransactionBuilder().from(walletAddress).to(token).stepLimit(Converter.toBigNumber("2000000")).nid(spokeProvider.chainConfig.nid).version("0x3").timestamp((/* @__PURE__ */ new Date()).getTime() * 1e3).value(value).method("transfer").params(params).build()
9689
+ new CallTransactionBuilder().from(walletAddress).to(to).stepLimit(Converter.toBigNumber("2000000")).nid(spokeProvider.chainConfig.nid).version("0x3").timestamp((/* @__PURE__ */ new Date()).getTime() * 1e3).value(value).method("transfer").params(params).build()
9569
9690
  );
9570
9691
  if (raw) {
9571
9692
  return rawTransaction;
9572
9693
  }
9573
9694
  return spokeProvider.walletProvider.sendTransaction({
9574
9695
  from: walletAddress,
9575
- to: isNativeToken(spokeProvider.chainConfig.chain.id, token) ? spokeProvider.chainConfig.addresses.wICX : token,
9696
+ to,
9576
9697
  value,
9577
9698
  nid: spokeProvider.chainConfig.nid,
9578
9699
  method: "transfer",
@@ -9603,15 +9724,13 @@ var IconSpokeService = class _IconSpokeService {
9603
9724
  });
9604
9725
  }
9605
9726
  };
9606
- async function getProvider(base58PublicKey, rpcUrl, wsUrl) {
9727
+ async function getProvider(base58PublicKey, rpcUrl) {
9607
9728
  const wallet = {
9608
9729
  publicKey: new web3_js.PublicKey(base58PublicKey),
9609
9730
  signTransaction: () => Promise.reject(),
9610
9731
  signAllTransactions: () => Promise.reject()
9611
9732
  };
9612
- const connection = new web3_js.Connection(rpcUrl, {
9613
- wsEndpoint: wsUrl
9614
- });
9733
+ const connection = new web3_js.Connection(rpcUrl);
9615
9734
  return new anchor__namespace.AnchorProvider(connection, wallet, { commitment: "confirmed" });
9616
9735
  }
9617
9736
  async function getAssetManagerIdl(assetManager, provider) {
@@ -9638,13 +9757,13 @@ async function getConnectionIdl(connection, provider) {
9638
9757
  throw err;
9639
9758
  }
9640
9759
  }
9641
- async function getAssetManagerProgram(base58PublicKey, rpcUrl, wsUrl, assetManager) {
9642
- const provider = await getProvider(base58PublicKey, rpcUrl, wsUrl);
9760
+ async function getAssetManagerProgram(base58PublicKey, rpcUrl, assetManager) {
9761
+ const provider = await getProvider(base58PublicKey, rpcUrl);
9643
9762
  const idl = await getAssetManagerIdl(assetManager, provider);
9644
9763
  return new anchor__namespace.Program(idl, provider);
9645
9764
  }
9646
- async function getConnectionProgram(base58PublicKey, rpcUrl, wsUrl, connection) {
9647
- const provider = await getProvider(base58PublicKey, rpcUrl, wsUrl);
9765
+ async function getConnectionProgram(base58PublicKey, rpcUrl, connection) {
9766
+ const provider = await getProvider(base58PublicKey, rpcUrl);
9648
9767
  const idl = await getConnectionIdl(connection, provider);
9649
9768
  return new anchor__namespace.Program(idl, provider);
9650
9769
  }
@@ -9689,6 +9808,22 @@ var AssetManagerPDA = {
9689
9808
  var SolanaSpokeService = class _SolanaSpokeService {
9690
9809
  constructor() {
9691
9810
  }
9811
+ /**
9812
+ * Estimate the gas for a transaction.
9813
+ * @param {SolanaRawTransaction} rawTx - The raw transaction to estimate the gas for.
9814
+ * @param {SolanaSpokeProvider} spokeProvider - The provider for the spoke chain.
9815
+ * @returns {Promise<number | undefined>} The units consumed for the transaction.
9816
+ */
9817
+ static async estimateGas(rawTx, spokeProvider) {
9818
+ const connection = new web3_js.Connection(spokeProvider.chainConfig.rpcUrl, "confirmed");
9819
+ const serializedTxBytes = Buffer.from(rawTx.data, "base64");
9820
+ const versionedTx = web3_js.VersionedTransaction.deserialize(serializedTxBytes);
9821
+ const { value } = await connection.simulateTransaction(versionedTx);
9822
+ if (value.err) {
9823
+ throw new Error(`Failed to simulate transaction: ${JSON.stringify(value.err, null, 2)}`);
9824
+ }
9825
+ return value.unitsConsumed;
9826
+ }
9692
9827
  static async deposit(params, spokeProvider, hubProvider, raw) {
9693
9828
  const userWallet = params.to ?? await EvmWalletAbstraction.getUserHubWalletAddress(
9694
9829
  spokeProvider.chainConfig.chain.id,
@@ -9710,7 +9845,6 @@ var SolanaSpokeService = class _SolanaSpokeService {
9710
9845
  const assetManagerProgram = await getAssetManagerProgram(
9711
9846
  spokeProvider.walletProvider.getWalletBase58PublicKey(),
9712
9847
  spokeProvider.chainConfig.rpcUrl,
9713
- spokeProvider.chainConfig.wsUrl,
9714
9848
  spokeProvider.chainConfig.addresses.assetManager
9715
9849
  );
9716
9850
  const solToken = new web3_js.PublicKey(Buffer.from(token, "hex"));
@@ -9740,18 +9874,16 @@ var SolanaSpokeService = class _SolanaSpokeService {
9740
9874
  let depositInstruction;
9741
9875
  const amountBN = new BN__default.default(amount);
9742
9876
  const { walletProvider, chainConfig } = spokeProvider;
9743
- const { rpcUrl, wsUrl, addresses } = chainConfig;
9877
+ const { rpcUrl, addresses } = chainConfig;
9744
9878
  const walletPublicKey = new web3_js.PublicKey(walletProvider.getWalletBase58PublicKey());
9745
9879
  const assetManagerProgram = await getAssetManagerProgram(
9746
9880
  walletProvider.getWalletBase58PublicKey(),
9747
9881
  rpcUrl,
9748
- wsUrl,
9749
9882
  addresses.assetManager
9750
9883
  );
9751
9884
  const connectionProgram = await getConnectionProgram(
9752
9885
  walletProvider.getWalletBase58PublicKey(),
9753
9886
  rpcUrl,
9754
- wsUrl,
9755
9887
  addresses.connection
9756
9888
  );
9757
9889
  if (isNative(token)) {
@@ -9826,12 +9958,11 @@ var SolanaSpokeService = class _SolanaSpokeService {
9826
9958
  */
9827
9959
  static async call(dstChainId, dstAddress, payload, spokeProvider, raw) {
9828
9960
  const { walletProvider, chainConfig } = spokeProvider;
9829
- const { rpcUrl, wsUrl, addresses } = chainConfig;
9961
+ const { rpcUrl, addresses } = chainConfig;
9830
9962
  const walletPublicKey = new web3_js.PublicKey(walletProvider.getWalletBase58PublicKey());
9831
9963
  const connectionProgram = await getConnectionProgram(
9832
9964
  walletProvider.getWalletBase58PublicKey(),
9833
9965
  rpcUrl,
9834
- wsUrl,
9835
9966
  addresses.connection
9836
9967
  );
9837
9968
  const sendMessageInstruction = await connectionProgram.methods.sendMessage(
@@ -9869,6 +10000,24 @@ var SolanaSpokeService = class _SolanaSpokeService {
9869
10000
  var StellarSpokeService = class _StellarSpokeService {
9870
10001
  constructor() {
9871
10002
  }
10003
+ /**
10004
+ * Estimate the gas for a transaction.
10005
+ * @param rawTx - The raw transaction to estimate the gas for.
10006
+ * @param spokeProvider - The spoke provider.
10007
+ * @returns The estimated gas (minResourceFee) for the transaction.
10008
+ */
10009
+ static async estimateGas(rawTx, spokeProvider) {
10010
+ const network = await spokeProvider.sorobanServer.getNetwork();
10011
+ let tx = stellarSdk.TransactionBuilder.fromXDR(rawTx.data, network.passphrase);
10012
+ if (tx instanceof stellarSdk.FeeBumpTransaction) {
10013
+ tx = tx.innerTransaction;
10014
+ }
10015
+ const simulationForFee = await spokeProvider.sorobanServer.simulateTransaction(tx);
10016
+ if (!stellarSdk.rpc.Api.isSimulationSuccess(simulationForFee)) {
10017
+ throw new Error(`Simulation error: ${JSON.stringify(simulationForFee)}`);
10018
+ }
10019
+ return BigInt(simulationForFee.minResourceFee);
10020
+ }
9872
10021
  static async deposit(params, spokeProvider, hubProvider, raw) {
9873
10022
  const userWallet = params.to ?? await EvmWalletAbstraction.getUserHubWalletAddress(
9874
10023
  spokeProvider.chainConfig.chain.id,
@@ -9923,6 +10072,20 @@ var StellarSpokeService = class _StellarSpokeService {
9923
10072
  var SuiSpokeService = class _SuiSpokeService {
9924
10073
  constructor() {
9925
10074
  }
10075
+ /**
10076
+ * Estimate the gas for a transaction.
10077
+ * @param {SuiRawTransaction} rawTx - The raw transaction to estimate the gas for.
10078
+ * @param {SuiSpokeProvider} spokeProvider - The spoke provider.
10079
+ * @returns {Promise<bigint>} The estimated computation cost.
10080
+ */
10081
+ static async estimateGas(rawTx, spokeProvider) {
10082
+ const txb = transactions.Transaction.fromKind(rawTx.data);
10083
+ const result = await spokeProvider.publicClient.devInspectTransactionBlock({
10084
+ sender: rawTx.from,
10085
+ transactionBlock: txb
10086
+ });
10087
+ return result.effects.gasUsed;
10088
+ }
9926
10089
  /**
9927
10090
  * Deposit tokens to the spoke chain.
9928
10091
  * @param {InjectiveSpokeDepositParams} params - The parameters for the deposit, including the user's address, token address, amount, and additional data.
@@ -9972,7 +10135,7 @@ var SuiSpokeService = class _SuiSpokeService {
9972
10135
  }
9973
10136
  /**
9974
10137
  * Transfers tokens to the hub chain.
9975
- * @param {TransferToHubParams} params - The parameters for the transfer, including:
10138
+ * @param {SuiTransferToHubParams} params - The parameters for the transfer, including:
9976
10139
  * - {string} token: The address of the token to transfer (use address(0) for native token).
9977
10140
  * - {Uint8Array} recipient: The recipient address on the hub chain.
9978
10141
  * - {string} amount: The amount to transfer.
@@ -10000,6 +10163,38 @@ var SuiSpokeService = class _SuiSpokeService {
10000
10163
  var SonicSpokeService = class _SonicSpokeService {
10001
10164
  constructor() {
10002
10165
  }
10166
+ /**
10167
+ /**
10168
+ * Estimates the gas necessary to complete a transaction without submitting it to the network.
10169
+ *
10170
+ * - Docs: https://viem.sh/docs/actions/public/estimateGas
10171
+ * - JSON-RPC Methods: [`eth_estimateGas`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_estimategas)
10172
+ *
10173
+ * @param {EvmRawTransaction} rawTx - The raw transaction to estimate the gas for.
10174
+ * @param {SonicSpokeProvider} spokeProvider - The EVM spoke provider.
10175
+ * @returns {Promise<bigint>} Estimated gas for the transaction.
10176
+ *
10177
+ * @example
10178
+ *
10179
+ * const rawTx: EvmRawTransaction = {
10180
+ * from: '0x1234...abcd', // sender address
10181
+ * to: '0xabcd...1234', // recipient address
10182
+ * value: 1000000000000000000n, // 1 ETH in wei
10183
+ * data: '0x', // no calldata
10184
+ * };
10185
+ *
10186
+ * // Assume spokeProvider is an initialized EvmSpokeProvider
10187
+ * const estimatedGas = await EvmSpokeService.estimateGas(rawTx, spokeProvider);
10188
+ * console.log(`Estimated gas: ${estimatedGas}`);
10189
+ */
10190
+ static async estimateGas(rawTx, spokeProvider) {
10191
+ return spokeProvider.publicClient.estimateGas({
10192
+ account: rawTx.from,
10193
+ to: rawTx.to,
10194
+ value: rawTx.value,
10195
+ data: rawTx.data
10196
+ });
10197
+ }
10003
10198
  /**
10004
10199
  * Get the derived address of a contract deployed with CREATE3.
10005
10200
  * @param address - User's address on the specified chain as hex
@@ -10440,6 +10635,57 @@ function isMoneyMarketRepayUnknownError(error) {
10440
10635
  var SpokeService = class {
10441
10636
  constructor() {
10442
10637
  }
10638
+ /**
10639
+ * Estimate the gas for a raw transaction.
10640
+ * @param {TxReturnType<T, true>} params - The parameters for the raw transaction.
10641
+ * @param {SpokeProvider} spokeProvider - The provider for the spoke chain.
10642
+ * @returns {Promise<GetEstimateGasReturnType<T>>} A promise that resolves to the gas.
10643
+ */
10644
+ static async estimateGas(params, spokeProvider) {
10645
+ if (spokeProvider instanceof EvmSpokeProvider) {
10646
+ return EvmSpokeService.estimateGas(
10647
+ params,
10648
+ spokeProvider
10649
+ );
10650
+ }
10651
+ if (spokeProvider instanceof SonicSpokeProvider) {
10652
+ return SonicSpokeService.estimateGas(
10653
+ params,
10654
+ spokeProvider
10655
+ );
10656
+ }
10657
+ if (spokeProvider instanceof InjectiveSpokeProvider) {
10658
+ return InjectiveSpokeService.estimateGas(
10659
+ params,
10660
+ spokeProvider
10661
+ );
10662
+ }
10663
+ if (spokeProvider instanceof IconSpokeProvider) {
10664
+ return IconSpokeService.estimateGas(
10665
+ params,
10666
+ spokeProvider
10667
+ );
10668
+ }
10669
+ if (spokeProvider instanceof SuiSpokeProvider) {
10670
+ return SuiSpokeService.estimateGas(
10671
+ params,
10672
+ spokeProvider
10673
+ );
10674
+ }
10675
+ if (spokeProvider instanceof SolanaSpokeProvider) {
10676
+ return SolanaSpokeService.estimateGas(
10677
+ params,
10678
+ spokeProvider
10679
+ );
10680
+ }
10681
+ if (spokeProvider instanceof StellarSpokeProvider) {
10682
+ return StellarSpokeService.estimateGas(
10683
+ params,
10684
+ spokeProvider
10685
+ );
10686
+ }
10687
+ throw new Error("Invalid spoke provider");
10688
+ }
10443
10689
  /**
10444
10690
  * Deposit tokens to the spoke chain.
10445
10691
  * @param {GetSpokeDepositParamsType<T extends SpokeProvider>} params - The parameters for the deposit, including the user's address, token address, amount, and additional data.
@@ -11078,6 +11324,15 @@ var SolverService = class {
11078
11324
  }
11079
11325
  this.hubProvider = hubProvider;
11080
11326
  }
11327
+ /**
11328
+ * Estimate the gas for a raw transaction.
11329
+ * @param {TxReturnType<T, true>} params - The parameters for the raw transaction.
11330
+ * @param {SpokeProvider} spokeProvider - The provider for the spoke chain.
11331
+ * @returns {Promise<GetEstimateGasReturnType<T>>} A promise that resolves to the gas.
11332
+ */
11333
+ static async estimateGas(params, spokeProvider) {
11334
+ return SpokeService.estimateGas(params, spokeProvider);
11335
+ }
11081
11336
  /**
11082
11337
  * Request a quote from the solver API
11083
11338
  * @param {SolverIntentQuoteRequest} payload - The solver intent quote request
@@ -12673,6 +12928,7 @@ exports.getSpokeChainIdFromIntentRelayChainId = getSpokeChainIdFromIntentRelayCh
12673
12928
  exports.getSupportedMoneyMarketTokens = getSupportedMoneyMarketTokens;
12674
12929
  exports.getSupportedSolverTokens = getSupportedSolverTokens;
12675
12930
  exports.getTransactionPackets = getTransactionPackets;
12931
+ exports.hexToBigInt = hexToBigInt;
12676
12932
  exports.hubAssetToOriginalAssetMap = hubAssetToOriginalAssetMap;
12677
12933
  exports.hubAssets = hubAssets;
12678
12934
  exports.hubVaults = hubVaults;