@t2000/sdk 0.19.24 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -150
- package/dist/adapters/descriptors.cjs +1 -42
- package/dist/adapters/descriptors.cjs.map +1 -1
- package/dist/adapters/descriptors.d.cts +1 -1
- package/dist/adapters/descriptors.d.ts +1 -1
- package/dist/adapters/descriptors.js +2 -41
- package/dist/adapters/descriptors.js.map +1 -1
- package/dist/adapters/index.cjs +3 -745
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.d.cts +4 -171
- package/dist/adapters/index.d.ts +4 -171
- package/dist/adapters/index.js +4 -742
- package/dist/adapters/index.js.map +1 -1
- package/dist/browser.js +20 -178
- package/dist/browser.js.map +1 -1
- package/dist/descriptors-Be4FAgN5.d.cts +127 -0
- package/dist/descriptors-Be4FAgN5.d.ts +127 -0
- package/dist/index-D1DxZ1DK.d.ts +292 -0
- package/dist/index-MP_J_nSO.d.cts +292 -0
- package/dist/index.cjs +680 -3461
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -313
- package/dist/index.d.ts +34 -313
- package/dist/index.js +592 -3360
- package/dist/index.js.map +1 -1
- package/package.json +5 -8
- package/dist/descriptors-B6qt_mwi.d.cts +0 -584
- package/dist/descriptors-B6qt_mwi.d.ts +0 -584
package/dist/adapters/index.js
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { Transaction } from '@mysten/sui/transactions';
|
|
2
2
|
import { getPools, getLendingPositions, getHealthFactor as getHealthFactor$1, depositCoinPTB, withdrawCoinPTB, borrowCoinPTB, repayCoinPTB, getUserAvailableLendingRewards, summaryLendingRewards, claimLendingRewardsPTB, updateOraclePriceBeforeUserOperationPTB } from '@naviprotocol/lending';
|
|
3
|
-
import { AggregatorClient, Env } from '@cetusprotocol/aggregator-sdk';
|
|
4
|
-
import { normalizeStructTag } from '@mysten/sui/utils';
|
|
5
|
-
import { SuilendClient, LENDING_MARKET_ID, LENDING_MARKET_TYPE } from '@suilend/sdk/client';
|
|
6
|
-
import { initializeSuilend, initializeObligations } from '@suilend/sdk/lib/initialize';
|
|
7
|
-
import { Side } from '@suilend/sdk/lib/types';
|
|
8
3
|
|
|
9
4
|
// src/constants.ts
|
|
10
5
|
var SAVE_FEE_BPS = 10n;
|
|
11
|
-
var SWAP_FEE_BPS = 0n;
|
|
12
6
|
var BORROW_FEE_BPS = 5n;
|
|
13
7
|
var SUPPORTED_ASSETS = {
|
|
14
8
|
USDC: {
|
|
@@ -40,39 +34,13 @@ var SUPPORTED_ASSETS = {
|
|
|
40
34
|
decimals: 9,
|
|
41
35
|
symbol: "SUI",
|
|
42
36
|
displayName: "SUI"
|
|
43
|
-
},
|
|
44
|
-
BTC: {
|
|
45
|
-
type: "0x0041f9f9344cac094454cd574e333c4fdb132d7bcc9379bcd4aab485b2a63942::wbtc::WBTC",
|
|
46
|
-
decimals: 8,
|
|
47
|
-
symbol: "BTC",
|
|
48
|
-
displayName: "Bitcoin"
|
|
49
|
-
},
|
|
50
|
-
ETH: {
|
|
51
|
-
type: "0xd0e89b2af5e4910726fbcd8b8dd37bb79b29e5f83f7491bca830e94f7f226d29::eth::ETH",
|
|
52
|
-
decimals: 8,
|
|
53
|
-
symbol: "ETH",
|
|
54
|
-
displayName: "Ethereum"
|
|
55
|
-
},
|
|
56
|
-
GOLD: {
|
|
57
|
-
type: "0x9d297676e7a4b771ab023291377b2adfaa4938fb9080b8d12430e4b108b836a9::xaum::XAUM",
|
|
58
|
-
decimals: 9,
|
|
59
|
-
symbol: "GOLD",
|
|
60
|
-
displayName: "Gold"
|
|
61
37
|
}
|
|
62
38
|
};
|
|
63
|
-
var STABLE_ASSETS = ["USDC"
|
|
39
|
+
var STABLE_ASSETS = ["USDC"];
|
|
64
40
|
var T2000_PACKAGE_ID = process.env.T2000_PACKAGE_ID ?? "0xab92e9f1fe549ad3d6a52924a73181b45791e76120b975138fac9ec9b75db9f3";
|
|
65
41
|
var T2000_CONFIG_ID = process.env.T2000_CONFIG_ID ?? "0x408add9aa9322f93cfd87523d8f603006eb8713894f4c460283c58a6888dae8a";
|
|
66
42
|
var T2000_TREASURY_ID = process.env.T2000_TREASURY_ID ?? "0x3bb501b8300125dca59019247941a42af6b292a150ce3cfcce9449456be2ec91";
|
|
67
43
|
process.env.T2000_API_URL ?? "https://api.t2000.ai";
|
|
68
|
-
var CETUS_USDC_SUI_POOL = "0x51e883ba7c0b566a26cbc8a94cd33eb0abd418a77cc1e60ad22fd9b1f29cd2ab";
|
|
69
|
-
var CETUS_PACKAGE = "0x1eabed72c53feb3805120a081dc15963c204dc8d091542592abaf7a35689b2fb";
|
|
70
|
-
var INVESTMENT_ASSETS = {
|
|
71
|
-
SUI: SUPPORTED_ASSETS.SUI,
|
|
72
|
-
BTC: SUPPORTED_ASSETS.BTC,
|
|
73
|
-
ETH: SUPPORTED_ASSETS.ETH,
|
|
74
|
-
GOLD: SUPPORTED_ASSETS.GOLD
|
|
75
|
-
};
|
|
76
44
|
|
|
77
45
|
// src/errors.ts
|
|
78
46
|
var T2000Error = class extends Error {
|
|
@@ -99,13 +67,9 @@ var T2000Error = class extends Error {
|
|
|
99
67
|
// src/adapters/registry.ts
|
|
100
68
|
var ProtocolRegistry = class {
|
|
101
69
|
lending = /* @__PURE__ */ new Map();
|
|
102
|
-
swap = /* @__PURE__ */ new Map();
|
|
103
70
|
registerLending(adapter) {
|
|
104
71
|
this.lending.set(adapter.id, adapter);
|
|
105
72
|
}
|
|
106
|
-
registerSwap(adapter) {
|
|
107
|
-
this.swap.set(adapter.id, adapter);
|
|
108
|
-
}
|
|
109
73
|
async bestSaveRate(asset) {
|
|
110
74
|
const candidates = [];
|
|
111
75
|
for (const adapter of this.lending.values()) {
|
|
@@ -141,23 +105,6 @@ var ProtocolRegistry = class {
|
|
|
141
105
|
candidates.sort((a, b) => a.rate.borrowApy - b.rate.borrowApy);
|
|
142
106
|
return candidates[0];
|
|
143
107
|
}
|
|
144
|
-
async bestSwapQuote(from, to, amount) {
|
|
145
|
-
const candidates = [];
|
|
146
|
-
for (const adapter of this.swap.values()) {
|
|
147
|
-
const pairs = adapter.getSupportedPairs();
|
|
148
|
-
if (!pairs.some((p) => p.from === from && p.to === to)) continue;
|
|
149
|
-
try {
|
|
150
|
-
const quote = await adapter.getQuote(from, to, amount);
|
|
151
|
-
candidates.push({ adapter, quote });
|
|
152
|
-
} catch {
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
if (candidates.length === 0) {
|
|
156
|
-
throw new T2000Error("ASSET_NOT_SUPPORTED", `No swap adapter supports ${from} \u2192 ${to}`);
|
|
157
|
-
}
|
|
158
|
-
candidates.sort((a, b) => b.quote.expectedOutput - a.quote.expectedOutput);
|
|
159
|
-
return candidates[0];
|
|
160
|
-
}
|
|
161
108
|
async bestSaveRateAcrossAssets() {
|
|
162
109
|
const candidates = [];
|
|
163
110
|
for (const asset of STABLE_ASSETS) {
|
|
@@ -179,9 +126,8 @@ var ProtocolRegistry = class {
|
|
|
179
126
|
}
|
|
180
127
|
async allRatesAcrossAssets() {
|
|
181
128
|
const results = [];
|
|
182
|
-
const allAssets = [...STABLE_ASSETS, ...Object.keys(INVESTMENT_ASSETS)];
|
|
183
129
|
const seen = /* @__PURE__ */ new Set();
|
|
184
|
-
for (const asset of
|
|
130
|
+
for (const asset of STABLE_ASSETS) {
|
|
185
131
|
if (seen.has(asset)) continue;
|
|
186
132
|
seen.add(asset);
|
|
187
133
|
for (const adapter of this.lending.values()) {
|
|
@@ -230,15 +176,9 @@ var ProtocolRegistry = class {
|
|
|
230
176
|
getLending(id) {
|
|
231
177
|
return this.lending.get(id);
|
|
232
178
|
}
|
|
233
|
-
getSwap(id) {
|
|
234
|
-
return this.swap.get(id);
|
|
235
|
-
}
|
|
236
179
|
listLending() {
|
|
237
180
|
return [...this.lending.values()];
|
|
238
181
|
}
|
|
239
|
-
listSwap() {
|
|
240
|
-
return [...this.swap.values()];
|
|
241
|
-
}
|
|
242
182
|
};
|
|
243
183
|
|
|
244
184
|
// src/utils/format.ts
|
|
@@ -259,12 +199,10 @@ function normalizeAsset(input) {
|
|
|
259
199
|
// src/protocols/protocolFee.ts
|
|
260
200
|
var FEE_RATES = {
|
|
261
201
|
save: SAVE_FEE_BPS,
|
|
262
|
-
swap: SWAP_FEE_BPS,
|
|
263
202
|
borrow: BORROW_FEE_BPS
|
|
264
203
|
};
|
|
265
204
|
var OP_CODES = {
|
|
266
205
|
save: 0,
|
|
267
|
-
swap: 1,
|
|
268
206
|
borrow: 2
|
|
269
207
|
};
|
|
270
208
|
function addCollectFeeToTx(tx, paymentCoin, operation) {
|
|
@@ -689,7 +627,6 @@ async function addClaimRewardsToTx(tx, client, address) {
|
|
|
689
627
|
}
|
|
690
628
|
|
|
691
629
|
// src/adapters/descriptors.ts
|
|
692
|
-
var SUILEND_PACKAGE = "0xf95b06141ed4a174f239417323bde3f209b972f5930d8521ea38a52aff3a6ddf";
|
|
693
630
|
var naviDescriptor = {
|
|
694
631
|
id: "navi",
|
|
695
632
|
name: "NAVI Protocol",
|
|
@@ -706,39 +643,8 @@ var naviDescriptor = {
|
|
|
706
643
|
"incentive_v3::repay": "repay"
|
|
707
644
|
}
|
|
708
645
|
};
|
|
709
|
-
var suilendDescriptor = {
|
|
710
|
-
id: "suilend",
|
|
711
|
-
name: "Suilend",
|
|
712
|
-
packages: [SUILEND_PACKAGE],
|
|
713
|
-
actionMap: {
|
|
714
|
-
"lending_market::deposit_liquidity_and_mint_ctokens": "save",
|
|
715
|
-
"lending_market::deposit_ctokens_into_obligation": "save",
|
|
716
|
-
"lending_market::create_obligation": "save",
|
|
717
|
-
"lending_market::withdraw_ctokens": "withdraw",
|
|
718
|
-
"lending_market::redeem_ctokens_and_withdraw_liquidity": "withdraw",
|
|
719
|
-
"lending_market::redeem_ctokens_and_withdraw_liquidity_request": "withdraw",
|
|
720
|
-
"lending_market::fulfill_liquidity_request": "withdraw",
|
|
721
|
-
"lending_market::unstake_sui_from_staker": "withdraw",
|
|
722
|
-
"lending_market::borrow": "borrow",
|
|
723
|
-
"lending_market::repay": "repay"
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
|
-
var cetusDescriptor = {
|
|
727
|
-
id: "cetus",
|
|
728
|
-
name: "Cetus DEX",
|
|
729
|
-
packages: [CETUS_PACKAGE],
|
|
730
|
-
actionMap: {
|
|
731
|
-
"router::swap": "swap",
|
|
732
|
-
"router::swap_ab_bc": "swap",
|
|
733
|
-
"router::swap_ab_cb": "swap",
|
|
734
|
-
"router::swap_ba_bc": "swap",
|
|
735
|
-
"router::swap_ba_cb": "swap"
|
|
736
|
-
}
|
|
737
|
-
};
|
|
738
646
|
var allDescriptors = [
|
|
739
|
-
naviDescriptor
|
|
740
|
-
suilendDescriptor,
|
|
741
|
-
cetusDescriptor
|
|
647
|
+
naviDescriptor
|
|
742
648
|
];
|
|
743
649
|
|
|
744
650
|
// src/adapters/navi.ts
|
|
@@ -822,651 +728,7 @@ var NaviAdapter = class {
|
|
|
822
728
|
return addClaimRewardsToTx(tx, this.client, address);
|
|
823
729
|
}
|
|
824
730
|
};
|
|
825
|
-
var DEFAULT_SLIPPAGE_BPS = 300;
|
|
826
|
-
function createAggregatorClient(client, signer) {
|
|
827
|
-
return new AggregatorClient({
|
|
828
|
-
client,
|
|
829
|
-
signer,
|
|
830
|
-
env: Env.Mainnet
|
|
831
|
-
});
|
|
832
|
-
}
|
|
833
|
-
async function buildSwapTx(params) {
|
|
834
|
-
const { client, address, fromAsset, toAsset, amount, maxSlippageBps = DEFAULT_SLIPPAGE_BPS } = params;
|
|
835
|
-
const fromInfo = SUPPORTED_ASSETS[fromAsset];
|
|
836
|
-
const toInfo = SUPPORTED_ASSETS[toAsset];
|
|
837
|
-
if (!fromInfo || !toInfo) {
|
|
838
|
-
throw new T2000Error("ASSET_NOT_SUPPORTED", `Swap pair ${fromAsset}/${toAsset} is not supported`);
|
|
839
|
-
}
|
|
840
|
-
const rawAmount = BigInt(Math.floor(amount * 10 ** fromInfo.decimals));
|
|
841
|
-
const aggClient = createAggregatorClient(client, address);
|
|
842
|
-
const _origLog = console.log;
|
|
843
|
-
console.log = () => {
|
|
844
|
-
};
|
|
845
|
-
let result;
|
|
846
|
-
try {
|
|
847
|
-
result = await aggClient.findRouters({
|
|
848
|
-
from: fromInfo.type,
|
|
849
|
-
target: toInfo.type,
|
|
850
|
-
amount: rawAmount,
|
|
851
|
-
byAmountIn: true
|
|
852
|
-
});
|
|
853
|
-
} finally {
|
|
854
|
-
console.log = _origLog;
|
|
855
|
-
}
|
|
856
|
-
if (!result || result.insufficientLiquidity) {
|
|
857
|
-
throw new T2000Error(
|
|
858
|
-
"ASSET_NOT_SUPPORTED",
|
|
859
|
-
`No swap route found for ${fromAsset} \u2192 ${toAsset}`
|
|
860
|
-
);
|
|
861
|
-
}
|
|
862
|
-
const tx = new Transaction();
|
|
863
|
-
const slippage = maxSlippageBps / 1e4;
|
|
864
|
-
console.log = () => {
|
|
865
|
-
};
|
|
866
|
-
try {
|
|
867
|
-
await aggClient.fastRouterSwap({
|
|
868
|
-
router: result,
|
|
869
|
-
txb: tx,
|
|
870
|
-
slippage
|
|
871
|
-
});
|
|
872
|
-
} finally {
|
|
873
|
-
console.log = _origLog;
|
|
874
|
-
}
|
|
875
|
-
const estimatedOut = Number(result.amountOut.toString());
|
|
876
|
-
return {
|
|
877
|
-
tx,
|
|
878
|
-
estimatedOut,
|
|
879
|
-
toDecimals: toInfo.decimals
|
|
880
|
-
};
|
|
881
|
-
}
|
|
882
|
-
async function addSwapToTx(params) {
|
|
883
|
-
const { tx, client, address, inputCoin, fromAsset, toAsset, amount, maxSlippageBps = DEFAULT_SLIPPAGE_BPS } = params;
|
|
884
|
-
const fromInfo = SUPPORTED_ASSETS[fromAsset];
|
|
885
|
-
const toInfo = SUPPORTED_ASSETS[toAsset];
|
|
886
|
-
if (!fromInfo || !toInfo) {
|
|
887
|
-
throw new T2000Error("ASSET_NOT_SUPPORTED", `Swap pair ${fromAsset}/${toAsset} is not supported`);
|
|
888
|
-
}
|
|
889
|
-
const rawAmount = BigInt(Math.floor(amount * 10 ** fromInfo.decimals));
|
|
890
|
-
const aggClient = createAggregatorClient(client, address);
|
|
891
|
-
const _origLog = console.log;
|
|
892
|
-
console.log = () => {
|
|
893
|
-
};
|
|
894
|
-
let result;
|
|
895
|
-
try {
|
|
896
|
-
result = await aggClient.findRouters({
|
|
897
|
-
from: fromInfo.type,
|
|
898
|
-
target: toInfo.type,
|
|
899
|
-
amount: rawAmount,
|
|
900
|
-
byAmountIn: true
|
|
901
|
-
});
|
|
902
|
-
} finally {
|
|
903
|
-
console.log = _origLog;
|
|
904
|
-
}
|
|
905
|
-
if (!result || result.insufficientLiquidity) {
|
|
906
|
-
throw new T2000Error(
|
|
907
|
-
"ASSET_NOT_SUPPORTED",
|
|
908
|
-
`No swap route found for ${fromAsset} \u2192 ${toAsset}`
|
|
909
|
-
);
|
|
910
|
-
}
|
|
911
|
-
const slippage = maxSlippageBps / 1e4;
|
|
912
|
-
console.log = () => {
|
|
913
|
-
};
|
|
914
|
-
let outputCoin;
|
|
915
|
-
try {
|
|
916
|
-
outputCoin = await aggClient.routerSwap({
|
|
917
|
-
router: result,
|
|
918
|
-
txb: tx,
|
|
919
|
-
inputCoin,
|
|
920
|
-
slippage
|
|
921
|
-
});
|
|
922
|
-
} finally {
|
|
923
|
-
console.log = _origLog;
|
|
924
|
-
}
|
|
925
|
-
const estimatedOut = Number(result.amountOut.toString());
|
|
926
|
-
return {
|
|
927
|
-
outputCoin,
|
|
928
|
-
estimatedOut,
|
|
929
|
-
toDecimals: toInfo.decimals
|
|
930
|
-
};
|
|
931
|
-
}
|
|
932
|
-
async function getPoolPrice(client) {
|
|
933
|
-
try {
|
|
934
|
-
const pool = await client.getObject({
|
|
935
|
-
id: CETUS_USDC_SUI_POOL,
|
|
936
|
-
options: { showContent: true }
|
|
937
|
-
});
|
|
938
|
-
if (pool.data?.content?.dataType === "moveObject") {
|
|
939
|
-
const fields = pool.data.content.fields;
|
|
940
|
-
const currentSqrtPrice = BigInt(String(fields.current_sqrt_price ?? "0"));
|
|
941
|
-
if (currentSqrtPrice > 0n) {
|
|
942
|
-
const Q64 = 2n ** 64n;
|
|
943
|
-
const sqrtPriceFloat = Number(currentSqrtPrice) / Number(Q64);
|
|
944
|
-
const rawPrice = sqrtPriceFloat * sqrtPriceFloat;
|
|
945
|
-
const suiPriceUsd = 1e3 / rawPrice;
|
|
946
|
-
if (suiPriceUsd > 0.01 && suiPriceUsd < 1e3) return suiPriceUsd;
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
} catch {
|
|
950
|
-
}
|
|
951
|
-
return 3.5;
|
|
952
|
-
}
|
|
953
|
-
async function getSwapQuote(client, fromAsset, toAsset, amount) {
|
|
954
|
-
const fromInfo = SUPPORTED_ASSETS[fromAsset];
|
|
955
|
-
const toInfo = SUPPORTED_ASSETS[toAsset];
|
|
956
|
-
if (!fromInfo || !toInfo) {
|
|
957
|
-
throw new T2000Error("ASSET_NOT_SUPPORTED", `Swap pair ${fromAsset}/${toAsset} is not supported`);
|
|
958
|
-
}
|
|
959
|
-
const rawAmount = BigInt(Math.floor(amount * 10 ** fromInfo.decimals));
|
|
960
|
-
const poolPrice = await getPoolPrice(client);
|
|
961
|
-
try {
|
|
962
|
-
const aggClient = createAggregatorClient(client);
|
|
963
|
-
const result = await aggClient.findRouters({
|
|
964
|
-
from: fromInfo.type,
|
|
965
|
-
target: toInfo.type,
|
|
966
|
-
amount: rawAmount,
|
|
967
|
-
byAmountIn: true
|
|
968
|
-
});
|
|
969
|
-
if (!result || result.insufficientLiquidity) {
|
|
970
|
-
return fallbackQuote(fromAsset, amount, poolPrice);
|
|
971
|
-
}
|
|
972
|
-
const expectedOutput = Number(result.amountOut.toString()) / 10 ** toInfo.decimals;
|
|
973
|
-
const priceImpact = result.deviationRatio ?? 0;
|
|
974
|
-
return { expectedOutput, priceImpact, poolPrice };
|
|
975
|
-
} catch {
|
|
976
|
-
return fallbackQuote(fromAsset, amount, poolPrice);
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
function fallbackQuote(fromAsset, amount, poolPrice) {
|
|
980
|
-
const expectedOutput = fromAsset === "USDC" ? amount / poolPrice : amount * poolPrice;
|
|
981
|
-
return { expectedOutput, priceImpact: 0, poolPrice };
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
// src/adapters/cetus.ts
|
|
985
|
-
var CetusAdapter = class {
|
|
986
|
-
id = "cetus";
|
|
987
|
-
name = "Cetus";
|
|
988
|
-
version = "1.0.0";
|
|
989
|
-
capabilities = ["swap"];
|
|
990
|
-
client;
|
|
991
|
-
async init(client) {
|
|
992
|
-
this.client = client;
|
|
993
|
-
}
|
|
994
|
-
initSync(client) {
|
|
995
|
-
this.client = client;
|
|
996
|
-
}
|
|
997
|
-
async getQuote(from, to, amount) {
|
|
998
|
-
return getSwapQuote(this.client, from, to, amount);
|
|
999
|
-
}
|
|
1000
|
-
async buildSwapTx(address, from, to, amount, maxSlippageBps) {
|
|
1001
|
-
const result = await buildSwapTx({
|
|
1002
|
-
client: this.client,
|
|
1003
|
-
address,
|
|
1004
|
-
fromAsset: from,
|
|
1005
|
-
toAsset: to,
|
|
1006
|
-
amount,
|
|
1007
|
-
maxSlippageBps
|
|
1008
|
-
});
|
|
1009
|
-
return {
|
|
1010
|
-
tx: result.tx,
|
|
1011
|
-
estimatedOut: result.estimatedOut,
|
|
1012
|
-
toDecimals: result.toDecimals
|
|
1013
|
-
};
|
|
1014
|
-
}
|
|
1015
|
-
getSupportedPairs() {
|
|
1016
|
-
const pairs = [];
|
|
1017
|
-
for (const asset of Object.keys(INVESTMENT_ASSETS)) {
|
|
1018
|
-
pairs.push({ from: "USDC", to: asset }, { from: asset, to: "USDC" });
|
|
1019
|
-
}
|
|
1020
|
-
for (const a of STABLE_ASSETS) {
|
|
1021
|
-
for (const b of STABLE_ASSETS) {
|
|
1022
|
-
if (a !== b) pairs.push({ from: a, to: b });
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
return pairs;
|
|
1026
|
-
}
|
|
1027
|
-
async getPoolPrice() {
|
|
1028
|
-
return getPoolPrice(this.client);
|
|
1029
|
-
}
|
|
1030
|
-
async addSwapToTx(tx, address, inputCoin, from, to, amount, maxSlippageBps) {
|
|
1031
|
-
return addSwapToTx({
|
|
1032
|
-
tx,
|
|
1033
|
-
client: this.client,
|
|
1034
|
-
address,
|
|
1035
|
-
inputCoin,
|
|
1036
|
-
fromAsset: from,
|
|
1037
|
-
toAsset: to,
|
|
1038
|
-
amount,
|
|
1039
|
-
maxSlippageBps
|
|
1040
|
-
});
|
|
1041
|
-
}
|
|
1042
|
-
};
|
|
1043
|
-
var MIN_HEALTH_FACTOR2 = 1.5;
|
|
1044
|
-
async function quietSuilend(fn) {
|
|
1045
|
-
const origLog = console.log;
|
|
1046
|
-
const origWarn = console.warn;
|
|
1047
|
-
const filter = (...args) => typeof args[0] === "string" && (args[0].includes("PythEndpoint") || args[0].includes("PythConnection"));
|
|
1048
|
-
console.log = (...args) => {
|
|
1049
|
-
if (!filter(...args)) origLog.apply(console, args);
|
|
1050
|
-
};
|
|
1051
|
-
console.warn = (...args) => {
|
|
1052
|
-
if (!filter(...args)) origWarn.apply(console, args);
|
|
1053
|
-
};
|
|
1054
|
-
return fn().finally(() => {
|
|
1055
|
-
console.log = origLog;
|
|
1056
|
-
console.warn = origWarn;
|
|
1057
|
-
});
|
|
1058
|
-
}
|
|
1059
|
-
var SuilendAdapter = class {
|
|
1060
|
-
id = "suilend";
|
|
1061
|
-
name = "Suilend";
|
|
1062
|
-
version = "3.0.0";
|
|
1063
|
-
capabilities = ["save", "withdraw", "borrow", "repay"];
|
|
1064
|
-
supportedAssets = [...STABLE_ASSETS, "SUI", "ETH", "BTC", "GOLD"];
|
|
1065
|
-
supportsSameAssetBorrow = false;
|
|
1066
|
-
client;
|
|
1067
|
-
sdkClient = null;
|
|
1068
|
-
async init(client) {
|
|
1069
|
-
this.client = client;
|
|
1070
|
-
}
|
|
1071
|
-
initSync(client) {
|
|
1072
|
-
this.client = client;
|
|
1073
|
-
}
|
|
1074
|
-
async getSdkClient() {
|
|
1075
|
-
if (!this.sdkClient) {
|
|
1076
|
-
this.sdkClient = await SuilendClient.initialize(
|
|
1077
|
-
LENDING_MARKET_ID,
|
|
1078
|
-
LENDING_MARKET_TYPE,
|
|
1079
|
-
this.client,
|
|
1080
|
-
false
|
|
1081
|
-
);
|
|
1082
|
-
}
|
|
1083
|
-
return this.sdkClient;
|
|
1084
|
-
}
|
|
1085
|
-
resolveSymbol(coinType) {
|
|
1086
|
-
try {
|
|
1087
|
-
const normalized = normalizeStructTag(coinType);
|
|
1088
|
-
for (const [key, info] of Object.entries(SUPPORTED_ASSETS)) {
|
|
1089
|
-
try {
|
|
1090
|
-
if (normalizeStructTag(info.type) === normalized) return key;
|
|
1091
|
-
} catch {
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
} catch {
|
|
1095
|
-
}
|
|
1096
|
-
const parts = coinType.split("::");
|
|
1097
|
-
return parts[parts.length - 1] || "UNKNOWN";
|
|
1098
|
-
}
|
|
1099
|
-
async getRates(asset) {
|
|
1100
|
-
try {
|
|
1101
|
-
const sdk = await this.getSdkClient();
|
|
1102
|
-
const { reserveMap } = await quietSuilend(() => initializeSuilend(this.client, sdk));
|
|
1103
|
-
const assetInfo = SUPPORTED_ASSETS[asset];
|
|
1104
|
-
if (!assetInfo) throw new T2000Error("ASSET_NOT_SUPPORTED", `Suilend does not support ${asset}`);
|
|
1105
|
-
const normalized = normalizeStructTag(assetInfo.type);
|
|
1106
|
-
const reserve = Object.values(reserveMap).find((r) => {
|
|
1107
|
-
try {
|
|
1108
|
-
return normalizeStructTag(r.coinType) === normalized;
|
|
1109
|
-
} catch {
|
|
1110
|
-
return false;
|
|
1111
|
-
}
|
|
1112
|
-
});
|
|
1113
|
-
if (!reserve) throw new T2000Error("ASSET_NOT_SUPPORTED", `Suilend does not support ${asset}`);
|
|
1114
|
-
return {
|
|
1115
|
-
asset,
|
|
1116
|
-
saveApy: reserve.depositAprPercent.toNumber(),
|
|
1117
|
-
borrowApy: reserve.borrowAprPercent.toNumber()
|
|
1118
|
-
};
|
|
1119
|
-
} catch (err) {
|
|
1120
|
-
if (err instanceof T2000Error) throw err;
|
|
1121
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1122
|
-
throw new T2000Error("PROTOCOL_UNAVAILABLE", `Suilend getRates failed: ${msg}`);
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
async getPositions(address) {
|
|
1126
|
-
const supplies = [];
|
|
1127
|
-
const borrows = [];
|
|
1128
|
-
try {
|
|
1129
|
-
const sdk = await this.getSdkClient();
|
|
1130
|
-
const { reserveMap, refreshedRawReserves } = await quietSuilend(() => initializeSuilend(this.client, sdk));
|
|
1131
|
-
const { obligations, obligationOwnerCaps } = await initializeObligations(
|
|
1132
|
-
this.client,
|
|
1133
|
-
sdk,
|
|
1134
|
-
refreshedRawReserves,
|
|
1135
|
-
reserveMap,
|
|
1136
|
-
address
|
|
1137
|
-
);
|
|
1138
|
-
if (obligationOwnerCaps.length === 0 || obligations.length === 0) {
|
|
1139
|
-
return { supplies, borrows };
|
|
1140
|
-
}
|
|
1141
|
-
const obligation = obligations[0];
|
|
1142
|
-
for (const dep of obligation.deposits) {
|
|
1143
|
-
const symbol = this.resolveSymbol(dep.coinType);
|
|
1144
|
-
const amount = dep.depositedAmount.toNumber();
|
|
1145
|
-
const amountUsd = dep.depositedAmountUsd.toNumber();
|
|
1146
|
-
const apy = dep.reserve.depositAprPercent.toNumber();
|
|
1147
|
-
if (amountUsd > 0.01) {
|
|
1148
|
-
supplies.push({ asset: symbol, amount, amountUsd, apy });
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
for (const bor of obligation.borrows) {
|
|
1152
|
-
const symbol = this.resolveSymbol(bor.coinType);
|
|
1153
|
-
const amount = bor.borrowedAmount.toNumber();
|
|
1154
|
-
const amountUsd = bor.borrowedAmountUsd.toNumber();
|
|
1155
|
-
const apy = bor.reserve.borrowAprPercent.toNumber();
|
|
1156
|
-
if (amountUsd > 0.01) {
|
|
1157
|
-
borrows.push({ asset: symbol, amount, amountUsd, apy });
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
} catch (err) {
|
|
1161
|
-
if (err instanceof T2000Error) throw err;
|
|
1162
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1163
|
-
throw new T2000Error("PROTOCOL_UNAVAILABLE", `Suilend getPositions failed: ${msg}`);
|
|
1164
|
-
}
|
|
1165
|
-
return { supplies, borrows };
|
|
1166
|
-
}
|
|
1167
|
-
async getHealth(address) {
|
|
1168
|
-
try {
|
|
1169
|
-
const sdk = await this.getSdkClient();
|
|
1170
|
-
const { reserveMap, refreshedRawReserves } = await quietSuilend(() => initializeSuilend(this.client, sdk));
|
|
1171
|
-
const { obligations, obligationOwnerCaps } = await initializeObligations(
|
|
1172
|
-
this.client,
|
|
1173
|
-
sdk,
|
|
1174
|
-
refreshedRawReserves,
|
|
1175
|
-
reserveMap,
|
|
1176
|
-
address
|
|
1177
|
-
);
|
|
1178
|
-
if (obligationOwnerCaps.length === 0 || obligations.length === 0) {
|
|
1179
|
-
return { healthFactor: Infinity, supplied: 0, borrowed: 0, maxBorrow: 0, liquidationThreshold: 0 };
|
|
1180
|
-
}
|
|
1181
|
-
const ob = obligations[0];
|
|
1182
|
-
const supplied = ob.depositedAmountUsd.toNumber();
|
|
1183
|
-
const borrowed = ob.borrowedAmountUsd.toNumber();
|
|
1184
|
-
const borrowLimit = ob.borrowLimitUsd.toNumber();
|
|
1185
|
-
const unhealthy = ob.unhealthyBorrowValueUsd.toNumber();
|
|
1186
|
-
const liqThreshold = supplied > 0 ? unhealthy / supplied : 0.75;
|
|
1187
|
-
const healthFactor = borrowed > 0 ? unhealthy / borrowed : Infinity;
|
|
1188
|
-
const maxBorrow = Math.max(0, borrowLimit - borrowed);
|
|
1189
|
-
return { healthFactor, supplied, borrowed, maxBorrow, liquidationThreshold: liqThreshold };
|
|
1190
|
-
} catch {
|
|
1191
|
-
return { healthFactor: Infinity, supplied: 0, borrowed: 0, maxBorrow: 0, liquidationThreshold: 0 };
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
async buildSaveTx(address, amount, asset, options) {
|
|
1195
|
-
const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
|
|
1196
|
-
const assetInfo = SUPPORTED_ASSETS[assetKey];
|
|
1197
|
-
const sdk = await this.getSdkClient();
|
|
1198
|
-
const caps = await SuilendClient.getObligationOwnerCaps(address, [LENDING_MARKET_TYPE], this.client);
|
|
1199
|
-
const tx = new Transaction();
|
|
1200
|
-
tx.setSender(address);
|
|
1201
|
-
const rawValue = stableToRaw(amount, assetInfo.decimals).toString();
|
|
1202
|
-
if (caps.length > 0) {
|
|
1203
|
-
if (options?.collectFee) {
|
|
1204
|
-
const allCoins = await this.fetchAllCoins(address, assetInfo.type);
|
|
1205
|
-
if (allCoins.length === 0) throw new T2000Error("INSUFFICIENT_BALANCE", `No ${assetInfo.displayName} coins found`);
|
|
1206
|
-
const primaryCoinId = allCoins[0].coinObjectId;
|
|
1207
|
-
if (allCoins.length > 1) {
|
|
1208
|
-
tx.mergeCoins(tx.object(primaryCoinId), allCoins.slice(1).map((c) => tx.object(c.coinObjectId)));
|
|
1209
|
-
}
|
|
1210
|
-
const [depositCoin] = tx.splitCoins(tx.object(primaryCoinId), [rawValue]);
|
|
1211
|
-
addCollectFeeToTx(tx, depositCoin, "save");
|
|
1212
|
-
}
|
|
1213
|
-
await sdk.depositIntoObligation(address, assetInfo.type, rawValue, tx, caps[0].id);
|
|
1214
|
-
} else {
|
|
1215
|
-
const newCap = sdk.createObligation(tx);
|
|
1216
|
-
let depositCoin;
|
|
1217
|
-
if (assetKey === "SUI") {
|
|
1218
|
-
[depositCoin] = tx.splitCoins(tx.gas, [rawValue]);
|
|
1219
|
-
} else {
|
|
1220
|
-
const allCoins = await this.fetchAllCoins(address, assetInfo.type);
|
|
1221
|
-
if (allCoins.length === 0) throw new T2000Error("INSUFFICIENT_BALANCE", `No ${assetInfo.displayName} coins found`);
|
|
1222
|
-
const primaryCoin = tx.object(allCoins[0].coinObjectId);
|
|
1223
|
-
if (allCoins.length > 1) {
|
|
1224
|
-
tx.mergeCoins(primaryCoin, allCoins.slice(1).map((c) => tx.object(c.coinObjectId)));
|
|
1225
|
-
}
|
|
1226
|
-
[depositCoin] = tx.splitCoins(primaryCoin, [rawValue]);
|
|
1227
|
-
}
|
|
1228
|
-
if (options?.collectFee) {
|
|
1229
|
-
addCollectFeeToTx(tx, depositCoin, "save");
|
|
1230
|
-
}
|
|
1231
|
-
sdk.deposit(depositCoin, assetInfo.type, newCap, tx);
|
|
1232
|
-
tx.transferObjects([newCap], address);
|
|
1233
|
-
}
|
|
1234
|
-
return { tx };
|
|
1235
|
-
}
|
|
1236
|
-
async buildWithdrawTx(address, amount, asset) {
|
|
1237
|
-
const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
|
|
1238
|
-
const assetInfo = SUPPORTED_ASSETS[assetKey];
|
|
1239
|
-
const sdk = await this.getSdkClient();
|
|
1240
|
-
const caps = await SuilendClient.getObligationOwnerCaps(address, [LENDING_MARKET_TYPE], this.client);
|
|
1241
|
-
if (caps.length === 0) throw new T2000Error("NO_COLLATERAL", "No Suilend position found");
|
|
1242
|
-
const { ctokenRaw, effectiveAmount, obligationIndex } = await this.resolveWithdrawCTokens(sdk, address, assetKey, assetInfo, amount);
|
|
1243
|
-
const cap = caps[obligationIndex] ?? caps[0];
|
|
1244
|
-
const tx = new Transaction();
|
|
1245
|
-
tx.setSender(address);
|
|
1246
|
-
await sdk.withdrawAndSendToUser(address, cap.id, cap.obligationId, assetInfo.type, ctokenRaw, tx);
|
|
1247
|
-
return { tx, effectiveAmount };
|
|
1248
|
-
}
|
|
1249
|
-
async addWithdrawToTx(tx, address, amount, asset) {
|
|
1250
|
-
const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
|
|
1251
|
-
const assetInfo = SUPPORTED_ASSETS[assetKey];
|
|
1252
|
-
const sdk = await this.getSdkClient();
|
|
1253
|
-
const caps = await SuilendClient.getObligationOwnerCaps(address, [LENDING_MARKET_TYPE], this.client);
|
|
1254
|
-
if (caps.length === 0) throw new T2000Error("NO_COLLATERAL", "No Suilend position found");
|
|
1255
|
-
const { ctokenRaw, effectiveAmount, obligationIndex } = await this.resolveWithdrawCTokens(sdk, address, assetKey, assetInfo, amount);
|
|
1256
|
-
const cap = caps[obligationIndex] ?? caps[0];
|
|
1257
|
-
const coin = await sdk.withdraw(cap.id, cap.obligationId, assetInfo.type, ctokenRaw, tx);
|
|
1258
|
-
return { coin, effectiveAmount };
|
|
1259
|
-
}
|
|
1260
|
-
async addSaveToTx(tx, address, coin, asset, options) {
|
|
1261
|
-
const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
|
|
1262
|
-
const assetInfo = SUPPORTED_ASSETS[assetKey];
|
|
1263
|
-
const sdk = await this.getSdkClient();
|
|
1264
|
-
const caps = await SuilendClient.getObligationOwnerCaps(address, [LENDING_MARKET_TYPE], this.client);
|
|
1265
|
-
let capRef;
|
|
1266
|
-
if (caps.length === 0) {
|
|
1267
|
-
const newCap = sdk.createObligation(tx);
|
|
1268
|
-
capRef = newCap;
|
|
1269
|
-
tx.transferObjects([newCap], address);
|
|
1270
|
-
} else {
|
|
1271
|
-
capRef = caps[0].id;
|
|
1272
|
-
}
|
|
1273
|
-
if (options?.collectFee) {
|
|
1274
|
-
addCollectFeeToTx(tx, coin, "save");
|
|
1275
|
-
}
|
|
1276
|
-
sdk.deposit(coin, assetInfo.type, capRef, tx);
|
|
1277
|
-
}
|
|
1278
|
-
async buildBorrowTx(address, amount, asset, options) {
|
|
1279
|
-
const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
|
|
1280
|
-
const assetInfo = SUPPORTED_ASSETS[assetKey];
|
|
1281
|
-
const sdk = await this.getSdkClient();
|
|
1282
|
-
const caps = await SuilendClient.getObligationOwnerCaps(address, [LENDING_MARKET_TYPE], this.client);
|
|
1283
|
-
if (caps.length === 0) throw new T2000Error("NO_COLLATERAL", "No Suilend position found. Deposit collateral first with: t2000 save <amount>");
|
|
1284
|
-
const rawValue = stableToRaw(amount, assetInfo.decimals).toString();
|
|
1285
|
-
const tx = new Transaction();
|
|
1286
|
-
tx.setSender(address);
|
|
1287
|
-
if (options?.collectFee) {
|
|
1288
|
-
const coin = await sdk.borrow(caps[0].id, caps[0].obligationId, assetInfo.type, rawValue, tx);
|
|
1289
|
-
addCollectFeeToTx(tx, coin, "borrow");
|
|
1290
|
-
tx.transferObjects([coin], address);
|
|
1291
|
-
} else {
|
|
1292
|
-
await sdk.borrowAndSendToUser(address, caps[0].id, caps[0].obligationId, assetInfo.type, rawValue, tx);
|
|
1293
|
-
}
|
|
1294
|
-
return { tx };
|
|
1295
|
-
}
|
|
1296
|
-
async buildRepayTx(address, amount, asset) {
|
|
1297
|
-
const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
|
|
1298
|
-
const assetInfo = SUPPORTED_ASSETS[assetKey];
|
|
1299
|
-
const sdk = await this.getSdkClient();
|
|
1300
|
-
const caps = await SuilendClient.getObligationOwnerCaps(address, [LENDING_MARKET_TYPE], this.client);
|
|
1301
|
-
if (caps.length === 0) throw new T2000Error("NO_COLLATERAL", "No Suilend obligation found");
|
|
1302
|
-
const rawValue = stableToRaw(amount, assetInfo.decimals).toString();
|
|
1303
|
-
const tx = new Transaction();
|
|
1304
|
-
tx.setSender(address);
|
|
1305
|
-
await sdk.repayIntoObligation(address, caps[0].obligationId, assetInfo.type, rawValue, tx);
|
|
1306
|
-
return { tx };
|
|
1307
|
-
}
|
|
1308
|
-
async addRepayToTx(tx, address, coin, asset) {
|
|
1309
|
-
const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
|
|
1310
|
-
const assetInfo = SUPPORTED_ASSETS[assetKey];
|
|
1311
|
-
const sdk = await this.getSdkClient();
|
|
1312
|
-
const caps = await SuilendClient.getObligationOwnerCaps(address, [LENDING_MARKET_TYPE], this.client);
|
|
1313
|
-
if (caps.length === 0) throw new T2000Error("NO_COLLATERAL", "No Suilend obligation found");
|
|
1314
|
-
sdk.repay(caps[0].obligationId, assetInfo.type, coin, tx);
|
|
1315
|
-
}
|
|
1316
|
-
async resolveWithdrawCTokens(sdk, address, assetKey, assetInfo, amount) {
|
|
1317
|
-
const { reserveMap, refreshedRawReserves } = await quietSuilend(() => initializeSuilend(this.client, sdk));
|
|
1318
|
-
const { obligations } = await initializeObligations(
|
|
1319
|
-
this.client,
|
|
1320
|
-
sdk,
|
|
1321
|
-
refreshedRawReserves,
|
|
1322
|
-
reserveMap,
|
|
1323
|
-
address
|
|
1324
|
-
);
|
|
1325
|
-
if (obligations.length === 0) throw new T2000Error("NO_COLLATERAL", `Nothing to withdraw for ${assetInfo.displayName} on Suilend \u2014 no obligations found`);
|
|
1326
|
-
let dep;
|
|
1327
|
-
let matchedObligation = 0;
|
|
1328
|
-
for (let oi = 0; oi < obligations.length; oi++) {
|
|
1329
|
-
dep = obligations[oi].deposits.find((d) => {
|
|
1330
|
-
const resolved = this.resolveSymbol(d.coinType);
|
|
1331
|
-
if (resolved === assetKey) return true;
|
|
1332
|
-
try {
|
|
1333
|
-
return normalizeStructTag(d.coinType) === normalizeStructTag(assetInfo.type);
|
|
1334
|
-
} catch {
|
|
1335
|
-
return false;
|
|
1336
|
-
}
|
|
1337
|
-
});
|
|
1338
|
-
if (dep && dep.depositedAmount.toNumber() > 1e-10) {
|
|
1339
|
-
matchedObligation = oi;
|
|
1340
|
-
break;
|
|
1341
|
-
}
|
|
1342
|
-
dep = void 0;
|
|
1343
|
-
}
|
|
1344
|
-
if (!dep) {
|
|
1345
|
-
const foundDeposits = obligations.flatMap(
|
|
1346
|
-
(o, i) => o.deposits.map((d) => `ob${i}:${this.resolveSymbol(d.coinType)}=${d.depositedAmount.toFixed(8)}`)
|
|
1347
|
-
);
|
|
1348
|
-
throw new T2000Error(
|
|
1349
|
-
"NO_COLLATERAL",
|
|
1350
|
-
`Nothing to withdraw for ${assetInfo.displayName} (${assetKey}) on Suilend. Found deposits: [${foundDeposits.join(", ")}]`
|
|
1351
|
-
);
|
|
1352
|
-
}
|
|
1353
|
-
const deposited = dep.depositedAmount.toNumber();
|
|
1354
|
-
const effectiveAmount = Math.min(amount, deposited);
|
|
1355
|
-
const proportion = effectiveAmount / deposited;
|
|
1356
|
-
const ctokenRaw = proportion >= 0.999 ? dep.depositedCtokenAmount.toFixed(0) : dep.depositedCtokenAmount.times(proportion).integerValue(1).toFixed(0);
|
|
1357
|
-
return { ctokenRaw, effectiveAmount, obligationIndex: matchedObligation };
|
|
1358
|
-
}
|
|
1359
|
-
async maxWithdraw(address, _asset) {
|
|
1360
|
-
const health = await this.getHealth(address);
|
|
1361
|
-
let maxAmount;
|
|
1362
|
-
if (health.borrowed === 0) {
|
|
1363
|
-
maxAmount = health.supplied;
|
|
1364
|
-
} else {
|
|
1365
|
-
maxAmount = Math.max(0, health.supplied - health.borrowed * MIN_HEALTH_FACTOR2 / health.liquidationThreshold);
|
|
1366
|
-
}
|
|
1367
|
-
const remainingSupply = health.supplied - maxAmount;
|
|
1368
|
-
const hfAfter = health.borrowed > 0 ? remainingSupply * health.liquidationThreshold / health.borrowed : Infinity;
|
|
1369
|
-
return { maxAmount, healthFactorAfter: hfAfter, currentHF: health.healthFactor };
|
|
1370
|
-
}
|
|
1371
|
-
async maxBorrow(address, _asset) {
|
|
1372
|
-
const health = await this.getHealth(address);
|
|
1373
|
-
return { maxAmount: health.maxBorrow, healthFactorAfter: MIN_HEALTH_FACTOR2, currentHF: health.healthFactor };
|
|
1374
|
-
}
|
|
1375
|
-
async fetchAllCoins(owner, coinType) {
|
|
1376
|
-
const all = [];
|
|
1377
|
-
let cursor = null;
|
|
1378
|
-
let hasNext = true;
|
|
1379
|
-
while (hasNext) {
|
|
1380
|
-
const page = await this.client.getCoins({ owner, coinType, cursor: cursor ?? void 0 });
|
|
1381
|
-
all.push(...page.data.map((c) => ({ coinObjectId: c.coinObjectId, balance: c.balance })));
|
|
1382
|
-
cursor = page.nextCursor;
|
|
1383
|
-
hasNext = page.hasNextPage;
|
|
1384
|
-
}
|
|
1385
|
-
return all;
|
|
1386
|
-
}
|
|
1387
|
-
async getPendingRewards(address) {
|
|
1388
|
-
try {
|
|
1389
|
-
const sdk = await this.getSdkClient();
|
|
1390
|
-
const { reserveMap, refreshedRawReserves } = await quietSuilend(() => initializeSuilend(this.client, sdk));
|
|
1391
|
-
const { obligations, obligationOwnerCaps } = await initializeObligations(
|
|
1392
|
-
this.client,
|
|
1393
|
-
sdk,
|
|
1394
|
-
refreshedRawReserves,
|
|
1395
|
-
reserveMap,
|
|
1396
|
-
address
|
|
1397
|
-
);
|
|
1398
|
-
if (obligationOwnerCaps.length === 0 || obligations.length === 0) return [];
|
|
1399
|
-
const ob = obligations[0];
|
|
1400
|
-
const rewards = [];
|
|
1401
|
-
const WAD = 1e18;
|
|
1402
|
-
for (const dep of ob.deposits) {
|
|
1403
|
-
const urm = dep.userRewardManager;
|
|
1404
|
-
for (const rw of dep.reserve.depositsPoolRewardManager?.poolRewards ?? []) {
|
|
1405
|
-
if (rw.endTimeMs <= Date.now()) continue;
|
|
1406
|
-
let claimableAmount = 0;
|
|
1407
|
-
const userReward = urm?.rewards?.[rw.rewardIndex];
|
|
1408
|
-
if (userReward?.earnedRewards) {
|
|
1409
|
-
claimableAmount = Number(BigInt(userReward.earnedRewards.value.toString())) / WAD / 10 ** rw.mintDecimals;
|
|
1410
|
-
}
|
|
1411
|
-
const symbol = rw.symbol || rw.coinType.split("::").pop() || "UNKNOWN";
|
|
1412
|
-
rewards.push({
|
|
1413
|
-
protocol: "suilend",
|
|
1414
|
-
asset: this.resolveSymbol(dep.coinType),
|
|
1415
|
-
coinType: rw.coinType,
|
|
1416
|
-
symbol,
|
|
1417
|
-
amount: claimableAmount,
|
|
1418
|
-
estimatedValueUsd: 0
|
|
1419
|
-
});
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
return rewards;
|
|
1423
|
-
} catch {
|
|
1424
|
-
return [];
|
|
1425
|
-
}
|
|
1426
|
-
}
|
|
1427
|
-
async addClaimRewardsToTx(tx, address) {
|
|
1428
|
-
try {
|
|
1429
|
-
const sdk = await this.getSdkClient();
|
|
1430
|
-
const caps = await SuilendClient.getObligationOwnerCaps(address, [LENDING_MARKET_TYPE], this.client);
|
|
1431
|
-
if (caps.length === 0) return [];
|
|
1432
|
-
const { reserveMap, refreshedRawReserves } = await quietSuilend(() => initializeSuilend(this.client, sdk));
|
|
1433
|
-
const { obligations } = await initializeObligations(
|
|
1434
|
-
this.client,
|
|
1435
|
-
sdk,
|
|
1436
|
-
refreshedRawReserves,
|
|
1437
|
-
reserveMap,
|
|
1438
|
-
address
|
|
1439
|
-
);
|
|
1440
|
-
if (obligations.length === 0) return [];
|
|
1441
|
-
const ob = obligations[0];
|
|
1442
|
-
const claimRewards = [];
|
|
1443
|
-
for (const dep of ob.deposits) {
|
|
1444
|
-
for (const rw of dep.reserve.depositsPoolRewardManager.poolRewards) {
|
|
1445
|
-
if (rw.endTimeMs <= Date.now()) continue;
|
|
1446
|
-
claimRewards.push({
|
|
1447
|
-
reserveArrayIndex: dep.reserveArrayIndex,
|
|
1448
|
-
rewardIndex: BigInt(rw.rewardIndex),
|
|
1449
|
-
rewardCoinType: rw.coinType,
|
|
1450
|
-
side: Side.DEPOSIT
|
|
1451
|
-
});
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
if (claimRewards.length === 0) return [];
|
|
1455
|
-
sdk.claimRewardsAndSendToUser(address, caps[0].id, claimRewards, tx);
|
|
1456
|
-
return claimRewards.map((r) => ({
|
|
1457
|
-
protocol: "suilend",
|
|
1458
|
-
asset: "",
|
|
1459
|
-
coinType: r.rewardCoinType,
|
|
1460
|
-
symbol: r.rewardCoinType.split("::").pop() ?? "UNKNOWN",
|
|
1461
|
-
amount: 0,
|
|
1462
|
-
estimatedValueUsd: 0
|
|
1463
|
-
}));
|
|
1464
|
-
} catch {
|
|
1465
|
-
return [];
|
|
1466
|
-
}
|
|
1467
|
-
}
|
|
1468
|
-
};
|
|
1469
731
|
|
|
1470
|
-
export {
|
|
732
|
+
export { NaviAdapter, ProtocolRegistry, allDescriptors, naviDescriptor };
|
|
1471
733
|
//# sourceMappingURL=index.js.map
|
|
1472
734
|
//# sourceMappingURL=index.js.map
|