@t2000/sdk 0.2.6 → 0.3.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.
- package/README.md +8 -0
- package/dist/index.cjs +286 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +67 -3
- package/dist/index.d.ts +67 -3
- package/dist/index.js +279 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,6 +111,14 @@ const agent = T2000.fromPrivateKey('suiprivkey1q...');
|
|
|
111
111
|
| `agent.deposit()` | Wallet address + funding instructions | `DepositInfo` |
|
|
112
112
|
| `agent.history({ limit? })` | Transaction history (default: all) | `TransactionRecord[]` |
|
|
113
113
|
|
|
114
|
+
### Sentinel Methods
|
|
115
|
+
|
|
116
|
+
| Method | Description | Returns |
|
|
117
|
+
|--------|-------------|---------|
|
|
118
|
+
| `agent.sentinelList()` | List active sentinels with prize pools | `SentinelAgent[]` |
|
|
119
|
+
| `agent.sentinelInfo(id)` | Get sentinel details (from API or on-chain) | `SentinelAgent` |
|
|
120
|
+
| `agent.sentinelAttack(id, prompt, fee?)` | Full attack flow: request → TEE → settle | `SentinelAttackResult` |
|
|
121
|
+
|
|
114
122
|
### Key Management
|
|
115
123
|
|
|
116
124
|
```typescript
|
package/dist/index.cjs
CHANGED
|
@@ -12,6 +12,7 @@ var os = require('os');
|
|
|
12
12
|
var transactions = require('@mysten/sui/transactions');
|
|
13
13
|
var lending = require('@naviprotocol/lending');
|
|
14
14
|
var suiClmmSdk = require('@cetusprotocol/sui-clmm-sdk');
|
|
15
|
+
var bcs = require('@mysten/sui/bcs');
|
|
15
16
|
|
|
16
17
|
// src/t2000.ts
|
|
17
18
|
|
|
@@ -39,14 +40,26 @@ var SUPPORTED_ASSETS = {
|
|
|
39
40
|
symbol: "SUI"
|
|
40
41
|
}
|
|
41
42
|
};
|
|
42
|
-
process.env.T2000_PACKAGE_ID ?? "
|
|
43
|
-
process.env.T2000_CONFIG_ID ?? "
|
|
44
|
-
process.env.T2000_TREASURY_ID ?? "
|
|
43
|
+
var T2000_PACKAGE_ID = process.env.T2000_PACKAGE_ID ?? "0xab92e9f1fe549ad3d6a52924a73181b45791e76120b975138fac9ec9b75db9f3";
|
|
44
|
+
var T2000_CONFIG_ID = process.env.T2000_CONFIG_ID ?? "0x408add9aa9322f93cfd87523d8f603006eb8713894f4c460283c58a6888dae8a";
|
|
45
|
+
var T2000_TREASURY_ID = process.env.T2000_TREASURY_ID ?? "0x3bb501b8300125dca59019247941a42af6b292a150ce3cfcce9449456be2ec91";
|
|
45
46
|
var DEFAULT_NETWORK = "mainnet";
|
|
46
47
|
var DEFAULT_RPC_URL = "https://fullnode.mainnet.sui.io:443";
|
|
47
48
|
var DEFAULT_KEY_PATH = "~/.t2000/wallet.key";
|
|
48
49
|
var API_BASE_URL = process.env.T2000_API_URL ?? "https://api.t2000.ai";
|
|
49
50
|
var CETUS_USDC_SUI_POOL = "0x51e883ba7c0b566a26cbc8a94cd33eb0abd418a77cc1e60ad22fd9b1f29cd2ab";
|
|
51
|
+
var SENTINEL = {
|
|
52
|
+
PACKAGE: "0x88b83f36dafcd5f6dcdcf1d2cb5889b03f61264ab3cee9cae35db7aa940a21b7",
|
|
53
|
+
AGENT_REGISTRY: "0xc47564f5f14c12b31e0dfa1a3dc99a6380a1edf8929c28cb0eaa3359c8db36ac",
|
|
54
|
+
ENCLAVE: "0xfb1261aeb9583514cb1341a548a5ec12d1231bd96af22215f1792617a93e1213",
|
|
55
|
+
PROTOCOL_CONFIG: "0x2fa4fa4a1dd0498612304635ff9334e1b922e78af325000e9d9c0e88adea459f",
|
|
56
|
+
TEE_API: "https://app.suisentinel.xyz/api/consume-prompt",
|
|
57
|
+
SENTINELS_API: "https://api.suisentinel.xyz/agents/mainnet",
|
|
58
|
+
RANDOM: "0x8",
|
|
59
|
+
MIN_FEE_MIST: 100000000n,
|
|
60
|
+
// 0.1 SUI
|
|
61
|
+
MAX_PROMPT_TOKENS: 600
|
|
62
|
+
};
|
|
50
63
|
|
|
51
64
|
// src/errors.ts
|
|
52
65
|
var T2000Error = class extends Error {
|
|
@@ -89,7 +102,8 @@ function mapMoveAbortCode(code) {
|
|
|
89
102
|
6: "Not authorized",
|
|
90
103
|
7: "Package version mismatch \u2014 upgrade required",
|
|
91
104
|
8: "Timelock is active \u2014 wait for expiry",
|
|
92
|
-
9: "No pending change to execute"
|
|
105
|
+
9: "No pending change to execute",
|
|
106
|
+
10: "Already at current version"
|
|
93
107
|
};
|
|
94
108
|
return abortMessages[code] ?? `Move abort code: ${code}`;
|
|
95
109
|
}
|
|
@@ -360,6 +374,61 @@ function inferAction(txBlock) {
|
|
|
360
374
|
if (kind === "ProgrammableTransaction") return "transaction";
|
|
361
375
|
return kind ?? "unknown";
|
|
362
376
|
}
|
|
377
|
+
|
|
378
|
+
// src/protocols/protocolFee.ts
|
|
379
|
+
var FEE_RATES = {
|
|
380
|
+
save: SAVE_FEE_BPS,
|
|
381
|
+
swap: SWAP_FEE_BPS,
|
|
382
|
+
borrow: BORROW_FEE_BPS
|
|
383
|
+
};
|
|
384
|
+
var OP_CODES = {
|
|
385
|
+
save: 0,
|
|
386
|
+
swap: 1,
|
|
387
|
+
borrow: 2
|
|
388
|
+
};
|
|
389
|
+
function calculateFee(operation, amount) {
|
|
390
|
+
const bps = FEE_RATES[operation];
|
|
391
|
+
const feeAmount = amount * Number(bps) / Number(BPS_DENOMINATOR);
|
|
392
|
+
const rawAmount = usdcToRaw(feeAmount);
|
|
393
|
+
return {
|
|
394
|
+
amount: feeAmount,
|
|
395
|
+
asset: "USDC",
|
|
396
|
+
rate: Number(bps) / Number(BPS_DENOMINATOR),
|
|
397
|
+
rawAmount
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
function addCollectFeeToTx(tx, paymentCoin, operation) {
|
|
401
|
+
const bps = FEE_RATES[operation];
|
|
402
|
+
if (bps <= 0n) return;
|
|
403
|
+
tx.moveCall({
|
|
404
|
+
target: `${T2000_PACKAGE_ID}::treasury::collect_fee`,
|
|
405
|
+
typeArguments: [SUPPORTED_ASSETS.USDC.type],
|
|
406
|
+
arguments: [
|
|
407
|
+
tx.object(T2000_TREASURY_ID),
|
|
408
|
+
tx.object(T2000_CONFIG_ID),
|
|
409
|
+
paymentCoin,
|
|
410
|
+
tx.pure.u8(OP_CODES[operation])
|
|
411
|
+
]
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
async function reportFee(agentAddress, operation, feeAmount, feeRate, txDigest) {
|
|
415
|
+
try {
|
|
416
|
+
await fetch(`${API_BASE_URL}/api/fees`, {
|
|
417
|
+
method: "POST",
|
|
418
|
+
headers: { "Content-Type": "application/json" },
|
|
419
|
+
body: JSON.stringify({
|
|
420
|
+
agentAddress,
|
|
421
|
+
operation,
|
|
422
|
+
feeAmount: feeAmount.toString(),
|
|
423
|
+
feeRate: feeRate.toString(),
|
|
424
|
+
txDigest
|
|
425
|
+
})
|
|
426
|
+
});
|
|
427
|
+
} catch {
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// src/protocols/navi.ts
|
|
363
432
|
var ENV = { env: "prod" };
|
|
364
433
|
var USDC_TYPE = SUPPORTED_ASSETS.USDC.type;
|
|
365
434
|
var RATE_DECIMALS = 27;
|
|
@@ -402,7 +471,7 @@ async function updateOracle(tx, client, address) {
|
|
|
402
471
|
} catch {
|
|
403
472
|
}
|
|
404
473
|
}
|
|
405
|
-
async function buildSaveTx(client, address, amount) {
|
|
474
|
+
async function buildSaveTx(client, address, amount, options = {}) {
|
|
406
475
|
const rawAmount = Number(usdcToRaw(amount));
|
|
407
476
|
const coins = await lending.getCoins(address, { coinType: USDC_TYPE, client });
|
|
408
477
|
if (!coins || coins.length === 0) {
|
|
@@ -411,6 +480,9 @@ async function buildSaveTx(client, address, amount) {
|
|
|
411
480
|
const tx = new transactions.Transaction();
|
|
412
481
|
tx.setSender(address);
|
|
413
482
|
const coinObj = lending.mergeCoinsPTB(tx, coins, { balance: rawAmount });
|
|
483
|
+
if (options.collectFee) {
|
|
484
|
+
addCollectFeeToTx(tx, coinObj, "save");
|
|
485
|
+
}
|
|
414
486
|
await lending.depositCoinPTB(tx, USDC_TYPE, coinObj, ENV);
|
|
415
487
|
return tx;
|
|
416
488
|
}
|
|
@@ -428,12 +500,15 @@ async function buildWithdrawTx(client, address, amount) {
|
|
|
428
500
|
tx.transferObjects([withdrawnCoin], address);
|
|
429
501
|
return { tx, effectiveAmount };
|
|
430
502
|
}
|
|
431
|
-
async function buildBorrowTx(client, address, amount) {
|
|
503
|
+
async function buildBorrowTx(client, address, amount, options = {}) {
|
|
432
504
|
const rawAmount = Number(usdcToRaw(amount));
|
|
433
505
|
const tx = new transactions.Transaction();
|
|
434
506
|
tx.setSender(address);
|
|
435
507
|
await updateOracle(tx, client, address);
|
|
436
508
|
const borrowedCoin = await lending.borrowCoinPTB(tx, USDC_TYPE, rawAmount, ENV);
|
|
509
|
+
if (options.collectFee) {
|
|
510
|
+
addCollectFeeToTx(tx, borrowedCoin, "borrow");
|
|
511
|
+
}
|
|
437
512
|
tx.transferObjects([borrowedCoin], address);
|
|
438
513
|
return tx;
|
|
439
514
|
}
|
|
@@ -641,40 +716,6 @@ async function getSwapQuote(client, fromAsset, toAsset, amount) {
|
|
|
641
716
|
}
|
|
642
717
|
}
|
|
643
718
|
|
|
644
|
-
// src/protocols/protocolFee.ts
|
|
645
|
-
var FEE_RATES = {
|
|
646
|
-
save: SAVE_FEE_BPS,
|
|
647
|
-
swap: SWAP_FEE_BPS,
|
|
648
|
-
borrow: BORROW_FEE_BPS
|
|
649
|
-
};
|
|
650
|
-
function calculateFee(operation, amount) {
|
|
651
|
-
const bps = FEE_RATES[operation];
|
|
652
|
-
const feeAmount = amount * Number(bps) / Number(BPS_DENOMINATOR);
|
|
653
|
-
const rawAmount = usdcToRaw(feeAmount);
|
|
654
|
-
return {
|
|
655
|
-
amount: feeAmount,
|
|
656
|
-
asset: "USDC",
|
|
657
|
-
rate: Number(bps) / Number(BPS_DENOMINATOR),
|
|
658
|
-
rawAmount
|
|
659
|
-
};
|
|
660
|
-
}
|
|
661
|
-
async function reportFee(agentAddress, operation, feeAmount, feeRate, txDigest) {
|
|
662
|
-
try {
|
|
663
|
-
await fetch(`${API_BASE_URL}/api/fees`, {
|
|
664
|
-
method: "POST",
|
|
665
|
-
headers: { "Content-Type": "application/json" },
|
|
666
|
-
body: JSON.stringify({
|
|
667
|
-
agentAddress,
|
|
668
|
-
operation,
|
|
669
|
-
feeAmount: feeAmount.toString(),
|
|
670
|
-
feeRate: feeRate.toString(),
|
|
671
|
-
txDigest
|
|
672
|
-
})
|
|
673
|
-
});
|
|
674
|
-
} catch {
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
|
|
678
719
|
// src/protocols/yieldTracker.ts
|
|
679
720
|
async function getEarnings(client, keypair) {
|
|
680
721
|
const hf = await getHealthFactor(client, keypair);
|
|
@@ -701,6 +742,190 @@ async function getFundStatus(client, keypair) {
|
|
|
701
742
|
projectedMonthly: earnings.dailyEarning * 30
|
|
702
743
|
};
|
|
703
744
|
}
|
|
745
|
+
function mapAgent(raw) {
|
|
746
|
+
return {
|
|
747
|
+
id: raw.agent_id,
|
|
748
|
+
objectId: raw.agent_object_id,
|
|
749
|
+
name: raw.agent_name,
|
|
750
|
+
model: raw.model ?? "unknown",
|
|
751
|
+
systemPrompt: raw.prompt,
|
|
752
|
+
attackFee: BigInt(raw.cost_per_message),
|
|
753
|
+
prizePool: BigInt(raw.total_balance),
|
|
754
|
+
totalAttacks: raw.total_attacks,
|
|
755
|
+
successfulBreaches: raw.successful_breaches ?? 0,
|
|
756
|
+
state: raw.state
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
async function listSentinels() {
|
|
760
|
+
const res = await fetch(SENTINEL.SENTINELS_API);
|
|
761
|
+
if (!res.ok) {
|
|
762
|
+
throw new T2000Error("SENTINEL_API_ERROR", `Sentinel API returned ${res.status}`);
|
|
763
|
+
}
|
|
764
|
+
const data = await res.json();
|
|
765
|
+
if (!Array.isArray(data.agents)) {
|
|
766
|
+
throw new T2000Error("SENTINEL_API_ERROR", "Unexpected API response shape");
|
|
767
|
+
}
|
|
768
|
+
return data.agents.filter((a) => a.state === "active").map(mapAgent);
|
|
769
|
+
}
|
|
770
|
+
async function getSentinelInfo(client, sentinelObjectId) {
|
|
771
|
+
const agents = await listSentinels();
|
|
772
|
+
const match = agents.find((a) => a.objectId === sentinelObjectId || a.id === sentinelObjectId);
|
|
773
|
+
if (match) return match;
|
|
774
|
+
const obj = await client.getObject({
|
|
775
|
+
id: sentinelObjectId,
|
|
776
|
+
options: { showContent: true, showType: true }
|
|
777
|
+
});
|
|
778
|
+
if (!obj.data) {
|
|
779
|
+
throw new T2000Error("SENTINEL_NOT_FOUND", `Sentinel ${sentinelObjectId} not found on-chain`);
|
|
780
|
+
}
|
|
781
|
+
const content = obj.data.content;
|
|
782
|
+
if (!content || content.dataType !== "moveObject") {
|
|
783
|
+
throw new T2000Error("SENTINEL_NOT_FOUND", `Object ${sentinelObjectId} is not a Move object`);
|
|
784
|
+
}
|
|
785
|
+
const fields = content.fields;
|
|
786
|
+
return {
|
|
787
|
+
id: fields.id?.id ?? sentinelObjectId,
|
|
788
|
+
objectId: sentinelObjectId,
|
|
789
|
+
name: fields.name ?? "Unknown",
|
|
790
|
+
model: fields.model ?? "unknown",
|
|
791
|
+
systemPrompt: fields.system_prompt ?? "",
|
|
792
|
+
attackFee: BigInt(fields.cost_per_message ?? "0"),
|
|
793
|
+
prizePool: BigInt(fields.balance ?? "0"),
|
|
794
|
+
totalAttacks: Number(fields.total_attacks ?? "0"),
|
|
795
|
+
successfulBreaches: Number(fields.successful_breaches ?? "0"),
|
|
796
|
+
state: fields.state ?? "unknown"
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
async function requestAttack(client, signer, sentinelObjectId, feeMist) {
|
|
800
|
+
if (feeMist < SENTINEL.MIN_FEE_MIST) {
|
|
801
|
+
throw new T2000Error("INVALID_AMOUNT", `Attack fee must be at least 0.1 SUI (${SENTINEL.MIN_FEE_MIST} MIST)`);
|
|
802
|
+
}
|
|
803
|
+
const tx = new transactions.Transaction();
|
|
804
|
+
const [coin] = tx.splitCoins(tx.gas, [Number(feeMist)]);
|
|
805
|
+
const [attack2] = tx.moveCall({
|
|
806
|
+
target: `${SENTINEL.PACKAGE}::sentinel::request_attack`,
|
|
807
|
+
arguments: [
|
|
808
|
+
tx.object(SENTINEL.AGENT_REGISTRY),
|
|
809
|
+
tx.object(sentinelObjectId),
|
|
810
|
+
tx.object(SENTINEL.PROTOCOL_CONFIG),
|
|
811
|
+
coin,
|
|
812
|
+
tx.object(SENTINEL.RANDOM),
|
|
813
|
+
tx.object(CLOCK_ID)
|
|
814
|
+
]
|
|
815
|
+
});
|
|
816
|
+
const address = signer.toSuiAddress();
|
|
817
|
+
tx.transferObjects([attack2], address);
|
|
818
|
+
const result = await client.signAndExecuteTransaction({
|
|
819
|
+
signer,
|
|
820
|
+
transaction: tx,
|
|
821
|
+
options: { showObjectChanges: true, showEffects: true }
|
|
822
|
+
});
|
|
823
|
+
await client.waitForTransaction({ digest: result.digest });
|
|
824
|
+
const attackObj = result.objectChanges?.find(
|
|
825
|
+
(c) => c.type === "created" && c.objectType?.includes("::sentinel::Attack")
|
|
826
|
+
);
|
|
827
|
+
const attackObjectId = attackObj && "objectId" in attackObj ? attackObj.objectId : void 0;
|
|
828
|
+
if (!attackObjectId) {
|
|
829
|
+
throw new T2000Error("SENTINEL_TX_FAILED", "Attack object was not created \u2014 transaction may have failed");
|
|
830
|
+
}
|
|
831
|
+
return { attackObjectId, digest: result.digest };
|
|
832
|
+
}
|
|
833
|
+
async function submitPrompt(agentId, attackObjectId, prompt) {
|
|
834
|
+
const res = await fetch(SENTINEL.TEE_API, {
|
|
835
|
+
method: "POST",
|
|
836
|
+
headers: { "Content-Type": "application/json" },
|
|
837
|
+
body: JSON.stringify({
|
|
838
|
+
agent_id: agentId,
|
|
839
|
+
attack_object_id: attackObjectId,
|
|
840
|
+
message: prompt
|
|
841
|
+
})
|
|
842
|
+
});
|
|
843
|
+
if (!res.ok) {
|
|
844
|
+
const body = await res.text().catch(() => "");
|
|
845
|
+
throw new T2000Error("SENTINEL_TEE_ERROR", `TEE returned ${res.status}: ${body.slice(0, 200)}`);
|
|
846
|
+
}
|
|
847
|
+
const raw = await res.json();
|
|
848
|
+
const envelope = raw.response ?? raw;
|
|
849
|
+
const data = envelope.data ?? envelope;
|
|
850
|
+
const signature = raw.signature ?? data.signature;
|
|
851
|
+
const timestampMs = envelope.timestamp_ms ?? data.timestamp_ms;
|
|
852
|
+
if (typeof signature !== "string") {
|
|
853
|
+
throw new T2000Error("SENTINEL_TEE_ERROR", "TEE response missing signature");
|
|
854
|
+
}
|
|
855
|
+
return {
|
|
856
|
+
success: data.success ?? data.is_success,
|
|
857
|
+
score: data.score,
|
|
858
|
+
agentResponse: data.agent_response,
|
|
859
|
+
juryResponse: data.jury_response,
|
|
860
|
+
funResponse: data.fun_response ?? "",
|
|
861
|
+
signature,
|
|
862
|
+
timestampMs
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
async function settleAttack(client, signer, sentinelObjectId, attackObjectId, prompt, verdict) {
|
|
866
|
+
const sigBytes = Array.from(Buffer.from(verdict.signature.replace(/^0x/, ""), "hex"));
|
|
867
|
+
const tx = new transactions.Transaction();
|
|
868
|
+
tx.moveCall({
|
|
869
|
+
target: `${SENTINEL.PACKAGE}::sentinel::consume_prompt`,
|
|
870
|
+
arguments: [
|
|
871
|
+
tx.object(SENTINEL.AGENT_REGISTRY),
|
|
872
|
+
tx.object(SENTINEL.PROTOCOL_CONFIG),
|
|
873
|
+
tx.object(sentinelObjectId),
|
|
874
|
+
tx.pure.bool(verdict.success),
|
|
875
|
+
tx.pure.string(verdict.agentResponse),
|
|
876
|
+
tx.pure.string(verdict.juryResponse),
|
|
877
|
+
tx.pure.string(verdict.funResponse),
|
|
878
|
+
tx.pure.string(prompt),
|
|
879
|
+
tx.pure.u8(verdict.score),
|
|
880
|
+
tx.pure.u64(verdict.timestampMs),
|
|
881
|
+
tx.pure(bcs.bcs.vector(bcs.bcs.u8()).serialize(sigBytes)),
|
|
882
|
+
tx.object(SENTINEL.ENCLAVE),
|
|
883
|
+
tx.object(attackObjectId),
|
|
884
|
+
tx.object(CLOCK_ID)
|
|
885
|
+
]
|
|
886
|
+
});
|
|
887
|
+
const result = await client.signAndExecuteTransaction({
|
|
888
|
+
signer,
|
|
889
|
+
transaction: tx,
|
|
890
|
+
options: { showEffects: true }
|
|
891
|
+
});
|
|
892
|
+
await client.waitForTransaction({ digest: result.digest });
|
|
893
|
+
const txSuccess = result.effects?.status?.status === "success";
|
|
894
|
+
return { digest: result.digest, success: txSuccess };
|
|
895
|
+
}
|
|
896
|
+
async function attack(client, signer, sentinelId, prompt, feeMist) {
|
|
897
|
+
const sentinel = await getSentinelInfo(client, sentinelId);
|
|
898
|
+
const fee = feeMist ?? sentinel.attackFee;
|
|
899
|
+
if (fee < SENTINEL.MIN_FEE_MIST) {
|
|
900
|
+
throw new T2000Error("INVALID_AMOUNT", `Attack fee must be at least 0.1 SUI`);
|
|
901
|
+
}
|
|
902
|
+
const { attackObjectId, digest: requestTx } = await requestAttack(
|
|
903
|
+
client,
|
|
904
|
+
signer,
|
|
905
|
+
sentinel.objectId,
|
|
906
|
+
fee
|
|
907
|
+
);
|
|
908
|
+
const verdict = await submitPrompt(sentinel.id, attackObjectId, prompt);
|
|
909
|
+
const { digest: settleTx } = await settleAttack(
|
|
910
|
+
client,
|
|
911
|
+
signer,
|
|
912
|
+
sentinel.objectId,
|
|
913
|
+
attackObjectId,
|
|
914
|
+
prompt,
|
|
915
|
+
verdict
|
|
916
|
+
);
|
|
917
|
+
const won = verdict.success && verdict.score >= 70;
|
|
918
|
+
return {
|
|
919
|
+
attackObjectId,
|
|
920
|
+
sentinelId: sentinel.id,
|
|
921
|
+
prompt,
|
|
922
|
+
verdict,
|
|
923
|
+
requestTx,
|
|
924
|
+
settleTx,
|
|
925
|
+
won,
|
|
926
|
+
feePaid: Number(fee) / Number(MIST_PER_SUI)
|
|
927
|
+
};
|
|
928
|
+
}
|
|
704
929
|
function hasLeadingZeroBits(hash, bits) {
|
|
705
930
|
const fullBytes = Math.floor(bits / 8);
|
|
706
931
|
const remainingBits = bits % 8;
|
|
@@ -1083,12 +1308,12 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
|
|
|
1083
1308
|
const gasResult = await executeWithGas(
|
|
1084
1309
|
this.client,
|
|
1085
1310
|
this.keypair,
|
|
1086
|
-
() => buildSaveTx(this.client, this._address, saveAmount)
|
|
1311
|
+
() => buildSaveTx(this.client, this._address, saveAmount, { collectFee: true })
|
|
1087
1312
|
);
|
|
1088
1313
|
const rates = await getRates(this.client);
|
|
1089
1314
|
reportFee(this._address, "save", fee.amount, fee.rate, gasResult.digest);
|
|
1090
1315
|
this.emitBalanceChange("USDC", saveAmount, "save", gasResult.digest);
|
|
1091
|
-
let savingsBalance = saveAmount
|
|
1316
|
+
let savingsBalance = saveAmount;
|
|
1092
1317
|
try {
|
|
1093
1318
|
const positions = await this.positions();
|
|
1094
1319
|
savingsBalance = positions.positions.filter((p) => p.type === "save").reduce((sum, p) => sum + p.amount, 0);
|
|
@@ -1172,7 +1397,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
|
|
|
1172
1397
|
const gasResult = await executeWithGas(
|
|
1173
1398
|
this.client,
|
|
1174
1399
|
this.keypair,
|
|
1175
|
-
() => buildBorrowTx(this.client, this._address, borrowAmount)
|
|
1400
|
+
() => buildBorrowTx(this.client, this._address, borrowAmount, { collectFee: true })
|
|
1176
1401
|
);
|
|
1177
1402
|
const hf = await getHealthFactor(this.client, this.keypair);
|
|
1178
1403
|
reportFee(this._address, "borrow", fee.amount, fee.rate, gasResult.digest);
|
|
@@ -1318,6 +1543,16 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
|
|
|
1318
1543
|
async fundStatus() {
|
|
1319
1544
|
return getFundStatus(this.client, this.keypair);
|
|
1320
1545
|
}
|
|
1546
|
+
// -- Sentinel --
|
|
1547
|
+
async sentinelList() {
|
|
1548
|
+
return listSentinels();
|
|
1549
|
+
}
|
|
1550
|
+
async sentinelInfo(id) {
|
|
1551
|
+
return getSentinelInfo(this.client, id);
|
|
1552
|
+
}
|
|
1553
|
+
async sentinelAttack(id, prompt, fee) {
|
|
1554
|
+
return attack(this.client, this.keypair, id, prompt, fee);
|
|
1555
|
+
}
|
|
1321
1556
|
// -- Helpers --
|
|
1322
1557
|
emitBalanceChange(asset, amount, cause, tx) {
|
|
1323
1558
|
this.emit("balanceChange", { asset, previous: 0, current: 0, cause, tx });
|
|
@@ -1421,11 +1656,13 @@ exports.BPS_DENOMINATOR = BPS_DENOMINATOR;
|
|
|
1421
1656
|
exports.CLOCK_ID = CLOCK_ID;
|
|
1422
1657
|
exports.DEFAULT_NETWORK = DEFAULT_NETWORK;
|
|
1423
1658
|
exports.MIST_PER_SUI = MIST_PER_SUI;
|
|
1659
|
+
exports.SENTINEL = SENTINEL;
|
|
1424
1660
|
exports.SUI_DECIMALS = SUI_DECIMALS;
|
|
1425
1661
|
exports.SUPPORTED_ASSETS = SUPPORTED_ASSETS;
|
|
1426
1662
|
exports.T2000 = T2000;
|
|
1427
1663
|
exports.T2000Error = T2000Error;
|
|
1428
1664
|
exports.USDC_DECIMALS = USDC_DECIMALS;
|
|
1665
|
+
exports.addCollectFeeToTx = addCollectFeeToTx;
|
|
1429
1666
|
exports.calculateFee = calculateFee;
|
|
1430
1667
|
exports.executeAutoTopUp = executeAutoTopUp;
|
|
1431
1668
|
exports.executeWithGas = executeWithGas;
|
|
@@ -1437,17 +1674,23 @@ exports.getAddress = getAddress;
|
|
|
1437
1674
|
exports.getGasStatus = getGasStatus;
|
|
1438
1675
|
exports.getPoolPrice = getPoolPrice;
|
|
1439
1676
|
exports.getRates = getRates;
|
|
1677
|
+
exports.getSentinelInfo = getSentinelInfo;
|
|
1440
1678
|
exports.getSwapQuote = getSwapQuote;
|
|
1441
1679
|
exports.keypairFromPrivateKey = keypairFromPrivateKey;
|
|
1680
|
+
exports.listSentinels = listSentinels;
|
|
1442
1681
|
exports.loadKey = loadKey;
|
|
1443
1682
|
exports.mapMoveAbortCode = mapMoveAbortCode;
|
|
1444
1683
|
exports.mapWalletError = mapWalletError;
|
|
1445
1684
|
exports.mistToSui = mistToSui;
|
|
1446
1685
|
exports.rawToUsdc = rawToUsdc;
|
|
1686
|
+
exports.requestAttack = requestAttack;
|
|
1447
1687
|
exports.saveKey = saveKey;
|
|
1688
|
+
exports.sentinelAttack = attack;
|
|
1689
|
+
exports.settleAttack = settleAttack;
|
|
1448
1690
|
exports.shouldAutoTopUp = shouldAutoTopUp;
|
|
1449
1691
|
exports.simulateTransaction = simulateTransaction;
|
|
1450
1692
|
exports.solveHashcash = solveHashcash;
|
|
1693
|
+
exports.submitPrompt = submitPrompt;
|
|
1451
1694
|
exports.suiToMist = suiToMist;
|
|
1452
1695
|
exports.throwIfSimulationFailed = throwIfSimulationFailed;
|
|
1453
1696
|
exports.truncateAddress = truncateAddress;
|