@t2000/sdk 1.0.1 → 1.1.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.
package/dist/browser.cjs CHANGED
@@ -2,6 +2,106 @@
2
2
 
3
3
  require('@mysten/sui/jsonRpc');
4
4
  var utils = require('@mysten/sui/utils');
5
+ var aggregatorSdk = require('@cetusprotocol/aggregator-sdk');
6
+
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropNames = Object.getOwnPropertyNames;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+
17
+ // src/errors.ts
18
+ var errors_exports = {};
19
+ __export(errors_exports, {
20
+ T2000Error: () => exports.T2000Error,
21
+ isMoveAbort: () => isMoveAbort,
22
+ mapMoveAbortCode: () => mapMoveAbortCode,
23
+ mapWalletError: () => mapWalletError,
24
+ parseMoveAbortMessage: () => parseMoveAbortMessage
25
+ });
26
+ function mapWalletError(error) {
27
+ const msg = error instanceof Error ? error.message : String(error);
28
+ if (msg.includes("rejected") || msg.includes("cancelled")) {
29
+ return new exports.T2000Error("TRANSACTION_FAILED", "Transaction cancelled");
30
+ }
31
+ if (msg.includes("Insufficient") || msg.includes("insufficient")) {
32
+ return new exports.T2000Error("INSUFFICIENT_BALANCE", "Insufficient balance");
33
+ }
34
+ return new exports.T2000Error("UNKNOWN", msg, void 0, true);
35
+ }
36
+ function mapMoveAbortCode(code) {
37
+ const abortMessages = {
38
+ 1: "Protocol is temporarily paused",
39
+ 2: "Amount must be greater than zero",
40
+ 3: "Invalid operation type",
41
+ 4: "Fee rate exceeds maximum",
42
+ 5: "Insufficient treasury balance",
43
+ 6: "Not authorized",
44
+ 7: "Package version mismatch \u2014 upgrade required",
45
+ 8: "Timelock is active \u2014 wait for expiry",
46
+ 9: "No pending change to execute",
47
+ 10: "Already at current version",
48
+ // NAVI Protocol abort codes
49
+ 1502: "Oracle price is stale \u2014 try again in a moment",
50
+ 1503: 'Withdrawal amount is invalid (zero or dust) \u2014 try a specific amount instead of "all"',
51
+ 1600: "Health factor too low \u2014 withdrawal would risk liquidation",
52
+ 1605: "Asset borrowing is disabled or at capacity on this protocol",
53
+ // NAVI utils abort codes
54
+ 46e3: "Insufficient balance to repay \u2014 withdraw some savings first to get cash"
55
+ };
56
+ return abortMessages[code] ?? `Move abort code: ${code}`;
57
+ }
58
+ function isMoveAbort(msg) {
59
+ return msg.includes("MoveAbort") || msg.includes("MovePrimitiveRuntimeError");
60
+ }
61
+ function parseMoveAbortMessage(msg) {
62
+ const abortMatch = msg.match(/abort code:\s*(\d+)/i) ?? msg.match(/MoveAbort[^,]*,\s*(\d+)/);
63
+ if (abortMatch) {
64
+ const code = parseInt(abortMatch[1], 10);
65
+ const moduleMatch = msg.match(/Identifier\("([^"]+)"\)/) ?? msg.match(/in '([^']+)'/);
66
+ const fnMatch = msg.match(/function_name:\s*Some\("([^"]+)"\)/);
67
+ const context = `${moduleMatch?.[1] ?? ""}${fnMatch ? `::${fnMatch[1]}` : ""}`.toLowerCase();
68
+ const suffix = moduleMatch ? ` [${moduleMatch[1]}${fnMatch ? `::${fnMatch[1]}` : ""}]` : "";
69
+ if (context.includes("slippage")) {
70
+ return `Slippage too high \u2014 price moved during execution${suffix}`;
71
+ }
72
+ if (context.includes("balance::split") || context.includes("balance::ENotEnough")) {
73
+ return `Insufficient on-chain balance${suffix}`;
74
+ }
75
+ const mapped = mapMoveAbortCode(code);
76
+ return `${mapped}${suffix}`;
77
+ }
78
+ return msg;
79
+ }
80
+ exports.T2000Error = void 0;
81
+ var init_errors = __esm({
82
+ "src/errors.ts"() {
83
+ exports.T2000Error = class extends Error {
84
+ code;
85
+ data;
86
+ retryable;
87
+ constructor(code, message, data, retryable = false) {
88
+ super(message);
89
+ this.name = "T2000Error";
90
+ this.code = code;
91
+ this.data = data;
92
+ this.retryable = retryable;
93
+ }
94
+ toJSON() {
95
+ return {
96
+ error: this.code,
97
+ message: this.message,
98
+ ...this.data && { data: this.data },
99
+ retryable: this.retryable
100
+ };
101
+ }
102
+ };
103
+ }
104
+ });
5
105
 
6
106
  // src/wallet/keypairSigner.ts
7
107
  var KeypairSigner = class {
@@ -47,61 +147,11 @@ var ZkLoginSigner = class {
47
147
  }
48
148
  };
49
149
 
50
- // src/errors.ts
51
- var T2000Error = class extends Error {
52
- code;
53
- data;
54
- retryable;
55
- constructor(code, message, data, retryable = false) {
56
- super(message);
57
- this.name = "T2000Error";
58
- this.code = code;
59
- this.data = data;
60
- this.retryable = retryable;
61
- }
62
- toJSON() {
63
- return {
64
- error: this.code,
65
- message: this.message,
66
- ...this.data && { data: this.data },
67
- retryable: this.retryable
68
- };
69
- }
70
- };
71
- function mapWalletError(error) {
72
- const msg = error instanceof Error ? error.message : String(error);
73
- if (msg.includes("rejected") || msg.includes("cancelled")) {
74
- return new T2000Error("TRANSACTION_FAILED", "Transaction cancelled");
75
- }
76
- if (msg.includes("Insufficient") || msg.includes("insufficient")) {
77
- return new T2000Error("INSUFFICIENT_BALANCE", "Insufficient balance");
78
- }
79
- return new T2000Error("UNKNOWN", msg, void 0, true);
80
- }
81
- function mapMoveAbortCode(code) {
82
- const abortMessages = {
83
- 1: "Protocol is temporarily paused",
84
- 2: "Amount must be greater than zero",
85
- 3: "Invalid operation type",
86
- 4: "Fee rate exceeds maximum",
87
- 5: "Insufficient treasury balance",
88
- 6: "Not authorized",
89
- 7: "Package version mismatch \u2014 upgrade required",
90
- 8: "Timelock is active \u2014 wait for expiry",
91
- 9: "No pending change to execute",
92
- 10: "Already at current version",
93
- // NAVI Protocol abort codes
94
- 1502: "Oracle price is stale \u2014 try again in a moment",
95
- 1503: 'Withdrawal amount is invalid (zero or dust) \u2014 try a specific amount instead of "all"',
96
- 1600: "Health factor too low \u2014 withdrawal would risk liquidation",
97
- 1605: "Asset borrowing is disabled or at capacity on this protocol",
98
- // NAVI utils abort codes
99
- 46e3: "Insufficient balance to repay \u2014 withdraw some savings first to get cash"
100
- };
101
- return abortMessages[code] ?? `Move abort code: ${code}`;
102
- }
150
+ // src/browser.ts
151
+ init_errors();
103
152
 
104
153
  // src/constants.ts
154
+ init_errors();
105
155
  var MIST_PER_SUI = 1000000000n;
106
156
  var SUI_DECIMALS = 9;
107
157
  var USDC_DECIMALS = 6;
@@ -167,16 +217,15 @@ var SUPPORTED_ASSETS = {
167
217
  };
168
218
  var STABLE_ASSETS = ["USDC"];
169
219
  var ALL_NAVI_ASSETS = Object.keys(SUPPORTED_ASSETS);
170
- var T2000_PACKAGE_ID = process.env.T2000_PACKAGE_ID ?? "0xd775fcc66eae26797654d435d751dea56b82eeb999de51fd285348e573b968ad";
171
- var T2000_CONFIG_ID = process.env.T2000_CONFIG_ID ?? "0x08ba26f0d260b5edf6a19c71492b3eb914906a7419baf2df1426765157e5862a";
172
- var T2000_TREASURY_ID = process.env.T2000_TREASURY_ID ?? "0xf420ec0dcad44433042fb56e1413fb88d3ff65be94fcf425ef9ff750164590e8";
220
+ var T2000_OVERLAY_FEE_WALLET = process.env.T2000_OVERLAY_FEE_WALLET ?? "0x5366efbf2b4fe5767fe2e78eb197aa5f5d138d88ac3333fbf3f80a1927da473a";
173
221
  var DEFAULT_NETWORK = "mainnet";
174
222
  process.env.T2000_API_URL ?? "https://api.t2000.ai";
175
223
  var GAS_RESERVE_MIN = 0.05;
224
+ init_errors();
176
225
  function validateAddress(address) {
177
226
  const normalized = utils.normalizeSuiAddress(address);
178
227
  if (!utils.isValidSuiAddress(normalized)) {
179
- throw new T2000Error("INVALID_ADDRESS", `Invalid Sui address: ${address}`);
228
+ throw new exports.T2000Error("INVALID_ADDRESS", `Invalid Sui address: ${address}`);
180
229
  }
181
230
  return normalized;
182
231
  }
@@ -525,11 +574,12 @@ function fromBase64(b64) {
525
574
  // src/protocols/protocolFee.ts
526
575
  var FEE_RATES = {
527
576
  save: SAVE_FEE_BPS,
528
- borrow: BORROW_FEE_BPS
529
- };
530
- var OP_CODES = {
531
- save: 0,
532
- borrow: 2
577
+ borrow: BORROW_FEE_BPS,
578
+ // Swap uses Cetus's overlay-fee mechanism (taken from output by the aggregator
579
+ // and transferred to `overlayFee.receiver`). We list the rate here for display
580
+ // / quote calculations only — `addFeeTransfer` is NOT called for swaps.
581
+ swap: 10n
582
+ // 0.1%
533
583
  };
534
584
  function calculateFee(operation, amount) {
535
585
  const bps = FEE_RATES[operation];
@@ -542,23 +592,83 @@ function calculateFee(operation, amount) {
542
592
  rawAmount
543
593
  };
544
594
  }
545
- function addCollectFeeToTx(tx, paymentCoin, operation) {
546
- const bps = FEE_RATES[operation];
547
- if (bps <= 0n) return;
548
- tx.moveCall({
549
- target: `${T2000_PACKAGE_ID}::treasury::collect_fee`,
550
- typeArguments: [SUPPORTED_ASSETS.USDC.type],
551
- arguments: [
552
- tx.object(T2000_TREASURY_ID),
553
- tx.object(T2000_CONFIG_ID),
554
- paymentCoin,
555
- tx.pure.u8(OP_CODES[operation])
556
- ]
595
+ function addFeeTransfer(tx, paymentCoin, feeBps, receiver, amount) {
596
+ if (feeBps <= 0n) return;
597
+ if (amount <= 0) return;
598
+ const feeAmount = amount * Number(feeBps) / Number(BPS_DENOMINATOR);
599
+ const rawFee = usdcToRaw(feeAmount);
600
+ if (rawFee <= 0n) return;
601
+ const [feeCoin] = tx.splitCoins(paymentCoin, [tx.pure.u64(rawFee)]);
602
+ tx.transferObjects([feeCoin], tx.pure.address(receiver));
603
+ }
604
+ var OVERLAY_FEE_RATE = 1e-3;
605
+ var clientCache = /* @__PURE__ */ new Map();
606
+ function getClient(walletAddress, overlayFee) {
607
+ const rate = overlayFee?.rate ?? 0;
608
+ const receiver = overlayFee?.receiver ?? "";
609
+ const key = `${walletAddress}|${rate}|${receiver}`;
610
+ const cached = clientCache.get(key);
611
+ if (cached) return cached;
612
+ const client = new aggregatorSdk.AggregatorClient({
613
+ signer: walletAddress,
614
+ env: aggregatorSdk.Env.Mainnet,
615
+ ...rate > 0 && receiver ? { overlayFeeRate: rate, overlayFeeReceiver: receiver } : {}
616
+ });
617
+ clientCache.set(key, client);
618
+ return client;
619
+ }
620
+ async function findSwapRoute(params) {
621
+ const client = getClient(params.walletAddress, params.overlayFee);
622
+ const findParams = {
623
+ from: params.from,
624
+ target: params.to,
625
+ amount: params.amount.toString(),
626
+ byAmountIn: params.byAmountIn
627
+ };
628
+ const routerData = await client.findRouters(findParams);
629
+ if (!routerData) return null;
630
+ if (routerData.insufficientLiquidity) {
631
+ return {
632
+ routerData,
633
+ amountIn: routerData.amountIn.toString(),
634
+ amountOut: routerData.amountOut.toString(),
635
+ byAmountIn: params.byAmountIn,
636
+ priceImpact: normalizePriceImpact(routerData.deviationRatio),
637
+ insufficientLiquidity: true
638
+ };
639
+ }
640
+ if (routerData.error) {
641
+ const { T2000Error: T2000Error2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
642
+ throw new T2000Error2("SWAP_FAILED", `Cetus routing error: ${routerData.error.msg} (code ${routerData.error.code})`);
643
+ }
644
+ return {
645
+ routerData,
646
+ amountIn: routerData.amountIn.toString(),
647
+ amountOut: routerData.amountOut.toString(),
648
+ byAmountIn: params.byAmountIn,
649
+ priceImpact: normalizePriceImpact(routerData.deviationRatio),
650
+ insufficientLiquidity: false
651
+ };
652
+ }
653
+ function normalizePriceImpact(value) {
654
+ const n = typeof value === "number" ? value : Number(value);
655
+ return Number.isFinite(n) ? n : 0;
656
+ }
657
+ async function buildSwapTx(params) {
658
+ const client = getClient(params.walletAddress, params.overlayFee);
659
+ const clampedSlippage = Math.max(1e-3, Math.min(params.slippage, 0.05));
660
+ const outputCoin = await client.routerSwap({
661
+ router: params.route.routerData,
662
+ inputCoin: params.inputCoin,
663
+ slippage: clampedSlippage,
664
+ txb: params.tx
557
665
  });
666
+ return outputCoin;
558
667
  }
559
668
 
560
669
  // src/safeguards/errors.ts
561
- var SafeguardError = class extends T2000Error {
670
+ init_errors();
671
+ var SafeguardError = class extends exports.T2000Error {
562
672
  rule;
563
673
  details;
564
674
  constructor(rule, details, message) {
@@ -602,6 +712,7 @@ var DEFAULT_SAFEGUARD_CONFIG = {
602
712
  };
603
713
 
604
714
  exports.ALL_NAVI_ASSETS = ALL_NAVI_ASSETS;
715
+ exports.BORROW_FEE_BPS = BORROW_FEE_BPS;
605
716
  exports.BPS_DENOMINATOR = BPS_DENOMINATOR;
606
717
  exports.CLOCK_ID = CLOCK_ID;
607
718
  exports.COIN_REGISTRY = COIN_REGISTRY;
@@ -618,12 +729,14 @@ exports.MANIFEST_TYPE = MANIFEST_TYPE;
618
729
  exports.MIST_PER_SUI = MIST_PER_SUI;
619
730
  exports.NAVX_TYPE = NAVX_TYPE;
620
731
  exports.OUTBOUND_OPS = OUTBOUND_OPS;
732
+ exports.OVERLAY_FEE_RATE = OVERLAY_FEE_RATE;
733
+ exports.SAVE_FEE_BPS = SAVE_FEE_BPS;
621
734
  exports.STABLE_ASSETS = STABLE_ASSETS;
622
735
  exports.SUI_DECIMALS = SUI_DECIMALS;
623
736
  exports.SUI_TYPE = SUI_TYPE;
624
737
  exports.SUPPORTED_ASSETS = SUPPORTED_ASSETS;
625
738
  exports.SafeguardError = SafeguardError;
626
- exports.T2000Error = T2000Error;
739
+ exports.T2000_OVERLAY_FEE_WALLET = T2000_OVERLAY_FEE_WALLET;
627
740
  exports.TOKEN_MAP = TOKEN_MAP;
628
741
  exports.USDC_DECIMALS = USDC_DECIMALS;
629
742
  exports.USDC_TYPE = USDC_TYPE;
@@ -633,7 +746,8 @@ exports.USDT_TYPE = USDT_TYPE;
633
746
  exports.WAL_TYPE = WAL_TYPE;
634
747
  exports.WBTC_TYPE = WBTC_TYPE;
635
748
  exports.ZkLoginSigner = ZkLoginSigner;
636
- exports.addCollectFeeToTx = addCollectFeeToTx;
749
+ exports.addFeeTransfer = addFeeTransfer;
750
+ exports.buildSwapTx = buildSwapTx;
637
751
  exports.calculateFee = calculateFee;
638
752
  exports.classifyAction = classifyAction;
639
753
  exports.classifyLabel = classifyLabel;
@@ -642,6 +756,7 @@ exports.extractTransferDetails = extractTransferDetails;
642
756
  exports.extractTxCommands = extractTxCommands;
643
757
  exports.extractTxSender = extractTxSender;
644
758
  exports.fallbackLabel = fallbackLabel;
759
+ exports.findSwapRoute = findSwapRoute;
645
760
  exports.formatAssetAmount = formatAssetAmount;
646
761
  exports.formatSui = formatSui;
647
762
  exports.formatUsd = formatUsd;