@t2000/sdk 0.18.29 → 0.18.31

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/index.d.cts CHANGED
@@ -620,6 +620,9 @@ interface GasExecutionResult {
620
620
  * 2. Auto-topup (swap USDC→SUI, then self-fund)
621
621
  * 3. Gas Station sponsored (fallback)
622
622
  * 4. Fail with INSUFFICIENT_GAS
623
+ *
624
+ * After every successful transaction, proactively tops up SUI if it
625
+ * dropped below threshold — so the user never hits a "no gas" wall.
623
626
  */
624
627
  declare function executeWithGas(client: SuiJsonRpcClient, keypair: Ed25519Keypair, buildTx: () => Transaction | Promise<Transaction>, options?: {
625
628
  metadata?: TxMetadata;
@@ -634,11 +637,9 @@ interface AutoTopUpResult {
634
637
  }
635
638
  declare function shouldAutoTopUp(client: SuiJsonRpcClient, address: string): Promise<boolean>;
636
639
  /**
637
- * Self-fund a USDC→SUI swap to replenish gas.
638
- *
639
- * Uses the agent's remaining SUI to pay for the swap gas (~0.007 SUI).
640
- * This avoids the chicken-and-egg problem of needing gas station sponsorship
641
- * to get gas, and works even when the gas station is down.
640
+ * Swap USDC→SUI to replenish gas. Tries self-funding first; if the agent
641
+ * doesn't have enough SUI to pay for the swap itself, falls back to
642
+ * gas station sponsorship eliminating the chicken-and-egg problem.
642
643
  */
643
644
  declare function executeAutoTopUp(client: SuiJsonRpcClient, keypair: Ed25519Keypair): Promise<AutoTopUpResult>;
644
645
 
package/dist/index.d.ts CHANGED
@@ -620,6 +620,9 @@ interface GasExecutionResult {
620
620
  * 2. Auto-topup (swap USDC→SUI, then self-fund)
621
621
  * 3. Gas Station sponsored (fallback)
622
622
  * 4. Fail with INSUFFICIENT_GAS
623
+ *
624
+ * After every successful transaction, proactively tops up SUI if it
625
+ * dropped below threshold — so the user never hits a "no gas" wall.
623
626
  */
624
627
  declare function executeWithGas(client: SuiJsonRpcClient, keypair: Ed25519Keypair, buildTx: () => Transaction | Promise<Transaction>, options?: {
625
628
  metadata?: TxMetadata;
@@ -634,11 +637,9 @@ interface AutoTopUpResult {
634
637
  }
635
638
  declare function shouldAutoTopUp(client: SuiJsonRpcClient, address: string): Promise<boolean>;
636
639
  /**
637
- * Self-fund a USDC→SUI swap to replenish gas.
638
- *
639
- * Uses the agent's remaining SUI to pay for the swap gas (~0.007 SUI).
640
- * This avoids the chicken-and-egg problem of needing gas station sponsorship
641
- * to get gas, and works even when the gas station is down.
640
+ * Swap USDC→SUI to replenish gas. Tries self-funding first; if the agent
641
+ * doesn't have enough SUI to pay for the swap itself, falls back to
642
+ * gas station sponsorship eliminating the chicken-and-egg problem.
642
643
  */
643
644
  declare function executeAutoTopUp(client: SuiJsonRpcClient, keypair: Ed25519Keypair): Promise<AutoTopUpResult>;
644
645
 
package/dist/index.js CHANGED
@@ -55977,49 +55977,6 @@ function solveHashcash(challenge) {
55977
55977
  }
55978
55978
  }
55979
55979
 
55980
- // src/gas/autoTopUp.ts
55981
- var AUTO_TOPUP_MIN_SUI_FOR_GAS = 5000000n;
55982
- async function shouldAutoTopUp(client, address) {
55983
- const [suiBalance, usdcBalance] = await Promise.all([
55984
- client.getBalance({ owner: address, coinType: SUPPORTED_ASSETS.SUI.type }),
55985
- client.getBalance({ owner: address, coinType: SUPPORTED_ASSETS.USDC.type })
55986
- ]);
55987
- const suiRaw = BigInt(suiBalance.totalBalance);
55988
- const usdcRaw = BigInt(usdcBalance.totalBalance);
55989
- return suiRaw < AUTO_TOPUP_THRESHOLD && suiRaw >= AUTO_TOPUP_MIN_SUI_FOR_GAS && usdcRaw >= AUTO_TOPUP_MIN_USDC;
55990
- }
55991
- async function executeAutoTopUp(client, keypair) {
55992
- const address = keypair.getPublicKey().toSuiAddress();
55993
- const topupAmountHuman = Number(AUTO_TOPUP_AMOUNT) / 1e6;
55994
- const { tx } = await buildSwapTx({
55995
- client,
55996
- address,
55997
- fromAsset: "USDC",
55998
- toAsset: "SUI",
55999
- amount: topupAmountHuman
56000
- });
56001
- const result = await client.signAndExecuteTransaction({
56002
- signer: keypair,
56003
- transaction: tx,
56004
- options: { showEffects: true, showBalanceChanges: true }
56005
- });
56006
- await client.waitForTransaction({ digest: result.digest });
56007
- let suiReceived = 0;
56008
- if (result.balanceChanges) {
56009
- for (const change of result.balanceChanges) {
56010
- if (change.coinType === SUPPORTED_ASSETS.SUI.type && change.owner && typeof change.owner === "object" && "AddressOwner" in change.owner && change.owner.AddressOwner === address) {
56011
- suiReceived += Number(change.amount) / Number(MIST_PER_SUI);
56012
- }
56013
- }
56014
- }
56015
- return {
56016
- success: true,
56017
- tx: result.digest,
56018
- usdcSpent: topupAmountHuman,
56019
- suiReceived: Math.abs(suiReceived)
56020
- };
56021
- }
56022
-
56023
55980
  // src/gas/gasStation.ts
56024
55981
  async function requestGasSponsorship(txJson, sender, type, txBcsBytes) {
56025
55982
  const payload = { sender, type };
@@ -56082,6 +56039,83 @@ async function getGasStatus(address) {
56082
56039
  return await res.json();
56083
56040
  }
56084
56041
 
56042
+ // src/gas/autoTopUp.ts
56043
+ async function shouldAutoTopUp(client, address) {
56044
+ const [suiBalance, usdcBalance] = await Promise.all([
56045
+ client.getBalance({ owner: address, coinType: SUPPORTED_ASSETS.SUI.type }),
56046
+ client.getBalance({ owner: address, coinType: SUPPORTED_ASSETS.USDC.type })
56047
+ ]);
56048
+ const suiRaw = BigInt(suiBalance.totalBalance);
56049
+ const usdcRaw = BigInt(usdcBalance.totalBalance);
56050
+ return suiRaw < AUTO_TOPUP_THRESHOLD && usdcRaw >= AUTO_TOPUP_MIN_USDC;
56051
+ }
56052
+ async function executeAutoTopUp(client, keypair) {
56053
+ const address = keypair.getPublicKey().toSuiAddress();
56054
+ const topupAmountHuman = Number(AUTO_TOPUP_AMOUNT) / 1e6;
56055
+ const { tx } = await buildSwapTx({
56056
+ client,
56057
+ address,
56058
+ fromAsset: "USDC",
56059
+ toAsset: "SUI",
56060
+ amount: topupAmountHuman
56061
+ });
56062
+ tx.setSender(address);
56063
+ let result;
56064
+ try {
56065
+ result = await client.signAndExecuteTransaction({
56066
+ signer: keypair,
56067
+ transaction: tx,
56068
+ options: { showEffects: true, showBalanceChanges: true }
56069
+ });
56070
+ } catch {
56071
+ const { tx: freshTx } = await buildSwapTx({
56072
+ client,
56073
+ address,
56074
+ fromAsset: "USDC",
56075
+ toAsset: "SUI",
56076
+ amount: topupAmountHuman
56077
+ });
56078
+ freshTx.setSender(address);
56079
+ let txJson;
56080
+ let txBcsBase64;
56081
+ try {
56082
+ txJson = freshTx.serialize();
56083
+ } catch {
56084
+ const bcsBytes = await freshTx.build({ client });
56085
+ txBcsBase64 = Buffer.from(bcsBytes).toString("base64");
56086
+ }
56087
+ const sponsored = await requestGasSponsorship(
56088
+ txJson ?? "",
56089
+ address,
56090
+ "auto-topup",
56091
+ txBcsBase64
56092
+ );
56093
+ const sponsoredTxBytes = Buffer.from(sponsored.txBytes, "base64");
56094
+ const { signature: agentSig } = await keypair.signTransaction(sponsoredTxBytes);
56095
+ result = await client.executeTransactionBlock({
56096
+ transactionBlock: sponsored.txBytes,
56097
+ signature: [agentSig, sponsored.sponsorSignature],
56098
+ options: { showEffects: true, showBalanceChanges: true }
56099
+ });
56100
+ reportGasUsage(address, result.digest, 0, 0, "auto-topup");
56101
+ }
56102
+ await client.waitForTransaction({ digest: result.digest });
56103
+ let suiReceived = 0;
56104
+ if (result.balanceChanges) {
56105
+ for (const change of result.balanceChanges) {
56106
+ if (change.coinType === SUPPORTED_ASSETS.SUI.type && change.owner && typeof change.owner === "object" && "AddressOwner" in change.owner && change.owner.AddressOwner === address) {
56107
+ suiReceived += Number(change.amount) / Number(MIST_PER_SUI);
56108
+ }
56109
+ }
56110
+ }
56111
+ return {
56112
+ success: true,
56113
+ tx: result.digest,
56114
+ usdcSpent: topupAmountHuman,
56115
+ suiReceived: Math.abs(suiReceived)
56116
+ };
56117
+ }
56118
+
56085
56119
  // src/gas/manager.ts
56086
56120
  function extractGasCost(effects) {
56087
56121
  if (!effects?.gasUsed) return 0;
@@ -56172,6 +56206,17 @@ async function executeWithGas(client, keypair, buildTx, options) {
56172
56206
  if (options?.enforcer && options?.metadata) {
56173
56207
  options.enforcer.check(options.metadata);
56174
56208
  }
56209
+ const result = await resolveGas(client, keypair, buildTx);
56210
+ try {
56211
+ const address = keypair.getPublicKey().toSuiAddress();
56212
+ if (await shouldAutoTopUp(client, address)) {
56213
+ await executeAutoTopUp(client, keypair);
56214
+ }
56215
+ } catch {
56216
+ }
56217
+ return result;
56218
+ }
56219
+ async function resolveGas(client, keypair, buildTx) {
56175
56220
  const errors = [];
56176
56221
  try {
56177
56222
  const tx = await buildTx();
@@ -57079,13 +57124,6 @@ To access invested funds: t2000 invest sell ${params.amount} ${asset}`,
57079
57124
  trackedCostBasis[pos.asset] = (trackedCostBasis[pos.asset] ?? 0) + pos.costBasis;
57080
57125
  if (pos.earning) earningAssetSet.add(pos.asset);
57081
57126
  }
57082
- for (const key of this.portfolio.getAllStrategyKeys()) {
57083
- for (const sp of this.portfolio.getStrategyPositions(key)) {
57084
- if (!(sp.asset in INVESTMENT_ASSETS)) continue;
57085
- trackedAmounts[sp.asset] = (trackedAmounts[sp.asset] ?? 0) + sp.totalAmount;
57086
- trackedCostBasis[sp.asset] = (trackedCostBasis[sp.asset] ?? 0) + sp.costBasis;
57087
- }
57088
- }
57089
57127
  let investmentValue = 0;
57090
57128
  let investmentCostBasis = 0;
57091
57129
  let trackedValue = 0;
@@ -58895,13 +58933,38 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
58895
58933
  strategyPositions[key] = enrichedStrat;
58896
58934
  }
58897
58935
  }
58898
- const allPositions = [...enriched, ...Object.values(strategyPositions).flat()];
58899
- const totalInvested = allPositions.reduce((sum, p) => sum + p.costBasis, 0);
58900
- const totalValue = allPositions.reduce((sum, p) => sum + p.currentValue, 0);
58936
+ const strategyAmountByAsset = {};
58937
+ for (const strats of Object.values(strategyPositions)) {
58938
+ for (const sp of strats) {
58939
+ const prev = strategyAmountByAsset[sp.asset] ?? { amount: 0, costBasis: 0 };
58940
+ strategyAmountByAsset[sp.asset] = {
58941
+ amount: prev.amount + sp.totalAmount,
58942
+ costBasis: prev.costBasis + sp.costBasis
58943
+ };
58944
+ }
58945
+ }
58946
+ const directOnly = enriched.map((pos) => {
58947
+ const strat = strategyAmountByAsset[pos.asset];
58948
+ if (!strat) return pos;
58949
+ const directAmt = pos.totalAmount - strat.amount;
58950
+ if (directAmt <= 1e-6) return null;
58951
+ const directCost = pos.costBasis - strat.costBasis;
58952
+ const currentValue = directAmt * (pos.currentPrice ?? 0);
58953
+ return {
58954
+ ...pos,
58955
+ totalAmount: directAmt,
58956
+ costBasis: directCost,
58957
+ currentValue,
58958
+ unrealizedPnL: currentValue - directCost,
58959
+ unrealizedPnLPct: directCost > 0 ? (currentValue - directCost) / directCost * 100 : 0
58960
+ };
58961
+ }).filter((p) => p !== null);
58962
+ const totalInvested = enriched.reduce((sum, p) => sum + p.costBasis, 0);
58963
+ const totalValue = enriched.reduce((sum, p) => sum + p.currentValue, 0);
58901
58964
  const totalUnrealizedPnL = totalValue - totalInvested;
58902
58965
  const totalUnrealizedPnLPct = totalInvested > 0 ? totalUnrealizedPnL / totalInvested * 100 : 0;
58903
58966
  const result = {
58904
- positions: enriched,
58967
+ positions: directOnly,
58905
58968
  totalInvested,
58906
58969
  totalValue,
58907
58970
  unrealizedPnL: totalUnrealizedPnL,
@@ -59253,16 +59316,7 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
59253
59316
  async getFreeBalance(asset) {
59254
59317
  if (!(asset in INVESTMENT_ASSETS)) return Infinity;
59255
59318
  const pos = this.portfolio.getPosition(asset);
59256
- const directAmount = pos && pos.totalAmount > 0 && !pos.earning ? pos.totalAmount : 0;
59257
- let strategyTotal = 0;
59258
- for (const key of this.portfolio.getAllStrategyKeys()) {
59259
- for (const sp of this.portfolio.getStrategyPositions(key)) {
59260
- if (sp.asset === asset && sp.totalAmount > 0) {
59261
- strategyTotal += sp.totalAmount;
59262
- }
59263
- }
59264
- }
59265
- const walletInvested = Math.max(directAmount, strategyTotal);
59319
+ const walletInvested = pos && pos.totalAmount > 0 && !pos.earning ? pos.totalAmount : 0;
59266
59320
  if (walletInvested <= 0) return Infinity;
59267
59321
  const assetInfo = SUPPORTED_ASSETS[asset];
59268
59322
  const balance = await this.client.getBalance({ owner: this._address, coinType: assetInfo.type });