@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.cjs +118 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -5
- package/dist/index.d.ts +6 -5
- package/dist/index.js +118 -64
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
*
|
|
638
|
-
*
|
|
639
|
-
*
|
|
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
|
-
*
|
|
638
|
-
*
|
|
639
|
-
*
|
|
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
|
|
58899
|
-
const
|
|
58900
|
-
|
|
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:
|
|
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
|
|
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 });
|