@sodax/sdk 1.0.1-beta-rc3 → 1.0.2-beta

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/dist/index.cjs CHANGED
@@ -6933,6 +6933,11 @@ var ConfigService = class {
6933
6933
  getMoneyMarketTokens() {
6934
6934
  return this.sodaxConfig.supportedMoneyMarketTokens;
6935
6935
  }
6936
+ getMoneyMarketToken(chainId, token) {
6937
+ return this.sodaxConfig.supportedMoneyMarketTokens[chainId].find(
6938
+ (t) => t.address.toLowerCase() === token.toLowerCase()
6939
+ );
6940
+ }
6936
6941
  getMoneyMarketReserveAssets() {
6937
6942
  return this.sodaxConfig.supportedMoneyMarketReserveAssets;
6938
6943
  }
@@ -6952,7 +6957,10 @@ var ConfigService = class {
6952
6957
  return this.supportedSodaVaultAssetsSet.has(vault.toLowerCase());
6953
6958
  }
6954
6959
  isValidVault(vault) {
6955
- return this.isValidSodaVaultAsset(vault);
6960
+ if (typeof vault === "string") {
6961
+ return this.isValidSodaVaultAsset(vault);
6962
+ }
6963
+ return this.isValidSodaVaultAsset(vault.address);
6956
6964
  }
6957
6965
  isValidChainHubAsset(chainId, hubAsset) {
6958
6966
  return this.chainIdToHubAssetsMap.get(chainId)?.has(hubAsset.toLowerCase()) ?? false;
@@ -12927,7 +12935,8 @@ var SwapService = class {
12927
12935
  intentParams: params,
12928
12936
  spokeProvider,
12929
12937
  fee = this.config.partnerFee,
12930
- raw
12938
+ raw,
12939
+ skipSimulation = false
12931
12940
  }) {
12932
12941
  invariant6__default.default(
12933
12942
  this.configService.isValidOriginalAssetAddress(params.srcChain, params.inputToken),
@@ -12996,7 +13005,8 @@ var SwapService = class {
12996
13005
  },
12997
13006
  spokeProvider,
12998
13007
  this.hubProvider,
12999
- raw
13008
+ raw,
13009
+ skipSimulation
13000
13010
  );
13001
13011
  return {
13002
13012
  ok: true,
@@ -13016,6 +13026,179 @@ var SwapService = class {
13016
13026
  };
13017
13027
  }
13018
13028
  }
13029
+ /**
13030
+ * Creates a limit order intent (no deadline, must be cancelled manually by user).
13031
+ * Similar to swap but enforces deadline=0n (no deadline).
13032
+ * Limit orders remain active until manually cancelled by the user.
13033
+ *
13034
+ * @param {Prettify<LimitOrderParams<S> & OptionalTimeout>} params - Object containing:
13035
+ * - intentParams: The parameters for creating the limit order (deadline is automatically set to 0n, deadline field should be omitted).
13036
+ * - spokeProvider: The spoke provider instance.
13037
+ * - fee: (Optional) Partner fee configuration.
13038
+ * - timeout: (Optional) Timeout in milliseconds for the transaction (default: 60 seconds).
13039
+ * - skipSimulation: (Optional) Whether to skip transaction simulation (default: false).
13040
+ * @returns {Promise<Result<[SolverExecutionResponse, Intent, IntentDeliveryInfo], IntentError<IntentErrorCode>>>} A promise resolving to a Result containing a tuple of SolverExecutionResponse, Intent, and intent delivery info, or an IntentError if the operation fails.
13041
+ *
13042
+ * @example
13043
+ * const payload = {
13044
+ * "inputToken": "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", // BSC ETH token address
13045
+ * "outputToken": "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f", // ARB WBTC token address
13046
+ * "inputAmount": 1000000000000000n, // The amount of input tokens
13047
+ * "minOutputAmount": 900000000000000n, // min amount you are expecting to receive
13048
+ * // deadline is omitted - will be automatically set to 0n
13049
+ * "allowPartialFill": false, // Whether the intent can be partially filled
13050
+ * "srcChain": "0x38.bsc", // Chain ID where input tokens originate
13051
+ * "dstChain": "0xa4b1.arbitrum", // Chain ID where output tokens should be delivered
13052
+ * "srcAddress": "0x..", // Source address (original address on spoke chain)
13053
+ * "dstAddress": "0x...", // Destination address (original address on spoke chain)
13054
+ * "solver": "0x..", // Optional specific solver address (address(0) = any solver)
13055
+ * "data": "0x..", // Additional arbitrary data
13056
+ * } satisfies CreateLimitOrderParams;
13057
+ *
13058
+ * const createLimitOrderResult = await swapService.createLimitOrder({
13059
+ * intentParams: payload,
13060
+ * spokeProvider,
13061
+ * fee, // optional
13062
+ * timeout, // optional
13063
+ * });
13064
+ *
13065
+ * if (createLimitOrderResult.ok) {
13066
+ * const [solverExecutionResponse, intent, intentDeliveryInfo] = createLimitOrderResult.value;
13067
+ * console.log('Intent execution response:', solverExecutionResponse);
13068
+ * console.log('Intent:', intent);
13069
+ * console.log('Intent delivery info:', intentDeliveryInfo);
13070
+ * // Limit order is now active and will remain until cancelled manually
13071
+ * } else {
13072
+ * // handle error
13073
+ * }
13074
+ */
13075
+ async createLimitOrder({
13076
+ intentParams: params,
13077
+ spokeProvider,
13078
+ fee = this.config.partnerFee,
13079
+ timeout = DEFAULT_RELAY_TX_TIMEOUT,
13080
+ skipSimulation = false
13081
+ }) {
13082
+ const limitOrderParams = {
13083
+ ...params,
13084
+ deadline: 0n
13085
+ };
13086
+ return this.createAndSubmitIntent({
13087
+ intentParams: limitOrderParams,
13088
+ spokeProvider,
13089
+ fee,
13090
+ timeout,
13091
+ skipSimulation
13092
+ });
13093
+ }
13094
+ /**
13095
+ * Creates a limit order intent (no deadline, must be cancelled manually by user).
13096
+ * Similar to createIntent but enforces deadline=0n (no deadline) and uses LimitOrderParams.
13097
+ * Limit orders remain active until manually cancelled by the user.
13098
+ * NOTE: This method does not submit the intent to the Solver API
13099
+ *
13100
+ * @param {Prettify<LimitOrderParams<S> & OptionalRaw<R>>} params - Object containing:
13101
+ * - intentParams: The parameters for creating the limit order (deadline is automatically set to 0n, deadline field should be omitted).
13102
+ * - spokeProvider: The spoke provider instance.
13103
+ * - fee: (Optional) Partner fee configuration.
13104
+ * - raw: (Optional) Whether to return the raw transaction data instead of executing it
13105
+ * - skipSimulation: (Optional) Whether to skip transaction simulation (default: false).
13106
+ * @returns {Promise<Result<[TxReturnType<S, R>, Intent & FeeAmount, Hex], IntentError<'CREATION_FAILED'>>>} The encoded contract call or raw transaction data, Intent and intent data as hex
13107
+ *
13108
+ * @example
13109
+ * const payload = {
13110
+ * "inputToken": "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", // BSC ETH token address
13111
+ * "outputToken": "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f", // ARB WBTC token address
13112
+ * "inputAmount": 1000000000000000n, // The amount of input tokens
13113
+ * "minOutputAmount": 900000000000000n, // min amount you are expecting to receive
13114
+ * // deadline is omitted - will be automatically set to 0n
13115
+ * "allowPartialFill": false, // Whether the intent can be partially filled
13116
+ * "srcChain": "0x38.bsc", // Chain ID where input tokens originate
13117
+ * "dstChain": "0xa4b1.arbitrum", // Chain ID where output tokens should be delivered
13118
+ * "srcAddress": "0x..", // Source address (original address on spoke chain)
13119
+ * "dstAddress": "0x...", // Destination address (original address on spoke chain)
13120
+ * "solver": "0x..", // Optional specific solver address (address(0) = any solver)
13121
+ * "data": "0x..", // Additional arbitrary data
13122
+ * } satisfies CreateLimitOrderParams;
13123
+ *
13124
+ * const createLimitOrderIntentResult = await swapService.createLimitOrderIntent({
13125
+ * intentParams: payload,
13126
+ * spokeProvider,
13127
+ * fee, // optional
13128
+ * raw, // optional
13129
+ * });
13130
+ *
13131
+ * if (createLimitOrderIntentResult.ok) {
13132
+ * const [txResult, intent, intentData] = createLimitOrderIntentResult.value;
13133
+ * console.log('Transaction result:', txResult);
13134
+ * console.log('Intent:', intent);
13135
+ * console.log('Intent data:', intentData);
13136
+ * } else {
13137
+ * // handle error
13138
+ * }
13139
+ */
13140
+ async createLimitOrderIntent({
13141
+ intentParams: params,
13142
+ spokeProvider,
13143
+ fee = this.config.partnerFee,
13144
+ raw,
13145
+ skipSimulation = false
13146
+ }) {
13147
+ const limitOrderParams = {
13148
+ ...params,
13149
+ deadline: 0n
13150
+ };
13151
+ return this.createIntent({
13152
+ intentParams: limitOrderParams,
13153
+ spokeProvider,
13154
+ fee,
13155
+ raw,
13156
+ skipSimulation
13157
+ });
13158
+ }
13159
+ /**
13160
+ * Syntactic sugar for cancelAndSubmitIntent: cancels a limit order intent and submits it to the Relayer API.
13161
+ * Similar to swap function that wraps createAndSubmitIntent.
13162
+ *
13163
+ * @param params - Object containing:
13164
+ * @param params.intent - The limit order intent to cancel.
13165
+ * @param params.spokeProvider - The spoke provider instance.
13166
+ * @param params.timeout - (Optional) Timeout in milliseconds for the transaction (default: 60 seconds).
13167
+ * @returns
13168
+ * A promise resolving to a Result containing a tuple of cancel transaction hash and destination transaction hash,
13169
+ * or an IntentError if the operation fails.
13170
+ *
13171
+ * @example
13172
+ * // Get intent first (or use intent from createLimitOrder response)
13173
+ * const intent: Intent = await swapService.getIntent(txHash);
13174
+ *
13175
+ * // Cancel the limit order
13176
+ * const result = await swapService.cancelLimitOrder({
13177
+ * intent,
13178
+ * spokeProvider,
13179
+ * timeout, // optional
13180
+ * });
13181
+ *
13182
+ * if (result.ok) {
13183
+ * const [cancelTxHash, dstTxHash] = result.value;
13184
+ * console.log('Cancel transaction hash:', cancelTxHash);
13185
+ * console.log('Destination transaction hash:', dstTxHash);
13186
+ * } else {
13187
+ * // handle error
13188
+ * console.error('[cancelLimitOrder] error:', result.error);
13189
+ * }
13190
+ */
13191
+ async cancelLimitOrder({
13192
+ intent,
13193
+ spokeProvider,
13194
+ timeout = DEFAULT_RELAY_TX_TIMEOUT
13195
+ }) {
13196
+ return this.cancelAndSubmitIntent({
13197
+ intent,
13198
+ spokeProvider,
13199
+ timeout
13200
+ });
13201
+ }
13019
13202
  /**
13020
13203
  * Cancels an intent
13021
13204
  * @param {Intent} intent - The intent to cancel
@@ -13057,7 +13240,97 @@ var SwapService = class {
13057
13240
  } catch (error) {
13058
13241
  return {
13059
13242
  ok: false,
13060
- error
13243
+ error: {
13244
+ code: "CANCEL_FAILED",
13245
+ data: {
13246
+ payload: intent,
13247
+ error
13248
+ }
13249
+ }
13250
+ };
13251
+ }
13252
+ }
13253
+ /**
13254
+ * Cancels an intent on the spoke chain, submits the cancel intent to the relayer API,
13255
+ * and waits until the intent cancel is executed (on the destination/hub chain).
13256
+ * Follows a similar workflow to createAndSubmitIntent, but for cancelling.
13257
+ *
13258
+ * @param params - The parameters for canceling and submitting the intent.
13259
+ * @param params.intent - The intent to be canceled.
13260
+ * @param params.spokeProvider - The provider for the spoke chain.
13261
+ * @param params.timeout - Optional timeout in milliseconds (default: 60 seconds).
13262
+ * @returns
13263
+ * A Result containing the SolverExecutionResponse (cancel tx), intent, and relay info,
13264
+ * or an IntentError on failure.
13265
+ */
13266
+ async cancelAndSubmitIntent({
13267
+ intent,
13268
+ spokeProvider,
13269
+ timeout = DEFAULT_RELAY_TX_TIMEOUT
13270
+ }) {
13271
+ try {
13272
+ const cancelResult = await this.cancelIntent(intent, spokeProvider, false);
13273
+ if (!cancelResult.ok) {
13274
+ return cancelResult;
13275
+ }
13276
+ const cancelTxHash = cancelResult.value;
13277
+ const verifyTxHashResult = await SpokeService.verifyTxHash(cancelTxHash, spokeProvider);
13278
+ if (!verifyTxHashResult.ok) {
13279
+ return {
13280
+ ok: false,
13281
+ error: {
13282
+ code: "CANCEL_FAILED",
13283
+ data: {
13284
+ payload: intent,
13285
+ error: verifyTxHashResult.error
13286
+ }
13287
+ }
13288
+ };
13289
+ }
13290
+ let dstIntentTxHash;
13291
+ if (spokeProvider.chainConfig.chain.id !== this.hubProvider.chainConfig.chain.id) {
13292
+ const intentRelayChainId = intent.srcChain.toString();
13293
+ const submitPayload = {
13294
+ action: "submit",
13295
+ params: {
13296
+ chain_id: intentRelayChainId,
13297
+ tx_hash: cancelTxHash
13298
+ }
13299
+ };
13300
+ const submitResult = await this.submitIntent(submitPayload);
13301
+ if (!submitResult.ok) {
13302
+ return submitResult;
13303
+ }
13304
+ const packet = await waitUntilIntentExecuted({
13305
+ intentRelayChainId,
13306
+ spokeTxHash: cancelTxHash,
13307
+ timeout,
13308
+ apiUrl: this.config.relayerApiEndpoint
13309
+ });
13310
+ if (!packet.ok) {
13311
+ return {
13312
+ ok: false,
13313
+ error: packet.error
13314
+ };
13315
+ }
13316
+ dstIntentTxHash = packet.value.dst_tx_hash;
13317
+ } else {
13318
+ dstIntentTxHash = cancelTxHash;
13319
+ }
13320
+ return {
13321
+ ok: true,
13322
+ value: [cancelTxHash, dstIntentTxHash]
13323
+ };
13324
+ } catch (error) {
13325
+ return {
13326
+ ok: false,
13327
+ error: {
13328
+ code: "CANCEL_FAILED",
13329
+ data: {
13330
+ payload: intent,
13331
+ error
13332
+ }
13333
+ }
13061
13334
  };
13062
13335
  }
13063
13336
  }
@@ -13374,7 +13647,7 @@ var SonicSpokeService = class _SonicSpokeService {
13374
13647
  const aTokenAddress = (await dataService.getReserveData(vaultAddress)).aTokenAddress;
13375
13648
  return {
13376
13649
  aTokenAddress,
13377
- aTokenAmount: amount,
13650
+ aTokenAmount: EvmVaultTokenService.translateIncomingDecimals(assetConfig.decimal, amount),
13378
13651
  token
13379
13652
  };
13380
13653
  }
@@ -13387,12 +13660,15 @@ var SonicSpokeService = class _SonicSpokeService {
13387
13660
  * @param configService - The config service
13388
13661
  * @returns BorrowInfo containing variable debt token address and vault address
13389
13662
  */
13390
- static async getBorrowInfo(token, amount, chainId, dataService, configService) {
13663
+ static async getBorrowInfo(token, amount, chainId, dataService, configService, moneyMarketConfig) {
13391
13664
  const assetConfig = configService.getHubAssetInfo(chainId, token);
13392
13665
  if (!assetConfig) {
13393
13666
  throw new Error("[SonicSpokeService.getBorrowInfo] Hub asset not found");
13394
13667
  }
13395
- const vaultAddress = assetConfig.vault;
13668
+ let vaultAddress = assetConfig.vault;
13669
+ if (moneyMarketConfig.bnUSDVault.toLowerCase() === vaultAddress.toLowerCase()) {
13670
+ vaultAddress = moneyMarketConfig.bnUSD;
13671
+ }
13396
13672
  const reserveData = await dataService.getReserveData(vaultAddress);
13397
13673
  const variableDebtTokenAddress = reserveData.variableDebtTokenAddress;
13398
13674
  return {
@@ -13604,10 +13880,18 @@ var MoneyMarketService = class _MoneyMarketService {
13604
13880
  try {
13605
13881
  invariant6__default.default(params.amount > 0n, "Amount must be greater than 0");
13606
13882
  invariant6__default.default(params.token.length > 0, "Token is required");
13607
- invariant6__default.default(
13608
- this.configService.isMoneyMarketSupportedToken(spokeProvider.chainConfig.chain.id, params.token),
13609
- `Unsupported spoke chain (${spokeProvider.chainConfig.chain.id}) token: ${params.token}`
13610
- );
13883
+ if (params.action === "withdraw" || params.action === "borrow") {
13884
+ const toChainId = params.toChainId ?? spokeProvider.chainConfig.chain.id;
13885
+ invariant6__default.default(
13886
+ this.configService.isMoneyMarketSupportedToken(toChainId, params.token),
13887
+ `Unsupported spoke chain (${toChainId}) token: ${params.token}`
13888
+ );
13889
+ } else {
13890
+ invariant6__default.default(
13891
+ this.configService.isMoneyMarketSupportedToken(spokeProvider.chainConfig.chain.id, params.token),
13892
+ `Unsupported spoke chain (${spokeProvider.chainConfig.chain.id}) token: ${params.token}`
13893
+ );
13894
+ }
13611
13895
  const walletAddress = await spokeProvider.walletProvider.getWalletAddress();
13612
13896
  if (spokeProvider instanceof StellarSpokeProvider && (params.action === "supply" || params.action === "repay")) {
13613
13897
  return {
@@ -13645,7 +13929,8 @@ var MoneyMarketService = class _MoneyMarketService {
13645
13929
  params.amount,
13646
13930
  params.toChainId ?? spokeProvider.chainConfig.chain.id,
13647
13931
  this.data,
13648
- this.configService
13932
+ this.configService,
13933
+ this.config
13649
13934
  );
13650
13935
  return await SonicSpokeService.isBorrowApproved(
13651
13936
  walletAddress,
@@ -13709,10 +13994,18 @@ var MoneyMarketService = class _MoneyMarketService {
13709
13994
  try {
13710
13995
  invariant6__default.default(params.amount > 0n, "Amount must be greater than 0");
13711
13996
  invariant6__default.default(params.token.length > 0, "Token is required");
13712
- invariant6__default.default(
13713
- this.configService.isMoneyMarketSupportedToken(spokeProvider.chainConfig.chain.id, params.token),
13714
- `Unsupported spoke chain (${spokeProvider.chainConfig.chain.id}) token: ${params.token}`
13715
- );
13997
+ if (params.action === "withdraw" || params.action === "borrow") {
13998
+ const toChainId = params.toChainId ?? spokeProvider.chainConfig.chain.id;
13999
+ invariant6__default.default(
14000
+ this.configService.isMoneyMarketSupportedToken(toChainId, params.token),
14001
+ `Unsupported spoke chain (${toChainId}) token: ${params.token}`
14002
+ );
14003
+ } else {
14004
+ invariant6__default.default(
14005
+ this.configService.isMoneyMarketSupportedToken(spokeProvider.chainConfig.chain.id, params.token),
14006
+ `Unsupported spoke chain (${spokeProvider.chainConfig.chain.id}) token: ${params.token}`
14007
+ );
14008
+ }
13716
14009
  const walletAddress = await spokeProvider.walletProvider.getWalletAddress();
13717
14010
  if (spokeProvider instanceof StellarSpokeProvider) {
13718
14011
  invariant6__default.default(
@@ -13774,7 +14067,8 @@ var MoneyMarketService = class _MoneyMarketService {
13774
14067
  params.amount,
13775
14068
  params?.toChainId ?? spokeProvider.chainConfig.chain.id,
13776
14069
  this.data,
13777
- this.configService
14070
+ this.configService,
14071
+ this.config
13778
14072
  );
13779
14073
  const result = await SonicSpokeService.approveBorrow(
13780
14074
  walletAddress,
@@ -13863,7 +14157,7 @@ var MoneyMarketService = class _MoneyMarketService {
13863
14157
  };
13864
14158
  }
13865
14159
  let intentTxHash = null;
13866
- if (spokeProvider.chainConfig.chain.id !== types.SONIC_MAINNET_CHAIN_ID) {
14160
+ if (spokeProvider.chainConfig.chain.id !== this.hubProvider.chainConfig.chain.id) {
13867
14161
  const packetResult = await relayTxAndWaitPacket(
13868
14162
  txResult.value,
13869
14163
  spokeProvider instanceof SolanaSpokeProvider ? txResult.data : void 0,
@@ -14028,10 +14322,8 @@ var MoneyMarketService = class _MoneyMarketService {
14028
14322
  }
14029
14323
  };
14030
14324
  }
14031
- const fromChainId = spokeProvider.chainConfig.chain.id;
14032
- const toChainId = params.toChainId ?? fromChainId;
14033
14325
  let intentTxHash = null;
14034
- if (toChainId !== types.SONIC_MAINNET_CHAIN_ID) {
14326
+ if (spokeProvider.chainConfig.chain.id !== this.hubProvider.chainConfig.chain.id || params.toChainId && params.toAddress && params.toChainId !== this.hubProvider.chainConfig.chain.id) {
14035
14327
  const packetResult = await relayTxAndWaitPacket(
14036
14328
  txResult.value,
14037
14329
  spokeProvider instanceof SolanaSpokeProvider ? txResult.data : void 0,
@@ -14107,13 +14399,11 @@ var MoneyMarketService = class _MoneyMarketService {
14107
14399
  const fromAddress = await spokeProvider.walletProvider.getWalletAddress();
14108
14400
  const toChainId = params.toChainId ?? fromChainId;
14109
14401
  const toAddress = params.toAddress ?? fromAddress;
14110
- invariant6__default.default(
14111
- this.configService.isMoneyMarketSupportedToken(toChainId, params.token),
14112
- `Unsupported spoke chain (${toChainId}) token: ${params.token}`
14113
- );
14402
+ const dstToken = this.configService.getMoneyMarketToken(toChainId, params.token);
14403
+ invariant6__default.default(dstToken, `Money market token not found for spoke chain (${toChainId}) token: ${params.token}`);
14114
14404
  const encodedToAddress = encodeAddress(toChainId, toAddress);
14115
14405
  const fromHubWallet = await deriveUserWalletAddress(this.hubProvider, fromChainId, fromAddress);
14116
- const data = this.buildBorrowData(fromHubWallet, encodedToAddress, params.token, params.amount, toChainId);
14406
+ const data = this.buildBorrowData(fromHubWallet, encodedToAddress, dstToken.address, params.amount, toChainId);
14117
14407
  let txResult;
14118
14408
  if (fromChainId === this.hubProvider.chainConfig.chain.id && isSonicSpokeProviderType(spokeProvider)) {
14119
14409
  txResult = await SonicSpokeService.callWallet(data, spokeProvider, raw);
@@ -14176,10 +14466,8 @@ var MoneyMarketService = class _MoneyMarketService {
14176
14466
  }
14177
14467
  };
14178
14468
  }
14179
- const fromChainId = spokeProvider.chainConfig.chain.id;
14180
- const toChainId = params.toChainId ?? fromChainId;
14181
14469
  let intentTxHash = null;
14182
- if (toChainId !== types.SONIC_MAINNET_CHAIN_ID) {
14470
+ if (spokeProvider.chainConfig.chain.id !== this.hubProvider.chainConfig.chain.id || params.toChainId && params.toAddress && params.toChainId !== this.hubProvider.chainConfig.chain.id && params.toAddress !== this.hubProvider.chainConfig.addresses.walletRouter) {
14183
14471
  const packetResult = await relayTxAndWaitPacket(
14184
14472
  txResult.value,
14185
14473
  spokeProvider instanceof SolanaSpokeProvider ? txResult.data : void 0,
@@ -14340,7 +14628,7 @@ var MoneyMarketService = class _MoneyMarketService {
14340
14628
  };
14341
14629
  }
14342
14630
  let intentTxHash = null;
14343
- if (spokeProvider.chainConfig.chain.id !== types.SONIC_MAINNET_CHAIN_ID) {
14631
+ if (spokeProvider.chainConfig.chain.id !== this.hubProvider.chainConfig.chain.id) {
14344
14632
  const packetResult = await relayTxAndWaitPacket(
14345
14633
  txResult.value,
14346
14634
  spokeProvider instanceof SolanaSpokeProvider ? txResult.data : void 0,
@@ -14459,8 +14747,10 @@ var MoneyMarketService = class _MoneyMarketService {
14459
14747
  const fromHubAsset = this.configService.getHubAssetInfo(fromChainId, fromToken);
14460
14748
  invariant6__default.default(fromHubAsset, `hub asset not found for source chain token (token): ${fromToken}`);
14461
14749
  const lendingPool = this.config.lendingPool;
14462
- calls.push(Erc20Service.encodeApprove(fromHubAsset.asset, fromHubAsset.vault, amount));
14463
- calls.push(EvmVaultTokenService.encodeDeposit(fromHubAsset.vault, fromHubAsset.asset, amount));
14750
+ if (!this.configService.isValidVault(fromHubAsset.asset)) {
14751
+ calls.push(Erc20Service.encodeApprove(fromHubAsset.asset, fromHubAsset.vault, amount));
14752
+ calls.push(EvmVaultTokenService.encodeDeposit(fromHubAsset.vault, fromHubAsset.asset, amount));
14753
+ }
14464
14754
  const translatedAmount = EvmVaultTokenService.translateIncomingDecimals(fromHubAsset.decimal, amount);
14465
14755
  calls.push(Erc20Service.encodeApprove(fromHubAsset.vault, lendingPool, translatedAmount));
14466
14756
  calls.push(
@@ -14482,29 +14772,44 @@ var MoneyMarketService = class _MoneyMarketService {
14482
14772
  */
14483
14773
  buildBorrowData(fromHubAddress, toAddress, toToken, amount, toChainId) {
14484
14774
  const toHubAsset = this.configService.getHubAssetInfo(toChainId, toToken);
14775
+ const dstToken = this.configService.getMoneyMarketToken(toChainId, toToken);
14485
14776
  invariant6__default.default(toHubAsset, `hub asset not found for target chain token (toToken): ${toToken}`);
14777
+ invariant6__default.default(dstToken, `Money market token not found for spoke chain (${toChainId}) token: ${toToken}`);
14486
14778
  const assetAddress = toHubAsset.asset;
14487
14779
  const vaultAddress = toHubAsset.vault;
14488
14780
  const bnUSDVault = this.config.bnUSDVault;
14489
14781
  const bnUSD = this.config.bnUSD;
14490
- const feeAmount = calculateFeeAmount(amount, this.config.partnerFee);
14782
+ const translatedInAmount = EvmVaultTokenService.translateIncomingDecimals(toHubAsset.decimal, amount);
14783
+ const feeAmount = calculateFeeAmount(translatedInAmount, this.config.partnerFee);
14491
14784
  const calls = [];
14492
- if (bnUSDVault && bnUSD && bnUSDVault.toLowerCase() === vaultAddress.toLowerCase()) {
14785
+ if (bnUSDVault.toLowerCase() === vaultAddress.toLowerCase()) {
14493
14786
  calls.push(
14494
14787
  _MoneyMarketService.encodeBorrow(
14495
- { asset: bnUSD, amount, interestRateMode: 2n, referralCode: 0, onBehalfOf: fromHubAddress },
14788
+ {
14789
+ asset: bnUSD,
14790
+ amount: translatedInAmount,
14791
+ interestRateMode: 2n,
14792
+ referralCode: 0,
14793
+ onBehalfOf: fromHubAddress
14794
+ },
14496
14795
  this.config.lendingPool
14497
14796
  )
14498
14797
  );
14499
- calls.push(Erc20Service.encodeApprove(bnUSD, bnUSDVault, amount));
14500
- calls.push(EvmVaultTokenService.encodeDeposit(bnUSDVault, bnUSD, amount));
14798
+ calls.push(Erc20Service.encodeApprove(bnUSD, bnUSDVault, translatedInAmount));
14799
+ calls.push(EvmVaultTokenService.encodeDeposit(bnUSDVault, bnUSD, translatedInAmount));
14501
14800
  if (this.config.partnerFee && feeAmount) {
14502
14801
  calls.push(Erc20Service.encodeTransfer(bnUSDVault, this.config.partnerFee.address, feeAmount));
14503
14802
  }
14504
14803
  } else {
14505
14804
  calls.push(
14506
14805
  _MoneyMarketService.encodeBorrow(
14507
- { asset: vaultAddress, amount, interestRateMode: 2n, referralCode: 0, onBehalfOf: fromHubAddress },
14806
+ {
14807
+ asset: vaultAddress,
14808
+ amount: translatedInAmount,
14809
+ interestRateMode: 2n,
14810
+ referralCode: 0,
14811
+ onBehalfOf: fromHubAddress
14812
+ },
14508
14813
  this.config.lendingPool
14509
14814
  )
14510
14815
  );
@@ -14512,8 +14817,21 @@ var MoneyMarketService = class _MoneyMarketService {
14512
14817
  calls.push(Erc20Service.encodeTransfer(vaultAddress, this.config.partnerFee.address, feeAmount));
14513
14818
  }
14514
14819
  }
14515
- calls.push(EvmVaultTokenService.encodeWithdraw(vaultAddress, assetAddress, amount - feeAmount));
14516
- const translatedAmountOut = EvmVaultTokenService.translateOutgoingDecimals(toHubAsset.decimal, amount - feeAmount);
14820
+ if (toToken.toLowerCase() !== vaultAddress.toLowerCase()) {
14821
+ calls.push(EvmVaultTokenService.encodeWithdraw(vaultAddress, assetAddress, translatedInAmount - feeAmount));
14822
+ }
14823
+ let translatedAmountOut;
14824
+ if (this.configService.isValidVault(toToken)) {
14825
+ translatedAmountOut = EvmVaultTokenService.translateOutgoingDecimals(
14826
+ toHubAsset.decimal,
14827
+ translatedInAmount - feeAmount
14828
+ );
14829
+ } else {
14830
+ translatedAmountOut = EvmVaultTokenService.translateOutgoingDecimals(
14831
+ dstToken.decimals,
14832
+ translatedInAmount - feeAmount
14833
+ );
14834
+ }
14517
14835
  if (toChainId === this.hubProvider.chainConfig.chain.id) {
14518
14836
  if (assetAddress.toLowerCase() === this.configService.spokeChainConfig[toChainId].addresses.wrappedSonic.toLowerCase()) {
14519
14837
  const withdrawToCall = {
@@ -14553,17 +14871,27 @@ var MoneyMarketService = class _MoneyMarketService {
14553
14871
  buildWithdrawData(fromHubAddress, toAddress, toToken, amount, toChainId) {
14554
14872
  const calls = [];
14555
14873
  const toHubAsset = this.configService.getHubAssetInfo(toChainId, toToken);
14874
+ const dstToken = this.configService.getMoneyMarketToken(toChainId, toToken);
14556
14875
  invariant6__default.default(toHubAsset, `hub asset not found for target chain token (toToken): ${toToken}`);
14876
+ invariant6__default.default(dstToken, `Money market token not found for spoke chain (${toChainId}) token: ${toToken}`);
14557
14877
  const assetAddress = toHubAsset.asset;
14558
14878
  const vaultAddress = toHubAsset.vault;
14879
+ const translatedInAmount = EvmVaultTokenService.translateIncomingDecimals(toHubAsset.decimal, amount);
14559
14880
  calls.push(
14560
14881
  _MoneyMarketService.encodeWithdraw(
14561
- { asset: vaultAddress, amount, to: fromHubAddress },
14882
+ { asset: vaultAddress, amount: translatedInAmount, to: fromHubAddress },
14562
14883
  this.config.lendingPool
14563
14884
  )
14564
14885
  );
14565
- calls.push(EvmVaultTokenService.encodeWithdraw(vaultAddress, assetAddress, amount));
14566
- const translatedAmountOut = EvmVaultTokenService.translateOutgoingDecimals(toHubAsset.decimal, amount);
14886
+ if (!this.configService.isValidVault(toToken)) {
14887
+ calls.push(EvmVaultTokenService.encodeWithdraw(vaultAddress, assetAddress, translatedInAmount));
14888
+ }
14889
+ let translatedAmountOut;
14890
+ if (this.configService.isValidVault(toToken)) {
14891
+ translatedAmountOut = EvmVaultTokenService.translateOutgoingDecimals(toHubAsset.decimal, translatedInAmount);
14892
+ } else {
14893
+ translatedAmountOut = EvmVaultTokenService.translateOutgoingDecimals(dstToken.decimals, translatedInAmount);
14894
+ }
14567
14895
  if (toChainId === this.hubProvider.chainConfig.chain.id) {
14568
14896
  if (assetAddress.toLowerCase() === this.configService.spokeChainConfig[toChainId].addresses.wrappedSonic.toLowerCase()) {
14569
14897
  const withdrawToCall = {
@@ -14607,18 +14935,23 @@ var MoneyMarketService = class _MoneyMarketService {
14607
14935
  const vaultAddress = fromHubAsset.vault;
14608
14936
  const bnUSDVault = this.config.bnUSDVault;
14609
14937
  const bnUSD = this.config.bnUSD;
14610
- calls.push(Erc20Service.encodeApprove(assetAddress, vaultAddress, amount));
14611
- calls.push(EvmVaultTokenService.encodeDeposit(vaultAddress, assetAddress, amount));
14612
- const translatedAmount = EvmVaultTokenService.translateIncomingDecimals(fromHubAsset.decimal, amount);
14938
+ const translatedAmountIn = EvmVaultTokenService.translateIncomingDecimals(fromHubAsset.decimal, amount);
14613
14939
  let repayToken = vaultAddress;
14614
- if (bnUSDVault && bnUSD && bnUSDVault.toLowerCase() === vaultAddress.toLowerCase()) {
14940
+ if (bnUSDVault.toLowerCase() === vaultAddress.toLowerCase()) {
14615
14941
  repayToken = bnUSD;
14616
- calls.push(EvmVaultTokenService.encodeWithdraw(bnUSDVault, bnUSD, translatedAmount));
14942
+ if (assetAddress.toLowerCase() !== bnUSDVault.toLowerCase()) {
14943
+ calls.push(Erc20Service.encodeApprove(assetAddress, vaultAddress, translatedAmountIn));
14944
+ calls.push(EvmVaultTokenService.encodeDeposit(vaultAddress, assetAddress, translatedAmountIn));
14945
+ }
14946
+ calls.push(EvmVaultTokenService.encodeWithdraw(bnUSDVault, bnUSD, translatedAmountIn));
14947
+ } else {
14948
+ calls.push(Erc20Service.encodeApprove(assetAddress, vaultAddress, amount));
14949
+ calls.push(EvmVaultTokenService.encodeDeposit(vaultAddress, assetAddress, amount));
14617
14950
  }
14618
- calls.push(Erc20Service.encodeApprove(repayToken, this.config.lendingPool, translatedAmount));
14951
+ calls.push(Erc20Service.encodeApprove(repayToken, this.config.lendingPool, translatedAmountIn));
14619
14952
  calls.push(
14620
14953
  _MoneyMarketService.encodeRepay(
14621
- { asset: repayToken, amount: translatedAmount, interestRateMode: 2n, onBehalfOf: toHubAddress },
14954
+ { asset: repayToken, amount: translatedAmountIn, interestRateMode: 2n, onBehalfOf: toHubAddress },
14622
14955
  this.config.lendingPool
14623
14956
  )
14624
14957
  );
@@ -15638,6 +15971,29 @@ var BackendApiService = class {
15638
15971
  const endpoint = `/solver/orderbook?${queryString}`;
15639
15972
  return this.makeRequest(endpoint, { method: "GET" });
15640
15973
  }
15974
+ /**
15975
+ * Get all intents created by a specific user address with optional filters.
15976
+ *
15977
+ * @param params - Options to filter the user intents.
15978
+ * @param params.userAddress - The user's wallet address on the hub chain (required).
15979
+ * @param params.startDate - Optional. Start timestamp in milliseconds (number, required if filtering by date).
15980
+ * @param params.endDate - Optional. End timestamp in milliseconds (number, required if filtering by date).
15981
+ * @param params.limit - Optional. Max number of results (string).
15982
+ * @param params.offset - Optional. Pagination offset (string).
15983
+ *
15984
+ * @returns {Promise<UserIntentsResponse>} Promise resolving to an array of intent responses for the user.
15985
+ */
15986
+ async getUserIntents(params) {
15987
+ const { userAddress, startDate, endDate, limit, offset } = params;
15988
+ const queryParams = new URLSearchParams();
15989
+ if (startDate) queryParams.append("startDate", new Date(startDate).toISOString());
15990
+ if (endDate) queryParams.append("endDate", new Date(endDate).toISOString());
15991
+ if (limit) queryParams.append("limit", limit);
15992
+ if (offset) queryParams.append("offset", offset);
15993
+ const queryString = queryParams.toString();
15994
+ const endpoint = queryString.length > 0 ? `/intent/user/${userAddress}?${queryString}` : `/intent/user/${userAddress}`;
15995
+ return this.makeRequest(endpoint, { method: "GET" });
15996
+ }
15641
15997
  // Money Market endpoints
15642
15998
  /**
15643
15999
  * Get money market position for a specific user
@@ -17114,7 +17470,13 @@ var StakingService = class {
17114
17470
  spokeProvider,
17115
17471
  this.hubProvider
17116
17472
  );
17117
- const data = this.buildUnstakeData(hubWallet, params);
17473
+ const xSoda = this.hubProvider.chainConfig.addresses.xSoda;
17474
+ const underlyingSodaAmount = await StakingLogic.convertXSodaSharesToSoda(
17475
+ xSoda,
17476
+ params.amount,
17477
+ this.hubProvider.publicClient
17478
+ );
17479
+ const data = this.buildUnstakeData(hubWallet, params, xSoda, underlyingSodaAmount);
17118
17480
  let txResult;
17119
17481
  if (isHub) {
17120
17482
  txResult = await SpokeService.deposit(
@@ -17157,13 +17519,12 @@ var StakingService = class {
17157
17519
  * @param params - The unstake parameters
17158
17520
  * @returns The encoded contract call data
17159
17521
  */
17160
- buildUnstakeData(hubWallet, params) {
17522
+ buildUnstakeData(hubWallet, params, xSoda, underlyingSodaAmount) {
17161
17523
  const hubConfig = getHubChainConfig();
17162
17524
  const stakedSoda = hubConfig.addresses.stakedSoda;
17163
- const xSoda = hubConfig.addresses.xSoda;
17164
17525
  const calls = [];
17165
17526
  calls.push(StakingLogic.encodeXSodaRedeem(xSoda, params.amount, hubWallet, hubWallet));
17166
- calls.push(StakingLogic.encodeUnstake(stakedSoda, hubWallet, params.amount));
17527
+ calls.push(StakingLogic.encodeUnstake(stakedSoda, hubWallet, underlyingSodaAmount));
17167
17528
  return encodeContractCalls(calls);
17168
17529
  }
17169
17530
  /**