@t2000/sdk 0.19.20 → 0.19.22

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.js CHANGED
@@ -9,7 +9,6 @@ import { access, mkdir, writeFile, readFile } from 'fs/promises';
9
9
  import { join, dirname, resolve } from 'path';
10
10
  import { homedir } from 'os';
11
11
  import { getPools, getLendingPositions, getHealthFactor as getHealthFactor$1, depositCoinPTB, withdrawCoinPTB, borrowCoinPTB, repayCoinPTB, getUserAvailableLendingRewards, summaryLendingRewards, claimLendingRewardsPTB, updateOraclePriceBeforeUserOperationPTB } from '@naviprotocol/lending';
12
- import { bcs } from '@mysten/sui/bcs';
13
12
  import { AggregatorClient, Env } from '@cetusprotocol/aggregator-sdk';
14
13
  import { SuilendClient, LENDING_MARKET_ID, LENDING_MARKET_TYPE } from '@suilend/sdk/client';
15
14
  import { initializeSuilend, initializeObligations } from '@suilend/sdk/lib/initialize';
@@ -133,18 +132,6 @@ var PERPS_MARKETS = ["SUI-PERP"];
133
132
  var DEFAULT_MAX_LEVERAGE = 5;
134
133
  var DEFAULT_MAX_POSITION_SIZE = 1e3;
135
134
  var GAS_RESERVE_MIN = 0.05;
136
- var SENTINEL = {
137
- PACKAGE: "0x88b83f36dafcd5f6dcdcf1d2cb5889b03f61264ab3cee9cae35db7aa940a21b7",
138
- AGENT_REGISTRY: "0xc47564f5f14c12b31e0dfa1a3dc99a6380a1edf8929c28cb0eaa3359c8db36ac",
139
- ENCLAVE: "0xfb1261aeb9583514cb1341a548a5ec12d1231bd96af22215f1792617a93e1213",
140
- PROTOCOL_CONFIG: "0x2fa4fa4a1dd0498612304635ff9334e1b922e78af325000e9d9c0e88adea459f",
141
- TEE_API: "https://app.suisentinel.xyz/api/consume-prompt",
142
- SENTINELS_API: "https://api.suisentinel.xyz/agents/mainnet",
143
- RANDOM: "0x8",
144
- MIN_FEE_MIST: 100000000n,
145
- // 0.1 SUI
146
- MAX_PROMPT_TOKENS: 600
147
- };
148
135
 
149
136
  // src/errors.ts
150
137
  var T2000Error = class extends Error {
@@ -557,7 +544,7 @@ async function queryBalance(client, address) {
557
544
  var SUI_TYPE = "0x2::sui::SUI";
558
545
  var KNOWN_TARGETS = [
559
546
  [/::suilend|::obligation/, "lending"],
560
- [/::navi|::incentive_v2/, "lending"],
547
+ [/::navi|::incentive_v\d+|::oracle_pro/, "lending"],
561
548
  [/::cetus|::pool/, "swap"],
562
549
  [/::deepbook/, "swap"],
563
550
  [/::transfer::public_transfer/, "send"]
@@ -711,6 +698,7 @@ function sdkOptions(client) {
711
698
  return { env: "prod", client, cacheTime: 0, disableCache: true };
712
699
  }
713
700
  async function refreshOracle(tx, client, address, options) {
701
+ if (options?.skipOracle) return;
714
702
  const origInfo = console.info;
715
703
  const origWarn = console.warn;
716
704
  console.info = (...args) => {
@@ -878,13 +866,14 @@ async function buildSaveTx(client, address, amount, options = {}) {
878
866
  const assetInfo = resolveAssetInfo(asset);
879
867
  const coins = await fetchCoins(client, address, assetInfo.type);
880
868
  if (coins.length === 0) throw new T2000Error("INSUFFICIENT_BALANCE", `No ${assetInfo.displayName} coins found`);
869
+ const totalBalance = coins.reduce((sum, c) => sum + BigInt(c.balance), 0n);
881
870
  const tx = new Transaction();
882
871
  tx.setSender(address);
883
872
  const coinObj = mergeCoins(tx, coins);
884
873
  if (options.collectFee) {
885
874
  addCollectFeeToTx(tx, coinObj, "save");
886
875
  }
887
- const rawAmount = Number(stableToRaw(amount, assetInfo.decimals));
876
+ const rawAmount = Math.min(Number(stableToRaw(amount, assetInfo.decimals)), Number(totalBalance));
888
877
  try {
889
878
  await depositCoinPTB(tx, assetInfo.type, coinObj, {
890
879
  ...sdkOptions(client),
@@ -925,6 +914,7 @@ async function buildWithdrawTx(client, address, amount, options = {}) {
925
914
  }
926
915
  async function addWithdrawToTx(tx, client, address, amount, options = {}) {
927
916
  const asset = options.asset ?? "USDC";
917
+ const sponsored = options.sponsored ?? true;
928
918
  const assetInfo = resolveAssetInfo(asset);
929
919
  const posResult = await getPositions(client, address);
930
920
  const supply = posResult.positions.find(
@@ -942,7 +932,7 @@ async function addWithdrawToTx(tx, client, address, amount, options = {}) {
942
932
  });
943
933
  return { coin, effectiveAmount: 0 };
944
934
  }
945
- await refreshOracle(tx, client, address);
935
+ await refreshOracle(tx, client, address, { skipPythUpdate: sponsored });
946
936
  try {
947
937
  const coin = await withdrawCoinPTB(tx, assetInfo.type, rawAmount, sdkOptions(client));
948
938
  return { coin, effectiveAmount };
@@ -966,8 +956,9 @@ async function addSaveToTx(tx, _client, _address, coin, options = {}) {
966
956
  }
967
957
  async function addRepayToTx(tx, client, address, coin, options = {}) {
968
958
  const asset = options.asset ?? "USDC";
959
+ const sponsored = options.sponsored ?? true;
969
960
  const assetInfo = resolveAssetInfo(asset);
970
- await refreshOracle(tx, client, address);
961
+ await refreshOracle(tx, client, address, { skipPythUpdate: sponsored });
971
962
  try {
972
963
  await repayCoinPTB(tx, assetInfo.type, coin, { env: "prod" });
973
964
  } catch (err) {
@@ -1005,12 +996,16 @@ async function buildRepayTx(client, address, amount, options = {}) {
1005
996
  const assetInfo = resolveAssetInfo(asset);
1006
997
  const coins = await fetchCoins(client, address, assetInfo.type);
1007
998
  if (coins.length === 0) throw new T2000Error("INSUFFICIENT_BALANCE", `No ${assetInfo.displayName} coins to repay with`);
999
+ const totalBalance = coins.reduce((sum, c) => sum + BigInt(c.balance), 0n);
1008
1000
  const tx = new Transaction();
1009
1001
  tx.setSender(address);
1010
1002
  const coinObj = mergeCoins(tx, coins);
1011
- const rawAmount = Number(stableToRaw(amount, assetInfo.decimals));
1003
+ const rawAmount = Math.min(Number(stableToRaw(amount, assetInfo.decimals)), Number(totalBalance));
1012
1004
  const [repayCoin] = tx.splitCoins(coinObj, [rawAmount]);
1013
- await refreshOracle(tx, client, address, { skipPythUpdate: options.sponsored });
1005
+ await refreshOracle(tx, client, address, {
1006
+ skipPythUpdate: options.sponsored,
1007
+ skipOracle: options.skipOracle
1008
+ });
1014
1009
  try {
1015
1010
  await repayCoinPTB(tx, assetInfo.type, repayCoin, {
1016
1011
  ...sdkOptions(client),
@@ -1124,206 +1119,6 @@ async function getFundStatus(client, address) {
1124
1119
  projectedMonthly: earnings.dailyEarning * 30
1125
1120
  };
1126
1121
  }
1127
- var descriptor = {
1128
- id: "sentinel",
1129
- name: "Sui Sentinel",
1130
- packages: [SENTINEL.PACKAGE],
1131
- actionMap: {
1132
- "sentinel::request_attack": "sentinel_attack",
1133
- "sentinel::consume_prompt": "sentinel_settle"
1134
- }
1135
- };
1136
- function mapAgent(raw) {
1137
- return {
1138
- id: raw.agent_id,
1139
- objectId: raw.agent_object_id,
1140
- name: raw.agent_name,
1141
- model: raw.model ?? "unknown",
1142
- systemPrompt: raw.prompt,
1143
- attackFee: BigInt(raw.cost_per_message),
1144
- prizePool: BigInt(raw.total_balance),
1145
- totalAttacks: raw.total_attacks,
1146
- successfulBreaches: raw.successful_breaches ?? 0,
1147
- state: raw.state
1148
- };
1149
- }
1150
- async function listSentinels() {
1151
- const res = await fetch(SENTINEL.SENTINELS_API);
1152
- if (!res.ok) {
1153
- throw new T2000Error("SENTINEL_API_ERROR", `Sentinel API returned ${res.status}`);
1154
- }
1155
- const data = await res.json();
1156
- if (!Array.isArray(data.agents)) {
1157
- throw new T2000Error("SENTINEL_API_ERROR", "Unexpected API response shape");
1158
- }
1159
- return data.agents.filter((a) => a.state === "active").map(mapAgent);
1160
- }
1161
- async function getSentinelInfo(client, sentinelObjectId) {
1162
- const agents = await listSentinels();
1163
- const match = agents.find((a) => a.objectId === sentinelObjectId || a.id === sentinelObjectId);
1164
- if (match) return match;
1165
- const obj = await client.getObject({
1166
- id: sentinelObjectId,
1167
- options: { showContent: true, showType: true }
1168
- });
1169
- if (!obj.data) {
1170
- throw new T2000Error("SENTINEL_NOT_FOUND", `Sentinel ${sentinelObjectId} not found on-chain`);
1171
- }
1172
- const content = obj.data.content;
1173
- if (!content || content.dataType !== "moveObject") {
1174
- throw new T2000Error("SENTINEL_NOT_FOUND", `Object ${sentinelObjectId} is not a Move object`);
1175
- }
1176
- const fields = content.fields;
1177
- return {
1178
- id: fields.id?.id ?? sentinelObjectId,
1179
- objectId: sentinelObjectId,
1180
- name: fields.name ?? "Unknown",
1181
- model: fields.model ?? "unknown",
1182
- systemPrompt: fields.system_prompt ?? "",
1183
- attackFee: BigInt(fields.cost_per_message ?? "0"),
1184
- prizePool: BigInt(fields.balance ?? "0"),
1185
- totalAttacks: Number(fields.total_attacks ?? "0"),
1186
- successfulBreaches: Number(fields.successful_breaches ?? "0"),
1187
- state: fields.state ?? "unknown"
1188
- };
1189
- }
1190
- async function requestAttack(client, signer, sentinelObjectId, feeMist) {
1191
- if (feeMist < SENTINEL.MIN_FEE_MIST) {
1192
- throw new T2000Error("INVALID_AMOUNT", `Attack fee must be at least 0.1 SUI (${SENTINEL.MIN_FEE_MIST} MIST)`);
1193
- }
1194
- const address = signer.getAddress();
1195
- const tx = new Transaction();
1196
- tx.setSender(address);
1197
- const [coin] = tx.splitCoins(tx.gas, [Number(feeMist)]);
1198
- const [attack2] = tx.moveCall({
1199
- target: `${SENTINEL.PACKAGE}::sentinel::request_attack`,
1200
- arguments: [
1201
- tx.object(SENTINEL.AGENT_REGISTRY),
1202
- tx.object(sentinelObjectId),
1203
- tx.object(SENTINEL.PROTOCOL_CONFIG),
1204
- coin,
1205
- tx.object(SENTINEL.RANDOM),
1206
- tx.object(CLOCK_ID)
1207
- ]
1208
- });
1209
- tx.transferObjects([attack2], address);
1210
- const built = await tx.build({ client });
1211
- const { signature } = await signer.signTransaction(built);
1212
- const result = await client.executeTransactionBlock({
1213
- transactionBlock: built,
1214
- signature,
1215
- options: { showObjectChanges: true, showEffects: true }
1216
- });
1217
- await client.waitForTransaction({ digest: result.digest });
1218
- const attackObj = result.objectChanges?.find(
1219
- (c) => c.type === "created" && c.objectType?.includes("::sentinel::Attack")
1220
- );
1221
- const attackObjectId = attackObj && "objectId" in attackObj ? attackObj.objectId : void 0;
1222
- if (!attackObjectId) {
1223
- throw new T2000Error("SENTINEL_TX_FAILED", "Attack object was not created \u2014 transaction may have failed");
1224
- }
1225
- return { attackObjectId, digest: result.digest };
1226
- }
1227
- async function submitPrompt(agentId, attackObjectId, prompt) {
1228
- const res = await fetch(SENTINEL.TEE_API, {
1229
- method: "POST",
1230
- headers: { "Content-Type": "application/json" },
1231
- body: JSON.stringify({
1232
- agent_id: agentId,
1233
- attack_object_id: attackObjectId,
1234
- message: prompt
1235
- })
1236
- });
1237
- if (!res.ok) {
1238
- const body = await res.text().catch(() => "");
1239
- throw new T2000Error("SENTINEL_TEE_ERROR", `TEE returned ${res.status}: ${body.slice(0, 200)}`);
1240
- }
1241
- const raw = await res.json();
1242
- const envelope = raw.response ?? raw;
1243
- const data = envelope.data ?? envelope;
1244
- const signature = raw.signature ?? data.signature;
1245
- const timestampMs = envelope.timestamp_ms ?? data.timestamp_ms;
1246
- if (typeof signature !== "string") {
1247
- throw new T2000Error("SENTINEL_TEE_ERROR", "TEE response missing signature");
1248
- }
1249
- return {
1250
- success: data.success ?? data.is_success,
1251
- score: data.score,
1252
- agentResponse: data.agent_response,
1253
- juryResponse: data.jury_response,
1254
- funResponse: data.fun_response ?? "",
1255
- signature,
1256
- timestampMs
1257
- };
1258
- }
1259
- async function settleAttack(client, signer, sentinelObjectId, attackObjectId, prompt, verdict) {
1260
- const sigBytes = Array.from(Buffer.from(verdict.signature.replace(/^0x/, ""), "hex"));
1261
- const address = signer.getAddress();
1262
- const tx = new Transaction();
1263
- tx.setSender(address);
1264
- tx.moveCall({
1265
- target: `${SENTINEL.PACKAGE}::sentinel::consume_prompt`,
1266
- arguments: [
1267
- tx.object(SENTINEL.AGENT_REGISTRY),
1268
- tx.object(SENTINEL.PROTOCOL_CONFIG),
1269
- tx.object(sentinelObjectId),
1270
- tx.pure.bool(verdict.success),
1271
- tx.pure.string(verdict.agentResponse),
1272
- tx.pure.string(verdict.juryResponse),
1273
- tx.pure.string(verdict.funResponse),
1274
- tx.pure.string(prompt),
1275
- tx.pure.u8(verdict.score),
1276
- tx.pure.u64(verdict.timestampMs),
1277
- tx.pure(bcs.vector(bcs.u8()).serialize(sigBytes)),
1278
- tx.object(SENTINEL.ENCLAVE),
1279
- tx.object(attackObjectId),
1280
- tx.object(CLOCK_ID)
1281
- ]
1282
- });
1283
- const built = await tx.build({ client });
1284
- const { signature } = await signer.signTransaction(built);
1285
- const result = await client.executeTransactionBlock({
1286
- transactionBlock: built,
1287
- signature,
1288
- options: { showEffects: true }
1289
- });
1290
- await client.waitForTransaction({ digest: result.digest });
1291
- const txSuccess = result.effects?.status?.status === "success";
1292
- return { digest: result.digest, success: txSuccess };
1293
- }
1294
- async function attack(client, signer, sentinelId, prompt, feeMist) {
1295
- const sentinel = await getSentinelInfo(client, sentinelId);
1296
- const fee = feeMist ?? sentinel.attackFee;
1297
- if (fee < SENTINEL.MIN_FEE_MIST) {
1298
- throw new T2000Error("INVALID_AMOUNT", `Attack fee must be at least 0.1 SUI`);
1299
- }
1300
- const { attackObjectId, digest: requestTx } = await requestAttack(
1301
- client,
1302
- signer,
1303
- sentinel.objectId,
1304
- fee
1305
- );
1306
- const verdict = await submitPrompt(sentinel.id, attackObjectId, prompt);
1307
- const { digest: settleTx } = await settleAttack(
1308
- client,
1309
- signer,
1310
- sentinel.objectId,
1311
- attackObjectId,
1312
- prompt,
1313
- verdict
1314
- );
1315
- const won = verdict.success && verdict.score >= 70;
1316
- return {
1317
- attackObjectId,
1318
- sentinelId: sentinel.id,
1319
- prompt,
1320
- verdict,
1321
- requestTx,
1322
- settleTx,
1323
- won,
1324
- feePaid: Number(fee) / Number(MIST_PER_SUI)
1325
- };
1326
- }
1327
1122
 
1328
1123
  // src/adapters/registry.ts
1329
1124
  var ProtocolRegistry = class {
@@ -1470,8 +1265,9 @@ var ProtocolRegistry = class {
1470
1265
  }
1471
1266
  };
1472
1267
 
1473
- // src/adapters/navi.ts
1474
- var descriptor2 = {
1268
+ // src/adapters/descriptors.ts
1269
+ var SUILEND_PACKAGE = "0xf95b06141ed4a174f239417323bde3f209b972f5930d8521ea38a52aff3a6ddf";
1270
+ var naviDescriptor = {
1475
1271
  id: "navi",
1476
1272
  name: "NAVI Protocol",
1477
1273
  packages: [],
@@ -1487,6 +1283,42 @@ var descriptor2 = {
1487
1283
  "incentive_v3::repay": "repay"
1488
1284
  }
1489
1285
  };
1286
+ var suilendDescriptor = {
1287
+ id: "suilend",
1288
+ name: "Suilend",
1289
+ packages: [SUILEND_PACKAGE],
1290
+ actionMap: {
1291
+ "lending_market::deposit_liquidity_and_mint_ctokens": "save",
1292
+ "lending_market::deposit_ctokens_into_obligation": "save",
1293
+ "lending_market::create_obligation": "save",
1294
+ "lending_market::withdraw_ctokens": "withdraw",
1295
+ "lending_market::redeem_ctokens_and_withdraw_liquidity": "withdraw",
1296
+ "lending_market::redeem_ctokens_and_withdraw_liquidity_request": "withdraw",
1297
+ "lending_market::fulfill_liquidity_request": "withdraw",
1298
+ "lending_market::unstake_sui_from_staker": "withdraw",
1299
+ "lending_market::borrow": "borrow",
1300
+ "lending_market::repay": "repay"
1301
+ }
1302
+ };
1303
+ var cetusDescriptor = {
1304
+ id: "cetus",
1305
+ name: "Cetus DEX",
1306
+ packages: [CETUS_PACKAGE],
1307
+ actionMap: {
1308
+ "router::swap": "swap",
1309
+ "router::swap_ab_bc": "swap",
1310
+ "router::swap_ab_cb": "swap",
1311
+ "router::swap_ba_bc": "swap",
1312
+ "router::swap_ba_cb": "swap"
1313
+ }
1314
+ };
1315
+ var allDescriptors = [
1316
+ naviDescriptor,
1317
+ suilendDescriptor,
1318
+ cetusDescriptor
1319
+ ];
1320
+
1321
+ // src/adapters/navi.ts
1490
1322
  var NaviAdapter = class {
1491
1323
  id = "navi";
1492
1324
  name = "NAVI Protocol";
@@ -1535,7 +1367,11 @@ var NaviAdapter = class {
1535
1367
  }
1536
1368
  async buildRepayTx(address, amount, asset, options) {
1537
1369
  const normalized = normalizeAsset(asset);
1538
- const tx = await buildRepayTx(this.client, address, amount, { asset: normalized, sponsored: options?.sponsored });
1370
+ const tx = await buildRepayTx(this.client, address, amount, {
1371
+ asset: normalized,
1372
+ sponsored: options?.sponsored,
1373
+ skipOracle: options?.skipOracle
1374
+ });
1539
1375
  return { tx };
1540
1376
  }
1541
1377
  async maxWithdraw(address, _asset) {
@@ -1762,18 +1598,6 @@ function fallbackQuote(fromAsset, amount, poolPrice) {
1762
1598
  }
1763
1599
 
1764
1600
  // src/adapters/cetus.ts
1765
- var descriptor3 = {
1766
- id: "cetus",
1767
- name: "Cetus DEX",
1768
- packages: [CETUS_PACKAGE],
1769
- actionMap: {
1770
- "router::swap": "swap",
1771
- "router::swap_ab_bc": "swap",
1772
- "router::swap_ab_cb": "swap",
1773
- "router::swap_ba_bc": "swap",
1774
- "router::swap_ba_cb": "swap"
1775
- }
1776
- };
1777
1601
  var CetusAdapter = class {
1778
1602
  id = "cetus";
1779
1603
  name = "Cetus";
@@ -1832,7 +1656,6 @@ var CetusAdapter = class {
1832
1656
  });
1833
1657
  }
1834
1658
  };
1835
- var SUILEND_PACKAGE = "0xf95b06141ed4a174f239417323bde3f209b972f5930d8521ea38a52aff3a6ddf";
1836
1659
  var MIN_HEALTH_FACTOR2 = 1.5;
1837
1660
  async function quietSuilend(fn) {
1838
1661
  const origLog = console.log;
@@ -1849,23 +1672,6 @@ async function quietSuilend(fn) {
1849
1672
  console.warn = origWarn;
1850
1673
  });
1851
1674
  }
1852
- var descriptor4 = {
1853
- id: "suilend",
1854
- name: "Suilend",
1855
- packages: [SUILEND_PACKAGE],
1856
- actionMap: {
1857
- "lending_market::deposit_liquidity_and_mint_ctokens": "save",
1858
- "lending_market::deposit_ctokens_into_obligation": "save",
1859
- "lending_market::create_obligation": "save",
1860
- "lending_market::withdraw_ctokens": "withdraw",
1861
- "lending_market::redeem_ctokens_and_withdraw_liquidity": "withdraw",
1862
- "lending_market::redeem_ctokens_and_withdraw_liquidity_request": "withdraw",
1863
- "lending_market::fulfill_liquidity_request": "withdraw",
1864
- "lending_market::unstake_sui_from_staker": "withdraw",
1865
- "lending_market::borrow": "borrow",
1866
- "lending_market::repay": "repay"
1867
- }
1868
- };
1869
1675
  var SuilendAdapter = class {
1870
1676
  id = "suilend";
1871
1677
  name = "Suilend";
@@ -2208,16 +2014,23 @@ var SuilendAdapter = class {
2208
2014
  if (obligationOwnerCaps.length === 0 || obligations.length === 0) return [];
2209
2015
  const ob = obligations[0];
2210
2016
  const rewards = [];
2017
+ const WAD = 1e18;
2211
2018
  for (const dep of ob.deposits) {
2212
- for (const rw of dep.reserve.depositsPoolRewardManager.poolRewards) {
2019
+ const urm = dep.userRewardManager;
2020
+ for (const rw of dep.reserve.depositsPoolRewardManager?.poolRewards ?? []) {
2213
2021
  if (rw.endTimeMs <= Date.now()) continue;
2022
+ let claimableAmount = 0;
2023
+ const userReward = urm?.rewards?.[rw.rewardIndex];
2024
+ if (userReward?.earnedRewards) {
2025
+ claimableAmount = Number(BigInt(userReward.earnedRewards.value.toString())) / WAD / 10 ** rw.mintDecimals;
2026
+ }
2214
2027
  const symbol = rw.symbol || rw.coinType.split("::").pop() || "UNKNOWN";
2215
2028
  rewards.push({
2216
2029
  protocol: "suilend",
2217
2030
  asset: this.resolveSymbol(dep.coinType),
2218
2031
  coinType: rw.coinType,
2219
2032
  symbol,
2220
- amount: 0,
2033
+ amount: claimableAmount,
2221
2034
  estimatedValueUsd: 0
2222
2035
  });
2223
2036
  }
@@ -2666,8 +2479,7 @@ async function resolveGas(client, signer, buildTx) {
2666
2479
  // src/safeguards/types.ts
2667
2480
  var OUTBOUND_OPS = /* @__PURE__ */ new Set([
2668
2481
  "send",
2669
- "pay",
2670
- "sentinel"
2482
+ "pay"
2671
2483
  ]);
2672
2484
  var DEFAULT_SAFEGUARD_CONFIG = {
2673
2485
  locked: false,
@@ -2901,6 +2713,7 @@ var ContactManager = class {
2901
2713
  }
2902
2714
  }
2903
2715
  };
2716
+ var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
2904
2717
  function emptyData() {
2905
2718
  return { positions: {}, strategies: {}, realizedPnL: 0 };
2906
2719
  }
@@ -3056,25 +2869,34 @@ var PortfolioManager = class {
3056
2869
  }
3057
2870
  // --- Strategy position tracking ---
3058
2871
  recordStrategyBuy(strategyKey, trade) {
2872
+ if (UNSAFE_KEYS.has(strategyKey) || UNSAFE_KEYS.has(trade.asset)) {
2873
+ throw new T2000Error("ASSET_NOT_SUPPORTED", "Invalid strategy key or asset name");
2874
+ }
3059
2875
  this.load();
3060
- if (!this.data.strategies[strategyKey]) {
3061
- this.data.strategies[strategyKey] = {};
2876
+ if (!Object.hasOwn(this.data.strategies, strategyKey)) {
2877
+ this.data.strategies[strategyKey] = /* @__PURE__ */ Object.create(null);
3062
2878
  }
3063
2879
  const bucket = this.data.strategies[strategyKey];
3064
- const pos = bucket[trade.asset] ?? { totalAmount: 0, costBasis: 0, avgPrice: 0, trades: [] };
2880
+ const pos = Object.hasOwn(bucket, trade.asset) ? bucket[trade.asset] : { totalAmount: 0, costBasis: 0, avgPrice: 0, trades: [] };
3065
2881
  pos.totalAmount += trade.amount;
3066
2882
  pos.costBasis += trade.usdValue;
3067
2883
  pos.avgPrice = pos.costBasis / pos.totalAmount;
3068
2884
  pos.trades.push(trade);
3069
- bucket[trade.asset] = pos;
2885
+ Object.defineProperty(bucket, trade.asset, { value: pos, writable: true, enumerable: true, configurable: true });
3070
2886
  this.save();
3071
2887
  }
3072
2888
  recordStrategySell(strategyKey, trade) {
2889
+ if (UNSAFE_KEYS.has(strategyKey) || UNSAFE_KEYS.has(trade.asset)) {
2890
+ throw new T2000Error("ASSET_NOT_SUPPORTED", "Invalid strategy key or asset name");
2891
+ }
3073
2892
  this.load();
3074
2893
  const bucket = this.data.strategies[strategyKey];
3075
2894
  if (!bucket) {
3076
2895
  throw new T2000Error("STRATEGY_NOT_FOUND", `No positions for strategy '${strategyKey}'`);
3077
2896
  }
2897
+ if (!Object.hasOwn(bucket, trade.asset)) {
2898
+ throw new T2000Error("INSUFFICIENT_INVESTMENT", `No ${trade.asset} position in strategy '${strategyKey}'`);
2899
+ }
3078
2900
  const pos = bucket[trade.asset];
3079
2901
  if (!pos || pos.totalAmount <= 0) {
3080
2902
  throw new T2000Error("INSUFFICIENT_INVESTMENT", `No ${trade.asset} position in strategy '${strategyKey}'`);
@@ -3091,7 +2913,7 @@ var PortfolioManager = class {
3091
2913
  pos.avgPrice = 0;
3092
2914
  }
3093
2915
  pos.trades.push(trade);
3094
- bucket[trade.asset] = pos;
2916
+ Object.defineProperty(bucket, trade.asset, { value: pos, writable: true, enumerable: true, configurable: true });
3095
2917
  const hasPositions = Object.values(bucket).some((p) => p.totalAmount > 0);
3096
2918
  if (!hasPositions) {
3097
2919
  delete this.data.strategies[strategyKey];
@@ -5925,17 +5747,6 @@ var T2000 = class _T2000 extends EventEmitter {
5925
5747
  async fundStatus() {
5926
5748
  return getFundStatus(this.client, this._address);
5927
5749
  }
5928
- // -- Sentinel --
5929
- async sentinelList() {
5930
- return listSentinels();
5931
- }
5932
- async sentinelInfo(id) {
5933
- return getSentinelInfo(this.client, id);
5934
- }
5935
- async sentinelAttack(id, prompt, fee) {
5936
- this.enforcer.check({ operation: "sentinel", amount: fee ? Number(fee) / 1e9 : 0.1 });
5937
- return attack(this.client, this._signer, id, prompt, fee);
5938
- }
5939
5750
  // -- Helpers --
5940
5751
  async getFreeBalance(asset) {
5941
5752
  if (!(asset in INVESTMENT_ASSETS)) return Infinity;
@@ -6088,14 +5899,6 @@ function parseMoveAbort(errorStr) {
6088
5899
  return { reason: errorStr };
6089
5900
  }
6090
5901
 
6091
- // src/adapters/index.ts
6092
- var allDescriptors = [
6093
- descriptor2,
6094
- descriptor4,
6095
- descriptor3,
6096
- descriptor
6097
- ];
6098
-
6099
- export { AutoInvestManager, BPS_DENOMINATOR, CLOCK_ID, CetusAdapter, ContactManager, DEFAULT_MAX_LEVERAGE, DEFAULT_MAX_POSITION_SIZE, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, DEFAULT_STRATEGIES, GAS_RESERVE_MIN, INVESTMENT_ASSETS, KeypairSigner, MIST_PER_SUI, NaviAdapter, OUTBOUND_OPS, PERPS_MARKETS, PortfolioManager, ProtocolRegistry, SENTINEL, STABLE_ASSETS, SUI_DECIMALS, SUPPORTED_ASSETS, SafeguardEnforcer, SafeguardError, StrategyManager, SuilendAdapter, T2000, T2000Error, USDC_DECIMALS, ZkLoginSigner, addCollectFeeToTx, allDescriptors, calculateFee, descriptor3 as cetusDescriptor, executeAutoTopUp, executeWithGas, exportPrivateKey, formatAssetAmount, formatSui, formatUsd, generateKeypair, getAddress, getDecimals, getGasStatus, getPoolPrice, getRates, getSentinelInfo, keypairFromPrivateKey, listSentinels, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, descriptor2 as naviDescriptor, rawToStable, rawToUsdc, requestAttack, saveKey, attack as sentinelAttack, descriptor as sentinelDescriptor, settleAttack, shouldAutoTopUp, simulateTransaction, solveHashcash, stableToRaw, submitPrompt, suiToMist, descriptor4 as suilendDescriptor, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
5902
+ export { AutoInvestManager, BPS_DENOMINATOR, CLOCK_ID, CetusAdapter, ContactManager, DEFAULT_MAX_LEVERAGE, DEFAULT_MAX_POSITION_SIZE, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, DEFAULT_STRATEGIES, GAS_RESERVE_MIN, INVESTMENT_ASSETS, KeypairSigner, MIST_PER_SUI, NaviAdapter, OUTBOUND_OPS, PERPS_MARKETS, PortfolioManager, ProtocolRegistry, STABLE_ASSETS, SUI_DECIMALS, SUPPORTED_ASSETS, SafeguardEnforcer, SafeguardError, StrategyManager, SuilendAdapter, T2000, T2000Error, USDC_DECIMALS, ZkLoginSigner, addCollectFeeToTx, allDescriptors, calculateFee, cetusDescriptor, executeAutoTopUp, executeWithGas, exportPrivateKey, formatAssetAmount, formatSui, formatUsd, generateKeypair, getAddress, getDecimals, getGasStatus, getPoolPrice, getRates, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, naviDescriptor, rawToStable, rawToUsdc, saveKey, shouldAutoTopUp, simulateTransaction, solveHashcash, stableToRaw, suiToMist, suilendDescriptor, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
6100
5903
  //# sourceMappingURL=index.js.map
6101
5904
  //# sourceMappingURL=index.js.map