@t2000/sdk 0.11.1 → 0.13.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.
@@ -148,6 +148,7 @@ interface GasReserve {
148
148
  interface BalanceResponse {
149
149
  available: number;
150
150
  savings: number;
151
+ debt: number;
151
152
  gasReserve: GasReserve;
152
153
  total: number;
153
154
  assets: Record<string, number>;
@@ -159,6 +160,7 @@ interface SendResult {
159
160
  tx: string;
160
161
  amount: number;
161
162
  to: string;
163
+ contactName?: string;
162
164
  gasCost: number;
163
165
  gasCostUnit: string;
164
166
  gasMethod: GasMethod;
@@ -148,6 +148,7 @@ interface GasReserve {
148
148
  interface BalanceResponse {
149
149
  available: number;
150
150
  savings: number;
151
+ debt: number;
151
152
  gasReserve: GasReserve;
152
153
  total: number;
153
154
  assets: Record<string, number>;
@@ -159,6 +160,7 @@ interface SendResult {
159
160
  tx: string;
160
161
  amount: number;
161
162
  to: string;
163
+ contactName?: string;
162
164
  gasCost: number;
163
165
  gasCostUnit: string;
164
166
  gasMethod: GasMethod;
package/dist/index.cjs CHANGED
@@ -405,6 +405,7 @@ async function queryBalance(client, address) {
405
405
  return {
406
406
  available: totalStables,
407
407
  savings,
408
+ debt: 0,
408
409
  gasReserve: {
409
410
  sui: suiAmount,
410
411
  usdEquiv
@@ -2698,6 +2699,83 @@ var SafeguardEnforcer = class {
2698
2699
  }
2699
2700
  }
2700
2701
  };
2702
+ var RESERVED_NAMES = /* @__PURE__ */ new Set(["to", "all", "address"]);
2703
+ var ContactManager = class {
2704
+ contacts = {};
2705
+ filePath;
2706
+ dir;
2707
+ constructor(configDir) {
2708
+ this.dir = configDir ?? path.join(os.homedir(), ".t2000");
2709
+ this.filePath = path.join(this.dir, "contacts.json");
2710
+ this.load();
2711
+ }
2712
+ load() {
2713
+ try {
2714
+ if (fs.existsSync(this.filePath)) {
2715
+ this.contacts = JSON.parse(fs.readFileSync(this.filePath, "utf-8"));
2716
+ }
2717
+ } catch {
2718
+ this.contacts = {};
2719
+ }
2720
+ }
2721
+ save() {
2722
+ if (!fs.existsSync(this.dir)) fs.mkdirSync(this.dir, { recursive: true });
2723
+ fs.writeFileSync(this.filePath, JSON.stringify(this.contacts, null, 2));
2724
+ }
2725
+ add(name, address) {
2726
+ this.validateName(name);
2727
+ const normalized = validateAddress(address);
2728
+ const key = name.toLowerCase();
2729
+ const existed = key in this.contacts;
2730
+ this.contacts[key] = { name, address: normalized };
2731
+ this.save();
2732
+ return { action: existed ? "updated" : "added" };
2733
+ }
2734
+ remove(name) {
2735
+ const key = name.toLowerCase();
2736
+ if (!(key in this.contacts)) return false;
2737
+ delete this.contacts[key];
2738
+ this.save();
2739
+ return true;
2740
+ }
2741
+ get(name) {
2742
+ this.load();
2743
+ return this.contacts[name.toLowerCase()];
2744
+ }
2745
+ list() {
2746
+ this.load();
2747
+ return Object.values(this.contacts);
2748
+ }
2749
+ resolve(nameOrAddress) {
2750
+ this.load();
2751
+ if (nameOrAddress.startsWith("0x") && nameOrAddress.length >= 42) {
2752
+ return { address: validateAddress(nameOrAddress) };
2753
+ }
2754
+ const contact = this.contacts[nameOrAddress.toLowerCase()];
2755
+ if (contact) {
2756
+ return { address: contact.address, contactName: contact.name };
2757
+ }
2758
+ throw new T2000Error(
2759
+ "CONTACT_NOT_FOUND",
2760
+ `"${nameOrAddress}" is not a valid Sui address or saved contact.
2761
+ Add it: t2000 contacts add ${nameOrAddress} 0x...`
2762
+ );
2763
+ }
2764
+ validateName(name) {
2765
+ if (name.startsWith("0x")) {
2766
+ throw new T2000Error("INVALID_CONTACT_NAME", "Contact names cannot start with 0x");
2767
+ }
2768
+ if (!/^[a-zA-Z0-9_]+$/.test(name)) {
2769
+ throw new T2000Error("INVALID_CONTACT_NAME", "Contact names can only contain letters, numbers, and underscores");
2770
+ }
2771
+ if (name.length > 32) {
2772
+ throw new T2000Error("INVALID_CONTACT_NAME", "Contact names must be 32 characters or fewer");
2773
+ }
2774
+ if (RESERVED_NAMES.has(name.toLowerCase())) {
2775
+ throw new T2000Error("INVALID_CONTACT_NAME", `"${name}" is a reserved name and cannot be used as a contact`);
2776
+ }
2777
+ }
2778
+ };
2701
2779
  var DEFAULT_CONFIG_DIR = path.join(os.homedir(), ".t2000");
2702
2780
  var T2000 = class _T2000 extends eventemitter3.EventEmitter {
2703
2781
  keypair;
@@ -2705,6 +2783,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
2705
2783
  _address;
2706
2784
  registry;
2707
2785
  enforcer;
2786
+ contacts;
2708
2787
  constructor(keypair, client, registry, configDir) {
2709
2788
  super();
2710
2789
  this.keypair = keypair;
@@ -2713,6 +2792,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
2713
2792
  this.registry = registry ?? _T2000.createDefaultRegistry(client);
2714
2793
  this.enforcer = new SafeguardEnforcer(configDir);
2715
2794
  this.enforcer.load();
2795
+ this.contacts = new ContactManager(configDir);
2716
2796
  }
2717
2797
  static createDefaultRegistry(client) {
2718
2798
  const registry = new ProtocolRegistry();
@@ -2792,8 +2872,9 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
2792
2872
  if (!(asset in SUPPORTED_ASSETS)) {
2793
2873
  throw new T2000Error("ASSET_NOT_SUPPORTED", `Asset ${asset} is not supported`);
2794
2874
  }
2875
+ const resolved = this.contacts.resolve(params.to);
2795
2876
  const sendAmount = params.amount;
2796
- const sendTo = params.to;
2877
+ const sendTo = resolved.address;
2797
2878
  const gasResult = await executeWithGas(
2798
2879
  this.client,
2799
2880
  this.keypair,
@@ -2807,7 +2888,8 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
2807
2888
  success: true,
2808
2889
  tx: gasResult.digest,
2809
2890
  amount: sendAmount,
2810
- to: params.to,
2891
+ to: resolved.address,
2892
+ contactName: resolved.contactName,
2811
2893
  gasCost: gasResult.gasCostSui,
2812
2894
  gasCostUnit: "SUI",
2813
2895
  gasMethod: gasResult.gasMethod,
@@ -2819,8 +2901,10 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
2819
2901
  try {
2820
2902
  const positions = await this.positions();
2821
2903
  const savings = positions.positions.filter((p) => p.type === "save").reduce((sum, p) => sum + p.amount, 0);
2904
+ const debt = positions.positions.filter((p) => p.type === "borrow").reduce((sum, p) => sum + p.amount, 0);
2822
2905
  bal.savings = savings;
2823
- bal.total = bal.available + savings + bal.gasReserve.usdEquiv;
2906
+ bal.debt = debt;
2907
+ bal.total = bal.available + savings - debt + bal.gasReserve.usdEquiv;
2824
2908
  } catch {
2825
2909
  }
2826
2910
  return bal;
@@ -3914,6 +3998,7 @@ var allDescriptors = [
3914
3998
  exports.BPS_DENOMINATOR = BPS_DENOMINATOR;
3915
3999
  exports.CLOCK_ID = CLOCK_ID;
3916
4000
  exports.CetusAdapter = CetusAdapter;
4001
+ exports.ContactManager = ContactManager;
3917
4002
  exports.DEFAULT_NETWORK = DEFAULT_NETWORK;
3918
4003
  exports.DEFAULT_SAFEGUARD_CONFIG = DEFAULT_SAFEGUARD_CONFIG;
3919
4004
  exports.MIST_PER_SUI = MIST_PER_SUI;