@sodax/sdk 2.0.0-rc.12 → 2.0.0-rc.14
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 +1271 -91
- package/dist/index.d.cts +572 -45
- package/dist/index.d.ts +572 -45
- package/dist/index.mjs +1260 -95
- package/package.json +5 -4
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');
|
|
@@ -197,7 +198,8 @@ var SODAX_FEATURES = [
|
|
|
197
198
|
"migration",
|
|
198
199
|
"dex",
|
|
199
200
|
"partner",
|
|
200
|
-
"recovery"
|
|
201
|
+
"recovery",
|
|
202
|
+
"leverageYield"
|
|
201
203
|
];
|
|
202
204
|
|
|
203
205
|
// src/shared/utils/tiny-invariant.ts
|
|
@@ -330,7 +332,8 @@ var HubVaultSymbols = [
|
|
|
330
332
|
"sodaNEAR",
|
|
331
333
|
"sodaKAIA",
|
|
332
334
|
"sodaSTX",
|
|
333
|
-
"sodaUSDS"
|
|
335
|
+
"sodaUSDS",
|
|
336
|
+
"sodaJITOSOL"
|
|
334
337
|
];
|
|
335
338
|
var SodaTokens = {
|
|
336
339
|
sodaBNB: {
|
|
@@ -557,6 +560,45 @@ var SodaTokens = {
|
|
|
557
560
|
chainKey: ChainKeys.SONIC_MAINNET,
|
|
558
561
|
hubAsset: "0x243b0c26c8b38793908d7C64e8510f21B19B4613",
|
|
559
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"
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
var LsodaSymbols = ["lsodaWEETH", "lsodaWSTETH", "lsodaJITOSOL"];
|
|
575
|
+
var LsodaTokens = {
|
|
576
|
+
lsodaWEETH: {
|
|
577
|
+
symbol: "lsodaWEETH",
|
|
578
|
+
name: "Leveraged Soda weETH",
|
|
579
|
+
decimals: 18,
|
|
580
|
+
address: "0xD09de2f5070699A909c0FD32fb5A909d3886701D",
|
|
581
|
+
chainKey: ChainKeys.SONIC_MAINNET,
|
|
582
|
+
hubAsset: "0xD09de2f5070699A909c0FD32fb5A909d3886701D",
|
|
583
|
+
vault: "0xD09de2f5070699A909c0FD32fb5A909d3886701D"
|
|
584
|
+
},
|
|
585
|
+
lsodaWSTETH: {
|
|
586
|
+
symbol: "lsodaWSTETH",
|
|
587
|
+
name: "Leveraged Soda wstETH",
|
|
588
|
+
decimals: 18,
|
|
589
|
+
address: "0x136E5D1CEC5db1829E24941Eddd9C8640E02Ce7a",
|
|
590
|
+
chainKey: ChainKeys.SONIC_MAINNET,
|
|
591
|
+
hubAsset: "0x136E5D1CEC5db1829E24941Eddd9C8640E02Ce7a",
|
|
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"
|
|
560
602
|
}
|
|
561
603
|
};
|
|
562
604
|
var sonicSupportedTokens = {
|
|
@@ -623,7 +665,8 @@ var sonicSupportedTokens = {
|
|
|
623
665
|
hubAsset: "0x7c7d53EEcda37a87ce0D5bf8E0b24512A48dC963",
|
|
624
666
|
vault: SodaTokens.sodaSODA.address
|
|
625
667
|
},
|
|
626
|
-
...SodaTokens
|
|
668
|
+
...SodaTokens,
|
|
669
|
+
...LsodaTokens
|
|
627
670
|
};
|
|
628
671
|
var redbellySupportedTokens = {
|
|
629
672
|
RBNT: {
|
|
@@ -833,7 +876,7 @@ var solanaSupportedTokens = {
|
|
|
833
876
|
address: "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn",
|
|
834
877
|
chainKey: ChainKeys.SOLANA_MAINNET,
|
|
835
878
|
hubAsset: "0x942f89a324d2652e447b9fcf08effc9f9776a680",
|
|
836
|
-
vault:
|
|
879
|
+
vault: SodaTokens.sodaJITOSOL.address
|
|
837
880
|
},
|
|
838
881
|
mSOL: {
|
|
839
882
|
symbol: "mSOL",
|
|
@@ -1266,6 +1309,15 @@ var baseSupportedTokens = {
|
|
|
1266
1309
|
chainKey: ChainKeys.BASE_MAINNET,
|
|
1267
1310
|
hubAsset: "0xaa81bb5ba3c972ab53605d3ba7e443a3de6d1cb9",
|
|
1268
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"
|
|
1269
1321
|
}
|
|
1270
1322
|
};
|
|
1271
1323
|
var optimismSupportedTokens = {
|
|
@@ -1948,6 +2000,33 @@ var stellarSupportedTokens = {
|
|
|
1948
2000
|
chainKey: ChainKeys.STELLAR_MAINNET,
|
|
1949
2001
|
hubAsset: "0xD749B5FfFED7cEDaa3239abDd16D677179C29AEc",
|
|
1950
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
|
|
1951
2030
|
}
|
|
1952
2031
|
};
|
|
1953
2032
|
var suiSupportedTokens = {
|
|
@@ -3087,6 +3166,21 @@ var spokeChainConfig = {
|
|
|
3087
3166
|
assetCode: "SODA",
|
|
3088
3167
|
contractId: "CAH5LKJC2ZB4RVUVEVL2QWJWNJLHQE2UF767ILLQ5EQ4O3OURR2XIUGM",
|
|
3089
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"
|
|
3090
3184
|
}
|
|
3091
3185
|
],
|
|
3092
3186
|
supportedTokens: stellarSupportedTokens,
|
|
@@ -3362,7 +3456,8 @@ var moneyMarketSupportedTokens = {
|
|
|
3362
3456
|
spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.bnUSD,
|
|
3363
3457
|
spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.USDC,
|
|
3364
3458
|
spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.SODA,
|
|
3365
|
-
spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.USDT
|
|
3459
|
+
spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.USDT,
|
|
3460
|
+
spokeChainConfig[ChainKeys.SOLANA_MAINNET].supportedTokens.JitoSOL
|
|
3366
3461
|
],
|
|
3367
3462
|
[ChainKeys.ICON_MAINNET]: [
|
|
3368
3463
|
// spokeChainConfig[ChainKeys.ICON].supportedTokens.ICX,
|
|
@@ -3373,7 +3468,10 @@ var moneyMarketSupportedTokens = {
|
|
|
3373
3468
|
spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.XLM,
|
|
3374
3469
|
spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.bnUSD,
|
|
3375
3470
|
spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.SODA,
|
|
3376
|
-
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
|
|
3377
3475
|
],
|
|
3378
3476
|
[ChainKeys.SUI_MAINNET]: [
|
|
3379
3477
|
spokeChainConfig[ChainKeys.SUI_MAINNET].supportedTokens.SUI,
|
|
@@ -3624,7 +3722,9 @@ var swapSupportedTokens = {
|
|
|
3624
3722
|
spokeChainConfig[ChainKeys.SONIC_MAINNET].supportedTokens.USDT,
|
|
3625
3723
|
spokeChainConfig[ChainKeys.SONIC_MAINNET].supportedTokens.wS,
|
|
3626
3724
|
spokeChainConfig[ChainKeys.SONIC_MAINNET].supportedTokens.SODA,
|
|
3627
|
-
|
|
3725
|
+
// sodaUSDS is staging-only — see stagingSwapSupportedTokens
|
|
3726
|
+
...Object.values(SodaTokens).filter((t) => t !== SodaTokens.sodaUSDS),
|
|
3727
|
+
...Object.values(LsodaTokens)
|
|
3628
3728
|
],
|
|
3629
3729
|
[ChainKeys.AVALANCHE_MAINNET]: [
|
|
3630
3730
|
spokeChainConfig[ChainKeys.AVALANCHE_MAINNET].supportedTokens.AVAX,
|
|
@@ -3643,36 +3743,35 @@ var swapSupportedTokens = {
|
|
|
3643
3743
|
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.tBTC,
|
|
3644
3744
|
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.USDC,
|
|
3645
3745
|
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.USDT,
|
|
3646
|
-
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.SODA,
|
|
3647
3746
|
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.ARB,
|
|
3648
3747
|
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.AAVE,
|
|
3649
3748
|
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.LINK,
|
|
3650
3749
|
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.UNI,
|
|
3651
3750
|
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.CRV,
|
|
3652
3751
|
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.PENDLE,
|
|
3653
|
-
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.rETH
|
|
3752
|
+
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.rETH,
|
|
3753
|
+
spokeChainConfig[ChainKeys.ARBITRUM_MAINNET].supportedTokens.SODA
|
|
3654
3754
|
],
|
|
3655
3755
|
[ChainKeys.BASE_MAINNET]: [
|
|
3656
3756
|
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.ETH,
|
|
3657
|
-
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.bnUSD,
|
|
3658
3757
|
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.weETH,
|
|
3659
3758
|
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.USDC,
|
|
3660
3759
|
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.wstETH,
|
|
3661
3760
|
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.cbBTC,
|
|
3662
|
-
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.SODA,
|
|
3663
3761
|
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.VIRTUAL,
|
|
3664
|
-
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.cbETH
|
|
3762
|
+
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.cbETH,
|
|
3763
|
+
spokeChainConfig[ChainKeys.BASE_MAINNET].supportedTokens.SODA
|
|
3665
3764
|
],
|
|
3666
3765
|
[ChainKeys.OPTIMISM_MAINNET]: [
|
|
3667
3766
|
spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.ETH,
|
|
3668
|
-
spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.bnUSD,
|
|
3669
3767
|
spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.USDC,
|
|
3670
3768
|
spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.wstETH,
|
|
3671
3769
|
// spokeChainConfig[OPTIMISM_MAINNET_CHAIN_ID].supportedTokens.weETH, // NOTE: Not Implemented
|
|
3672
3770
|
spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.USDT,
|
|
3673
3771
|
spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.SODA,
|
|
3674
3772
|
spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.OP,
|
|
3675
|
-
spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.WBTC
|
|
3773
|
+
spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.WBTC,
|
|
3774
|
+
spokeChainConfig[ChainKeys.OPTIMISM_MAINNET].supportedTokens.bnUSD
|
|
3676
3775
|
],
|
|
3677
3776
|
[ChainKeys.POLYGON_MAINNET]: [
|
|
3678
3777
|
spokeChainConfig[ChainKeys.POLYGON_MAINNET].supportedTokens.POL,
|
|
@@ -3728,7 +3827,6 @@ var swapSupportedTokens = {
|
|
|
3728
3827
|
spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens["SUI.LL"],
|
|
3729
3828
|
spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens["S.LL"],
|
|
3730
3829
|
spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens["POL.LL"],
|
|
3731
|
-
spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens["HYPE.LL"],
|
|
3732
3830
|
spokeChainConfig[ChainKeys.LIGHTLINK_MAINNET].supportedTokens.LL
|
|
3733
3831
|
],
|
|
3734
3832
|
[ChainKeys.SOLANA_MAINNET]: [
|
|
@@ -3767,7 +3865,10 @@ var swapSupportedTokens = {
|
|
|
3767
3865
|
spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.bnUSD,
|
|
3768
3866
|
// NOTE: Not Implemented
|
|
3769
3867
|
spokeChainConfig[ChainKeys.STELLAR_MAINNET].supportedTokens.USDC,
|
|
3770
|
-
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
|
|
3771
3872
|
],
|
|
3772
3873
|
[ChainKeys.SUI_MAINNET]: [
|
|
3773
3874
|
spokeChainConfig[ChainKeys.SUI_MAINNET].supportedTokens.SUI,
|
|
@@ -3785,12 +3886,8 @@ var swapSupportedTokens = {
|
|
|
3785
3886
|
spokeChainConfig[ChainKeys.SUI_MAINNET].supportedTokens.WAL,
|
|
3786
3887
|
spokeChainConfig[ChainKeys.SUI_MAINNET].supportedTokens.NAVX
|
|
3787
3888
|
],
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.bnUSD,
|
|
3791
|
-
spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.USDC
|
|
3792
|
-
// spokeChainConfig[ChainKeys.INJECTIVE_MAINNET].supportedTokens.SODA, // NOTE: not in solver wiki
|
|
3793
|
-
],
|
|
3889
|
+
// Injective is currently staging-only — see stagingSwapSupportedTokens
|
|
3890
|
+
[ChainKeys.INJECTIVE_MAINNET]: [],
|
|
3794
3891
|
[ChainKeys.NEAR_MAINNET]: [
|
|
3795
3892
|
spokeChainConfig[ChainKeys.NEAR_MAINNET].supportedTokens.NEAR,
|
|
3796
3893
|
spokeChainConfig[ChainKeys.NEAR_MAINNET].supportedTokens.bnUSD,
|
|
@@ -3857,24 +3954,112 @@ var swapSupportedTokens = {
|
|
|
3857
3954
|
spokeChainConfig[ChainKeys.STACKS_MAINNET].supportedTokens.USDC
|
|
3858
3955
|
]
|
|
3859
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
|
+
};
|
|
3860
3995
|
var swapsConfig = {
|
|
3861
|
-
partnerFee: void 0,
|
|
3862
3996
|
supportedTokens: swapSupportedTokens
|
|
3863
3997
|
};
|
|
3864
3998
|
var getSupportedSolverTokens = (chainId) => swapSupportedTokens[chainId];
|
|
3865
|
-
var
|
|
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());
|
|
3866
4004
|
|
|
3867
|
-
// ../types/dist/
|
|
3868
|
-
var
|
|
3869
|
-
|
|
4005
|
+
// ../types/dist/leverageYield/leverageYield.js
|
|
4006
|
+
var leverageYieldVaults = [
|
|
4007
|
+
{
|
|
4008
|
+
name: LsodaTokens.lsodaWEETH.symbol,
|
|
4009
|
+
vault: LsodaTokens.lsodaWEETH.vault,
|
|
4010
|
+
asset: SodaTokens.sodaWEETH.address,
|
|
4011
|
+
// sodaWEETH on Sonic
|
|
4012
|
+
borrowToken: SodaTokens.sodaETH.address,
|
|
4013
|
+
// sodaETH on Sonic
|
|
4014
|
+
lsdSource: {
|
|
4015
|
+
// DefiLlama pool for EtherFi's weETH on Ethereum (project: 'ether.fi-stake').
|
|
4016
|
+
poolId: "46bd2bdf-6d92-4066-b482-e885ee172264",
|
|
4017
|
+
fallbackAprPct: 3,
|
|
4018
|
+
label: "EtherFi (weETH)"
|
|
4019
|
+
}
|
|
4020
|
+
},
|
|
4021
|
+
{
|
|
4022
|
+
name: LsodaTokens.lsodaWSTETH.symbol,
|
|
4023
|
+
vault: LsodaTokens.lsodaWSTETH.vault,
|
|
4024
|
+
asset: SodaTokens.sodaWSTETH.address,
|
|
4025
|
+
// sodaWSTETH on Sonic
|
|
4026
|
+
borrowToken: SodaTokens.sodaETH.address,
|
|
4027
|
+
// sodaETH on Sonic
|
|
4028
|
+
lsdSource: {
|
|
4029
|
+
// DefiLlama pool for Lido's stETH on Ethereum (wstETH inherits this rate via redeem).
|
|
4030
|
+
poolId: "747c1d2a-c668-4682-b9f9-296708a3dd90",
|
|
4031
|
+
fallbackAprPct: 2.4,
|
|
4032
|
+
label: "Lido (stETH)"
|
|
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
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
];
|
|
4050
|
+
var leverageYieldConfig = {
|
|
4051
|
+
vaults: leverageYieldVaults
|
|
3870
4052
|
};
|
|
4053
|
+
|
|
4054
|
+
// ../types/dist/sodax-config/sodax-config.js
|
|
4055
|
+
var bridgeConfig = {};
|
|
3871
4056
|
var sodaxConfig = {
|
|
3872
|
-
fee: void 0,
|
|
3873
4057
|
chains: spokeChainConfig,
|
|
3874
4058
|
swaps: swapsConfig,
|
|
3875
4059
|
moneyMarket: moneyMarketConfig,
|
|
3876
4060
|
bridge: bridgeConfig,
|
|
3877
4061
|
dex: dexConfig,
|
|
4062
|
+
leverageYield: leverageYieldConfig,
|
|
3878
4063
|
hub: hubConfig,
|
|
3879
4064
|
api: apiConfig,
|
|
3880
4065
|
solver: solverConfig,
|
|
@@ -4016,7 +4201,7 @@ function isValidWalletProviderForChainKey(chainKey, walletProvider) {
|
|
|
4016
4201
|
}
|
|
4017
4202
|
|
|
4018
4203
|
// ../types/dist/index.js
|
|
4019
|
-
var CONFIG_VERSION =
|
|
4204
|
+
var CONFIG_VERSION = 212;
|
|
4020
4205
|
function isEvmSpokeChainConfig(value) {
|
|
4021
4206
|
return typeof value === "object" && value !== null && value.chain.type === "EVM" && value.chain.key !== HUB_CHAIN_KEY;
|
|
4022
4207
|
}
|
|
@@ -4403,7 +4588,10 @@ async function pollForExecutedPacket(payload) {
|
|
|
4403
4588
|
}
|
|
4404
4589
|
const txPackets = txPacketsResult.value;
|
|
4405
4590
|
if (txPackets.success && txPackets.data.length > 0) {
|
|
4406
|
-
const
|
|
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];
|
|
4407
4595
|
if (packet?.status === "executed") {
|
|
4408
4596
|
return { kind: "found", packet };
|
|
4409
4597
|
}
|
|
@@ -13293,14 +13481,7 @@ function deepMerge(target, source) {
|
|
|
13293
13481
|
|
|
13294
13482
|
// src/shared/config/mergeSodaxConfig.ts
|
|
13295
13483
|
function mergeSodaxConfig(base2, override) {
|
|
13296
|
-
|
|
13297
|
-
if (override.fee !== void 0) {
|
|
13298
|
-
merged.fee = override.fee;
|
|
13299
|
-
}
|
|
13300
|
-
if (override.bridge?.partnerFee !== void 0) {
|
|
13301
|
-
merged.bridge.partnerFee = override.bridge.partnerFee;
|
|
13302
|
-
}
|
|
13303
|
-
return merged;
|
|
13484
|
+
return deepMerge(base2, override);
|
|
13304
13485
|
}
|
|
13305
13486
|
|
|
13306
13487
|
// src/shared/logger.ts
|
|
@@ -13340,6 +13521,12 @@ var ConfigService = class {
|
|
|
13340
13521
|
* {@link initialize}'s dynamic-config swap never clobbers it. Read by services via `config.logger`.
|
|
13341
13522
|
*/
|
|
13342
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;
|
|
13343
13530
|
initialized = false;
|
|
13344
13531
|
// data structures for quick lookup
|
|
13345
13532
|
supportedHubAssetsSet;
|
|
@@ -13351,11 +13538,12 @@ var ConfigService = class {
|
|
|
13351
13538
|
stakedATokenAddressesSet;
|
|
13352
13539
|
chainToSupportedTokenAddressMap;
|
|
13353
13540
|
hubAssetToXTokenMap;
|
|
13354
|
-
constructor({ api, config, userConfig, logger }) {
|
|
13541
|
+
constructor({ api, config, userConfig, logger, fee }) {
|
|
13355
13542
|
this.api = api;
|
|
13356
13543
|
this.sodax = config;
|
|
13357
13544
|
this.userConfig = userConfig;
|
|
13358
13545
|
this.logger = logger ?? resolveLogger(void 0);
|
|
13546
|
+
this.fee = fee;
|
|
13359
13547
|
this.loadSodaxConfigDataStructures(config);
|
|
13360
13548
|
}
|
|
13361
13549
|
async initialize() {
|
|
@@ -13588,6 +13776,24 @@ var ConfigService = class {
|
|
|
13588
13776
|
get moneyMarket() {
|
|
13589
13777
|
return this.sodax.moneyMarket;
|
|
13590
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
|
+
}
|
|
13591
13797
|
get dex() {
|
|
13592
13798
|
return this.sodax.dex;
|
|
13593
13799
|
}
|
|
@@ -14399,12 +14605,23 @@ var StacksSpokeService = class {
|
|
|
14399
14605
|
postConditionMode: core.PostConditionMode.Allow
|
|
14400
14606
|
};
|
|
14401
14607
|
if (params.raw === true) {
|
|
14402
|
-
if (
|
|
14403
|
-
throw new Error(
|
|
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
|
+
);
|
|
14404
14621
|
}
|
|
14405
14622
|
const tx = await core.makeUnsignedContractCall({
|
|
14406
14623
|
...reqData,
|
|
14407
|
-
publicKey: params.
|
|
14624
|
+
publicKey: params.srcPublicKey,
|
|
14408
14625
|
network: this.network,
|
|
14409
14626
|
fee: 0,
|
|
14410
14627
|
// placeholder — we'll estimate
|
|
@@ -17360,8 +17577,8 @@ function chain(...args) {
|
|
|
17360
17577
|
const id = (a) => a;
|
|
17361
17578
|
const wrap = (a, b) => (c) => a(b(c));
|
|
17362
17579
|
const encode3 = args.map((x) => x.encode).reduceRight(wrap, id);
|
|
17363
|
-
const
|
|
17364
|
-
return { encode: encode3, decode };
|
|
17580
|
+
const decode2 = args.map((x) => x.decode).reduce(wrap, id);
|
|
17581
|
+
return { encode: encode3, decode: decode2 };
|
|
17365
17582
|
}
|
|
17366
17583
|
// @__NO_SIDE_EFFECTS__
|
|
17367
17584
|
function alphabet(letters) {
|
|
@@ -22295,17 +22512,11 @@ var SuiSpokeService = class {
|
|
|
22295
22512
|
]
|
|
22296
22513
|
});
|
|
22297
22514
|
if (params.raw === true) {
|
|
22298
|
-
tx.setSender(from);
|
|
22299
|
-
const transactionRaw = await tx.build({
|
|
22300
|
-
client: this.publicClient,
|
|
22301
|
-
onlyTransactionKind: true
|
|
22302
|
-
});
|
|
22303
|
-
const transactionRawBase64String = Buffer.from(transactionRaw).toString("base64");
|
|
22304
22515
|
return {
|
|
22305
22516
|
from,
|
|
22306
22517
|
to: `${assetManager.packageId}::${assetManager.moduleId}::transfer`,
|
|
22307
22518
|
value: amount,
|
|
22308
|
-
data:
|
|
22519
|
+
data: tx.serialize()
|
|
22309
22520
|
};
|
|
22310
22521
|
}
|
|
22311
22522
|
return params.walletProvider.signAndExecuteTxn(tx);
|
|
@@ -22325,17 +22536,11 @@ var SuiSpokeService = class {
|
|
|
22325
22536
|
]
|
|
22326
22537
|
});
|
|
22327
22538
|
if (params.raw === true) {
|
|
22328
|
-
txb.setSender(from);
|
|
22329
|
-
const transactionRaw = await txb.build({
|
|
22330
|
-
client: this.publicClient,
|
|
22331
|
-
onlyTransactionKind: true
|
|
22332
|
-
});
|
|
22333
|
-
const transactionRawBase64String = Buffer.from(transactionRaw).toString("base64");
|
|
22334
22539
|
return {
|
|
22335
22540
|
from,
|
|
22336
22541
|
to: `${connection.packageId}::${connection.moduleId}::send_message_ua`,
|
|
22337
22542
|
value: 0n,
|
|
22338
|
-
data:
|
|
22543
|
+
data: txb.serialize()
|
|
22339
22544
|
};
|
|
22340
22545
|
}
|
|
22341
22546
|
return params.walletProvider.signAndExecuteTxn(txb);
|
|
@@ -22346,7 +22551,7 @@ var SuiSpokeService = class {
|
|
|
22346
22551
|
* @returns {Promise<bigint>} The estimated computation cost.
|
|
22347
22552
|
*/
|
|
22348
22553
|
async estimateGas({ tx }) {
|
|
22349
|
-
const txb = transactions.Transaction.
|
|
22554
|
+
const txb = transactions.Transaction.from(tx.data);
|
|
22350
22555
|
const result = await this.publicClient.devInspectTransactionBlock({
|
|
22351
22556
|
sender: tx.from,
|
|
22352
22557
|
transactionBlock: txb
|
|
@@ -22577,6 +22782,7 @@ var CustomStellarAccount = class {
|
|
|
22577
22782
|
decrementSequenceNumber() {
|
|
22578
22783
|
if (this.sequenceNumber > this.startingSequenceNumber) {
|
|
22579
22784
|
this.sequenceNumber--;
|
|
22785
|
+
return;
|
|
22580
22786
|
}
|
|
22581
22787
|
throw new Error(
|
|
22582
22788
|
`Sequence number cannot be decremented below the starting sequence number: ${this.startingSequenceNumber}`
|
|
@@ -22683,7 +22889,7 @@ var StellarSpokeService = class {
|
|
|
22683
22889
|
);
|
|
22684
22890
|
const assembledPriorityTx = stellarSdk.rpc.assembleTransaction(rawPriorityTx, simulation).build();
|
|
22685
22891
|
if (params.raw) {
|
|
22686
|
-
const transactionXdr =
|
|
22892
|
+
const transactionXdr = assembledPriorityTx.toXDR();
|
|
22687
22893
|
return {
|
|
22688
22894
|
from,
|
|
22689
22895
|
to: this.config.getChainConfig(srcChainKey).addresses.assetManager,
|
|
@@ -22800,7 +23006,7 @@ var StellarSpokeService = class {
|
|
|
22800
23006
|
);
|
|
22801
23007
|
const assembledPriorityTx = stellarSdk.rpc.assembleTransaction(rawPriorityTx, simulation).build();
|
|
22802
23008
|
if (params.raw) {
|
|
22803
|
-
const transactionXdr =
|
|
23009
|
+
const transactionXdr = assembledPriorityTx.toXDR();
|
|
22804
23010
|
return {
|
|
22805
23011
|
from,
|
|
22806
23012
|
to: this.config.getChainConfig(srcChainKey).addresses.assetManager,
|
|
@@ -23473,6 +23679,8 @@ var IconSpokeService = class {
|
|
|
23473
23679
|
};
|
|
23474
23680
|
}
|
|
23475
23681
|
};
|
|
23682
|
+
var GAS_BUFFER_MULTIPLIER = 1.2;
|
|
23683
|
+
var GAS_PRICE_REGEX = /^(\d+)(.*)$/;
|
|
23476
23684
|
var InjectiveSpokeService = class {
|
|
23477
23685
|
config;
|
|
23478
23686
|
chainGrpcWasmApi;
|
|
@@ -23480,6 +23688,7 @@ var InjectiveSpokeService = class {
|
|
|
23480
23688
|
endpoints;
|
|
23481
23689
|
pollingIntervalMs;
|
|
23482
23690
|
maxTimeoutMs;
|
|
23691
|
+
gasPrice;
|
|
23483
23692
|
constructor(config) {
|
|
23484
23693
|
this.config = config;
|
|
23485
23694
|
this.endpoints = networks.getNetworkEndpoints(networks.Network.Mainnet);
|
|
@@ -23487,6 +23696,16 @@ var InjectiveSpokeService = class {
|
|
|
23487
23696
|
this.txClient = new sdkTs.TxGrpcApi(this.endpoints.grpc);
|
|
23488
23697
|
this.pollingIntervalMs = this.config.sodaxConfig.chains[ChainKeys.INJECTIVE_MAINNET].pollingConfig.pollingIntervalMs;
|
|
23489
23698
|
this.maxTimeoutMs = this.config.sodaxConfig.chains[ChainKeys.INJECTIVE_MAINNET].pollingConfig.maxTimeoutMs;
|
|
23699
|
+
this.gasPrice = this.config.getChainConfig(ChainKeys.INJECTIVE_MAINNET).gasPrice;
|
|
23700
|
+
}
|
|
23701
|
+
/** Parse a chain-config gas price like `"500000000inj"` into its numeric price and denom. */
|
|
23702
|
+
parseGasPrice(gasPrice) {
|
|
23703
|
+
const match = GAS_PRICE_REGEX.exec(gasPrice);
|
|
23704
|
+
const price = match?.[1];
|
|
23705
|
+
if (price === void 0) {
|
|
23706
|
+
throw new Error(`Invalid Injective gasPrice config: ${gasPrice}`);
|
|
23707
|
+
}
|
|
23708
|
+
return { price: BigInt(price), denom: match?.[2] || "inj" };
|
|
23490
23709
|
}
|
|
23491
23710
|
/**
|
|
23492
23711
|
* Estimate the gas for a transaction.
|
|
@@ -23495,7 +23714,7 @@ var InjectiveSpokeService = class {
|
|
|
23495
23714
|
* @returns {Promise<InjectiveGasEstimate>} The estimated gas for the transaction.
|
|
23496
23715
|
*/
|
|
23497
23716
|
async estimateGas({ tx }) {
|
|
23498
|
-
const txRaw =
|
|
23717
|
+
const txRaw = tx_js.TxRaw.fromPartial({
|
|
23499
23718
|
bodyBytes: tx.signedDoc.bodyBytes,
|
|
23500
23719
|
authInfoBytes: tx.signedDoc.authInfoBytes,
|
|
23501
23720
|
signatures: []
|
|
@@ -23534,7 +23753,9 @@ var InjectiveSpokeService = class {
|
|
|
23534
23753
|
chainConfig.networkId,
|
|
23535
23754
|
from,
|
|
23536
23755
|
chainConfig.addresses.assetManager,
|
|
23537
|
-
msg
|
|
23756
|
+
msg,
|
|
23757
|
+
void 0,
|
|
23758
|
+
funds
|
|
23538
23759
|
);
|
|
23539
23760
|
}
|
|
23540
23761
|
const res = await params.walletProvider.execute(from, chainConfig.addresses.assetManager, msg, funds);
|
|
@@ -23555,27 +23776,50 @@ var InjectiveSpokeService = class {
|
|
|
23555
23776
|
);
|
|
23556
23777
|
return BigInt(sdkTs.fromBase64(response.data));
|
|
23557
23778
|
}
|
|
23558
|
-
async getRawTransaction(chainId, senderAddress, contractAddress, msg, memo) {
|
|
23779
|
+
async getRawTransaction(chainId, senderAddress, contractAddress, msg, memo, funds = []) {
|
|
23559
23780
|
const msgExec = sdkTs.MsgExecuteContract.fromJSON({
|
|
23560
23781
|
contractAddress,
|
|
23561
23782
|
sender: senderAddress,
|
|
23562
23783
|
msg,
|
|
23563
|
-
funds
|
|
23784
|
+
funds
|
|
23564
23785
|
});
|
|
23565
|
-
const
|
|
23786
|
+
const accountResponse = await new sdkTs.ChainRestAuthApi(this.endpoints.rest).fetchCosmosAccount(senderAddress);
|
|
23787
|
+
const baseAccount = sdkTs.BaseAccount.fromRestCosmosApi(accountResponse);
|
|
23788
|
+
const pubKey = baseAccount.pubKey.key;
|
|
23789
|
+
if (!pubKey) {
|
|
23790
|
+
throw new Error(`The pubKey for ${senderAddress} is missing \u2014 the account has not signed a transaction yet.`);
|
|
23791
|
+
}
|
|
23792
|
+
const txArgs = {
|
|
23566
23793
|
message: msgExec,
|
|
23567
23794
|
memo: memo || "",
|
|
23568
|
-
|
|
23569
|
-
|
|
23795
|
+
pubKey,
|
|
23796
|
+
sequence: baseAccount.sequence,
|
|
23797
|
+
accountNumber: baseAccount.accountNumber,
|
|
23570
23798
|
chainId
|
|
23571
|
-
}
|
|
23799
|
+
};
|
|
23800
|
+
const draft = sdkTs.createTransaction(txArgs);
|
|
23801
|
+
const { gasInfo } = await this.txClient.simulate(
|
|
23802
|
+
tx_js.TxRaw.fromPartial({
|
|
23803
|
+
bodyBytes: draft.txRaw.bodyBytes,
|
|
23804
|
+
authInfoBytes: draft.txRaw.authInfoBytes,
|
|
23805
|
+
signatures: []
|
|
23806
|
+
// not required for simulation
|
|
23807
|
+
})
|
|
23808
|
+
);
|
|
23809
|
+
const gas = Math.ceil(gasInfo.gasUsed * GAS_BUFFER_MULTIPLIER);
|
|
23810
|
+
const { price, denom } = this.parseGasPrice(this.gasPrice);
|
|
23811
|
+
const fee = {
|
|
23812
|
+
amount: [{ denom, amount: (BigInt(gas) * price).toString() }],
|
|
23813
|
+
gas: gas.toString()
|
|
23814
|
+
};
|
|
23815
|
+
const { txRaw, signDoc } = sdkTs.createTransaction({ ...txArgs, fee });
|
|
23572
23816
|
const rawTx = {
|
|
23573
23817
|
from: senderAddress,
|
|
23574
23818
|
to: contractAddress,
|
|
23575
23819
|
signedDoc: {
|
|
23576
23820
|
bodyBytes: txRaw.bodyBytes,
|
|
23577
23821
|
chainId,
|
|
23578
|
-
accountNumber: BigInt(
|
|
23822
|
+
accountNumber: BigInt(signDoc.accountNumber),
|
|
23579
23823
|
authInfoBytes: txRaw.authInfoBytes
|
|
23580
23824
|
}
|
|
23581
23825
|
};
|
|
@@ -25714,6 +25958,24 @@ var SolverApiService = class {
|
|
|
25714
25958
|
}
|
|
25715
25959
|
}
|
|
25716
25960
|
};
|
|
25961
|
+
function decodePacketIntentTarget(payload) {
|
|
25962
|
+
try {
|
|
25963
|
+
const hex = payload.startsWith("0x") ? payload.slice(2) : payload;
|
|
25964
|
+
const decoded = rlp__namespace.decode(Buffer.from(hex, "hex"));
|
|
25965
|
+
const field1 = decoded?.[1];
|
|
25966
|
+
if (!field1 || field1.length === 0) return void 0;
|
|
25967
|
+
return `0x${Buffer.from(field1).toString("hex")}`.toLowerCase();
|
|
25968
|
+
} catch {
|
|
25969
|
+
return void 0;
|
|
25970
|
+
}
|
|
25971
|
+
}
|
|
25972
|
+
function selectSolvedIntentPacket(packets, intentsContract) {
|
|
25973
|
+
if (packets.length <= 1) return packets[0];
|
|
25974
|
+
const target = intentsContract.toLowerCase();
|
|
25975
|
+
const matched = packets.find((packet) => decodePacketIntentTarget(packet.payload) === target);
|
|
25976
|
+
if (matched) return matched;
|
|
25977
|
+
return packets.reduce((highest, packet) => packet.conn_sn > highest.conn_sn ? packet : highest);
|
|
25978
|
+
}
|
|
25717
25979
|
|
|
25718
25980
|
// src/swap/errors.ts
|
|
25719
25981
|
var swapInvariant = createInvariant("swap");
|
|
@@ -25749,7 +26011,7 @@ var SwapService = class {
|
|
|
25749
26011
|
relayerApiEndpoint;
|
|
25750
26012
|
constructor({ config, hubProvider, spoke }) {
|
|
25751
26013
|
this.solver = config.solver;
|
|
25752
|
-
this.partnerFee = config.
|
|
26014
|
+
this.partnerFee = config.swapPartnerFee;
|
|
25753
26015
|
this.relayerApiEndpoint = config.relay.relayerApiEndpoint;
|
|
25754
26016
|
this.config = config;
|
|
25755
26017
|
this.hubProvider = hubProvider;
|
|
@@ -25767,10 +26029,13 @@ var SwapService = class {
|
|
|
25767
26029
|
/**
|
|
25768
26030
|
* Requests a price quote from the solver API for a given token pair and amount.
|
|
25769
26031
|
*
|
|
25770
|
-
* Adjusts `payload.amount` by the
|
|
25771
|
-
*
|
|
26032
|
+
* Adjusts `payload.amount` by the partner fee before forwarding to the solver, so the returned
|
|
26033
|
+
* `quoted_amount` reflects the net output the user actually receives. Pass `partnerFee` to match
|
|
26034
|
+
* a per-action override supplied to `createIntent` (`extras.partnerFee`); omit it to use the
|
|
26035
|
+
* configured swap fee.
|
|
25772
26036
|
*
|
|
25773
|
-
* @param payload -
|
|
26037
|
+
* @param payload - The solver quote request, optionally carrying a per-call `partnerFee` override
|
|
26038
|
+
* (defaults to the configured swap partner fee). `partnerFee` is stripped before forwarding.
|
|
25774
26039
|
* @returns A `Result` containing `{ quoted_amount: bigint }` on success, or a
|
|
25775
26040
|
* `SolverErrorResponse` (with a `SolverIntentErrorCode`) on failure.
|
|
25776
26041
|
*
|
|
@@ -25786,11 +26051,12 @@ var SwapService = class {
|
|
|
25786
26051
|
* if (response.ok) console.log('Quoted amount:', response.value.quoted_amount);
|
|
25787
26052
|
*/
|
|
25788
26053
|
async getQuote(payload) {
|
|
25789
|
-
|
|
25790
|
-
|
|
25791
|
-
|
|
26054
|
+
const { partnerFee = this.partnerFee, ...request } = payload;
|
|
26055
|
+
const adjustedPayload = {
|
|
26056
|
+
...request,
|
|
26057
|
+
amount: adjustAmountByFee(request.amount, partnerFee, request.quote_type)
|
|
25792
26058
|
};
|
|
25793
|
-
return SolverApiService.getQuote(
|
|
26059
|
+
return SolverApiService.getQuote(adjustedPayload, this.solver, this.config);
|
|
25794
26060
|
}
|
|
25795
26061
|
/**
|
|
25796
26062
|
* Calculates the partner fee that will be deducted from the given input amount.
|
|
@@ -26140,7 +26406,8 @@ var SwapService = class {
|
|
|
26140
26406
|
* - `UNKNOWN` — defensive fallback.
|
|
26141
26407
|
*/
|
|
26142
26408
|
async createIntent(_params) {
|
|
26143
|
-
const { params, skipSimulation } = _params;
|
|
26409
|
+
const { params, skipSimulation, extras } = _params;
|
|
26410
|
+
const partnerFee = extras?.partnerFee ?? this.partnerFee;
|
|
26144
26411
|
const baseCtx = { srcChainKey: params.srcChainKey, dstChainKey: params.dstChainKey };
|
|
26145
26412
|
try {
|
|
26146
26413
|
swapInvariant(
|
|
@@ -26175,6 +26442,13 @@ var SwapService = class {
|
|
|
26175
26442
|
{ ...baseCtx, field: "minOutputAmount" }
|
|
26176
26443
|
);
|
|
26177
26444
|
}
|
|
26445
|
+
if (isStacksChainKeyType(params.srcChainKey) && _params.raw === true) {
|
|
26446
|
+
swapInvariant(
|
|
26447
|
+
extras?.srcPublicKey !== void 0,
|
|
26448
|
+
"srcPublicKey is required for Stacks createIntent (raw) \u2014 the source tx is built unsigned and needs the signer public key",
|
|
26449
|
+
{ ...baseCtx, field: "srcPublicKey" }
|
|
26450
|
+
);
|
|
26451
|
+
}
|
|
26178
26452
|
const personalAddress = params.srcAddress;
|
|
26179
26453
|
let walletAddress = personalAddress;
|
|
26180
26454
|
if (isBitcoinChainKeyType(params.srcChainKey) && _params.raw === false) {
|
|
@@ -26192,7 +26466,7 @@ var SwapService = class {
|
|
|
26192
26466
|
createIntentParams: params,
|
|
26193
26467
|
creatorHubWalletAddress,
|
|
26194
26468
|
solverConfig: this.solver,
|
|
26195
|
-
fee:
|
|
26469
|
+
fee: partnerFee,
|
|
26196
26470
|
hubProvider: this.hubProvider
|
|
26197
26471
|
};
|
|
26198
26472
|
const [txResult2, intent2, feeAmount2, data2] = await SonicSpokeService.createSwapIntent(
|
|
@@ -26218,11 +26492,12 @@ var SwapService = class {
|
|
|
26218
26492
|
},
|
|
26219
26493
|
creatorHubWalletAddress,
|
|
26220
26494
|
this.config,
|
|
26221
|
-
|
|
26495
|
+
partnerFee
|
|
26222
26496
|
);
|
|
26223
26497
|
const coreDepositParams = {
|
|
26224
26498
|
srcChainKey: params.srcChainKey,
|
|
26225
26499
|
srcAddress: walletAddress,
|
|
26500
|
+
srcPublicKey: extras?.srcPublicKey,
|
|
26226
26501
|
to: creatorHubWalletAddress,
|
|
26227
26502
|
token: params.inputToken,
|
|
26228
26503
|
amount: params.inputAmount,
|
|
@@ -26541,6 +26816,11 @@ var SwapService = class {
|
|
|
26541
26816
|
* Use this after `getStatus` returns `SolverIntentStatusCode.SOLVED (3)` to obtain the
|
|
26542
26817
|
* destination-chain transaction hash from `packet.dst_tx_hash`.
|
|
26543
26818
|
*
|
|
26819
|
+
* A single solver fill tx emits multiple relay packets sharing the same `src_tx_hash`. The
|
|
26820
|
+
* user-facing `IntentFilled` delivery is the packet whose payload targets the hub intents
|
|
26821
|
+
* contract; `selectSolvedIntentPacket` disambiguates so the returned `dst_tx_hash` is the
|
|
26822
|
+
* destination delivery tx rather than an internal hop.
|
|
26823
|
+
*
|
|
26544
26824
|
* @param chainId - The destination spoke chain key (where output tokens are delivered).
|
|
26545
26825
|
* @param fillTxHash - The solver's fill transaction hash, obtained from `getStatus.fill_tx_hash`.
|
|
26546
26826
|
* @param timeout - Poll timeout in milliseconds. Defaults to `DEFAULT_RELAY_TX_TIMEOUT` (120 s).
|
|
@@ -26556,7 +26836,8 @@ var SwapService = class {
|
|
|
26556
26836
|
intentRelayChainId: getIntentRelayChainId(chainId).toString(),
|
|
26557
26837
|
srcTxHash: fillTxHash,
|
|
26558
26838
|
timeout,
|
|
26559
|
-
apiUrl: this.relayerApiEndpoint
|
|
26839
|
+
apiUrl: this.relayerApiEndpoint,
|
|
26840
|
+
selectPacket: (packets) => selectSolvedIntentPacket(packets, this.solver.intentsContract)
|
|
26560
26841
|
});
|
|
26561
26842
|
}
|
|
26562
26843
|
/**
|
|
@@ -29081,10 +29362,10 @@ var BridgeService = class {
|
|
|
29081
29362
|
* @returns Fee amount to be deducted, in the same units as `inputAmount`.
|
|
29082
29363
|
*/
|
|
29083
29364
|
getFee(inputAmount) {
|
|
29084
|
-
if (!this.config.
|
|
29365
|
+
if (!this.config.bridgePartnerFee) {
|
|
29085
29366
|
return 0n;
|
|
29086
29367
|
}
|
|
29087
|
-
return calculateFeeAmount(inputAmount, this.config.
|
|
29368
|
+
return calculateFeeAmount(inputAmount, this.config.bridgePartnerFee);
|
|
29088
29369
|
}
|
|
29089
29370
|
/**
|
|
29090
29371
|
* Checks whether the caller has sufficient token allowance to execute the bridge.
|
|
@@ -29361,7 +29642,7 @@ var BridgeService = class {
|
|
|
29361
29642
|
}
|
|
29362
29643
|
const hubWallet = await this.hubProvider.getUserHubWalletAddress(walletAddress, params.srcChainKey);
|
|
29363
29644
|
const effectiveSkipSimulation = skipSimulation || isBitcoinChainKeyType(params.srcChainKey) && this.spoke.bitcoin.walletMode === "USER";
|
|
29364
|
-
const data = this.buildBridgeData(params, srcToken, dstToken, this.config.
|
|
29645
|
+
const data = this.buildBridgeData(params, srcToken, dstToken, this.config.bridgePartnerFee);
|
|
29365
29646
|
const coreParams = {
|
|
29366
29647
|
srcChainKey: params.srcChainKey,
|
|
29367
29648
|
srcAddress: walletAddress,
|
|
@@ -35240,7 +35521,7 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
35240
35521
|
this.config = config;
|
|
35241
35522
|
this.hubProvider = hubProvider;
|
|
35242
35523
|
this.spoke = spoke;
|
|
35243
|
-
this.partnerFee = config.
|
|
35524
|
+
this.partnerFee = config.moneyMarketPartnerFee;
|
|
35244
35525
|
this.relayerApiEndpoint = config.relay.relayerApiEndpoint;
|
|
35245
35526
|
this.data = new MoneyMarketDataService({ hubProvider, config });
|
|
35246
35527
|
}
|
|
@@ -37013,7 +37294,12 @@ var RecoveryService = class {
|
|
|
37013
37294
|
srcChainKey: chainKey,
|
|
37014
37295
|
field: "chainKey"
|
|
37015
37296
|
});
|
|
37016
|
-
const
|
|
37297
|
+
const leverageVaultAddresses = new Set(
|
|
37298
|
+
this.config.sodaxConfig.leverageYield.vaults.map((vault) => vault.vault.toLowerCase())
|
|
37299
|
+
);
|
|
37300
|
+
const entries = Object.values(chainConfig.supportedTokens).filter(
|
|
37301
|
+
(token) => viem.isAddress(token.hubAsset) && !leverageVaultAddresses.has(token.hubAsset.toLowerCase())
|
|
37302
|
+
);
|
|
37017
37303
|
if (entries.length === 0) {
|
|
37018
37304
|
return { ok: true, value: [] };
|
|
37019
37305
|
}
|
|
@@ -37115,6 +37401,871 @@ var RecoveryService = class {
|
|
|
37115
37401
|
}
|
|
37116
37402
|
};
|
|
37117
37403
|
|
|
37404
|
+
// src/leverageYield/errors.ts
|
|
37405
|
+
var leverageYieldInvariant = createInvariant("leverageYield");
|
|
37406
|
+
var LEVERAGE_YIELD_CODES = /* @__PURE__ */ new Set([
|
|
37407
|
+
"VALIDATION_FAILED",
|
|
37408
|
+
"INTENT_CREATION_FAILED",
|
|
37409
|
+
"APPROVE_FAILED",
|
|
37410
|
+
"ALLOWANCE_CHECK_FAILED",
|
|
37411
|
+
"LOOKUP_FAILED",
|
|
37412
|
+
"TX_VERIFICATION_FAILED",
|
|
37413
|
+
"TX_SUBMIT_FAILED",
|
|
37414
|
+
"RELAY_TIMEOUT",
|
|
37415
|
+
"RELAY_FAILED",
|
|
37416
|
+
"EXECUTION_FAILED",
|
|
37417
|
+
"EXTERNAL_API_ERROR",
|
|
37418
|
+
"UNKNOWN"
|
|
37419
|
+
]);
|
|
37420
|
+
var LEVERAGE_YIELD_POST_EXECUTION_CODES = /* @__PURE__ */ new Set([
|
|
37421
|
+
"EXECUTION_FAILED",
|
|
37422
|
+
"EXTERNAL_API_ERROR",
|
|
37423
|
+
"UNKNOWN"
|
|
37424
|
+
]);
|
|
37425
|
+
var LEVERAGE_YIELD_SWAP_CODES = /* @__PURE__ */ new Set([
|
|
37426
|
+
"VALIDATION_FAILED",
|
|
37427
|
+
"INTENT_CREATION_FAILED",
|
|
37428
|
+
"TX_VERIFICATION_FAILED",
|
|
37429
|
+
"TX_SUBMIT_FAILED",
|
|
37430
|
+
"RELAY_TIMEOUT",
|
|
37431
|
+
"RELAY_FAILED",
|
|
37432
|
+
"EXECUTION_FAILED",
|
|
37433
|
+
"EXTERNAL_API_ERROR",
|
|
37434
|
+
"UNKNOWN"
|
|
37435
|
+
]);
|
|
37436
|
+
var isLeverageYieldCreateIntentError = isCodeMember(CREATE_INTENT_CODES);
|
|
37437
|
+
var isLeverageYieldApproveError = isCodeMember(APPROVE_CODES);
|
|
37438
|
+
var isLeverageYieldAllowanceCheckError = isCodeMember(ALLOWANCE_CHECK_CODES);
|
|
37439
|
+
var isLeverageYieldLookupError = isCodeMember(LOOKUP_CODES);
|
|
37440
|
+
var isLeverageYieldPostExecutionError = isCodeMember(
|
|
37441
|
+
LEVERAGE_YIELD_POST_EXECUTION_CODES
|
|
37442
|
+
);
|
|
37443
|
+
var isLeverageYieldSwapError = isCodeMember(LEVERAGE_YIELD_SWAP_CODES);
|
|
37444
|
+
var isLeverageYieldError = isCodeMember(LEVERAGE_YIELD_CODES);
|
|
37445
|
+
|
|
37446
|
+
// src/leverageYield/LeverageYieldService.ts
|
|
37447
|
+
var leverageYieldVaultAbi = viem.parseAbi([
|
|
37448
|
+
"function asset() view returns (address)",
|
|
37449
|
+
"function getPositionDetails() view returns (uint256 collateral, uint256 debt, uint256 ltv, uint256 healthFactor, uint256 idleAsset)",
|
|
37450
|
+
// Used by getApr() — read-only metadata that doesn't change per pass.
|
|
37451
|
+
"function pool() view returns (address)",
|
|
37452
|
+
"function borrowToken() view returns (address)",
|
|
37453
|
+
"function targetLTV() view returns (uint256)"
|
|
37454
|
+
]);
|
|
37455
|
+
var INTENT_DEADLINE_BUFFER_SECONDS = 5 * 60;
|
|
37456
|
+
var ANY_SOLVER_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
37457
|
+
var MAX_WITHDRAW_DUST_BUFFER = 1000n;
|
|
37458
|
+
function pctToRay(aprPct) {
|
|
37459
|
+
return BigInt(Math.round(aprPct * 1e9)) * 10n ** 16n;
|
|
37460
|
+
}
|
|
37461
|
+
var DEFILLAMA_FETCH_TIMEOUT_MS = 1e4;
|
|
37462
|
+
var DEFILLAMA_FETCH_MAX_ATTEMPTS = 2;
|
|
37463
|
+
async function fetchWithTimeout(url, timeoutMs) {
|
|
37464
|
+
const controller = new AbortController();
|
|
37465
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
37466
|
+
try {
|
|
37467
|
+
return await fetch(url, { signal: controller.signal });
|
|
37468
|
+
} finally {
|
|
37469
|
+
clearTimeout(timeoutId);
|
|
37470
|
+
}
|
|
37471
|
+
}
|
|
37472
|
+
async function fetchDefillamaApr(poolId) {
|
|
37473
|
+
return retry(async () => {
|
|
37474
|
+
const response = await fetchWithTimeout(`https://yields.llama.fi/chart/${poolId}`, DEFILLAMA_FETCH_TIMEOUT_MS);
|
|
37475
|
+
if (!response.ok) throw new Error(`DefiLlama APR fetch failed: HTTP ${response.status}`);
|
|
37476
|
+
const json = await response.json();
|
|
37477
|
+
const series = json?.data;
|
|
37478
|
+
if (!Array.isArray(series) || series.length === 0) {
|
|
37479
|
+
throw new Error("DefiLlama APR response: empty time series");
|
|
37480
|
+
}
|
|
37481
|
+
const latest = series[series.length - 1]?.apy;
|
|
37482
|
+
if (typeof latest !== "number") throw new Error("DefiLlama APR: latest entry missing numeric apy");
|
|
37483
|
+
return latest;
|
|
37484
|
+
}, DEFILLAMA_FETCH_MAX_ATTEMPTS);
|
|
37485
|
+
}
|
|
37486
|
+
var LeverageYieldService = class {
|
|
37487
|
+
hubProvider;
|
|
37488
|
+
config;
|
|
37489
|
+
spoke;
|
|
37490
|
+
constructor({ hubProvider, config, spoke }) {
|
|
37491
|
+
this.hubProvider = hubProvider;
|
|
37492
|
+
this.config = config;
|
|
37493
|
+
this.spoke = spoke;
|
|
37494
|
+
}
|
|
37495
|
+
// ─── Registry ──────────────────────────────────────────────────────────
|
|
37496
|
+
/** Returns the static registry of known leverage-yield vaults. */
|
|
37497
|
+
listVaults() {
|
|
37498
|
+
return this.config.sodaxConfig.leverageYield.vaults;
|
|
37499
|
+
}
|
|
37500
|
+
/** Looks up a vault by its `name` field. Returns `undefined` when not registered. */
|
|
37501
|
+
getVault(name) {
|
|
37502
|
+
return this.listVaults().find((v) => v.name === name);
|
|
37503
|
+
}
|
|
37504
|
+
/**
|
|
37505
|
+
* Looks up a registered vault by its on-chain proxy address (case-insensitive).
|
|
37506
|
+
* Returns `undefined` when the address isn't in the registry.
|
|
37507
|
+
*/
|
|
37508
|
+
getVaultByAddress(address) {
|
|
37509
|
+
const normalized = address.toLowerCase();
|
|
37510
|
+
return this.listVaults().find((v) => v.vault.toLowerCase() === normalized);
|
|
37511
|
+
}
|
|
37512
|
+
/**
|
|
37513
|
+
* Resolves the intent `deadline`: returns the caller-supplied value verbatim, otherwise
|
|
37514
|
+
* derives a default from the hub-chain (Sonic) block timestamp plus
|
|
37515
|
+
* {@link INTENT_DEADLINE_BUFFER_SECONDS}. The deadline is enforced on-chain against the hub
|
|
37516
|
+
* block time, so the default is anchored to that block — never the client clock, which can
|
|
37517
|
+
* drift and produce an already-expired or over-extended deadline.
|
|
37518
|
+
*
|
|
37519
|
+
* Returns a {@link Result}: a `getBlock` RPC outage is a read failure, surfaced as
|
|
37520
|
+
* `LOOKUP_FAILED` (`method: 'resolveDeadline'`) rather than masquerading as an intent-build
|
|
37521
|
+
* failure. The `deposit` / `withdraw` callers forward it verbatim.
|
|
37522
|
+
*/
|
|
37523
|
+
async resolveDeadline(deadline, srcChainKey) {
|
|
37524
|
+
if (deadline !== void 0) return { ok: true, value: deadline };
|
|
37525
|
+
try {
|
|
37526
|
+
const block = await this.hubProvider.publicClient.getBlock({
|
|
37527
|
+
includeTransactions: false,
|
|
37528
|
+
blockTag: "latest"
|
|
37529
|
+
});
|
|
37530
|
+
return { ok: true, value: block.timestamp + BigInt(INTENT_DEADLINE_BUFFER_SECONDS) };
|
|
37531
|
+
} catch (error) {
|
|
37532
|
+
return { ok: false, error: lookupFailed("leverageYield", "resolveDeadline", error, { srcChainKey }) };
|
|
37533
|
+
}
|
|
37534
|
+
}
|
|
37535
|
+
/**
|
|
37536
|
+
* Builds the {@link LeverageYieldSwapPayload} for a leverage-yield deposit (any token → lsoda*).
|
|
37537
|
+
* The lsoda* output is delivered to the user's hub wallet on Sonic so a later
|
|
37538
|
+
* {@link LeverageYieldService.withdraw} can swap it back. Spread the result into
|
|
37539
|
+
* {@link LeverageYieldService.vaultSwap}: `vaultSwap({ ...payload, walletProvider })`.
|
|
37540
|
+
* An optional `partnerFee` is forwarded on the payload as the per-intent fee override.
|
|
37541
|
+
*
|
|
37542
|
+
* For `minOutputAmount`, quote via `sodax.swaps.getQuote` with the vault address as the
|
|
37543
|
+
* destination token (`token_dst`) — vault shares are solver-tradeable, so the generic swap
|
|
37544
|
+
* quote applies; then subtract your slippage tolerance.
|
|
37545
|
+
*/
|
|
37546
|
+
async deposit(params) {
|
|
37547
|
+
const baseCtx = { srcChainKey: params.srcChainKey, action: "deposit" };
|
|
37548
|
+
try {
|
|
37549
|
+
leverageYieldInvariant(params.inputAmount > 0n, "inputAmount must be greater than 0", {
|
|
37550
|
+
...baseCtx,
|
|
37551
|
+
field: "inputAmount"
|
|
37552
|
+
});
|
|
37553
|
+
leverageYieldInvariant(params.vault.length > 0, "Vault address is required", { ...baseCtx, field: "vault" });
|
|
37554
|
+
leverageYieldInvariant(params.inputToken.length > 0, "inputToken is required", {
|
|
37555
|
+
...baseCtx,
|
|
37556
|
+
field: "inputToken"
|
|
37557
|
+
});
|
|
37558
|
+
const hubWallet = await this.hubProvider.getUserHubWalletAddress(params.srcAddress, params.srcChainKey);
|
|
37559
|
+
const deadlineResult = await this.resolveDeadline(params.deadline, params.srcChainKey);
|
|
37560
|
+
if (!deadlineResult.ok) return deadlineResult;
|
|
37561
|
+
const deadline = deadlineResult.value;
|
|
37562
|
+
return {
|
|
37563
|
+
ok: true,
|
|
37564
|
+
value: {
|
|
37565
|
+
params: {
|
|
37566
|
+
inputToken: params.inputToken,
|
|
37567
|
+
outputToken: params.vault,
|
|
37568
|
+
inputAmount: params.inputAmount,
|
|
37569
|
+
minOutputAmount: params.minOutputAmount,
|
|
37570
|
+
deadline,
|
|
37571
|
+
allowPartialFill: false,
|
|
37572
|
+
srcChainKey: params.srcChainKey,
|
|
37573
|
+
dstChainKey: this.hubProvider.chainConfig.chain.key,
|
|
37574
|
+
srcAddress: params.srcAddress,
|
|
37575
|
+
dstAddress: hubWallet,
|
|
37576
|
+
solver: params.solver ?? ANY_SOLVER_ADDRESS,
|
|
37577
|
+
data: "0x"
|
|
37578
|
+
},
|
|
37579
|
+
// Per-intent fee override — only included when the caller supplies one, so the
|
|
37580
|
+
// payload stays free of undefined-valued keys.
|
|
37581
|
+
...params.partnerFee !== void 0 && { partnerFee: params.partnerFee }
|
|
37582
|
+
}
|
|
37583
|
+
};
|
|
37584
|
+
} catch (error) {
|
|
37585
|
+
if (isLeverageYieldCreateIntentError(error)) return { ok: false, error };
|
|
37586
|
+
return { ok: false, error: intentCreationFailed("leverageYield", error, baseCtx) };
|
|
37587
|
+
}
|
|
37588
|
+
}
|
|
37589
|
+
/**
|
|
37590
|
+
* Builds the {@link LeverageYieldSwapPayload} for a leverage-yield withdraw (lsoda* → any
|
|
37591
|
+
* token). The payload carries `hubWalletSwap: true` — {@link LeverageYieldService.vaultSwap}
|
|
37592
|
+
* then spends the lsoda* held in the user's hub wallet by authorising it via a
|
|
37593
|
+
* `Connection.sendMessage` the user signs on `srcChainKey`. Wrapped in a {@link Result} for
|
|
37594
|
+
* a call shape uniform with {@link LeverageYieldService.deposit}; async because the default
|
|
37595
|
+
* `deadline` is read from the hub block timestamp.
|
|
37596
|
+
*
|
|
37597
|
+
* For `minOutputAmount`, quote via `sodax.swaps.getQuote` with the vault address as the
|
|
37598
|
+
* source token (`token_src`) — vault shares are solver-tradeable, so the generic swap quote
|
|
37599
|
+
* applies; then subtract your slippage tolerance.
|
|
37600
|
+
*/
|
|
37601
|
+
async withdraw(params) {
|
|
37602
|
+
const baseCtx = { srcChainKey: params.srcChainKey, action: "withdraw" };
|
|
37603
|
+
try {
|
|
37604
|
+
leverageYieldInvariant(params.inputAmount > 0n, "inputAmount must be greater than 0", {
|
|
37605
|
+
...baseCtx,
|
|
37606
|
+
field: "inputAmount"
|
|
37607
|
+
});
|
|
37608
|
+
leverageYieldInvariant(params.vault.length > 0, "Vault address is required", { ...baseCtx, field: "vault" });
|
|
37609
|
+
leverageYieldInvariant(params.outputToken.length > 0, "outputToken is required", {
|
|
37610
|
+
...baseCtx,
|
|
37611
|
+
field: "outputToken"
|
|
37612
|
+
});
|
|
37613
|
+
const deadlineResult = await this.resolveDeadline(params.deadline, params.srcChainKey);
|
|
37614
|
+
if (!deadlineResult.ok) return deadlineResult;
|
|
37615
|
+
const deadline = deadlineResult.value;
|
|
37616
|
+
return {
|
|
37617
|
+
ok: true,
|
|
37618
|
+
value: {
|
|
37619
|
+
params: {
|
|
37620
|
+
inputToken: params.vault,
|
|
37621
|
+
outputToken: params.outputToken,
|
|
37622
|
+
inputAmount: params.inputAmount,
|
|
37623
|
+
minOutputAmount: params.minOutputAmount,
|
|
37624
|
+
deadline,
|
|
37625
|
+
allowPartialFill: false,
|
|
37626
|
+
srcChainKey: params.srcChainKey,
|
|
37627
|
+
dstChainKey: params.dstChainKey,
|
|
37628
|
+
srcAddress: params.srcAddress,
|
|
37629
|
+
dstAddress: params.recipient ?? params.srcAddress,
|
|
37630
|
+
solver: params.solver ?? ANY_SOLVER_ADDRESS,
|
|
37631
|
+
data: "0x"
|
|
37632
|
+
},
|
|
37633
|
+
hubWalletSwap: true
|
|
37634
|
+
}
|
|
37635
|
+
};
|
|
37636
|
+
} catch (error) {
|
|
37637
|
+
if (isLeverageYieldCreateIntentError(error)) return { ok: false, error };
|
|
37638
|
+
return { ok: false, error: intentCreationFailed("leverageYield", error, baseCtx) };
|
|
37639
|
+
}
|
|
37640
|
+
}
|
|
37641
|
+
/**
|
|
37642
|
+
* Creates a vault swap intent on the user's source spoke chain without submitting it to
|
|
37643
|
+
* the solver. Leverage-yield copy of the swap domain's `createIntent`, specialised for
|
|
37644
|
+
* vault flows — duplicated deliberately so the vault-specific execution modifiers
|
|
37645
|
+
* (`hubWalletSwap`, per-intent `partnerFee`) stay off the generic swap surface.
|
|
37646
|
+
*
|
|
37647
|
+
* Use {@link LeverageYieldService.vaultSwap} for the full end-to-end flow
|
|
37648
|
+
* (create → relay → notify solver); use this directly when you need the raw transaction
|
|
37649
|
+
* or drive the relay yourself (e.g. the backend submit-tx path). To complete a manual flow,
|
|
37650
|
+
* relay the returned `relayData` (the shared `relayTxAndWaitPacket` helper) and then call
|
|
37651
|
+
* {@link LeverageYieldService.notifySolver} with the hub-side intent tx hash.
|
|
37652
|
+
*
|
|
37653
|
+
* @param _params - Intent parameters, source chain key, wallet provider (when `raw: false`),
|
|
37654
|
+
* and optional `skipSimulation` / `hubWalletSwap` / `partnerFee`.
|
|
37655
|
+
* @returns A `Result<CreateVaultIntentResult<K, Raw>, LeverageYieldCreateIntentError>`.
|
|
37656
|
+
* On success contains:
|
|
37657
|
+
* - `tx` — chain-specific tx hash (executed) or raw tx data (raw mode).
|
|
37658
|
+
* - `intent` — the fully constructed `Intent` object augmented with `feeAmount`.
|
|
37659
|
+
* - `relayData` — `{ address, payload }` needed to submit the intent to the relayer.
|
|
37660
|
+
*
|
|
37661
|
+
* On failure `result.error` is a SodaxError with `VALIDATION_FAILED` (invariant
|
|
37662
|
+
* precondition), `INTENT_CREATION_FAILED` (spoke-side creation/deposit failed) or
|
|
37663
|
+
* `UNKNOWN` (defensive fallback).
|
|
37664
|
+
*/
|
|
37665
|
+
async createVaultIntent(_params) {
|
|
37666
|
+
const { params, skipSimulation, hubWalletSwap, partnerFee = this.config.swapPartnerFee } = _params;
|
|
37667
|
+
const baseCtx = { srcChainKey: params.srcChainKey, dstChainKey: params.dstChainKey };
|
|
37668
|
+
try {
|
|
37669
|
+
leverageYieldInvariant(
|
|
37670
|
+
isUndefinedOrValidWalletProviderForChainKey(params.srcChainKey, _params.walletProvider),
|
|
37671
|
+
`Invalid wallet provider for chain key: ${params.srcChainKey}`,
|
|
37672
|
+
baseCtx
|
|
37673
|
+
);
|
|
37674
|
+
const hubChainKey = this.hubProvider.chainConfig.chain.key;
|
|
37675
|
+
const inputTokenChainKey = hubWalletSwap ? hubChainKey : params.srcChainKey;
|
|
37676
|
+
leverageYieldInvariant(
|
|
37677
|
+
this.config.isValidOriginalAssetAddress(inputTokenChainKey, params.inputToken),
|
|
37678
|
+
`Unsupported spoke chain token (srcChainKey: ${inputTokenChainKey}, inputToken: ${params.inputToken})`,
|
|
37679
|
+
{ ...baseCtx, field: "inputToken" }
|
|
37680
|
+
);
|
|
37681
|
+
leverageYieldInvariant(
|
|
37682
|
+
this.config.isValidOriginalAssetAddress(params.dstChainKey, params.outputToken),
|
|
37683
|
+
`Unsupported spoke chain token (params.dstChain: ${params.dstChainKey}, params.outputToken: ${params.outputToken})`,
|
|
37684
|
+
{ ...baseCtx, field: "outputToken" }
|
|
37685
|
+
);
|
|
37686
|
+
leverageYieldInvariant(
|
|
37687
|
+
this.config.isValidSpokeChainKey(params.srcChainKey),
|
|
37688
|
+
`Invalid spoke chain (srcChainKey): ${params.srcChainKey}`,
|
|
37689
|
+
{ ...baseCtx, field: "srcChainKey" }
|
|
37690
|
+
);
|
|
37691
|
+
leverageYieldInvariant(
|
|
37692
|
+
this.config.isValidSpokeChainKey(params.dstChainKey),
|
|
37693
|
+
`Invalid spoke chain (params.dstChain): ${params.dstChainKey}`,
|
|
37694
|
+
{ ...baseCtx, field: "dstChainKey" }
|
|
37695
|
+
);
|
|
37696
|
+
if (isBitcoinChainKey(params.dstChainKey) && params.outputToken === "BTC") {
|
|
37697
|
+
leverageYieldInvariant(
|
|
37698
|
+
params.minOutputAmount >= 546n,
|
|
37699
|
+
`Invalid minOutputAmount (params.minOutputAmount): ${params.minOutputAmount}`,
|
|
37700
|
+
{ ...baseCtx, field: "minOutputAmount" }
|
|
37701
|
+
);
|
|
37702
|
+
}
|
|
37703
|
+
const personalAddress = params.srcAddress;
|
|
37704
|
+
let walletAddress = personalAddress;
|
|
37705
|
+
if (isBitcoinChainKeyType(params.srcChainKey) && _params.raw === false) {
|
|
37706
|
+
leverageYieldInvariant(
|
|
37707
|
+
isBitcoinWalletProviderType(_params.walletProvider),
|
|
37708
|
+
`Invalid wallet provider for chain key: ${params.srcChainKey}`,
|
|
37709
|
+
baseCtx
|
|
37710
|
+
);
|
|
37711
|
+
walletAddress = await this.spoke.bitcoin.getEffectiveWalletAddress(personalAddress);
|
|
37712
|
+
await this.spoke.bitcoin.radfi.ensureRadfiAccessToken(_params.walletProvider);
|
|
37713
|
+
}
|
|
37714
|
+
const creatorHubWalletAddress = await this.hubProvider.getUserHubWalletAddress(walletAddress, params.srcChainKey);
|
|
37715
|
+
if (hubWalletSwap) {
|
|
37716
|
+
const [data2, intent2, feeAmount2] = EvmSolverService.constructCreateIntentData(
|
|
37717
|
+
{ ...params, srcChainKey: hubChainKey, srcAddress: creatorHubWalletAddress },
|
|
37718
|
+
creatorHubWalletAddress,
|
|
37719
|
+
this.config,
|
|
37720
|
+
partnerFee
|
|
37721
|
+
);
|
|
37722
|
+
const coreSendMessageParams = {
|
|
37723
|
+
srcChainKey: params.srcChainKey,
|
|
37724
|
+
// Personal address — NOT the resolved trading `walletAddress`. SpokeService.sendMessage
|
|
37725
|
+
// re-resolves the effective (Bitcoin trading) address itself; passing the already-resolved
|
|
37726
|
+
// trading address here would double-resolve it (getTradingWallet(tradingAddress) →
|
|
37727
|
+
// "Trading wallet not found"). The trading address is used only for the hub-wallet
|
|
37728
|
+
// derivation above (creatorHubWalletAddress). Mirrors MoneyMarketService borrow/withdraw.
|
|
37729
|
+
srcAddress: personalAddress,
|
|
37730
|
+
dstChainKey: hubChainKey,
|
|
37731
|
+
dstAddress: creatorHubWalletAddress,
|
|
37732
|
+
payload: data2,
|
|
37733
|
+
skipSimulation
|
|
37734
|
+
};
|
|
37735
|
+
const txResult2 = await this.spoke.sendMessage(
|
|
37736
|
+
_params.raw ? { ...coreSendMessageParams, raw: true } : {
|
|
37737
|
+
...coreSendMessageParams,
|
|
37738
|
+
raw: false,
|
|
37739
|
+
walletProvider: _params.walletProvider
|
|
37740
|
+
}
|
|
37741
|
+
);
|
|
37742
|
+
if (!txResult2.ok) {
|
|
37743
|
+
if (isLeverageYieldCreateIntentError(txResult2.error)) {
|
|
37744
|
+
return { ok: false, error: txResult2.error };
|
|
37745
|
+
}
|
|
37746
|
+
return { ok: false, error: intentCreationFailed("leverageYield", txResult2.error, baseCtx) };
|
|
37747
|
+
}
|
|
37748
|
+
return {
|
|
37749
|
+
ok: true,
|
|
37750
|
+
value: {
|
|
37751
|
+
tx: txResult2.value,
|
|
37752
|
+
intent: { ...intent2, feeAmount: feeAmount2 },
|
|
37753
|
+
relayData: { address: creatorHubWalletAddress, payload: data2 }
|
|
37754
|
+
}
|
|
37755
|
+
};
|
|
37756
|
+
}
|
|
37757
|
+
if (isHubChainKeyType(params.srcChainKey) && isSonicChainKeyType(params.srcChainKey)) {
|
|
37758
|
+
const coreSonicParams = {
|
|
37759
|
+
createIntentParams: params,
|
|
37760
|
+
creatorHubWalletAddress,
|
|
37761
|
+
solverConfig: this.config.solver,
|
|
37762
|
+
fee: partnerFee,
|
|
37763
|
+
hubProvider: this.hubProvider
|
|
37764
|
+
};
|
|
37765
|
+
const [txResult2, intent2, feeAmount2, data2] = await SonicSpokeService.createSwapIntent(
|
|
37766
|
+
_params.raw ? { ...coreSonicParams, raw: true } : {
|
|
37767
|
+
...coreSonicParams,
|
|
37768
|
+
raw: false,
|
|
37769
|
+
walletProvider: _params.walletProvider
|
|
37770
|
+
}
|
|
37771
|
+
);
|
|
37772
|
+
return {
|
|
37773
|
+
ok: true,
|
|
37774
|
+
value: {
|
|
37775
|
+
tx: txResult2,
|
|
37776
|
+
intent: { ...intent2, feeAmount: feeAmount2 },
|
|
37777
|
+
relayData: { address: intent2.creator, payload: data2 }
|
|
37778
|
+
}
|
|
37779
|
+
};
|
|
37780
|
+
}
|
|
37781
|
+
const [data, intent, feeAmount] = EvmSolverService.constructCreateIntentData(
|
|
37782
|
+
{
|
|
37783
|
+
...params,
|
|
37784
|
+
srcAddress: walletAddress
|
|
37785
|
+
},
|
|
37786
|
+
creatorHubWalletAddress,
|
|
37787
|
+
this.config,
|
|
37788
|
+
partnerFee
|
|
37789
|
+
);
|
|
37790
|
+
const coreDepositParams = {
|
|
37791
|
+
srcChainKey: params.srcChainKey,
|
|
37792
|
+
srcAddress: walletAddress,
|
|
37793
|
+
to: creatorHubWalletAddress,
|
|
37794
|
+
token: params.inputToken,
|
|
37795
|
+
amount: params.inputAmount,
|
|
37796
|
+
data,
|
|
37797
|
+
skipSimulation
|
|
37798
|
+
};
|
|
37799
|
+
const txResult = await this.spoke.deposit(
|
|
37800
|
+
_params.raw ? {
|
|
37801
|
+
...coreDepositParams,
|
|
37802
|
+
raw: true
|
|
37803
|
+
} : {
|
|
37804
|
+
...coreDepositParams,
|
|
37805
|
+
raw: false,
|
|
37806
|
+
walletProvider: _params.walletProvider
|
|
37807
|
+
}
|
|
37808
|
+
);
|
|
37809
|
+
if (!txResult.ok) {
|
|
37810
|
+
if (isLeverageYieldCreateIntentError(txResult.error)) {
|
|
37811
|
+
return { ok: false, error: txResult.error };
|
|
37812
|
+
}
|
|
37813
|
+
return {
|
|
37814
|
+
ok: false,
|
|
37815
|
+
error: intentCreationFailed("leverageYield", txResult.error, baseCtx)
|
|
37816
|
+
};
|
|
37817
|
+
}
|
|
37818
|
+
return {
|
|
37819
|
+
ok: true,
|
|
37820
|
+
value: {
|
|
37821
|
+
tx: txResult.value,
|
|
37822
|
+
intent: { ...intent, feeAmount },
|
|
37823
|
+
relayData: { address: intent.creator, payload: data }
|
|
37824
|
+
}
|
|
37825
|
+
};
|
|
37826
|
+
} catch (error) {
|
|
37827
|
+
if (isLeverageYieldCreateIntentError(error)) return { ok: false, error };
|
|
37828
|
+
return {
|
|
37829
|
+
ok: false,
|
|
37830
|
+
error: intentCreationFailed("leverageYield", error, baseCtx)
|
|
37831
|
+
};
|
|
37832
|
+
}
|
|
37833
|
+
}
|
|
37834
|
+
/**
|
|
37835
|
+
* Executes a full end-to-end leverage-yield vault swap (deposit or withdraw).
|
|
37836
|
+
* Leverage-yield copy of the swap domain's `swap()` orchestrator:
|
|
37837
|
+
* 1. Calls {@link LeverageYieldService.createVaultIntent} to submit the intent
|
|
37838
|
+
* transaction on the source spoke chain.
|
|
37839
|
+
* 2. Verifies the spoke transaction landed on-chain.
|
|
37840
|
+
* 3. For non-hub source chains: submits the spoke tx to the relayer and waits for the
|
|
37841
|
+
* relay packet to land on the hub (Sonic). Skipped when `srcChainKey` is the hub.
|
|
37842
|
+
* 4. Notifies the solver, triggering it to fill the intent.
|
|
37843
|
+
*
|
|
37844
|
+
* Spread a {@link LeverageYieldSwapPayload} from `deposit` / `withdraw` into this method
|
|
37845
|
+
* alongside the wallet provider: `vaultSwap({ ...payload, walletProvider })`.
|
|
37846
|
+
*
|
|
37847
|
+
* @returns A `Result<VaultSwapResponse, LeverageYieldSwapError>`. On success:
|
|
37848
|
+
* - `solverExecutionResponse` — solver acknowledgement (`{ answer: 'OK', intent_hash }`).
|
|
37849
|
+
* - `intent` — the on-chain intent object that was created.
|
|
37850
|
+
* - `intentDeliveryInfo` — source/destination chain keys, tx hashes, and user addresses.
|
|
37851
|
+
*
|
|
37852
|
+
* On failure `result.error` carries one of the create-intent codes plus
|
|
37853
|
+
* `TX_VERIFICATION_FAILED`, `TX_SUBMIT_FAILED`, `RELAY_TIMEOUT`, `RELAY_FAILED`,
|
|
37854
|
+
* `EXECUTION_FAILED`, `EXTERNAL_API_ERROR` or `UNKNOWN`.
|
|
37855
|
+
*/
|
|
37856
|
+
async vaultSwap(_params) {
|
|
37857
|
+
const { params } = _params;
|
|
37858
|
+
const srcChainKey = params.srcChainKey;
|
|
37859
|
+
const baseCtx = { srcChainKey, dstChainKey: params.dstChainKey, action: "vaultSwap" };
|
|
37860
|
+
try {
|
|
37861
|
+
const timeout = _params.timeout;
|
|
37862
|
+
const createIntentResult = await this.createVaultIntent(_params);
|
|
37863
|
+
if (!createIntentResult.ok) {
|
|
37864
|
+
return { ok: false, error: createIntentResult.error };
|
|
37865
|
+
}
|
|
37866
|
+
const { tx: spokeTxHash, intent, relayData } = createIntentResult.value;
|
|
37867
|
+
const verifyTxHashResult = await this.spoke.verifyTxHash({
|
|
37868
|
+
txHash: spokeTxHash,
|
|
37869
|
+
chainKey: srcChainKey
|
|
37870
|
+
});
|
|
37871
|
+
if (!verifyTxHashResult.ok) {
|
|
37872
|
+
return {
|
|
37873
|
+
ok: false,
|
|
37874
|
+
error: verifyFailed("leverageYield", verifyTxHashResult.error, baseCtx)
|
|
37875
|
+
};
|
|
37876
|
+
}
|
|
37877
|
+
let dstIntentTxHash;
|
|
37878
|
+
if (isHubChainKeyType(srcChainKey)) {
|
|
37879
|
+
dstIntentTxHash = spokeTxHash;
|
|
37880
|
+
} else {
|
|
37881
|
+
const packet = await relayTxAndWaitPacket({
|
|
37882
|
+
srcTxHash: spokeTxHash,
|
|
37883
|
+
data: relayData,
|
|
37884
|
+
chainKey: srcChainKey,
|
|
37885
|
+
relayerApiEndpoint: this.config.relay.relayerApiEndpoint,
|
|
37886
|
+
timeout
|
|
37887
|
+
});
|
|
37888
|
+
if (!packet.ok) {
|
|
37889
|
+
return {
|
|
37890
|
+
ok: false,
|
|
37891
|
+
error: mapRelayFailure(packet.error, { feature: "leverageYield", ...baseCtx })
|
|
37892
|
+
};
|
|
37893
|
+
}
|
|
37894
|
+
dstIntentTxHash = packet.value.dst_tx_hash;
|
|
37895
|
+
}
|
|
37896
|
+
const postExecResult = await this.notifySolver({
|
|
37897
|
+
intent_tx_hash: dstIntentTxHash
|
|
37898
|
+
});
|
|
37899
|
+
if (!postExecResult.ok) {
|
|
37900
|
+
return { ok: false, error: postExecResult.error };
|
|
37901
|
+
}
|
|
37902
|
+
return {
|
|
37903
|
+
ok: true,
|
|
37904
|
+
value: {
|
|
37905
|
+
solverExecutionResponse: postExecResult.value,
|
|
37906
|
+
intent,
|
|
37907
|
+
intentDeliveryInfo: {
|
|
37908
|
+
srcChainKey,
|
|
37909
|
+
srcTxHash: spokeTxHash,
|
|
37910
|
+
srcAddress: params.srcAddress,
|
|
37911
|
+
dstChainKey: params.dstChainKey,
|
|
37912
|
+
dstTxHash: dstIntentTxHash,
|
|
37913
|
+
dstAddress: params.dstAddress
|
|
37914
|
+
}
|
|
37915
|
+
}
|
|
37916
|
+
};
|
|
37917
|
+
} catch (error) {
|
|
37918
|
+
if (isLeverageYieldSwapError(error)) return { ok: false, error };
|
|
37919
|
+
return {
|
|
37920
|
+
ok: false,
|
|
37921
|
+
error: unknownFailed("leverageYield", error, baseCtx)
|
|
37922
|
+
};
|
|
37923
|
+
}
|
|
37924
|
+
}
|
|
37925
|
+
/**
|
|
37926
|
+
* Notifies the solver that the vault intent landed on the hub, triggering it to fill.
|
|
37927
|
+
* Leverage-yield copy of the swap domain's `postExecution` — emits only
|
|
37928
|
+
* `EXECUTION_FAILED` / `EXTERNAL_API_ERROR` / `UNKNOWN` (relay/verify codes appear only
|
|
37929
|
+
* on {@link LeverageYieldService.vaultSwap}, which owns the verify + relay steps).
|
|
37930
|
+
*
|
|
37931
|
+
* Called automatically by {@link LeverageYieldService.vaultSwap} after the relay packet
|
|
37932
|
+
* lands on the hub. Public so callers who created the intent via
|
|
37933
|
+
* {@link LeverageYieldService.createVaultIntent} and relayed it themselves can finish the
|
|
37934
|
+
* flow manually.
|
|
37935
|
+
*
|
|
37936
|
+
* @param request - `{ intent_tx_hash }` — the hub-chain (Sonic) tx hash where the intent
|
|
37937
|
+
* was registered (the relay packet's `dst_tx_hash`, or the spoke tx hash for hub-sourced
|
|
37938
|
+
* intents).
|
|
37939
|
+
*/
|
|
37940
|
+
async notifySolver(request) {
|
|
37941
|
+
try {
|
|
37942
|
+
const result = await SolverApiService.postExecution(request, this.config.solver, this.config.logger);
|
|
37943
|
+
if (result.ok) return result;
|
|
37944
|
+
const detail = result.error?.detail ?? {
|
|
37945
|
+
code: -999,
|
|
37946
|
+
// SolverIntentErrorCode.UNKNOWN
|
|
37947
|
+
message: "Solver returned malformed error response"
|
|
37948
|
+
};
|
|
37949
|
+
return {
|
|
37950
|
+
ok: false,
|
|
37951
|
+
error: new SodaxError("EXTERNAL_API_ERROR", detail.message, {
|
|
37952
|
+
feature: "leverageYield",
|
|
37953
|
+
context: {
|
|
37954
|
+
phase: "postExecution",
|
|
37955
|
+
api: "solver",
|
|
37956
|
+
solverCode: detail.code,
|
|
37957
|
+
solverDetail: detail
|
|
37958
|
+
}
|
|
37959
|
+
})
|
|
37960
|
+
};
|
|
37961
|
+
} catch (error) {
|
|
37962
|
+
if (isLeverageYieldPostExecutionError(error)) return { ok: false, error };
|
|
37963
|
+
return { ok: false, error: executionFailed("leverageYield", error, { phase: "postExecution" }) };
|
|
37964
|
+
}
|
|
37965
|
+
}
|
|
37966
|
+
/**
|
|
37967
|
+
* Approves the vault's underlying asset to the leverage vault on Sonic. For callers
|
|
37968
|
+
* interacting with the vault directly on the hub — the swap-style {@link
|
|
37969
|
+
* LeverageYieldService.deposit} flow handles its own approvals.
|
|
37970
|
+
*/
|
|
37971
|
+
async approve(params) {
|
|
37972
|
+
const baseCtx = { action: "approve" };
|
|
37973
|
+
try {
|
|
37974
|
+
leverageYieldInvariant(params.amount > 0n, "Amount must be greater than 0", { ...baseCtx, field: "amount" });
|
|
37975
|
+
leverageYieldInvariant(params.vault.length > 0, "Vault address is required", { ...baseCtx, field: "vault" });
|
|
37976
|
+
const assetResult = await this.getAsset(params.vault);
|
|
37977
|
+
if (!assetResult.ok) {
|
|
37978
|
+
return { ok: false, error: approveFailed("leverageYield", assetResult.error, baseCtx) };
|
|
37979
|
+
}
|
|
37980
|
+
const from = await params.walletProvider.getWalletAddress();
|
|
37981
|
+
const baseApprove = {
|
|
37982
|
+
token: assetResult.value,
|
|
37983
|
+
amount: params.amount,
|
|
37984
|
+
from,
|
|
37985
|
+
spender: params.vault
|
|
37986
|
+
};
|
|
37987
|
+
if (params.raw) {
|
|
37988
|
+
const tx2 = await Erc20Service.approve({ ...baseApprove, raw: true });
|
|
37989
|
+
return { ok: true, value: tx2 };
|
|
37990
|
+
}
|
|
37991
|
+
const tx = await Erc20Service.approve({
|
|
37992
|
+
...baseApprove,
|
|
37993
|
+
raw: false,
|
|
37994
|
+
walletProvider: params.walletProvider
|
|
37995
|
+
});
|
|
37996
|
+
return { ok: true, value: tx };
|
|
37997
|
+
} catch (error) {
|
|
37998
|
+
if (isLeverageYieldApproveError(error)) return { ok: false, error };
|
|
37999
|
+
return { ok: false, error: approveFailed("leverageYield", error, baseCtx) };
|
|
38000
|
+
}
|
|
38001
|
+
}
|
|
38002
|
+
/**
|
|
38003
|
+
* Reads on-chain allowance of the vault's underlying asset for `owner → vault`. Returns
|
|
38004
|
+
* `true` when the allowance covers `amount`. Use before a direct
|
|
38005
|
+
* {@link LeverageYieldService.deposit}.
|
|
38006
|
+
*/
|
|
38007
|
+
async isAllowanceValid(params) {
|
|
38008
|
+
const baseCtx = { action: "allowanceCheck" };
|
|
38009
|
+
try {
|
|
38010
|
+
leverageYieldInvariant(params.amount > 0n, "Amount must be greater than 0", { ...baseCtx, field: "amount" });
|
|
38011
|
+
const assetResult = await this.getAsset(params.vault);
|
|
38012
|
+
if (!assetResult.ok) {
|
|
38013
|
+
return { ok: false, error: allowanceCheckFailed("leverageYield", assetResult.error, baseCtx) };
|
|
38014
|
+
}
|
|
38015
|
+
const allowance = await this.hubProvider.publicClient.readContract({
|
|
38016
|
+
address: assetResult.value,
|
|
38017
|
+
abi: viem.erc20Abi,
|
|
38018
|
+
functionName: "allowance",
|
|
38019
|
+
args: [params.owner, params.vault]
|
|
38020
|
+
});
|
|
38021
|
+
return { ok: true, value: allowance >= params.amount };
|
|
38022
|
+
} catch (error) {
|
|
38023
|
+
if (isLeverageYieldAllowanceCheckError(error)) return { ok: false, error };
|
|
38024
|
+
return { ok: false, error: allowanceCheckFailed("leverageYield", error, baseCtx) };
|
|
38025
|
+
}
|
|
38026
|
+
}
|
|
38027
|
+
// ─── Reads ──────────────────────────────────────────────────────────────
|
|
38028
|
+
/** ERC-4626 `asset()` of the vault — the sodaWEETH-style underlying. */
|
|
38029
|
+
async getAsset(vault) {
|
|
38030
|
+
try {
|
|
38031
|
+
const value = await this.hubProvider.publicClient.readContract({
|
|
38032
|
+
address: vault,
|
|
38033
|
+
abi: leverageYieldVaultAbi,
|
|
38034
|
+
functionName: "asset"
|
|
38035
|
+
});
|
|
38036
|
+
return { ok: true, value };
|
|
38037
|
+
} catch (error) {
|
|
38038
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38039
|
+
return { ok: false, error: lookupFailed("leverageYield", "getAsset", error) };
|
|
38040
|
+
}
|
|
38041
|
+
}
|
|
38042
|
+
/** Reads the vault's leveraged position snapshot via the non-standard `getPositionDetails`. */
|
|
38043
|
+
async getPosition(vault) {
|
|
38044
|
+
try {
|
|
38045
|
+
const [collateral, debt, ltv, healthFactor, idleAsset] = await this.hubProvider.publicClient.readContract({
|
|
38046
|
+
address: vault,
|
|
38047
|
+
abi: leverageYieldVaultAbi,
|
|
38048
|
+
functionName: "getPositionDetails"
|
|
38049
|
+
});
|
|
38050
|
+
return { ok: true, value: { collateral, debt, ltv, healthFactor, idleAsset } };
|
|
38051
|
+
} catch (error) {
|
|
38052
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38053
|
+
return { ok: false, error: lookupFailed("leverageYield", "getPosition", error) };
|
|
38054
|
+
}
|
|
38055
|
+
}
|
|
38056
|
+
/**
|
|
38057
|
+
* Computes the steady-state APR of a leverage-yield vault from the AAVE supply/borrow
|
|
38058
|
+
* rates of its asset and borrowToken, scaled by the vault's target leverage. Matches the
|
|
38059
|
+
* convention used by leveraged-LSD vaults (Origami, Gearbox, etc.) — assumes constant
|
|
38060
|
+
* LTV at `targetLTV` and constant AAVE rates.
|
|
38061
|
+
*
|
|
38062
|
+
* Returns raw fields in RAY (1e27, AAVE's native rate scale) plus the leverage multiplier
|
|
38063
|
+
* in WAD (1e18). See {@link LeverageYieldApr} for the formula and caveats.
|
|
38064
|
+
*/
|
|
38065
|
+
async getApr(vault) {
|
|
38066
|
+
try {
|
|
38067
|
+
const [pool, asset, borrowToken, targetLtvBps] = await Promise.all([
|
|
38068
|
+
this.hubProvider.publicClient.readContract({
|
|
38069
|
+
address: vault,
|
|
38070
|
+
abi: leverageYieldVaultAbi,
|
|
38071
|
+
functionName: "pool"
|
|
38072
|
+
}),
|
|
38073
|
+
this.hubProvider.publicClient.readContract({
|
|
38074
|
+
address: vault,
|
|
38075
|
+
abi: leverageYieldVaultAbi,
|
|
38076
|
+
functionName: "asset"
|
|
38077
|
+
}),
|
|
38078
|
+
this.hubProvider.publicClient.readContract({
|
|
38079
|
+
address: vault,
|
|
38080
|
+
abi: leverageYieldVaultAbi,
|
|
38081
|
+
functionName: "borrowToken"
|
|
38082
|
+
}),
|
|
38083
|
+
this.hubProvider.publicClient.readContract({
|
|
38084
|
+
address: vault,
|
|
38085
|
+
abi: leverageYieldVaultAbi,
|
|
38086
|
+
functionName: "targetLTV"
|
|
38087
|
+
})
|
|
38088
|
+
]);
|
|
38089
|
+
const [assetReserve, borrowReserve] = await Promise.all([
|
|
38090
|
+
this.hubProvider.publicClient.readContract({
|
|
38091
|
+
address: pool,
|
|
38092
|
+
abi: poolAbi,
|
|
38093
|
+
functionName: "getReserveData",
|
|
38094
|
+
args: [asset]
|
|
38095
|
+
}),
|
|
38096
|
+
this.hubProvider.publicClient.readContract({
|
|
38097
|
+
address: pool,
|
|
38098
|
+
abi: poolAbi,
|
|
38099
|
+
functionName: "getReserveData",
|
|
38100
|
+
args: [borrowToken]
|
|
38101
|
+
})
|
|
38102
|
+
]);
|
|
38103
|
+
const supplyAprRay = assetReserve.currentLiquidityRate;
|
|
38104
|
+
const borrowAprRay = borrowReserve.currentVariableBorrowRate;
|
|
38105
|
+
const BPS = 10000n;
|
|
38106
|
+
const WAD2 = 1000000000000000000n;
|
|
38107
|
+
leverageYieldInvariant(targetLtvBps < BPS, `targetLTV (${targetLtvBps}) must be < 100% (10_000 bps)`, {
|
|
38108
|
+
method: "getApr",
|
|
38109
|
+
field: "targetLtvBps"
|
|
38110
|
+
});
|
|
38111
|
+
const leverageMultiplierWad = targetLtvBps * WAD2 / (BPS - targetLtvBps);
|
|
38112
|
+
const spreadRay = supplyAprRay - borrowAprRay;
|
|
38113
|
+
const netAprRay = supplyAprRay + spreadRay * leverageMultiplierWad / WAD2;
|
|
38114
|
+
return {
|
|
38115
|
+
ok: true,
|
|
38116
|
+
value: { supplyAprRay, borrowAprRay, targetLtvBps, leverageMultiplierWad, netAprRay }
|
|
38117
|
+
};
|
|
38118
|
+
} catch (error) {
|
|
38119
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38120
|
+
return { ok: false, error: lookupFailed("leverageYield", "getApr", error) };
|
|
38121
|
+
}
|
|
38122
|
+
}
|
|
38123
|
+
/**
|
|
38124
|
+
* Off-chain LSD staking-APR for the vault's underlying asset. Looks the vault up in the
|
|
38125
|
+
* registry, hits DefiLlama's per-pool chart endpoint for the configured `poolId`, and on
|
|
38126
|
+
* any fetch failure returns the registry's hardcoded `fallbackAprPct` with `stale: true`.
|
|
38127
|
+
*
|
|
38128
|
+
* Always resolves to `{ ok: true, ... }` for a known vault — the fallback path replaces
|
|
38129
|
+
* the error, since a missing LSD APR shouldn't break the parent call. Returns
|
|
38130
|
+
* `{ aprRay: 0n, stale: true, label: 'no LSD source' }` for vaults without an
|
|
38131
|
+
* `lsdSource` configured (non-LSD strategies); callers can treat that as "skip LSD".
|
|
38132
|
+
*/
|
|
38133
|
+
async getLsdApr(vault) {
|
|
38134
|
+
try {
|
|
38135
|
+
const cfg = this.getVaultByAddress(vault);
|
|
38136
|
+
const source = cfg?.lsdSource;
|
|
38137
|
+
if (!source) {
|
|
38138
|
+
return { ok: true, value: { aprRay: 0n, label: "no LSD source", stale: true } };
|
|
38139
|
+
}
|
|
38140
|
+
try {
|
|
38141
|
+
const aprPct = await fetchDefillamaApr(source.poolId);
|
|
38142
|
+
return { ok: true, value: { aprRay: pctToRay(aprPct), label: source.label, stale: false } };
|
|
38143
|
+
} catch (fetchError) {
|
|
38144
|
+
this.config.logger.warn("[leverageYield] DefiLlama APR fetch failed; using fallbackAprPct", {
|
|
38145
|
+
vault,
|
|
38146
|
+
poolId: source.poolId,
|
|
38147
|
+
fallbackAprPct: source.fallbackAprPct,
|
|
38148
|
+
error: fetchError instanceof Error ? fetchError.message : String(fetchError)
|
|
38149
|
+
});
|
|
38150
|
+
return {
|
|
38151
|
+
ok: true,
|
|
38152
|
+
value: { aprRay: pctToRay(source.fallbackAprPct), label: `${source.label} (fallback)`, stale: true }
|
|
38153
|
+
};
|
|
38154
|
+
}
|
|
38155
|
+
} catch (error) {
|
|
38156
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38157
|
+
return { ok: false, error: lookupFailed("leverageYield", "getLsdApr", error) };
|
|
38158
|
+
}
|
|
38159
|
+
}
|
|
38160
|
+
/**
|
|
38161
|
+
* Combined view of {@link getApr} + {@link getLsdApr}: re-applies the vault's leverage
|
|
38162
|
+
* formula with the LSD's native staking yield folded into the supply side, exposing the
|
|
38163
|
+
* **effective** net APR that LSD-backed strategies actually earn. The AAVE-only
|
|
38164
|
+
* `netAprRay` is preserved on the return value for callers who want to display both.
|
|
38165
|
+
*
|
|
38166
|
+
* effectiveSupply = supplyAprRay + lsdApr.aprRay
|
|
38167
|
+
* effectiveNet = effectiveSupply + leverage × (effectiveSupply − borrowAprRay)
|
|
38168
|
+
*
|
|
38169
|
+
* Fetches AAVE rates and the LSD APR in parallel for one round-trip's worth of latency.
|
|
38170
|
+
*/
|
|
38171
|
+
async getEffectiveApr(vault) {
|
|
38172
|
+
try {
|
|
38173
|
+
const [aprResult, lsdResult] = await Promise.all([this.getApr(vault), this.getLsdApr(vault)]);
|
|
38174
|
+
if (!aprResult.ok) return aprResult;
|
|
38175
|
+
if (!lsdResult.ok) return lsdResult;
|
|
38176
|
+
const apr = aprResult.value;
|
|
38177
|
+
const lsd = lsdResult.value;
|
|
38178
|
+
const effectiveSupplyAprRay = apr.supplyAprRay + lsd.aprRay;
|
|
38179
|
+
const spreadRay = effectiveSupplyAprRay - apr.borrowAprRay;
|
|
38180
|
+
const WAD2 = 1000000000000000000n;
|
|
38181
|
+
const effectiveNetAprRay = effectiveSupplyAprRay + spreadRay * apr.leverageMultiplierWad / WAD2;
|
|
38182
|
+
return {
|
|
38183
|
+
ok: true,
|
|
38184
|
+
value: { ...apr, lsdApr: lsd, effectiveSupplyAprRay, effectiveNetAprRay }
|
|
38185
|
+
};
|
|
38186
|
+
} catch (error) {
|
|
38187
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38188
|
+
return { ok: false, error: lookupFailed("leverageYield", "getEffectiveApr", error) };
|
|
38189
|
+
}
|
|
38190
|
+
}
|
|
38191
|
+
/** Synchronously withdrawable assets for `owner` (clamped against leverage HF floor). */
|
|
38192
|
+
async getMaxWithdraw(vault, owner) {
|
|
38193
|
+
const inner = await Erc4626Service.getMaxWithdraw(vault, owner, this.hubProvider.publicClient);
|
|
38194
|
+
if (!inner.ok) return { ok: false, error: lookupFailed("leverageYield", "getMaxWithdraw", inner.error) };
|
|
38195
|
+
return { ok: true, value: inner.value };
|
|
38196
|
+
}
|
|
38197
|
+
/** Total underlying assets currently held by the vault (vault-asset units, 18 decimals) — TVL. */
|
|
38198
|
+
async getTotalAssets(vault) {
|
|
38199
|
+
const inner = await Erc4626Service.getTotalAssets(vault, this.hubProvider.publicClient);
|
|
38200
|
+
if (!inner.ok) return { ok: false, error: lookupFailed("leverageYield", "getTotalAssets", inner.error) };
|
|
38201
|
+
return { ok: true, value: inner.value };
|
|
38202
|
+
}
|
|
38203
|
+
/** Shares minted for a given asset deposit. */
|
|
38204
|
+
async previewDeposit(vault, assets) {
|
|
38205
|
+
const inner = await Erc4626Service.previewDeposit(vault, assets, this.hubProvider.publicClient);
|
|
38206
|
+
if (!inner.ok) return { ok: false, error: lookupFailed("leverageYield", "previewDeposit", inner.error) };
|
|
38207
|
+
return { ok: true, value: inner.value };
|
|
38208
|
+
}
|
|
38209
|
+
/** Shares burned for a given asset withdrawal. */
|
|
38210
|
+
async previewWithdraw(vault, assets) {
|
|
38211
|
+
const inner = await Erc4626Service.previewWithdraw(vault, assets, this.hubProvider.publicClient);
|
|
38212
|
+
if (!inner.ok) return { ok: false, error: lookupFailed("leverageYield", "previewWithdraw", inner.error) };
|
|
38213
|
+
return { ok: true, value: inner.value };
|
|
38214
|
+
}
|
|
38215
|
+
/** Assets received for a given share redemption. */
|
|
38216
|
+
async previewRedeem(vault, shares) {
|
|
38217
|
+
const inner = await Erc4626Service.previewRedeem(vault, shares, this.hubProvider.publicClient);
|
|
38218
|
+
if (!inner.ok) return { ok: false, error: lookupFailed("leverageYield", "previewRedeem", inner.error) };
|
|
38219
|
+
return { ok: true, value: inner.value };
|
|
38220
|
+
}
|
|
38221
|
+
/** Vault shares held by `owner`. */
|
|
38222
|
+
async getShareBalance(vault, owner) {
|
|
38223
|
+
try {
|
|
38224
|
+
const value = await this.hubProvider.publicClient.readContract({
|
|
38225
|
+
address: vault,
|
|
38226
|
+
abi: viem.erc20Abi,
|
|
38227
|
+
functionName: "balanceOf",
|
|
38228
|
+
args: [owner]
|
|
38229
|
+
});
|
|
38230
|
+
return { ok: true, value };
|
|
38231
|
+
} catch (error) {
|
|
38232
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38233
|
+
return { ok: false, error: lookupFailed("leverageYield", "getShareBalance", error) };
|
|
38234
|
+
}
|
|
38235
|
+
}
|
|
38236
|
+
/**
|
|
38237
|
+
* Convenience: resolves the user's hub wallet from `(srcChainKey, srcAddress)` and
|
|
38238
|
+
* returns its on-chain `maxWithdraw`, less {@link MAX_WITHDRAW_DUST_BUFFER}. The trim
|
|
38239
|
+
* keeps the value safe for an asset-denominated ERC-4626 `withdraw` — the raw
|
|
38240
|
+
* `maxWithdraw` can trip the round-up that asks for one more share than the user holds.
|
|
38241
|
+
*/
|
|
38242
|
+
async getMaxWithdrawForUser(vault, srcChainKey, srcAddress) {
|
|
38243
|
+
try {
|
|
38244
|
+
const hubWallet = await this.hubProvider.getUserHubWalletAddress(srcAddress, srcChainKey);
|
|
38245
|
+
const maxWithdrawResult = await this.getMaxWithdraw(vault, hubWallet);
|
|
38246
|
+
if (!maxWithdrawResult.ok) return maxWithdrawResult;
|
|
38247
|
+
const buffered = maxWithdrawResult.value > MAX_WITHDRAW_DUST_BUFFER ? maxWithdrawResult.value - MAX_WITHDRAW_DUST_BUFFER : 0n;
|
|
38248
|
+
return { ok: true, value: buffered };
|
|
38249
|
+
} catch (error) {
|
|
38250
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38251
|
+
return { ok: false, error: lookupFailed("leverageYield", "getMaxWithdrawForUser", error, { srcChainKey }) };
|
|
38252
|
+
}
|
|
38253
|
+
}
|
|
38254
|
+
/**
|
|
38255
|
+
* Convenience: resolves the user's hub wallet from `(srcChainKey, srcAddress)` and
|
|
38256
|
+
* returns its on-chain share balance.
|
|
38257
|
+
*/
|
|
38258
|
+
async getShareBalanceForUser(vault, srcChainKey, srcAddress) {
|
|
38259
|
+
try {
|
|
38260
|
+
const hubWallet = await this.hubProvider.getUserHubWalletAddress(srcAddress, srcChainKey);
|
|
38261
|
+
return await this.getShareBalance(vault, hubWallet);
|
|
38262
|
+
} catch (error) {
|
|
38263
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38264
|
+
return { ok: false, error: lookupFailed("leverageYield", "getShareBalanceForUser", error, { srcChainKey }) };
|
|
38265
|
+
}
|
|
38266
|
+
}
|
|
38267
|
+
};
|
|
38268
|
+
|
|
37118
38269
|
// src/shared/entities/Sodax.ts
|
|
37119
38270
|
var Sodax = class {
|
|
37120
38271
|
instanceConfig;
|
|
@@ -37136,17 +38287,26 @@ var Sodax = class {
|
|
|
37136
38287
|
// Recovery service for withdrawing stuck hub-wallet assets back to a spoke chain
|
|
37137
38288
|
dex;
|
|
37138
38289
|
// Dex service enabling DEX operations
|
|
38290
|
+
leverageYield;
|
|
38291
|
+
// Leverage-yield service: cross-chain deposits / withdrawals into ERC-4626 leverage vaults on Sonic
|
|
37139
38292
|
config;
|
|
37140
38293
|
// Config service enabling configuration data fetching from the backend API or fallbacking to default values
|
|
37141
38294
|
hubProvider;
|
|
37142
38295
|
// hub provider for the hub chain (e.g. Sonic mainnet)
|
|
37143
38296
|
spoke;
|
|
37144
38297
|
// spoke service enabling spoke chain operations
|
|
37145
|
-
constructor(
|
|
37146
|
-
const logger = resolveLogger(
|
|
37147
|
-
|
|
38298
|
+
constructor(options) {
|
|
38299
|
+
const logger = resolveLogger(options?.logger);
|
|
38300
|
+
const fee = options?.fee;
|
|
38301
|
+
this.instanceConfig = options ? mergeSodaxConfig(sodaxConfig, options) : sodaxConfig;
|
|
37148
38302
|
this.backendApi = new BackendApiService(this.instanceConfig.api, logger);
|
|
37149
|
-
this.config = new ConfigService({
|
|
38303
|
+
this.config = new ConfigService({
|
|
38304
|
+
api: this.backendApi,
|
|
38305
|
+
config: this.instanceConfig,
|
|
38306
|
+
userConfig: options,
|
|
38307
|
+
logger,
|
|
38308
|
+
fee
|
|
38309
|
+
});
|
|
37150
38310
|
this.hubProvider = new EvmHubProvider({ config: this.config });
|
|
37151
38311
|
this.spoke = new SpokeService({ config: this.config, hubProvider: this.hubProvider });
|
|
37152
38312
|
this.swaps = new SwapService({
|
|
@@ -37181,6 +38341,11 @@ var Sodax = class {
|
|
|
37181
38341
|
config: this.config,
|
|
37182
38342
|
spoke: this.spoke
|
|
37183
38343
|
});
|
|
38344
|
+
this.leverageYield = new LeverageYieldService({
|
|
38345
|
+
hubProvider: this.hubProvider,
|
|
38346
|
+
config: this.config,
|
|
38347
|
+
spoke: this.spoke
|
|
38348
|
+
});
|
|
37184
38349
|
}
|
|
37185
38350
|
/**
|
|
37186
38351
|
* Initializes the Sodax instance with dynamic configuration.
|
|
@@ -37289,8 +38454,11 @@ exports.IntentsAbi = IntentsAbi;
|
|
|
37289
38454
|
exports.LOOKUP_CODES = LOOKUP_CODES;
|
|
37290
38455
|
exports.LTV_PRECISION = LTV_PRECISION;
|
|
37291
38456
|
exports.LendingPoolService = LendingPoolService;
|
|
38457
|
+
exports.LeverageYieldService = LeverageYieldService;
|
|
37292
38458
|
exports.LockupMultiplier = LockupMultiplier;
|
|
37293
38459
|
exports.LockupPeriod = LockupPeriod;
|
|
38460
|
+
exports.LsodaSymbols = LsodaSymbols;
|
|
38461
|
+
exports.LsodaTokens = LsodaTokens;
|
|
37294
38462
|
exports.MAX_UINT256 = MAX_UINT256;
|
|
37295
38463
|
exports.MigrationService = MigrationService;
|
|
37296
38464
|
exports.MintPositionEventAbi = MintPositionEventAbi;
|
|
@@ -37433,6 +38601,7 @@ exports.getReserveNormalizedIncome = getReserveNormalizedIncome;
|
|
|
37433
38601
|
exports.getReservesEModes = getReservesEModes;
|
|
37434
38602
|
exports.getSolanaAddressBytes = getSolanaAddressBytes;
|
|
37435
38603
|
exports.getSolverConfig = getSolverConfig;
|
|
38604
|
+
exports.getStagingSolverTokens = getStagingSolverTokens;
|
|
37436
38605
|
exports.getSupportedSolverTokens = getSupportedSolverTokens;
|
|
37437
38606
|
exports.getTransactionPackets = getTransactionPackets;
|
|
37438
38607
|
exports.getbnUSDToken = getbnUSDToken;
|
|
@@ -37475,6 +38644,13 @@ exports.isInjectiveChainKeyType = isInjectiveChainKeyType;
|
|
|
37475
38644
|
exports.isJsonRpcPayloadResponse = isJsonRpcPayloadResponse;
|
|
37476
38645
|
exports.isLegacybnUSDChainId = isLegacybnUSDChainId;
|
|
37477
38646
|
exports.isLegacybnUSDToken = isLegacybnUSDToken;
|
|
38647
|
+
exports.isLeverageYieldAllowanceCheckError = isLeverageYieldAllowanceCheckError;
|
|
38648
|
+
exports.isLeverageYieldApproveError = isLeverageYieldApproveError;
|
|
38649
|
+
exports.isLeverageYieldCreateIntentError = isLeverageYieldCreateIntentError;
|
|
38650
|
+
exports.isLeverageYieldError = isLeverageYieldError;
|
|
38651
|
+
exports.isLeverageYieldLookupError = isLeverageYieldLookupError;
|
|
38652
|
+
exports.isLeverageYieldPostExecutionError = isLeverageYieldPostExecutionError;
|
|
38653
|
+
exports.isLeverageYieldSwapError = isLeverageYieldSwapError;
|
|
37478
38654
|
exports.isMigrateOrchestrationError = isMigrateOrchestrationError;
|
|
37479
38655
|
exports.isMigrationAllowanceCheckError = isMigrationAllowanceCheckError;
|
|
37480
38656
|
exports.isMigrationApproveError = isMigrationApproveError;
|
|
@@ -37541,6 +38717,9 @@ exports.isUndefinedOrValidWalletProviderForChainKey = isUndefinedOrValidWalletPr
|
|
|
37541
38717
|
exports.isUnifiedBnUSDMigrateParams = isUnifiedBnUSDMigrateParams;
|
|
37542
38718
|
exports.isValidWalletProviderForChainKey = isValidWalletProviderForChainKey;
|
|
37543
38719
|
exports.kaiaSupportedTokens = kaiaSupportedTokens;
|
|
38720
|
+
exports.leverageYieldConfig = leverageYieldConfig;
|
|
38721
|
+
exports.leverageYieldInvariant = leverageYieldInvariant;
|
|
38722
|
+
exports.leverageYieldVaults = leverageYieldVaults;
|
|
37544
38723
|
exports.lightlinkSupportedTokens = lightlinkSupportedTokens;
|
|
37545
38724
|
exports.lookupFailed = lookupFailed;
|
|
37546
38725
|
exports.mapRelayFailure = mapRelayFailure;
|
|
@@ -37600,6 +38779,7 @@ exports.spokeAssetManagerAbi = spokeAssetManagerAbi;
|
|
|
37600
38779
|
exports.spokeChainConfig = spokeChainConfig;
|
|
37601
38780
|
exports.spokeChainKeysSet = spokeChainKeysSet;
|
|
37602
38781
|
exports.stacksSupportedTokens = stacksSupportedTokens;
|
|
38782
|
+
exports.stagingSwapSupportedTokens = stagingSwapSupportedTokens;
|
|
37603
38783
|
exports.stakedSodaAbi = stakedSodaAbi;
|
|
37604
38784
|
exports.stakingInvariant = stakingInvariant;
|
|
37605
38785
|
exports.stakingRouterAbi = stakingRouterAbi;
|