@t2000/sdk 0.6.0 → 0.6.2

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.
@@ -5,6 +5,28 @@ var bcs = require('@mysten/sui/bcs');
5
5
  var aggregatorSdk = require('@cetusprotocol/aggregator-sdk');
6
6
  var utils = require('@mysten/sui/utils');
7
7
 
8
+ // src/errors.ts
9
+ var T2000Error = class extends Error {
10
+ code;
11
+ data;
12
+ retryable;
13
+ constructor(code, message, data, retryable = false) {
14
+ super(message);
15
+ this.name = "T2000Error";
16
+ this.code = code;
17
+ this.data = data;
18
+ this.retryable = retryable;
19
+ }
20
+ toJSON() {
21
+ return {
22
+ error: this.code,
23
+ message: this.message,
24
+ ...this.data && { data: this.data },
25
+ retryable: this.retryable
26
+ };
27
+ }
28
+ };
29
+
8
30
  // src/adapters/registry.ts
9
31
  var ProtocolRegistry = class {
10
32
  lending = /* @__PURE__ */ new Map();
@@ -27,7 +49,7 @@ var ProtocolRegistry = class {
27
49
  }
28
50
  }
29
51
  if (candidates.length === 0) {
30
- throw new Error(`No lending adapter supports saving ${asset}`);
52
+ throw new T2000Error("ASSET_NOT_SUPPORTED", `No lending adapter supports saving ${asset}`);
31
53
  }
32
54
  candidates.sort((a, b) => b.rate.saveApy - a.rate.saveApy);
33
55
  return candidates[0];
@@ -45,7 +67,7 @@ var ProtocolRegistry = class {
45
67
  }
46
68
  }
47
69
  if (candidates.length === 0) {
48
- throw new Error(`No lending adapter supports borrowing ${asset}`);
70
+ throw new T2000Error("ASSET_NOT_SUPPORTED", `No lending adapter supports borrowing ${asset}`);
49
71
  }
50
72
  candidates.sort((a, b) => a.rate.borrowApy - b.rate.borrowApy);
51
73
  return candidates[0];
@@ -62,7 +84,7 @@ var ProtocolRegistry = class {
62
84
  }
63
85
  }
64
86
  if (candidates.length === 0) {
65
- throw new Error(`No swap adapter supports ${from} \u2192 ${to}`);
87
+ throw new T2000Error("ASSET_NOT_SUPPORTED", `No swap adapter supports ${from} \u2192 ${to}`);
66
88
  }
67
89
  candidates.sort((a, b) => b.quote.expectedOutput - a.quote.expectedOutput);
68
90
  return candidates[0];
@@ -129,28 +151,6 @@ var T2000_TREASURY_ID = process.env.T2000_TREASURY_ID ?? "0x3bb501b8300125dca590
129
151
  process.env.T2000_API_URL ?? "https://api.t2000.ai";
130
152
  var CETUS_USDC_SUI_POOL = "0x51e883ba7c0b566a26cbc8a94cd33eb0abd418a77cc1e60ad22fd9b1f29cd2ab";
131
153
 
132
- // src/errors.ts
133
- var T2000Error = class extends Error {
134
- code;
135
- data;
136
- retryable;
137
- constructor(code, message, data, retryable = false) {
138
- super(message);
139
- this.name = "T2000Error";
140
- this.code = code;
141
- this.data = data;
142
- this.retryable = retryable;
143
- }
144
- toJSON() {
145
- return {
146
- error: this.code,
147
- message: this.message,
148
- ...this.data && { data: this.data },
149
- retryable: this.retryable
150
- };
151
- }
152
- };
153
-
154
154
  // src/utils/format.ts
155
155
  function usdcToRaw(amount) {
156
156
  return BigInt(Math.round(amount * 10 ** USDC_DECIMALS));
@@ -252,6 +252,24 @@ async function getUsdcPool() {
252
252
  if (!usdc) throw new T2000Error("PROTOCOL_UNAVAILABLE", "USDC pool not found on NAVI");
253
253
  return usdc;
254
254
  }
255
+ function addOracleUpdate(tx, config, pool) {
256
+ const feed = config.oracle.feeds?.find((f2) => f2.assetId === pool.id);
257
+ if (!feed) {
258
+ throw new T2000Error("PROTOCOL_UNAVAILABLE", `Oracle feed not found for asset ${pool.token?.symbol ?? pool.id}`);
259
+ }
260
+ tx.moveCall({
261
+ target: `${config.oracle.packageId}::oracle_pro::update_single_price_v2`,
262
+ arguments: [
263
+ tx.object(CLOCK),
264
+ tx.object(config.oracle.oracleConfig),
265
+ tx.object(config.oracle.priceOracle),
266
+ tx.object(config.oracle.supraOracleHolder),
267
+ tx.object(feed.pythPriceInfoObject),
268
+ tx.object(config.oracle.switchboardAggregator),
269
+ tx.pure.address(feed.feedId)
270
+ ]
271
+ });
272
+ }
255
273
  function rateToApy(rawRate) {
256
274
  if (!rawRate || rawRate === "0") return 0;
257
275
  return Number(BigInt(rawRate)) / 10 ** RATE_DECIMALS * 100;
@@ -274,7 +292,7 @@ function compoundBalance(rawBalance, currentIndex) {
274
292
  if (!rawBalance || !currentIndex || currentIndex === "0") return 0;
275
293
  const scale = BigInt("1" + "0".repeat(RATE_DECIMALS));
276
294
  const half = scale / 2n;
277
- const result = (rawBalance * scale + half) / BigInt(currentIndex);
295
+ const result = (rawBalance * BigInt(currentIndex) + half) / scale;
278
296
  return Number(result) / 10 ** NAVI_BALANCE_DECIMALS;
279
297
  }
280
298
  async function getUserState(client, address) {
@@ -317,6 +335,9 @@ function mergeCoins(tx, coins) {
317
335
  return primary;
318
336
  }
319
337
  async function buildSaveTx(client, address, amount, options = {}) {
338
+ if (!amount || amount <= 0 || !Number.isFinite(amount)) {
339
+ throw new T2000Error("INVALID_AMOUNT", "Save amount must be a positive number");
340
+ }
320
341
  const rawAmount = Number(usdcToRaw(amount));
321
342
  const [config, pool] = await Promise.all([getConfig(), getUsdcPool()]);
322
343
  const coins = await fetchCoins(client, address, USDC_TYPE);
@@ -357,6 +378,7 @@ async function buildWithdrawTx(client, address, amount) {
357
378
  const rawAmount = Number(usdcToRaw(effectiveAmount));
358
379
  const tx = new transactions.Transaction();
359
380
  tx.setSender(address);
381
+ addOracleUpdate(tx, config, pool);
360
382
  const [balance] = tx.moveCall({
361
383
  target: `${config.package}::incentive_v3::withdraw_v2`,
362
384
  arguments: [
@@ -381,10 +403,14 @@ async function buildWithdrawTx(client, address, amount) {
381
403
  return { tx, effectiveAmount };
382
404
  }
383
405
  async function buildBorrowTx(client, address, amount, options = {}) {
406
+ if (!amount || amount <= 0 || !Number.isFinite(amount)) {
407
+ throw new T2000Error("INVALID_AMOUNT", "Borrow amount must be a positive number");
408
+ }
384
409
  const rawAmount = Number(usdcToRaw(amount));
385
410
  const [config, pool] = await Promise.all([getConfig(), getUsdcPool()]);
386
411
  const tx = new transactions.Transaction();
387
412
  tx.setSender(address);
413
+ addOracleUpdate(tx, config, pool);
388
414
  const [balance] = tx.moveCall({
389
415
  target: `${config.package}::incentive_v3::borrow_v2`,
390
416
  arguments: [
@@ -405,16 +431,23 @@ async function buildBorrowTx(client, address, amount, options = {}) {
405
431
  arguments: [balance],
406
432
  typeArguments: [pool.suiCoinType]
407
433
  });
434
+ if (options.collectFee) {
435
+ addCollectFeeToTx(tx, borrowedCoin, "borrow");
436
+ }
408
437
  tx.transferObjects([borrowedCoin], address);
409
438
  return tx;
410
439
  }
411
440
  async function buildRepayTx(client, address, amount) {
441
+ if (!amount || amount <= 0 || !Number.isFinite(amount)) {
442
+ throw new T2000Error("INVALID_AMOUNT", "Repay amount must be a positive number");
443
+ }
412
444
  const rawAmount = Number(usdcToRaw(amount));
413
445
  const [config, pool] = await Promise.all([getConfig(), getUsdcPool()]);
414
446
  const coins = await fetchCoins(client, address, USDC_TYPE);
415
447
  if (coins.length === 0) throw new T2000Error("INSUFFICIENT_BALANCE", "No USDC coins to repay with");
416
448
  const tx = new transactions.Transaction();
417
449
  tx.setSender(address);
450
+ addOracleUpdate(tx, config, pool);
418
451
  const coinObj = mergeCoins(tx, coins);
419
452
  tx.moveCall({
420
453
  target: `${config.package}::incentive_v3::entry_repay`,
@@ -571,7 +604,7 @@ var NaviAdapter = class {
571
604
  const rates = await getRates(this.client);
572
605
  const key = asset.toUpperCase();
573
606
  const r = rates[key];
574
- if (!r) throw new Error(`NAVI does not support ${asset}`);
607
+ if (!r) throw new T2000Error("ASSET_NOT_SUPPORTED", `NAVI does not support ${asset}`);
575
608
  return { asset, saveApy: r.saveApy, borrowApy: r.borrowApy };
576
609
  }
577
610
  async getPositions(address) {