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