@t2000/sdk 1.0.1 → 1.1.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/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,17 @@ 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
+ process.env.T2000_PACKAGE_ID ?? "0xd775fcc66eae26797654d435d751dea56b82eeb999de51fd285348e573b968ad";
221
+ process.env.T2000_CONFIG_ID ?? "0x08ba26f0d260b5edf6a19c71492b3eb914906a7419baf2df1426765157e5862a";
222
+ var T2000_OVERLAY_FEE_WALLET = process.env.T2000_OVERLAY_FEE_WALLET ?? "0x5366efbf2b4fe5767fe2e78eb197aa5f5d138d88ac3333fbf3f80a1927da473a";
173
223
  var DEFAULT_NETWORK = "mainnet";
174
224
  process.env.T2000_API_URL ?? "https://api.t2000.ai";
175
225
  var GAS_RESERVE_MIN = 0.05;
226
+ init_errors();
176
227
  function validateAddress(address) {
177
228
  const normalized = utils.normalizeSuiAddress(address);
178
229
  if (!utils.isValidSuiAddress(normalized)) {
179
- throw new T2000Error("INVALID_ADDRESS", `Invalid Sui address: ${address}`);
230
+ throw new exports.T2000Error("INVALID_ADDRESS", `Invalid Sui address: ${address}`);
180
231
  }
181
232
  return normalized;
182
233
  }
@@ -525,11 +576,12 @@ function fromBase64(b64) {
525
576
  // src/protocols/protocolFee.ts
526
577
  var FEE_RATES = {
527
578
  save: SAVE_FEE_BPS,
528
- borrow: BORROW_FEE_BPS
529
- };
530
- var OP_CODES = {
531
- save: 0,
532
- borrow: 2
579
+ borrow: BORROW_FEE_BPS,
580
+ // Swap uses Cetus's overlay-fee mechanism (taken from output by the aggregator
581
+ // and transferred to `overlayFee.receiver`). We list the rate here for display
582
+ // / quote calculations only — `addFeeTransfer` is NOT called for swaps.
583
+ swap: 10n
584
+ // 0.1%
533
585
  };
534
586
  function calculateFee(operation, amount) {
535
587
  const bps = FEE_RATES[operation];
@@ -542,23 +594,83 @@ function calculateFee(operation, amount) {
542
594
  rawAmount
543
595
  };
544
596
  }
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
- ]
597
+ function addFeeTransfer(tx, paymentCoin, feeBps, receiver, amount) {
598
+ if (feeBps <= 0n) return;
599
+ if (amount <= 0) return;
600
+ const feeAmount = amount * Number(feeBps) / Number(BPS_DENOMINATOR);
601
+ const rawFee = usdcToRaw(feeAmount);
602
+ if (rawFee <= 0n) return;
603
+ const [feeCoin] = tx.splitCoins(paymentCoin, [tx.pure.u64(rawFee)]);
604
+ tx.transferObjects([feeCoin], tx.pure.address(receiver));
605
+ }
606
+ var OVERLAY_FEE_RATE = 1e-3;
607
+ var clientCache = /* @__PURE__ */ new Map();
608
+ function getClient(walletAddress, overlayFee) {
609
+ const rate = overlayFee?.rate ?? 0;
610
+ const receiver = overlayFee?.receiver ?? "";
611
+ const key = `${walletAddress}|${rate}|${receiver}`;
612
+ const cached = clientCache.get(key);
613
+ if (cached) return cached;
614
+ const client = new aggregatorSdk.AggregatorClient({
615
+ signer: walletAddress,
616
+ env: aggregatorSdk.Env.Mainnet,
617
+ ...rate > 0 && receiver ? { overlayFeeRate: rate, overlayFeeReceiver: receiver } : {}
618
+ });
619
+ clientCache.set(key, client);
620
+ return client;
621
+ }
622
+ async function findSwapRoute(params) {
623
+ const client = getClient(params.walletAddress, params.overlayFee);
624
+ const findParams = {
625
+ from: params.from,
626
+ target: params.to,
627
+ amount: params.amount.toString(),
628
+ byAmountIn: params.byAmountIn
629
+ };
630
+ const routerData = await client.findRouters(findParams);
631
+ if (!routerData) return null;
632
+ if (routerData.insufficientLiquidity) {
633
+ return {
634
+ routerData,
635
+ amountIn: routerData.amountIn.toString(),
636
+ amountOut: routerData.amountOut.toString(),
637
+ byAmountIn: params.byAmountIn,
638
+ priceImpact: normalizePriceImpact(routerData.deviationRatio),
639
+ insufficientLiquidity: true
640
+ };
641
+ }
642
+ if (routerData.error) {
643
+ const { T2000Error: T2000Error2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
644
+ throw new T2000Error2("SWAP_FAILED", `Cetus routing error: ${routerData.error.msg} (code ${routerData.error.code})`);
645
+ }
646
+ return {
647
+ routerData,
648
+ amountIn: routerData.amountIn.toString(),
649
+ amountOut: routerData.amountOut.toString(),
650
+ byAmountIn: params.byAmountIn,
651
+ priceImpact: normalizePriceImpact(routerData.deviationRatio),
652
+ insufficientLiquidity: false
653
+ };
654
+ }
655
+ function normalizePriceImpact(value) {
656
+ const n = typeof value === "number" ? value : Number(value);
657
+ return Number.isFinite(n) ? n : 0;
658
+ }
659
+ async function buildSwapTx(params) {
660
+ const client = getClient(params.walletAddress, params.overlayFee);
661
+ const clampedSlippage = Math.max(1e-3, Math.min(params.slippage, 0.05));
662
+ const outputCoin = await client.routerSwap({
663
+ router: params.route.routerData,
664
+ inputCoin: params.inputCoin,
665
+ slippage: clampedSlippage,
666
+ txb: params.tx
557
667
  });
668
+ return outputCoin;
558
669
  }
559
670
 
560
671
  // src/safeguards/errors.ts
561
- var SafeguardError = class extends T2000Error {
672
+ init_errors();
673
+ var SafeguardError = class extends exports.T2000Error {
562
674
  rule;
563
675
  details;
564
676
  constructor(rule, details, message) {
@@ -602,6 +714,7 @@ var DEFAULT_SAFEGUARD_CONFIG = {
602
714
  };
603
715
 
604
716
  exports.ALL_NAVI_ASSETS = ALL_NAVI_ASSETS;
717
+ exports.BORROW_FEE_BPS = BORROW_FEE_BPS;
605
718
  exports.BPS_DENOMINATOR = BPS_DENOMINATOR;
606
719
  exports.CLOCK_ID = CLOCK_ID;
607
720
  exports.COIN_REGISTRY = COIN_REGISTRY;
@@ -618,12 +731,14 @@ exports.MANIFEST_TYPE = MANIFEST_TYPE;
618
731
  exports.MIST_PER_SUI = MIST_PER_SUI;
619
732
  exports.NAVX_TYPE = NAVX_TYPE;
620
733
  exports.OUTBOUND_OPS = OUTBOUND_OPS;
734
+ exports.OVERLAY_FEE_RATE = OVERLAY_FEE_RATE;
735
+ exports.SAVE_FEE_BPS = SAVE_FEE_BPS;
621
736
  exports.STABLE_ASSETS = STABLE_ASSETS;
622
737
  exports.SUI_DECIMALS = SUI_DECIMALS;
623
738
  exports.SUI_TYPE = SUI_TYPE;
624
739
  exports.SUPPORTED_ASSETS = SUPPORTED_ASSETS;
625
740
  exports.SafeguardError = SafeguardError;
626
- exports.T2000Error = T2000Error;
741
+ exports.T2000_OVERLAY_FEE_WALLET = T2000_OVERLAY_FEE_WALLET;
627
742
  exports.TOKEN_MAP = TOKEN_MAP;
628
743
  exports.USDC_DECIMALS = USDC_DECIMALS;
629
744
  exports.USDC_TYPE = USDC_TYPE;
@@ -633,7 +748,8 @@ exports.USDT_TYPE = USDT_TYPE;
633
748
  exports.WAL_TYPE = WAL_TYPE;
634
749
  exports.WBTC_TYPE = WBTC_TYPE;
635
750
  exports.ZkLoginSigner = ZkLoginSigner;
636
- exports.addCollectFeeToTx = addCollectFeeToTx;
751
+ exports.addFeeTransfer = addFeeTransfer;
752
+ exports.buildSwapTx = buildSwapTx;
637
753
  exports.calculateFee = calculateFee;
638
754
  exports.classifyAction = classifyAction;
639
755
  exports.classifyLabel = classifyLabel;
@@ -642,6 +758,7 @@ exports.extractTransferDetails = extractTransferDetails;
642
758
  exports.extractTxCommands = extractTxCommands;
643
759
  exports.extractTxSender = extractTxSender;
644
760
  exports.fallbackLabel = fallbackLabel;
761
+ exports.findSwapRoute = findSwapRoute;
645
762
  exports.formatAssetAmount = formatAssetAmount;
646
763
  exports.formatSui = formatSui;
647
764
  exports.formatUsd = formatUsd;