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