@sodax/sdk 2.0.0-rc.13 → 2.0.0-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/dist/index.cjs CHANGED
@@ -17,6 +17,7 @@ var anchor = require('@coral-xyz/anchor');
17
17
  var BN = require('bn.js');
18
18
  var IconSdkRaw = require('icon-sdk-js');
19
19
  var sdkTs = require('@injectivelabs/sdk-ts');
20
+ var tx_js = require('cosmjs-types/cosmos/tx/v1beta1/tx.js');
20
21
  var networks = require('@injectivelabs/networks');
21
22
  var BigNumber5 = require('bignumber.js');
22
23
  var swapSdkCore = require('@pancakeswap/swap-sdk-core');
@@ -331,7 +332,8 @@ var HubVaultSymbols = [
331
332
  "sodaNEAR",
332
333
  "sodaKAIA",
333
334
  "sodaSTX",
334
- "sodaUSDS"
335
+ "sodaUSDS",
336
+ "sodaJITOSOL"
335
337
  ];
336
338
  var SodaTokens = {
337
339
  sodaBNB: {
@@ -558,9 +560,18 @@ var SodaTokens = {
558
560
  chainKey: ChainKeys.SONIC_MAINNET,
559
561
  hubAsset: "0x243b0c26c8b38793908d7C64e8510f21B19B4613",
560
562
  vault: "0x243b0c26c8b38793908d7C64e8510f21B19B4613"
563
+ },
564
+ sodaJITOSOL: {
565
+ symbol: "sodaJITOSOL",
566
+ name: "Soda JITOSOL",
567
+ decimals: 18,
568
+ address: "0xe1bad4400d947Bc4fa66f9c0A143D800002083a0",
569
+ chainKey: ChainKeys.SONIC_MAINNET,
570
+ hubAsset: "0xe1bad4400d947Bc4fa66f9c0A143D800002083a0",
571
+ vault: "0xe1bad4400d947Bc4fa66f9c0A143D800002083a0"
561
572
  }
562
573
  };
563
- var LsodaSymbols = ["lsodaWEETH", "lsodaWSTETH"];
574
+ var LsodaSymbols = ["lsodaWEETH", "lsodaWSTETH", "lsodaJITOSOL"];
564
575
  var LsodaTokens = {
565
576
  lsodaWEETH: {
566
577
  symbol: "lsodaWEETH",
@@ -579,6 +590,15 @@ var LsodaTokens = {
579
590
  chainKey: ChainKeys.SONIC_MAINNET,
580
591
  hubAsset: "0x136E5D1CEC5db1829E24941Eddd9C8640E02Ce7a",
581
592
  vault: "0x136E5D1CEC5db1829E24941Eddd9C8640E02Ce7a"
593
+ },
594
+ lsodaJITOSOL: {
595
+ symbol: "lsodaJITOSOL",
596
+ name: "Leveraged Soda JITOSOL",
597
+ decimals: 18,
598
+ address: "0xD7Ae4853E0f93682F5DaA14734F5D18cBa09Bd78",
599
+ chainKey: ChainKeys.SONIC_MAINNET,
600
+ hubAsset: "0xD7Ae4853E0f93682F5DaA14734F5D18cBa09Bd78",
601
+ vault: "0xD7Ae4853E0f93682F5DaA14734F5D18cBa09Bd78"
582
602
  }
583
603
  };
584
604
  var sonicSupportedTokens = {
@@ -856,7 +876,7 @@ var solanaSupportedTokens = {
856
876
  address: "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn",
857
877
  chainKey: ChainKeys.SOLANA_MAINNET,
858
878
  hubAsset: "0x942f89a324d2652e447b9fcf08effc9f9776a680",
859
- vault: "0x942f89a324d2652e447b9fcf08effc9f9776a680"
879
+ vault: SodaTokens.sodaJITOSOL.address
860
880
  },
861
881
  mSOL: {
862
882
  symbol: "mSOL",
@@ -1289,6 +1309,15 @@ var baseSupportedTokens = {
1289
1309
  chainKey: ChainKeys.BASE_MAINNET,
1290
1310
  hubAsset: "0xaa81bb5ba3c972ab53605d3ba7e443a3de6d1cb9",
1291
1311
  vault: "0xaa81bb5ba3c972ab53605d3ba7e443a3de6d1cb9"
1312
+ },
1313
+ AERO: {
1314
+ symbol: "AERO",
1315
+ name: "Aerodrome Finance",
1316
+ decimals: 18,
1317
+ address: "0x940181a94A35A4569e4529A3CDfB74e38FD98631",
1318
+ chainKey: ChainKeys.BASE_MAINNET,
1319
+ hubAsset: "0x348e086ab6f424dfc575a325c28624ed23973173",
1320
+ vault: "0x348e086ab6f424dfc575a325c28624ed23973173"
1292
1321
  }
1293
1322
  };
1294
1323
  var optimismSupportedTokens = {
@@ -1971,6 +2000,33 @@ var stellarSupportedTokens = {
1971
2000
  chainKey: ChainKeys.STELLAR_MAINNET,
1972
2001
  hubAsset: "0xD749B5FfFED7cEDaa3239abDd16D677179C29AEc",
1973
2002
  vault: SodaTokens.sodaSODA.address
2003
+ },
2004
+ sodaETH: {
2005
+ symbol: "sodaETH",
2006
+ name: "Soda ETH",
2007
+ decimals: 7,
2008
+ address: "CDK5EWVTZLGSLI6D5OSES7XUKWZUKBXDRNOWUVDNPP5RJRP5EYWCW7SL",
2009
+ chainKey: ChainKeys.STELLAR_MAINNET,
2010
+ hubAsset: "0x4985a4b72ac723723e9ae82382d12d77e9a715de",
2011
+ vault: SodaTokens.sodaETH.address
2012
+ },
2013
+ sodaBTC: {
2014
+ symbol: "sodaBTC",
2015
+ name: "Soda BTC",
2016
+ decimals: 7,
2017
+ address: "CD6XWBW74YVFDQQYUM2GALCULMA5MAWGP6NTCWF3ZYXP4Z7MEVY4JKBX",
2018
+ chainKey: ChainKeys.STELLAR_MAINNET,
2019
+ hubAsset: "0xddee01f63c18843e2bac30cb702864d7632c83a2",
2020
+ vault: SodaTokens.sodaBTC.address
2021
+ },
2022
+ sodaBNB: {
2023
+ symbol: "sodaBNB",
2024
+ name: "Soda BNB",
2025
+ decimals: 7,
2026
+ address: "CCXTXZAFLVNTMORVWYB6BGL7YEW3U3ONDAL2FGBRGDUQH7AGANVQPRS6",
2027
+ chainKey: ChainKeys.STELLAR_MAINNET,
2028
+ hubAsset: "0xa10be5f5c2dea7d272555dc73ea2a7317c3c5b63",
2029
+ vault: SodaTokens.sodaBNB.address
1974
2030
  }
1975
2031
  };
1976
2032
  var suiSupportedTokens = {
@@ -3110,6 +3166,21 @@ var spokeChainConfig = {
3110
3166
  assetCode: "SODA",
3111
3167
  contractId: "CAH5LKJC2ZB4RVUVEVL2QWJWNJLHQE2UF767ILLQ5EQ4O3OURR2XIUGM",
3112
3168
  assetIssuer: "GDYUTHY75A7WUZJQDPOP66FB32BOYGZRXHWTWO4Q6LQTANT5X3V5HNFA"
3169
+ },
3170
+ {
3171
+ assetCode: "sodaETH",
3172
+ contractId: "CDK5EWVTZLGSLI6D5OSES7XUKWZUKBXDRNOWUVDNPP5RJRP5EYWCW7SL",
3173
+ assetIssuer: "GDYUTHY75A7WUZJQDPOP66FB32BOYGZRXHWTWO4Q6LQTANT5X3V5HNFA"
3174
+ },
3175
+ {
3176
+ assetCode: "sodaBTC",
3177
+ contractId: "CD6XWBW74YVFDQQYUM2GALCULMA5MAWGP6NTCWF3ZYXP4Z7MEVY4JKBX",
3178
+ assetIssuer: "GDYUTHY75A7WUZJQDPOP66FB32BOYGZRXHWTWO4Q6LQTANT5X3V5HNFA"
3179
+ },
3180
+ {
3181
+ assetCode: "sodaBNB",
3182
+ contractId: "CCXTXZAFLVNTMORVWYB6BGL7YEW3U3ONDAL2FGBRGDUQH7AGANVQPRS6",
3183
+ assetIssuer: "GDYUTHY75A7WUZJQDPOP66FB32BOYGZRXHWTWO4Q6LQTANT5X3V5HNFA"
3113
3184
  }
3114
3185
  ],
3115
3186
  supportedTokens: stellarSupportedTokens,
@@ -3385,7 +3456,8 @@ var moneyMarketSupportedTokens = {
3385
3456
  spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.bnUSD,
3386
3457
  spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.USDC,
3387
3458
  spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.SODA,
3388
- spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.USDT
3459
+ spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.USDT,
3460
+ spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.JitoSOL
3389
3461
  ],
3390
3462
  [ChainKeys.ICON_MAINNET]: [
3391
3463
  // spokeChainConfig[ChainKeys.ICON].supportedTokens.ICX,
@@ -3396,7 +3468,10 @@ var moneyMarketSupportedTokens = {
3396
3468
  spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.XLM,
3397
3469
  spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.bnUSD,
3398
3470
  spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.SODA,
3399
- spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.USDC
3471
+ spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.USDC,
3472
+ spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.sodaETH,
3473
+ spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.sodaBTC,
3474
+ spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.sodaBNB
3400
3475
  ],
3401
3476
  [ChainKeys.SUI_MAINNET]: [
3402
3477
  spokeChainConfig[ChainKeys.SUI_MAINNET].supportedTokens.SUI,
@@ -3647,7 +3722,8 @@ var swapSupportedTokens = {
3647
3722
  spokeChainConfig[ChainKeys.SONIC_MAINNET].supportedTokens.USDT,
3648
3723
  spokeChainConfig[ChainKeys.SONIC_MAINNET].supportedTokens.wS,
3649
3724
  spokeChainConfig[ChainKeys.SONIC_MAINNET].supportedTokens.SODA,
3650
- ...Object.values(SodaTokens),
3725
+ // sodaUSDS is staging-only — see stagingSwapSupportedTokens
3726
+ ...Object.values(SodaTokens).filter((t) => t !== SodaTokens.sodaUSDS),
3651
3727
  ...Object.values(LsodaTokens)
3652
3728
  ],
3653
3729
  [ChainKeys.AVALANCHE_MAINNET]: [
@@ -3667,36 +3743,35 @@ var swapSupportedTokens = {
3667
3743
  spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.tBTC,
3668
3744
  spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.USDC,
3669
3745
  spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.USDT,
3670
- spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.SODA,
3671
3746
  spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.ARB,
3672
3747
  spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.AAVE,
3673
3748
  spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.LINK,
3674
3749
  spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.UNI,
3675
3750
  spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.CRV,
3676
3751
  spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.PENDLE,
3677
- spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.rETH
3752
+ spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.rETH,
3753
+ spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.SODA
3678
3754
  ],
3679
3755
  [ChainKeys.BASE_MAINNET]: [
3680
3756
  spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.ETH,
3681
- spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.bnUSD,
3682
3757
  spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.weETH,
3683
3758
  spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.USDC,
3684
3759
  spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.wstETH,
3685
3760
  spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.cbBTC,
3686
- spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.SODA,
3687
3761
  spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.VIRTUAL,
3688
- spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.cbETH
3762
+ spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.cbETH,
3763
+ spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.SODA
3689
3764
  ],
3690
3765
  [ChainKeys.OPTIMISM_MAINNET]: [
3691
3766
  spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.ETH,
3692
- spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.bnUSD,
3693
3767
  spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.USDC,
3694
3768
  spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.wstETH,
3695
3769
  // spokeChainConfig[OPTIMISM_MAINNET_CHAIN_ID].supportedTokens.weETH, // NOTE: Not Implemented
3696
3770
  spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.USDT,
3697
3771
  spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.SODA,
3698
3772
  spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.OP,
3699
- spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.WBTC
3773
+ spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.WBTC,
3774
+ spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.bnUSD
3700
3775
  ],
3701
3776
  [ChainKeys.POLYGON_MAINNET]: [
3702
3777
  spokeChainConfig[ChainKeys.POLYGON_MAINNET].supportedTokens.POL,
@@ -3752,7 +3827,6 @@ var swapSupportedTokens = {
3752
3827
  spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens["SUI.LL"],
3753
3828
  spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens["S.LL"],
3754
3829
  spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens["POL.LL"],
3755
- spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens["HYPE.LL"],
3756
3830
  spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens.LL
3757
3831
  ],
3758
3832
  [ChainKeys.SOLANA_MAINNET]: [
@@ -3791,7 +3865,10 @@ var swapSupportedTokens = {
3791
3865
  spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.bnUSD,
3792
3866
  // NOTE: Not Implemented
3793
3867
  spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.USDC,
3794
- spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.SODA
3868
+ spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.SODA,
3869
+ spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.sodaETH,
3870
+ spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.sodaBTC,
3871
+ spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.sodaBNB
3795
3872
  ],
3796
3873
  [ChainKeys.SUI_MAINNET]: [
3797
3874
  spokeChainConfig[ChainKeys.SUI_MAINNET].supportedTokens.SUI,
@@ -3809,12 +3886,8 @@ var swapSupportedTokens = {
3809
3886
  spokeChainConfig[ChainKeys.SUI_MAINNET].supportedTokens.WAL,
3810
3887
  spokeChainConfig[ChainKeys.SUI_MAINNET].supportedTokens.NAVX
3811
3888
  ],
3812
- [ChainKeys.INJECTIVE_MAINNET]: [
3813
- spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.INJ,
3814
- spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.bnUSD,
3815
- spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.USDC
3816
- // spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.SODA, // NOTE: not in solver wiki
3817
- ],
3889
+ // Injective is currently staging-only — see stagingSwapSupportedTokens
3890
+ [ChainKeys.INJECTIVE_MAINNET]: [],
3818
3891
  [ChainKeys.NEAR_MAINNET]: [
3819
3892
  spokeChainConfig[ChainKeys.NEAR_MAINNET].supportedTokens.NEAR,
3820
3893
  spokeChainConfig[ChainKeys.NEAR_MAINNET].supportedTokens.bnUSD,
@@ -3881,12 +3954,53 @@ var swapSupportedTokens = {
3881
3954
  spokeChainConfig[ChainKeys.STACKS_MAINNET].supportedTokens.USDC
3882
3955
  ]
3883
3956
  };
3957
+ var stagingSwapSupportedTokens = {
3958
+ [ChainKeys.SONIC_MAINNET]: [SodaTokens.sodaUSDS],
3959
+ [ChainKeys.AVALANCHE_MAINNET]: [],
3960
+ [ChainKeys.ARBITRUM_MAINNET]: [],
3961
+ [ChainKeys.BASE_MAINNET]: [
3962
+ spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.bnUSD,
3963
+ spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.AERO
3964
+ ],
3965
+ [ChainKeys.OPTIMISM_MAINNET]: [],
3966
+ [ChainKeys.POLYGON_MAINNET]: [
3967
+ spokeChainConfig[ChainKeys.POLYGON_MAINNET].supportedTokens.USDT,
3968
+ spokeChainConfig[ChainKeys.POLYGON_MAINNET].supportedTokens.wstETH
3969
+ ],
3970
+ [ChainKeys.BSC_MAINNET]: [],
3971
+ [ChainKeys.HYPEREVM_MAINNET]: [],
3972
+ [ChainKeys.LIGHTLINK_MAINNET]: [
3973
+ spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens["HYPE.LL"]
3974
+ ],
3975
+ [ChainKeys.SOLANA_MAINNET]: [],
3976
+ [ChainKeys.ICON_MAINNET]: [],
3977
+ [ChainKeys.STELLAR_MAINNET]: [],
3978
+ [ChainKeys.SUI_MAINNET]: [spokeChainConfig[ChainKeys.SUI_MAINNET].supportedTokens.USDT],
3979
+ [ChainKeys.INJECTIVE_MAINNET]: [
3980
+ spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.INJ,
3981
+ spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.bnUSD,
3982
+ spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.USDC
3983
+ // spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.SODA, // NOTE: not in solver wiki
3984
+ ],
3985
+ [ChainKeys.NEAR_MAINNET]: [],
3986
+ [ChainKeys.BITCOIN_MAINNET]: [],
3987
+ [ChainKeys.ETHEREUM_MAINNET]: [
3988
+ spokeChainConfig[ChainKeys.ETHEREUM_MAINNET].supportedTokens.wstETH,
3989
+ spokeChainConfig[ChainKeys.ETHEREUM_MAINNET].supportedTokens.weETH
3990
+ ],
3991
+ [ChainKeys.REDBELLY_MAINNET]: [],
3992
+ [ChainKeys.KAIA_MAINNET]: [],
3993
+ [ChainKeys.STACKS_MAINNET]: []
3994
+ };
3884
3995
  var swapsConfig = {
3885
- partnerFee: void 0,
3886
3996
  supportedTokens: swapSupportedTokens
3887
3997
  };
3888
3998
  var getSupportedSolverTokens = (chainId) => swapSupportedTokens[chainId];
3889
- var isSwapSupportedToken = (chainId, token) => swapSupportedTokens[chainId].some((t) => t.address.toLowerCase() === token.toLowerCase());
3999
+ var getStagingSolverTokens = (chainId) => [
4000
+ ...swapSupportedTokens[chainId],
4001
+ ...stagingSwapSupportedTokens[chainId]
4002
+ ];
4003
+ var isSwapSupportedToken = (chainId, token) => [...swapSupportedTokens[chainId], ...stagingSwapSupportedTokens[chainId]].some((t) => t.address.toLowerCase() === token.toLowerCase());
3890
4004
 
3891
4005
  // ../types/dist/leverageYield/leverageYield.js
3892
4006
  var leverageYieldVaults = [
@@ -3917,6 +4031,20 @@ var leverageYieldVaults = [
3917
4031
  fallbackAprPct: 2.4,
3918
4032
  label: "Lido (stETH)"
3919
4033
  }
4034
+ },
4035
+ {
4036
+ name: LsodaTokens.lsodaJITOSOL.symbol,
4037
+ vault: LsodaTokens.lsodaJITOSOL.vault,
4038
+ asset: SodaTokens.sodaJITOSOL.address,
4039
+ // sodaJITOSOL on Sonic
4040
+ borrowToken: SodaTokens.sodaSOL.address,
4041
+ // sodaSOL on Sonic
4042
+ lsdSource: {
4043
+ // DefiLlama pool for Jito's JitoSOL native staking on Solana (project: 'jito-liquid-staking').
4044
+ poolId: "0e7d0722-9054-4907-8593-567b353c0900",
4045
+ fallbackAprPct: 5.5,
4046
+ label: "Jito (JitoSOL)"
4047
+ }
3920
4048
  }
3921
4049
  ];
3922
4050
  var leverageYieldConfig = {
@@ -3924,11 +4052,8 @@ var leverageYieldConfig = {
3924
4052
  };
3925
4053
 
3926
4054
  // ../types/dist/sodax-config/sodax-config.js
3927
- var bridgeConfig = {
3928
- partnerFee: void 0
3929
- };
4055
+ var bridgeConfig = {};
3930
4056
  var sodaxConfig = {
3931
- fee: void 0,
3932
4057
  chains: spokeChainConfig,
3933
4058
  swaps: swapsConfig,
3934
4059
  moneyMarket: moneyMarketConfig,
@@ -4076,7 +4201,7 @@ function isValidWalletProviderForChainKey(chainKey, walletProvider) {
4076
4201
  }
4077
4202
 
4078
4203
  // ../types/dist/index.js
4079
- var CONFIG_VERSION = 211;
4204
+ var CONFIG_VERSION = 213;
4080
4205
  function isEvmSpokeChainConfig(value) {
4081
4206
  return typeof value === "object" && value !== null && value.chain.type === "EVM" && value.chain.key !== HUB_CHAIN_KEY;
4082
4207
  }
@@ -4463,7 +4588,10 @@ async function pollForExecutedPacket(payload) {
4463
4588
  }
4464
4589
  const txPackets = txPacketsResult.value;
4465
4590
  if (txPackets.success && txPackets.data.length > 0) {
4466
- const packet = txPackets.data.find((packet2) => packet2.src_tx_hash.toLowerCase() === payload.srcTxHash.toLowerCase());
4591
+ const candidates = txPackets.data.filter(
4592
+ (packet2) => packet2.src_tx_hash.toLowerCase() === payload.srcTxHash.toLowerCase()
4593
+ );
4594
+ const packet = payload.selectPacket ? payload.selectPacket(candidates) : candidates[0];
4467
4595
  if (packet?.status === "executed") {
4468
4596
  return { kind: "found", packet };
4469
4597
  }
@@ -13353,14 +13481,7 @@ function deepMerge(target, source) {
13353
13481
 
13354
13482
  // src/shared/config/mergeSodaxConfig.ts
13355
13483
  function mergeSodaxConfig(base2, override) {
13356
- const merged = deepMerge(base2, override);
13357
- if (override.fee !== void 0) {
13358
- merged.fee = override.fee;
13359
- }
13360
- if (override.bridge?.partnerFee !== void 0) {
13361
- merged.bridge.partnerFee = override.bridge.partnerFee;
13362
- }
13363
- return merged;
13484
+ return deepMerge(base2, override);
13364
13485
  }
13365
13486
 
13366
13487
  // src/shared/logger.ts
@@ -13400,6 +13521,12 @@ var ConfigService = class {
13400
13521
  * {@link initialize}'s dynamic-config swap never clobbers it. Read by services via `config.logger`.
13401
13522
  */
13402
13523
  logger;
13524
+ /**
13525
+ * Global partner fee. Resolved once at construction and kept independent of {@link sodax} so that
13526
+ * {@link initialize}'s dynamic-config swap never clobbers it. The backend never supplies it — it is
13527
+ * a client-side option set via `new Sodax({ fee })`. Per-feature overrides live on the feature config.
13528
+ */
13529
+ fee;
13403
13530
  initialized = false;
13404
13531
  // data structures for quick lookup
13405
13532
  supportedHubAssetsSet;
@@ -13411,11 +13538,12 @@ var ConfigService = class {
13411
13538
  stakedATokenAddressesSet;
13412
13539
  chainToSupportedTokenAddressMap;
13413
13540
  hubAssetToXTokenMap;
13414
- constructor({ api, config, userConfig, logger }) {
13541
+ constructor({ api, config, userConfig, logger, fee }) {
13415
13542
  this.api = api;
13416
13543
  this.sodax = config;
13417
13544
  this.userConfig = userConfig;
13418
13545
  this.logger = logger ?? resolveLogger(void 0);
13546
+ this.fee = fee;
13419
13547
  this.loadSodaxConfigDataStructures(config);
13420
13548
  }
13421
13549
  async initialize() {
@@ -13648,6 +13776,24 @@ var ConfigService = class {
13648
13776
  get moneyMarket() {
13649
13777
  return this.sodax.moneyMarket;
13650
13778
  }
13779
+ get leverageYield() {
13780
+ return this.sodax.leverageYield;
13781
+ }
13782
+ // Effective partner fee per feature: the feature-specific override if set, otherwise the global
13783
+ // `fee` client option ({@link fee}). The global fee is the default, overridable per-feature. `??`
13784
+ // (never a merge) keeps the chosen PartnerFee variant intact — no discriminated-union hybrid.
13785
+ get swapPartnerFee() {
13786
+ return this.swaps.partnerFee ?? this.fee;
13787
+ }
13788
+ get moneyMarketPartnerFee() {
13789
+ return this.moneyMarket.partnerFee ?? this.fee;
13790
+ }
13791
+ get bridgePartnerFee() {
13792
+ return this.bridge.partnerFee ?? this.fee;
13793
+ }
13794
+ get leverageYieldPartnerFee() {
13795
+ return this.leverageYield.partnerFee ?? this.fee;
13796
+ }
13651
13797
  get dex() {
13652
13798
  return this.sodax.dex;
13653
13799
  }
@@ -14459,12 +14605,23 @@ var StacksSpokeService = class {
14459
14605
  postConditionMode: core.PostConditionMode.Allow
14460
14606
  };
14461
14607
  if (params.raw === true) {
14462
- if (core.validateStacksAddress(params.srcAddress)) {
14463
- throw new Error('When using raw transactions, the public key must be provided as "from" parameter');
14608
+ if (!params.srcPublicKey) {
14609
+ throw new Error("Stacks raw transactions require srcPublicKey (the signer public key for srcAddress).");
14610
+ }
14611
+ let derivedAddress;
14612
+ try {
14613
+ derivedAddress = core.getAddressFromPublicKey(params.srcPublicKey, this.network);
14614
+ } catch (error) {
14615
+ throw new Error(`srcPublicKey is not a valid Stacks public key: ${error.message}`);
14616
+ }
14617
+ if (derivedAddress !== params.srcAddress) {
14618
+ throw new Error(
14619
+ `srcPublicKey does not match srcAddress: it derives ${derivedAddress}, but srcAddress is ${params.srcAddress}.`
14620
+ );
14464
14621
  }
14465
14622
  const tx = await core.makeUnsignedContractCall({
14466
14623
  ...reqData,
14467
- publicKey: params.srcAddress,
14624
+ publicKey: params.srcPublicKey,
14468
14625
  network: this.network,
14469
14626
  fee: 0,
14470
14627
  // placeholder — we'll estimate
@@ -14574,6 +14731,8 @@ var RadfiProvider = class {
14574
14731
  refreshToken = "";
14575
14732
  constructor(config) {
14576
14733
  this.config = config;
14734
+ this.accessToken = config.accessToken ?? "";
14735
+ this.refreshToken = config.refreshToken ?? "";
14577
14736
  if (config.apiUrl.endsWith("/")) {
14578
14737
  this.config.apiUrl = config.apiUrl.slice(0, -1);
14579
14738
  }
@@ -14614,13 +14773,11 @@ var RadfiProvider = class {
14614
14773
  try {
14615
14774
  const { accessToken, refreshToken } = await this.refreshAccessToken(this.refreshToken);
14616
14775
  this.setRadfiAccessToken(accessToken, refreshToken);
14617
- console.log("[ensureRadfiAccessToken] token refreshed successfully");
14618
14776
  return;
14619
14777
  } catch (error) {
14620
14778
  console.warn("[ensureRadfiAccessToken] refresh failed, falling back to full re-auth", error);
14621
14779
  }
14622
14780
  }
14623
- console.log("[ensureRadfiAccessToken] performing full re-authentication (BIP322 sign)");
14624
14781
  this.accessToken = "";
14625
14782
  this.refreshToken = "";
14626
14783
  await this.authenticateWithWallet(walletProvider);
@@ -14636,55 +14793,53 @@ var RadfiProvider = class {
14636
14793
  method: "POST",
14637
14794
  body: JSON.stringify(params)
14638
14795
  });
14796
+ const body = await this.parseJsonBody(res, "Bound Exchange authentication failed");
14639
14797
  if (!res.ok) {
14640
- const err = await res.json();
14641
- throw new RadfiApiError(res.status, err, "Bound Exchange authentication failed");
14798
+ throw new RadfiApiError(res.status, body, "Bound Exchange authentication failed");
14642
14799
  }
14643
- return res.json().then((r) => ({
14644
- accessToken: r.data?.accessToken ?? "",
14645
- refreshToken: r.data?.refreshToken ?? "",
14646
- tradingAddress: r.data?.tradingAddress ?? r.data?.wallet?.tradingAddress ?? ""
14647
- }));
14800
+ return {
14801
+ accessToken: body.data?.accessToken ?? "",
14802
+ refreshToken: body.data?.refreshToken ?? "",
14803
+ tradingAddress: body.data?.tradingAddress ?? body.data?.wallet?.tradingAddress ?? ""
14804
+ };
14648
14805
  }
14649
14806
  async refreshAccessToken(refreshToken) {
14650
14807
  const res = await this.request("/auth/refresh-token", {
14651
14808
  method: "POST",
14652
14809
  body: JSON.stringify({ refreshToken })
14653
14810
  });
14811
+ const body = await this.parseJsonBody(res, "Token refresh failed");
14654
14812
  if (!res.ok) {
14655
- const err = await res.json();
14656
- throw new RadfiApiError(res.status, err, "Token refresh failed");
14813
+ throw new RadfiApiError(res.status, body, "Token refresh failed");
14657
14814
  }
14658
- return res.json().then((r) => ({
14659
- accessToken: r.data?.accessToken ?? "",
14660
- refreshToken: r.data?.refreshToken ?? refreshToken
14661
- }));
14815
+ return {
14816
+ accessToken: body.data?.accessToken ?? "",
14817
+ refreshToken: body.data?.refreshToken ?? refreshToken
14818
+ };
14662
14819
  }
14663
14820
  async createTradingWallet(params, accessToken) {
14664
14821
  const res = await this.request("/wallets", {
14665
14822
  method: "POST",
14666
14823
  headers: {
14667
- Authorization: `Bearer ${accessToken || this.config.apiKey}`
14824
+ Authorization: `Bearer ${this.resolveAuth(accessToken)}`
14668
14825
  },
14669
14826
  body: JSON.stringify(params)
14670
14827
  });
14671
- if (!res.ok) {
14672
- const err = await res.json();
14673
- throw new RadfiApiError(res.status, err, "Failed to create trading wallet");
14828
+ const body = await this.parseJsonBody(res, "Failed to create trading wallet");
14829
+ if (!res.ok || !body.data) {
14830
+ throw new RadfiApiError(res.status, body, "Failed to create trading wallet");
14674
14831
  }
14675
- return res.json().then((r) => r.data);
14832
+ return body.data;
14676
14833
  }
14677
- async getTradingWallet(userAddress, accessToken) {
14834
+ async getTradingWallet(userAddress) {
14678
14835
  const res = await this.request(`/wallets/details/${userAddress}`, {
14679
- method: "GET",
14680
- headers: accessToken ? { Authorization: `Bearer ${accessToken}` } : {}
14836
+ method: "GET"
14681
14837
  });
14682
- if (!res.ok) {
14683
- throw new Error("Trading wallet not found");
14838
+ const body = await this.parseJsonBody(res, "Trading wallet not found");
14839
+ if (!res.ok || !body.data) {
14840
+ throw new RadfiApiError(res.status, body, "Trading wallet not found");
14684
14841
  }
14685
- const data = await res.json().then((r) => r.data);
14686
- if (!data) throw new Error("Trading wallet not found");
14687
- return data;
14842
+ return body.data;
14688
14843
  }
14689
14844
  async getBalance(address) {
14690
14845
  if (!this.config.umsUrl) {
@@ -14698,12 +14853,12 @@ var RadfiProvider = class {
14698
14853
  if (!res.ok) {
14699
14854
  throw new Error("Failed to fetch wallet balance");
14700
14855
  }
14701
- const { data } = await res.json();
14856
+ const { data } = await this.parseJsonBody(res, "Failed to fetch wallet balance");
14702
14857
  return {
14703
- btcSatoshi: BigInt(data.btcSatoshi ?? "0"),
14704
- pendingSatoshi: BigInt(data.pendingSatoshi ?? "0"),
14705
- externalPendingSatoshi: BigInt(data.externalPendingSatoshi ?? "0"),
14706
- totalUtxos: Number(data.totalUtxos ?? 0)
14858
+ btcSatoshi: BigInt(data?.btcSatoshi ?? "0"),
14859
+ pendingSatoshi: BigInt(data?.pendingSatoshi ?? "0"),
14860
+ externalPendingSatoshi: BigInt(data?.externalPendingSatoshi ?? "0"),
14861
+ totalUtxos: Number(data?.totalUtxos ?? 0)
14707
14862
  };
14708
14863
  }
14709
14864
  async checkIfTradingWalletExists(userAddress) {
@@ -14719,7 +14874,7 @@ var RadfiProvider = class {
14719
14874
  const res = await this.request("/sodax/transaction", {
14720
14875
  method: "POST",
14721
14876
  headers: {
14722
- Authorization: `Bearer ${accessToken || this.config.apiKey}`
14877
+ Authorization: `Bearer ${this.resolveAuth(accessToken)}`
14723
14878
  },
14724
14879
  body: JSON.stringify({
14725
14880
  type: "sodax-withdraw",
@@ -14730,8 +14885,8 @@ var RadfiProvider = class {
14730
14885
  }
14731
14886
  })
14732
14887
  });
14733
- const body = await res.json();
14734
- if (!res.ok || !body?.data) {
14888
+ const body = await this.parseJsonBody(res, "Bound Exchange transaction request failed");
14889
+ if (!res.ok || !body.data) {
14735
14890
  throw new RadfiApiError(res.status, body, "Bound Exchange transaction request failed");
14736
14891
  }
14737
14892
  return body.data;
@@ -14748,18 +14903,18 @@ var RadfiProvider = class {
14748
14903
  const res = await this.request("/sodax/transaction/sign", {
14749
14904
  method: "POST",
14750
14905
  headers: {
14751
- Authorization: `Bearer ${accessToken || this.config.apiKey}`
14906
+ Authorization: `Bearer ${this.resolveAuth(accessToken)}`
14752
14907
  },
14753
14908
  body: JSON.stringify({
14754
14909
  type: "sodax-withdraw",
14755
14910
  params
14756
14911
  })
14757
14912
  });
14758
- if (!res.ok) {
14759
- const err = await res.json();
14760
- throw new RadfiApiError(res.status, err, "Bound Exchange signature request failed");
14913
+ const body = await this.parseJsonBody(res, "Bound Exchange signature request failed");
14914
+ if (!res.ok || !body.data?.txId) {
14915
+ throw new RadfiApiError(res.status, body, "Bound Exchange signature request failed");
14761
14916
  }
14762
- return res.json().then((r) => r.data.txId);
14917
+ return body.data.txId;
14763
14918
  }
14764
14919
  /**
14765
14920
  * Fetch expired (or near-expiry) UTXOs for a trading wallet address from UMS API.
@@ -14778,7 +14933,8 @@ var RadfiProvider = class {
14778
14933
  if (!res.ok) {
14779
14934
  throw new Error("Failed to fetch expired UTXOs");
14780
14935
  }
14781
- return res.json();
14936
+ const body = await this.parseJsonBody(res, "Failed to fetch expired UTXOs");
14937
+ return { code: body.code ?? "", message: body.message ?? "", data: body.data ?? [] };
14782
14938
  }
14783
14939
  /**
14784
14940
  * Build a renew-utxo transaction via the Bound Exchange API.
@@ -14798,11 +14954,11 @@ var RadfiProvider = class {
14798
14954
  }
14799
14955
  })
14800
14956
  });
14801
- if (!res.ok) {
14802
- const err = await res.json();
14803
- throw new RadfiApiError(res.status, err, "Failed to build renew-utxo transaction");
14957
+ const body = await this.parseJsonBody(res, "Failed to build renew-utxo transaction");
14958
+ if (!res.ok || !body.data) {
14959
+ throw new RadfiApiError(res.status, body, "Failed to build renew-utxo transaction");
14804
14960
  }
14805
- return res.json().then((r) => r.data);
14961
+ return body.data;
14806
14962
  }
14807
14963
  /**
14808
14964
  * Sign and broadcast a renew-utxo transaction via the Bound Exchange API.
@@ -14819,11 +14975,14 @@ var RadfiProvider = class {
14819
14975
  params
14820
14976
  })
14821
14977
  });
14822
- if (!res.ok) {
14823
- const err = await res.json();
14824
- throw new RadfiApiError(res.status, err, "Failed to sign and broadcast renew-utxo transaction");
14978
+ const body = await this.parseJsonBody(
14979
+ res,
14980
+ "Failed to sign and broadcast renew-utxo transaction"
14981
+ );
14982
+ if (!res.ok || !body.data?.txId) {
14983
+ throw new RadfiApiError(res.status, body, "Failed to sign and broadcast renew-utxo transaction");
14825
14984
  }
14826
- return res.json().then((r) => r.data.txId);
14985
+ return body.data.txId;
14827
14986
  }
14828
14987
  /**
14829
14988
  * Withdraw BTC from trading wallet to user's personal wallet.
@@ -14840,11 +14999,11 @@ var RadfiProvider = class {
14840
14999
  params
14841
15000
  })
14842
15001
  });
14843
- if (!res.ok) {
14844
- const err = await res.json();
14845
- throw new RadfiApiError(res.status, err, "Failed to build withdraw transaction");
15002
+ const body = await this.parseJsonBody(res, "Failed to build withdraw transaction");
15003
+ if (!res.ok || !body.data) {
15004
+ throw new RadfiApiError(res.status, body, "Failed to build withdraw transaction");
14846
15005
  }
14847
- return res.json().then((r) => r.data);
15006
+ return body.data;
14848
15007
  }
14849
15008
  /**
14850
15009
  * Sign and broadcast a withdraw transaction via Bound Exchange.
@@ -14860,14 +15019,19 @@ var RadfiProvider = class {
14860
15019
  params
14861
15020
  })
14862
15021
  });
15022
+ const body = await this.parseJsonBody(
15023
+ res,
15024
+ "Failed to sign and broadcast withdraw transaction"
15025
+ );
14863
15026
  if (!res.ok) {
14864
- const err = await res.json();
14865
- throw new RadfiApiError(res.status, err, "Failed to sign and broadcast withdraw transaction");
15027
+ throw new RadfiApiError(res.status, body, "Failed to sign and broadcast withdraw transaction");
14866
15028
  }
14867
- return res.json().then((r) => {
14868
- const txId = r.data?.txId;
14869
- return typeof txId === "object" && txId?.data ? txId.data : txId;
14870
- });
15029
+ const raw = body.data?.txId;
15030
+ const txId = typeof raw === "object" ? raw?.data : raw;
15031
+ if (!txId) {
15032
+ throw new RadfiApiError(res.status, body, "Failed to sign and broadcast withdraw transaction");
15033
+ }
15034
+ return txId;
14871
15035
  }
14872
15036
  /**
14873
15037
  * Get max spendable amount for a withdraw transaction (amount after fee).
@@ -14883,11 +15047,56 @@ var RadfiProvider = class {
14883
15047
  params
14884
15048
  })
14885
15049
  });
14886
- if (!res.ok) {
14887
- const err = await res.json();
14888
- throw new RadfiApiError(res.status, err, "Failed to get max withdrawable amount");
15050
+ const body = await this.parseJsonBody(res, "Failed to get max withdrawable amount");
15051
+ if (!res.ok || !body.data) {
15052
+ throw new RadfiApiError(res.status, body, "Failed to get max withdrawable amount");
15053
+ }
15054
+ return body.data;
15055
+ }
15056
+ /**
15057
+ * Resolve the bearer credential for an authenticated Bound Exchange call, failing fast when none
15058
+ * is available. A server-side raw-build caller that never ran the interactive sign-in would
15059
+ * otherwise send `Authorization: Bearer ` (empty) and get an opaque 403 from Bound's gateway;
15060
+ * throwing here turns that into an actionable client-side error naming the fix. We deliberately do
15061
+ * NOT validate the token's contents (expiry / scope / signature) — only Bound can, and an invalid
15062
+ * token still surfaces as a legible 401/403 via `parseJsonBody`.
15063
+ */
15064
+ resolveAuth(accessToken) {
15065
+ const auth = accessToken || this.config.apiKey;
15066
+ if (!auth) {
15067
+ throw new RadfiApiError(
15068
+ 401,
15069
+ {
15070
+ message: "Bound Exchange access token (or apiKey) is required but none was set. Inject one via sodax.spoke.bitcoin.radfi.setRadfiAccessToken(token) or new Sodax({ ... }) with radfi.accessToken."
15071
+ },
15072
+ "Missing Bound Exchange credentials"
15073
+ );
15074
+ }
15075
+ return auth;
15076
+ }
15077
+ /**
15078
+ * Parse a Bound Exchange response body as JSON defensively.
15079
+ *
15080
+ * Bound (or an upstream gateway / WAF / CDN) can answer a request with an HTML error page
15081
+ * instead of JSON — e.g. an unauthenticated call, a blocked origin, a 404, or a 5xx. Calling
15082
+ * `res.json()` on that throws a cryptic `SyntaxError: Unexpected token '<'` that masks the real
15083
+ * HTTP status and bubbles up as an opaque failure (it surfaced as a `createIntent` /
15084
+ * `INTENT_CREATION_FAILED` "is not valid JSON" error on the Bitcoin raw-tx path). Reading the
15085
+ * body as text first and parsing it ourselves lets us raise a `RadfiApiError` carrying the
15086
+ * actual status code and a body snippet instead.
15087
+ */
15088
+ async parseJsonBody(res, fallback) {
15089
+ const text = await res.text();
15090
+ try {
15091
+ return text.length ? JSON.parse(text) : {};
15092
+ } catch {
15093
+ const snippet = text.replace(/\s+/g, " ").trim().slice(0, 200);
15094
+ throw new RadfiApiError(
15095
+ res.status,
15096
+ { message: `Bound Exchange returned a non-JSON response (HTTP ${res.status})${snippet ? `: ${snippet}` : ""}` },
15097
+ fallback
15098
+ );
14889
15099
  }
14890
- return res.json().then((r) => r.data);
14891
15100
  }
14892
15101
  async request(endpoint, options) {
14893
15102
  return fetch(`${this.config.apiUrl}${endpoint}`, {
@@ -17420,8 +17629,8 @@ function chain(...args) {
17420
17629
  const id = (a) => a;
17421
17630
  const wrap = (a, b) => (c) => a(b(c));
17422
17631
  const encode3 = args.map((x) => x.encode).reduceRight(wrap, id);
17423
- const decode = args.map((x) => x.decode).reduce(wrap, id);
17424
- return { encode: encode3, decode };
17632
+ const decode2 = args.map((x) => x.decode).reduce(wrap, id);
17633
+ return { encode: encode3, decode: decode2 };
17425
17634
  }
17426
17635
  // @__NO_SIDE_EFFECTS__
17427
17636
  function alphabet(letters) {
@@ -23522,6 +23731,8 @@ var IconSpokeService = class {
23522
23731
  };
23523
23732
  }
23524
23733
  };
23734
+ var GAS_BUFFER_MULTIPLIER = 1.2;
23735
+ var GAS_PRICE_REGEX = /^(\d+)(.*)$/;
23525
23736
  var InjectiveSpokeService = class {
23526
23737
  config;
23527
23738
  chainGrpcWasmApi;
@@ -23529,6 +23740,7 @@ var InjectiveSpokeService = class {
23529
23740
  endpoints;
23530
23741
  pollingIntervalMs;
23531
23742
  maxTimeoutMs;
23743
+ gasPrice;
23532
23744
  constructor(config) {
23533
23745
  this.config = config;
23534
23746
  this.endpoints = networks.getNetworkEndpoints(networks.Network.Mainnet);
@@ -23536,6 +23748,16 @@ var InjectiveSpokeService = class {
23536
23748
  this.txClient = new sdkTs.TxGrpcApi(this.endpoints.grpc);
23537
23749
  this.pollingIntervalMs = this.config.sodaxConfig.chains[ChainKeys.INJECTIVE_MAINNET].pollingConfig.pollingIntervalMs;
23538
23750
  this.maxTimeoutMs = this.config.sodaxConfig.chains[ChainKeys.INJECTIVE_MAINNET].pollingConfig.maxTimeoutMs;
23751
+ this.gasPrice = this.config.getChainConfig(ChainKeys.INJECTIVE_MAINNET).gasPrice;
23752
+ }
23753
+ /** Parse a chain-config gas price like `"500000000inj"` into its numeric price and denom. */
23754
+ parseGasPrice(gasPrice) {
23755
+ const match = GAS_PRICE_REGEX.exec(gasPrice);
23756
+ const price = match?.[1];
23757
+ if (price === void 0) {
23758
+ throw new Error(`Invalid Injective gasPrice config: ${gasPrice}`);
23759
+ }
23760
+ return { price: BigInt(price), denom: match?.[2] || "inj" };
23539
23761
  }
23540
23762
  /**
23541
23763
  * Estimate the gas for a transaction.
@@ -23544,7 +23766,7 @@ var InjectiveSpokeService = class {
23544
23766
  * @returns {Promise<InjectiveGasEstimate>} The estimated gas for the transaction.
23545
23767
  */
23546
23768
  async estimateGas({ tx }) {
23547
- const txRaw = sdkTs.CosmosTxV1Beta1TxPb.TxRaw.fromPartial({
23769
+ const txRaw = tx_js.TxRaw.fromPartial({
23548
23770
  bodyBytes: tx.signedDoc.bodyBytes,
23549
23771
  authInfoBytes: tx.signedDoc.authInfoBytes,
23550
23772
  signatures: []
@@ -23583,7 +23805,9 @@ var InjectiveSpokeService = class {
23583
23805
  chainConfig.networkId,
23584
23806
  from,
23585
23807
  chainConfig.addresses.assetManager,
23586
- msg
23808
+ msg,
23809
+ void 0,
23810
+ funds
23587
23811
  );
23588
23812
  }
23589
23813
  const res = await params.walletProvider.execute(from, chainConfig.addresses.assetManager, msg, funds);
@@ -23604,27 +23828,50 @@ var InjectiveSpokeService = class {
23604
23828
  );
23605
23829
  return BigInt(sdkTs.fromBase64(response.data));
23606
23830
  }
23607
- async getRawTransaction(chainId, senderAddress, contractAddress, msg, memo) {
23831
+ async getRawTransaction(chainId, senderAddress, contractAddress, msg, memo, funds = []) {
23608
23832
  const msgExec = sdkTs.MsgExecuteContract.fromJSON({
23609
23833
  contractAddress,
23610
23834
  sender: senderAddress,
23611
23835
  msg,
23612
- funds: []
23836
+ funds
23613
23837
  });
23614
- const { txRaw } = await sdkTs.createTransactionForAddressAndMsg({
23838
+ const accountResponse = await new sdkTs.ChainRestAuthApi(this.endpoints.rest).fetchCosmosAccount(senderAddress);
23839
+ const baseAccount = sdkTs.BaseAccount.fromRestCosmosApi(accountResponse);
23840
+ const pubKey = baseAccount.pubKey.key;
23841
+ if (!pubKey) {
23842
+ throw new Error(`The pubKey for ${senderAddress} is missing \u2014 the account has not signed a transaction yet.`);
23843
+ }
23844
+ const txArgs = {
23615
23845
  message: msgExec,
23616
23846
  memo: memo || "",
23617
- address: senderAddress,
23618
- endpoint: this.endpoints.grpc,
23847
+ pubKey,
23848
+ sequence: baseAccount.sequence,
23849
+ accountNumber: baseAccount.accountNumber,
23619
23850
  chainId
23620
- });
23851
+ };
23852
+ const draft = sdkTs.createTransaction(txArgs);
23853
+ const { gasInfo } = await this.txClient.simulate(
23854
+ tx_js.TxRaw.fromPartial({
23855
+ bodyBytes: draft.txRaw.bodyBytes,
23856
+ authInfoBytes: draft.txRaw.authInfoBytes,
23857
+ signatures: []
23858
+ // not required for simulation
23859
+ })
23860
+ );
23861
+ const gas = Math.ceil(gasInfo.gasUsed * GAS_BUFFER_MULTIPLIER);
23862
+ const { price, denom } = this.parseGasPrice(this.gasPrice);
23863
+ const fee = {
23864
+ amount: [{ denom, amount: (BigInt(gas) * price).toString() }],
23865
+ gas: gas.toString()
23866
+ };
23867
+ const { txRaw, signDoc } = sdkTs.createTransaction({ ...txArgs, fee });
23621
23868
  const rawTx = {
23622
23869
  from: senderAddress,
23623
23870
  to: contractAddress,
23624
23871
  signedDoc: {
23625
23872
  bodyBytes: txRaw.bodyBytes,
23626
23873
  chainId,
23627
- accountNumber: BigInt(0),
23874
+ accountNumber: BigInt(signDoc.accountNumber),
23628
23875
  authInfoBytes: txRaw.authInfoBytes
23629
23876
  }
23630
23877
  };
@@ -25763,6 +26010,24 @@ var SolverApiService = class {
25763
26010
  }
25764
26011
  }
25765
26012
  };
26013
+ function decodePacketIntentTarget(payload) {
26014
+ try {
26015
+ const hex = payload.startsWith("0x") ? payload.slice(2) : payload;
26016
+ const decoded = rlp__namespace.decode(Buffer.from(hex, "hex"));
26017
+ const field1 = decoded?.[1];
26018
+ if (!field1 || field1.length === 0) return void 0;
26019
+ return `0x${Buffer.from(field1).toString("hex")}`.toLowerCase();
26020
+ } catch {
26021
+ return void 0;
26022
+ }
26023
+ }
26024
+ function selectSolvedIntentPacket(packets, intentsContract) {
26025
+ if (packets.length <= 1) return packets[0];
26026
+ const target = intentsContract.toLowerCase();
26027
+ const matched = packets.find((packet) => decodePacketIntentTarget(packet.payload) === target);
26028
+ if (matched) return matched;
26029
+ return packets.reduce((highest, packet) => packet.conn_sn > highest.conn_sn ? packet : highest);
26030
+ }
25766
26031
 
25767
26032
  // src/swap/errors.ts
25768
26033
  var swapInvariant = createInvariant("swap");
@@ -25798,7 +26063,7 @@ var SwapService = class {
25798
26063
  relayerApiEndpoint;
25799
26064
  constructor({ config, hubProvider, spoke }) {
25800
26065
  this.solver = config.solver;
25801
- this.partnerFee = config.swaps.partnerFee;
26066
+ this.partnerFee = config.swapPartnerFee;
25802
26067
  this.relayerApiEndpoint = config.relay.relayerApiEndpoint;
25803
26068
  this.config = config;
25804
26069
  this.hubProvider = hubProvider;
@@ -25816,10 +26081,13 @@ var SwapService = class {
25816
26081
  /**
25817
26082
  * Requests a price quote from the solver API for a given token pair and amount.
25818
26083
  *
25819
- * Adjusts `payload.amount` by the configured partner fee before forwarding to the solver,
25820
- * so the returned `quoted_amount` reflects the net output the user actually receives.
26084
+ * Adjusts `payload.amount` by the partner fee before forwarding to the solver, so the returned
26085
+ * `quoted_amount` reflects the net output the user actually receives. Pass `partnerFee` to match
26086
+ * a per-action override supplied to `createIntent` (`extras.partnerFee`); omit it to use the
26087
+ * configured swap fee.
25821
26088
  *
25822
- * @param payload - Source/destination tokens, chain IDs, input amount, and quote type.
26089
+ * @param payload - The solver quote request, optionally carrying a per-call `partnerFee` override
26090
+ * (defaults to the configured swap partner fee). `partnerFee` is stripped before forwarding.
25823
26091
  * @returns A `Result` containing `{ quoted_amount: bigint }` on success, or a
25824
26092
  * `SolverErrorResponse` (with a `SolverIntentErrorCode`) on failure.
25825
26093
  *
@@ -25835,11 +26103,12 @@ var SwapService = class {
25835
26103
  * if (response.ok) console.log('Quoted amount:', response.value.quoted_amount);
25836
26104
  */
25837
26105
  async getQuote(payload) {
25838
- payload = {
25839
- ...payload,
25840
- amount: adjustAmountByFee(payload.amount, this.partnerFee, payload.quote_type)
26106
+ const { partnerFee = this.partnerFee, ...request } = payload;
26107
+ const adjustedPayload = {
26108
+ ...request,
26109
+ amount: adjustAmountByFee(request.amount, partnerFee, request.quote_type)
25841
26110
  };
25842
- return SolverApiService.getQuote(payload, this.solver, this.config);
26111
+ return SolverApiService.getQuote(adjustedPayload, this.solver, this.config);
25843
26112
  }
25844
26113
  /**
25845
26114
  * Calculates the partner fee that will be deducted from the given input amount.
@@ -26189,7 +26458,8 @@ var SwapService = class {
26189
26458
  * - `UNKNOWN` — defensive fallback.
26190
26459
  */
26191
26460
  async createIntent(_params) {
26192
- const { params, skipSimulation } = _params;
26461
+ const { params, skipSimulation, extras } = _params;
26462
+ const partnerFee = extras?.partnerFee ?? this.partnerFee;
26193
26463
  const baseCtx = { srcChainKey: params.srcChainKey, dstChainKey: params.dstChainKey };
26194
26464
  try {
26195
26465
  swapInvariant(
@@ -26224,16 +26494,27 @@ var SwapService = class {
26224
26494
  { ...baseCtx, field: "minOutputAmount" }
26225
26495
  );
26226
26496
  }
26227
- const personalAddress = params.srcAddress;
26228
- let walletAddress = personalAddress;
26229
- if (isBitcoinChainKeyType(params.srcChainKey) && _params.raw === false) {
26497
+ if (isStacksChainKeyType(params.srcChainKey) && _params.raw === true) {
26230
26498
  swapInvariant(
26231
- isBitcoinWalletProviderType(_params.walletProvider),
26232
- `Invalid wallet provider for chain key: ${params.srcChainKey}`,
26233
- baseCtx
26499
+ extras?.srcPublicKey !== void 0,
26500
+ "srcPublicKey is required for Stacks createIntent (raw) \u2014 the source tx is built unsigned and needs the signer public key",
26501
+ { ...baseCtx, field: "srcPublicKey" }
26234
26502
  );
26503
+ }
26504
+ const personalAddress = params.srcAddress;
26505
+ let walletAddress = personalAddress;
26506
+ if (isBitcoinChainKeyType(params.srcChainKey)) {
26507
+ if (_params.raw === false) {
26508
+ swapInvariant(
26509
+ isBitcoinWalletProviderType(_params.walletProvider),
26510
+ `Invalid wallet provider for chain key: ${params.srcChainKey}`,
26511
+ baseCtx
26512
+ );
26513
+ if (this.spoke.bitcoin.walletMode === "TRADING") {
26514
+ await this.spoke.bitcoin.radfi.ensureRadfiAccessToken(_params.walletProvider);
26515
+ }
26516
+ }
26235
26517
  walletAddress = await this.spoke.bitcoin.getEffectiveWalletAddress(personalAddress);
26236
- await this.spoke.bitcoin.radfi.ensureRadfiAccessToken(_params.walletProvider);
26237
26518
  }
26238
26519
  const creatorHubWalletAddress = await this.hubProvider.getUserHubWalletAddress(walletAddress, params.srcChainKey);
26239
26520
  if (isHubChainKeyType(params.srcChainKey) && isSonicChainKeyType(params.srcChainKey)) {
@@ -26241,7 +26522,7 @@ var SwapService = class {
26241
26522
  createIntentParams: params,
26242
26523
  creatorHubWalletAddress,
26243
26524
  solverConfig: this.solver,
26244
- fee: this.config.swaps.partnerFee,
26525
+ fee: partnerFee,
26245
26526
  hubProvider: this.hubProvider
26246
26527
  };
26247
26528
  const [txResult2, intent2, feeAmount2, data2] = await SonicSpokeService.createSwapIntent(
@@ -26267,11 +26548,14 @@ var SwapService = class {
26267
26548
  },
26268
26549
  creatorHubWalletAddress,
26269
26550
  this.config,
26270
- this.config.swaps.partnerFee
26551
+ partnerFee
26271
26552
  );
26272
26553
  const coreDepositParams = {
26273
26554
  srcChainKey: params.srcChainKey,
26274
26555
  srcAddress: walletAddress,
26556
+ srcPublicKey: extras?.srcPublicKey,
26557
+ // Bitcoin Bound token; BitcoinSpokeService.deposit falls back to the RadfiProvider instance token when undefined.
26558
+ accessToken: extras?.bound?.accessToken,
26275
26559
  to: creatorHubWalletAddress,
26276
26560
  token: params.inputToken,
26277
26561
  amount: params.inputAmount,
@@ -26590,6 +26874,11 @@ var SwapService = class {
26590
26874
  * Use this after `getStatus` returns `SolverIntentStatusCode.SOLVED (3)` to obtain the
26591
26875
  * destination-chain transaction hash from `packet.dst_tx_hash`.
26592
26876
  *
26877
+ * A single solver fill tx emits multiple relay packets sharing the same `src_tx_hash`. The
26878
+ * user-facing `IntentFilled` delivery is the packet whose payload targets the hub intents
26879
+ * contract; `selectSolvedIntentPacket` disambiguates so the returned `dst_tx_hash` is the
26880
+ * destination delivery tx rather than an internal hop.
26881
+ *
26593
26882
  * @param chainId - The destination spoke chain key (where output tokens are delivered).
26594
26883
  * @param fillTxHash - The solver's fill transaction hash, obtained from `getStatus.fill_tx_hash`.
26595
26884
  * @param timeout - Poll timeout in milliseconds. Defaults to `DEFAULT_RELAY_TX_TIMEOUT` (120 s).
@@ -26605,7 +26894,8 @@ var SwapService = class {
26605
26894
  intentRelayChainId: getIntentRelayChainId(chainId).toString(),
26606
26895
  srcTxHash: fillTxHash,
26607
26896
  timeout,
26608
- apiUrl: this.relayerApiEndpoint
26897
+ apiUrl: this.relayerApiEndpoint,
26898
+ selectPacket: (packets) => selectSolvedIntentPacket(packets, this.solver.intentsContract)
26609
26899
  });
26610
26900
  }
26611
26901
  /**
@@ -29130,10 +29420,10 @@ var BridgeService = class {
29130
29420
  * @returns Fee amount to be deducted, in the same units as `inputAmount`.
29131
29421
  */
29132
29422
  getFee(inputAmount) {
29133
- if (!this.config.bridge.partnerFee) {
29423
+ if (!this.config.bridgePartnerFee) {
29134
29424
  return 0n;
29135
29425
  }
29136
- return calculateFeeAmount(inputAmount, this.config.bridge.partnerFee);
29426
+ return calculateFeeAmount(inputAmount, this.config.bridgePartnerFee);
29137
29427
  }
29138
29428
  /**
29139
29429
  * Checks whether the caller has sufficient token allowance to execute the bridge.
@@ -29410,7 +29700,7 @@ var BridgeService = class {
29410
29700
  }
29411
29701
  const hubWallet = await this.hubProvider.getUserHubWalletAddress(walletAddress, params.srcChainKey);
29412
29702
  const effectiveSkipSimulation = skipSimulation || isBitcoinChainKeyType(params.srcChainKey) && this.spoke.bitcoin.walletMode === "USER";
29413
- const data = this.buildBridgeData(params, srcToken, dstToken, this.config.bridge.partnerFee);
29703
+ const data = this.buildBridgeData(params, srcToken, dstToken, this.config.bridgePartnerFee);
29414
29704
  const coreParams = {
29415
29705
  srcChainKey: params.srcChainKey,
29416
29706
  srcAddress: walletAddress,
@@ -35289,7 +35579,7 @@ var MoneyMarketService = class _MoneyMarketService {
35289
35579
  this.config = config;
35290
35580
  this.hubProvider = hubProvider;
35291
35581
  this.spoke = spoke;
35292
- this.partnerFee = config.moneyMarket.partnerFee;
35582
+ this.partnerFee = config.moneyMarketPartnerFee;
35293
35583
  this.relayerApiEndpoint = config.relay.relayerApiEndpoint;
35294
35584
  this.data = new MoneyMarketDataService({ hubProvider, config });
35295
35585
  }
@@ -37431,7 +37721,7 @@ var LeverageYieldService = class {
37431
37721
  * `UNKNOWN` (defensive fallback).
37432
37722
  */
37433
37723
  async createVaultIntent(_params) {
37434
- const { params, skipSimulation, hubWalletSwap, partnerFee = this.config.swaps.partnerFee } = _params;
37724
+ const { params, skipSimulation, hubWalletSwap, partnerFee = this.config.swapPartnerFee } = _params;
37435
37725
  const baseCtx = { srcChainKey: params.srcChainKey, dstChainKey: params.dstChainKey };
37436
37726
  try {
37437
37727
  leverageYieldInvariant(
@@ -38063,11 +38353,18 @@ var Sodax = class {
38063
38353
  // hub provider for the hub chain (e.g. Sonic mainnet)
38064
38354
  spoke;
38065
38355
  // spoke service enabling spoke chain operations
38066
- constructor(config) {
38067
- const logger = resolveLogger(config?.logger);
38068
- this.instanceConfig = config ? mergeSodaxConfig(sodaxConfig, config) : sodaxConfig;
38356
+ constructor(options) {
38357
+ const logger = resolveLogger(options?.logger);
38358
+ const fee = options?.fee;
38359
+ this.instanceConfig = options ? mergeSodaxConfig(sodaxConfig, options) : sodaxConfig;
38069
38360
  this.backendApi = new BackendApiService(this.instanceConfig.api, logger);
38070
- this.config = new ConfigService({ api: this.backendApi, config: this.instanceConfig, userConfig: config, logger });
38361
+ this.config = new ConfigService({
38362
+ api: this.backendApi,
38363
+ config: this.instanceConfig,
38364
+ userConfig: options,
38365
+ logger,
38366
+ fee
38367
+ });
38071
38368
  this.hubProvider = new EvmHubProvider({ config: this.config });
38072
38369
  this.spoke = new SpokeService({ config: this.config, hubProvider: this.hubProvider });
38073
38370
  this.swaps = new SwapService({
@@ -38362,6 +38659,7 @@ exports.getReserveNormalizedIncome = getReserveNormalizedIncome;
38362
38659
  exports.getReservesEModes = getReservesEModes;
38363
38660
  exports.getSolanaAddressBytes = getSolanaAddressBytes;
38364
38661
  exports.getSolverConfig = getSolverConfig;
38662
+ exports.getStagingSolverTokens = getStagingSolverTokens;
38365
38663
  exports.getSupportedSolverTokens = getSupportedSolverTokens;
38366
38664
  exports.getTransactionPackets = getTransactionPackets;
38367
38665
  exports.getbnUSDToken = getbnUSDToken;
@@ -38539,6 +38837,7 @@ exports.spokeAssetManagerAbi = spokeAssetManagerAbi;
38539
38837
  exports.spokeChainConfig = spokeChainConfig;
38540
38838
  exports.spokeChainKeysSet = spokeChainKeysSet;
38541
38839
  exports.stacksSupportedTokens = stacksSupportedTokens;
38840
+ exports.stagingSwapSupportedTokens = stagingSwapSupportedTokens;
38542
38841
  exports.stakedSodaAbi = stakedSodaAbi;
38543
38842
  exports.stakingInvariant = stakingInvariant;
38544
38843
  exports.stakingRouterAbi = stakingRouterAbi;