@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/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { EventEmitter } from 'eventemitter3';
2
2
  import { SuiClient } from '@mysten/sui/client';
3
3
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
4
- import { Transaction } from '@mysten/sui/transactions';
4
+ import { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions';
5
5
 
6
6
  interface T2000Options {
7
7
  keyPath?: string;
@@ -142,8 +142,39 @@ interface TransactionRecord {
142
142
  timestamp: number;
143
143
  gasMethod?: GasMethod;
144
144
  }
145
+ interface SentinelAgent {
146
+ id: string;
147
+ objectId: string;
148
+ name: string;
149
+ model: string;
150
+ systemPrompt: string;
151
+ attackFee: bigint;
152
+ prizePool: bigint;
153
+ totalAttacks: number;
154
+ successfulBreaches: number;
155
+ state: string;
156
+ }
157
+ interface SentinelVerdict {
158
+ success: boolean;
159
+ score: number;
160
+ agentResponse: string;
161
+ juryResponse: string;
162
+ funResponse: string;
163
+ signature: string;
164
+ timestampMs: number;
165
+ }
166
+ interface SentinelAttackResult {
167
+ attackObjectId: string;
168
+ sentinelId: string;
169
+ prompt: string;
170
+ verdict: SentinelVerdict;
171
+ requestTx: string;
172
+ settleTx: string;
173
+ won: boolean;
174
+ feePaid: number;
175
+ }
145
176
 
146
- type T2000ErrorCode = 'INSUFFICIENT_BALANCE' | 'INSUFFICIENT_GAS' | 'INVALID_ADDRESS' | 'INVALID_AMOUNT' | 'WALLET_NOT_FOUND' | 'WALLET_LOCKED' | 'WALLET_EXISTS' | 'SPONSOR_FAILED' | 'SPONSOR_RATE_LIMITED' | 'GAS_STATION_UNAVAILABLE' | 'GAS_FEE_EXCEEDED' | 'SIMULATION_FAILED' | 'TRANSACTION_FAILED' | 'ASSET_NOT_SUPPORTED' | 'SLIPPAGE_EXCEEDED' | 'HEALTH_FACTOR_TOO_LOW' | 'WITHDRAW_WOULD_LIQUIDATE' | 'NO_COLLATERAL' | 'PROTOCOL_PAUSED' | 'PROTOCOL_UNAVAILABLE' | 'RPC_ERROR' | 'RPC_UNREACHABLE' | 'SPONSOR_UNAVAILABLE' | 'AUTO_TOPUP_FAILED' | 'PRICE_EXCEEDS_LIMIT' | 'UNSUPPORTED_NETWORK' | 'PAYMENT_EXPIRED' | 'DUPLICATE_PAYMENT' | 'FACILITATOR_REJECTION' | 'FACILITATOR_TIMEOUT' | 'UNKNOWN';
177
+ type T2000ErrorCode = 'INSUFFICIENT_BALANCE' | 'INSUFFICIENT_GAS' | 'INVALID_ADDRESS' | 'INVALID_AMOUNT' | 'WALLET_NOT_FOUND' | 'WALLET_LOCKED' | 'WALLET_EXISTS' | 'SPONSOR_FAILED' | 'SPONSOR_RATE_LIMITED' | 'GAS_STATION_UNAVAILABLE' | 'GAS_FEE_EXCEEDED' | 'SIMULATION_FAILED' | 'TRANSACTION_FAILED' | 'ASSET_NOT_SUPPORTED' | 'SLIPPAGE_EXCEEDED' | 'HEALTH_FACTOR_TOO_LOW' | 'WITHDRAW_WOULD_LIQUIDATE' | 'NO_COLLATERAL' | 'PROTOCOL_PAUSED' | 'PROTOCOL_UNAVAILABLE' | 'RPC_ERROR' | 'RPC_UNREACHABLE' | 'SPONSOR_UNAVAILABLE' | 'AUTO_TOPUP_FAILED' | 'PRICE_EXCEEDS_LIMIT' | 'UNSUPPORTED_NETWORK' | 'PAYMENT_EXPIRED' | 'DUPLICATE_PAYMENT' | 'FACILITATOR_REJECTION' | 'FACILITATOR_TIMEOUT' | 'SENTINEL_API_ERROR' | 'SENTINEL_NOT_FOUND' | 'SENTINEL_TX_FAILED' | 'SENTINEL_TEE_ERROR' | 'UNKNOWN';
147
178
  interface T2000ErrorData {
148
179
  reason?: string;
149
180
  [key: string]: unknown;
@@ -277,6 +308,9 @@ declare class T2000 extends EventEmitter<T2000Events> {
277
308
  rates(): Promise<RatesResult>;
278
309
  earnings(): Promise<EarningsResult>;
279
310
  fundStatus(): Promise<FundStatusResult>;
311
+ sentinelList(): Promise<SentinelAgent[]>;
312
+ sentinelInfo(id: string): Promise<SentinelAgent>;
313
+ sentinelAttack(id: string, prompt: string, fee?: bigint): Promise<SentinelAttackResult>;
280
314
  private emitBalanceChange;
281
315
  }
282
316
 
@@ -299,6 +333,17 @@ declare const SUPPORTED_ASSETS: {
299
333
  };
300
334
  type SupportedAsset = keyof typeof SUPPORTED_ASSETS;
301
335
  declare const DEFAULT_NETWORK: "mainnet";
336
+ declare const SENTINEL: {
337
+ readonly PACKAGE: "0x88b83f36dafcd5f6dcdcf1d2cb5889b03f61264ab3cee9cae35db7aa940a21b7";
338
+ readonly AGENT_REGISTRY: "0xc47564f5f14c12b31e0dfa1a3dc99a6380a1edf8929c28cb0eaa3359c8db36ac";
339
+ readonly ENCLAVE: "0xfb1261aeb9583514cb1341a548a5ec12d1231bd96af22215f1792617a93e1213";
340
+ readonly PROTOCOL_CONFIG: "0x2fa4fa4a1dd0498612304635ff9334e1b922e78af325000e9d9c0e88adea459f";
341
+ readonly TEE_API: "https://app.suisentinel.xyz/api/consume-prompt";
342
+ readonly SENTINELS_API: "https://api.suisentinel.xyz/agents/mainnet";
343
+ readonly RANDOM: "0x8";
344
+ readonly MIN_FEE_MIST: 100000000n;
345
+ readonly MAX_PROMPT_TOKENS: 600;
346
+ };
302
347
 
303
348
  declare function validateAddress(address: string): string;
304
349
  declare function truncateAddress(address: string): string;
@@ -328,6 +373,12 @@ interface ProtocolFeeInfo {
328
373
  rawAmount: bigint;
329
374
  }
330
375
  declare function calculateFee(operation: FeeOperation, amount: number): ProtocolFeeInfo;
376
+ /**
377
+ * Add on-chain fee collection to an existing PTB via t2000::treasury::collect_fee().
378
+ * The Move function splits the fee from the payment coin and stores it in the
379
+ * Treasury's internal Balance<T>. Atomic — reverts with the operation if it fails.
380
+ */
381
+ declare function addCollectFeeToTx(tx: Transaction, paymentCoin: TransactionObjectArgument, operation: FeeOperation): void;
331
382
 
332
383
  interface SimulationResult {
333
384
  success: boolean;
@@ -351,6 +402,19 @@ declare function getSwapQuote(client: SuiClient, fromAsset: 'USDC' | 'SUI', toAs
351
402
 
352
403
  declare function getRates(client: SuiClient): Promise<RatesResult>;
353
404
 
405
+ declare function listSentinels(): Promise<SentinelAgent[]>;
406
+ declare function getSentinelInfo(client: SuiClient, sentinelObjectId: string): Promise<SentinelAgent>;
407
+ declare function requestAttack(client: SuiClient, signer: Ed25519Keypair, sentinelObjectId: string, feeMist: bigint): Promise<{
408
+ attackObjectId: string;
409
+ digest: string;
410
+ }>;
411
+ declare function submitPrompt(agentId: string, attackObjectId: string, prompt: string): Promise<SentinelVerdict>;
412
+ declare function settleAttack(client: SuiClient, signer: Ed25519Keypair, sentinelObjectId: string, attackObjectId: string, prompt: string, verdict: SentinelVerdict): Promise<{
413
+ digest: string;
414
+ success: boolean;
415
+ }>;
416
+ declare function attack(client: SuiClient, signer: Ed25519Keypair, sentinelId: string, prompt: string, feeMist?: bigint): Promise<SentinelAttackResult>;
417
+
354
418
  interface GasExecutionResult {
355
419
  digest: string;
356
420
  effects: unknown;
@@ -390,4 +454,4 @@ interface GasStatusResponse {
390
454
  }
391
455
  declare function getGasStatus(address?: string): Promise<GasStatusResponse>;
392
456
 
393
- export { type AutoTopUpResult, BPS_DENOMINATOR, type BalanceResponse, type BorrowResult, CLOCK_ID, DEFAULT_NETWORK, type DepositInfo, type EarningsResult, type FeeOperation, type FundStatusResult, type GasExecutionResult, type GasMethod, type GasRequestType, type GasReserve, type GasSponsorResponse, type GasStatusResponse, type HealthFactorResult, MIST_PER_SUI, type MaxBorrowResult, type MaxWithdrawResult, type PositionEntry, type PositionsResult, type ProtocolFeeInfo, type RatesResult, type RepayResult, SUI_DECIMALS, SUPPORTED_ASSETS, type SaveResult, type SendResult, type SimulationResult, type SupportedAsset, type SwapResult, T2000, T2000Error, type T2000ErrorCode, type T2000ErrorData, type T2000Options, type TransactionRecord, USDC_DECIMALS, type WithdrawResult, calculateFee, executeAutoTopUp, executeWithGas, exportPrivateKey, formatSui, formatUsd, generateKeypair, getAddress, getGasStatus, getPoolPrice, getRates, getSwapQuote, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, rawToUsdc, saveKey, shouldAutoTopUp, simulateTransaction, solveHashcash, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
457
+ export { type AutoTopUpResult, BPS_DENOMINATOR, type BalanceResponse, type BorrowResult, CLOCK_ID, DEFAULT_NETWORK, type DepositInfo, type EarningsResult, type FeeOperation, type FundStatusResult, type GasExecutionResult, type GasMethod, type GasRequestType, type GasReserve, type GasSponsorResponse, type GasStatusResponse, type HealthFactorResult, MIST_PER_SUI, type MaxBorrowResult, type MaxWithdrawResult, type PositionEntry, type PositionsResult, type ProtocolFeeInfo, type RatesResult, type RepayResult, SENTINEL, SUI_DECIMALS, SUPPORTED_ASSETS, type SaveResult, type SendResult, type SentinelAgent, type SentinelAttackResult, type SentinelVerdict, type SimulationResult, type SupportedAsset, type SwapResult, T2000, T2000Error, type T2000ErrorCode, type T2000ErrorData, type T2000Options, type TransactionRecord, USDC_DECIMALS, type WithdrawResult, addCollectFeeToTx, calculateFee, executeAutoTopUp, executeWithGas, exportPrivateKey, formatSui, formatUsd, generateKeypair, getAddress, getGasStatus, getPoolPrice, getRates, getSentinelInfo, getSwapQuote, keypairFromPrivateKey, listSentinels, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, rawToUsdc, requestAttack, saveKey, attack as sentinelAttack, settleAttack, shouldAutoTopUp, simulateTransaction, solveHashcash, submitPrompt, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { EventEmitter } from 'eventemitter3';
2
2
  import { SuiClient } from '@mysten/sui/client';
3
3
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
4
- import { Transaction } from '@mysten/sui/transactions';
4
+ import { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions';
5
5
 
6
6
  interface T2000Options {
7
7
  keyPath?: string;
@@ -142,8 +142,39 @@ interface TransactionRecord {
142
142
  timestamp: number;
143
143
  gasMethod?: GasMethod;
144
144
  }
145
+ interface SentinelAgent {
146
+ id: string;
147
+ objectId: string;
148
+ name: string;
149
+ model: string;
150
+ systemPrompt: string;
151
+ attackFee: bigint;
152
+ prizePool: bigint;
153
+ totalAttacks: number;
154
+ successfulBreaches: number;
155
+ state: string;
156
+ }
157
+ interface SentinelVerdict {
158
+ success: boolean;
159
+ score: number;
160
+ agentResponse: string;
161
+ juryResponse: string;
162
+ funResponse: string;
163
+ signature: string;
164
+ timestampMs: number;
165
+ }
166
+ interface SentinelAttackResult {
167
+ attackObjectId: string;
168
+ sentinelId: string;
169
+ prompt: string;
170
+ verdict: SentinelVerdict;
171
+ requestTx: string;
172
+ settleTx: string;
173
+ won: boolean;
174
+ feePaid: number;
175
+ }
145
176
 
146
- type T2000ErrorCode = 'INSUFFICIENT_BALANCE' | 'INSUFFICIENT_GAS' | 'INVALID_ADDRESS' | 'INVALID_AMOUNT' | 'WALLET_NOT_FOUND' | 'WALLET_LOCKED' | 'WALLET_EXISTS' | 'SPONSOR_FAILED' | 'SPONSOR_RATE_LIMITED' | 'GAS_STATION_UNAVAILABLE' | 'GAS_FEE_EXCEEDED' | 'SIMULATION_FAILED' | 'TRANSACTION_FAILED' | 'ASSET_NOT_SUPPORTED' | 'SLIPPAGE_EXCEEDED' | 'HEALTH_FACTOR_TOO_LOW' | 'WITHDRAW_WOULD_LIQUIDATE' | 'NO_COLLATERAL' | 'PROTOCOL_PAUSED' | 'PROTOCOL_UNAVAILABLE' | 'RPC_ERROR' | 'RPC_UNREACHABLE' | 'SPONSOR_UNAVAILABLE' | 'AUTO_TOPUP_FAILED' | 'PRICE_EXCEEDS_LIMIT' | 'UNSUPPORTED_NETWORK' | 'PAYMENT_EXPIRED' | 'DUPLICATE_PAYMENT' | 'FACILITATOR_REJECTION' | 'FACILITATOR_TIMEOUT' | 'UNKNOWN';
177
+ type T2000ErrorCode = 'INSUFFICIENT_BALANCE' | 'INSUFFICIENT_GAS' | 'INVALID_ADDRESS' | 'INVALID_AMOUNT' | 'WALLET_NOT_FOUND' | 'WALLET_LOCKED' | 'WALLET_EXISTS' | 'SPONSOR_FAILED' | 'SPONSOR_RATE_LIMITED' | 'GAS_STATION_UNAVAILABLE' | 'GAS_FEE_EXCEEDED' | 'SIMULATION_FAILED' | 'TRANSACTION_FAILED' | 'ASSET_NOT_SUPPORTED' | 'SLIPPAGE_EXCEEDED' | 'HEALTH_FACTOR_TOO_LOW' | 'WITHDRAW_WOULD_LIQUIDATE' | 'NO_COLLATERAL' | 'PROTOCOL_PAUSED' | 'PROTOCOL_UNAVAILABLE' | 'RPC_ERROR' | 'RPC_UNREACHABLE' | 'SPONSOR_UNAVAILABLE' | 'AUTO_TOPUP_FAILED' | 'PRICE_EXCEEDS_LIMIT' | 'UNSUPPORTED_NETWORK' | 'PAYMENT_EXPIRED' | 'DUPLICATE_PAYMENT' | 'FACILITATOR_REJECTION' | 'FACILITATOR_TIMEOUT' | 'SENTINEL_API_ERROR' | 'SENTINEL_NOT_FOUND' | 'SENTINEL_TX_FAILED' | 'SENTINEL_TEE_ERROR' | 'UNKNOWN';
147
178
  interface T2000ErrorData {
148
179
  reason?: string;
149
180
  [key: string]: unknown;
@@ -277,6 +308,9 @@ declare class T2000 extends EventEmitter<T2000Events> {
277
308
  rates(): Promise<RatesResult>;
278
309
  earnings(): Promise<EarningsResult>;
279
310
  fundStatus(): Promise<FundStatusResult>;
311
+ sentinelList(): Promise<SentinelAgent[]>;
312
+ sentinelInfo(id: string): Promise<SentinelAgent>;
313
+ sentinelAttack(id: string, prompt: string, fee?: bigint): Promise<SentinelAttackResult>;
280
314
  private emitBalanceChange;
281
315
  }
282
316
 
@@ -299,6 +333,17 @@ declare const SUPPORTED_ASSETS: {
299
333
  };
300
334
  type SupportedAsset = keyof typeof SUPPORTED_ASSETS;
301
335
  declare const DEFAULT_NETWORK: "mainnet";
336
+ declare const SENTINEL: {
337
+ readonly PACKAGE: "0x88b83f36dafcd5f6dcdcf1d2cb5889b03f61264ab3cee9cae35db7aa940a21b7";
338
+ readonly AGENT_REGISTRY: "0xc47564f5f14c12b31e0dfa1a3dc99a6380a1edf8929c28cb0eaa3359c8db36ac";
339
+ readonly ENCLAVE: "0xfb1261aeb9583514cb1341a548a5ec12d1231bd96af22215f1792617a93e1213";
340
+ readonly PROTOCOL_CONFIG: "0x2fa4fa4a1dd0498612304635ff9334e1b922e78af325000e9d9c0e88adea459f";
341
+ readonly TEE_API: "https://app.suisentinel.xyz/api/consume-prompt";
342
+ readonly SENTINELS_API: "https://api.suisentinel.xyz/agents/mainnet";
343
+ readonly RANDOM: "0x8";
344
+ readonly MIN_FEE_MIST: 100000000n;
345
+ readonly MAX_PROMPT_TOKENS: 600;
346
+ };
302
347
 
303
348
  declare function validateAddress(address: string): string;
304
349
  declare function truncateAddress(address: string): string;
@@ -328,6 +373,12 @@ interface ProtocolFeeInfo {
328
373
  rawAmount: bigint;
329
374
  }
330
375
  declare function calculateFee(operation: FeeOperation, amount: number): ProtocolFeeInfo;
376
+ /**
377
+ * Add on-chain fee collection to an existing PTB via t2000::treasury::collect_fee().
378
+ * The Move function splits the fee from the payment coin and stores it in the
379
+ * Treasury's internal Balance<T>. Atomic — reverts with the operation if it fails.
380
+ */
381
+ declare function addCollectFeeToTx(tx: Transaction, paymentCoin: TransactionObjectArgument, operation: FeeOperation): void;
331
382
 
332
383
  interface SimulationResult {
333
384
  success: boolean;
@@ -351,6 +402,19 @@ declare function getSwapQuote(client: SuiClient, fromAsset: 'USDC' | 'SUI', toAs
351
402
 
352
403
  declare function getRates(client: SuiClient): Promise<RatesResult>;
353
404
 
405
+ declare function listSentinels(): Promise<SentinelAgent[]>;
406
+ declare function getSentinelInfo(client: SuiClient, sentinelObjectId: string): Promise<SentinelAgent>;
407
+ declare function requestAttack(client: SuiClient, signer: Ed25519Keypair, sentinelObjectId: string, feeMist: bigint): Promise<{
408
+ attackObjectId: string;
409
+ digest: string;
410
+ }>;
411
+ declare function submitPrompt(agentId: string, attackObjectId: string, prompt: string): Promise<SentinelVerdict>;
412
+ declare function settleAttack(client: SuiClient, signer: Ed25519Keypair, sentinelObjectId: string, attackObjectId: string, prompt: string, verdict: SentinelVerdict): Promise<{
413
+ digest: string;
414
+ success: boolean;
415
+ }>;
416
+ declare function attack(client: SuiClient, signer: Ed25519Keypair, sentinelId: string, prompt: string, feeMist?: bigint): Promise<SentinelAttackResult>;
417
+
354
418
  interface GasExecutionResult {
355
419
  digest: string;
356
420
  effects: unknown;
@@ -390,4 +454,4 @@ interface GasStatusResponse {
390
454
  }
391
455
  declare function getGasStatus(address?: string): Promise<GasStatusResponse>;
392
456
 
393
- export { type AutoTopUpResult, BPS_DENOMINATOR, type BalanceResponse, type BorrowResult, CLOCK_ID, DEFAULT_NETWORK, type DepositInfo, type EarningsResult, type FeeOperation, type FundStatusResult, type GasExecutionResult, type GasMethod, type GasRequestType, type GasReserve, type GasSponsorResponse, type GasStatusResponse, type HealthFactorResult, MIST_PER_SUI, type MaxBorrowResult, type MaxWithdrawResult, type PositionEntry, type PositionsResult, type ProtocolFeeInfo, type RatesResult, type RepayResult, SUI_DECIMALS, SUPPORTED_ASSETS, type SaveResult, type SendResult, type SimulationResult, type SupportedAsset, type SwapResult, T2000, T2000Error, type T2000ErrorCode, type T2000ErrorData, type T2000Options, type TransactionRecord, USDC_DECIMALS, type WithdrawResult, calculateFee, executeAutoTopUp, executeWithGas, exportPrivateKey, formatSui, formatUsd, generateKeypair, getAddress, getGasStatus, getPoolPrice, getRates, getSwapQuote, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, rawToUsdc, saveKey, shouldAutoTopUp, simulateTransaction, solveHashcash, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
457
+ export { type AutoTopUpResult, BPS_DENOMINATOR, type BalanceResponse, type BorrowResult, CLOCK_ID, DEFAULT_NETWORK, type DepositInfo, type EarningsResult, type FeeOperation, type FundStatusResult, type GasExecutionResult, type GasMethod, type GasRequestType, type GasReserve, type GasSponsorResponse, type GasStatusResponse, type HealthFactorResult, MIST_PER_SUI, type MaxBorrowResult, type MaxWithdrawResult, type PositionEntry, type PositionsResult, type ProtocolFeeInfo, type RatesResult, type RepayResult, SENTINEL, SUI_DECIMALS, SUPPORTED_ASSETS, type SaveResult, type SendResult, type SentinelAgent, type SentinelAttackResult, type SentinelVerdict, type SimulationResult, type SupportedAsset, type SwapResult, T2000, T2000Error, type T2000ErrorCode, type T2000ErrorData, type T2000Options, type TransactionRecord, USDC_DECIMALS, type WithdrawResult, addCollectFeeToTx, calculateFee, executeAutoTopUp, executeWithGas, exportPrivateKey, formatSui, formatUsd, generateKeypair, getAddress, getGasStatus, getPoolPrice, getRates, getSentinelInfo, getSwapQuote, keypairFromPrivateKey, listSentinels, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, rawToUsdc, requestAttack, saveKey, attack as sentinelAttack, settleAttack, shouldAutoTopUp, simulateTransaction, solveHashcash, submitPrompt, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ import { homedir } from 'os';
10
10
  import { Transaction } from '@mysten/sui/transactions';
11
11
  import { getPool, getCoins, mergeCoinsPTB, depositCoinPTB, getLendingState, withdrawCoinPTB, borrowCoinPTB, getHealthFactor as getHealthFactor$1, repayCoinPTB, getPriceFeeds, filterPriceFeeds, updateOraclePricesPTB } from '@naviprotocol/lending';
12
12
  import { CetusClmmSDK } from '@cetusprotocol/sui-clmm-sdk';
13
+ import { bcs } from '@mysten/sui/bcs';
13
14
 
14
15
  // src/t2000.ts
15
16
 
@@ -37,14 +38,26 @@ var SUPPORTED_ASSETS = {
37
38
  symbol: "SUI"
38
39
  }
39
40
  };
40
- process.env.T2000_PACKAGE_ID ?? "0x51c44bb2ad3ba608cf9adbc6e37ee67268ef9313a4ff70957d4c6e7955dc7eef";
41
- process.env.T2000_CONFIG_ID ?? "0xd30408960ac38eced670acc102df9e178b5b46b3a8c0e96a53ec2fd3f39b5936";
42
- process.env.T2000_TREASURY_ID ?? "0x2398c2759cfce40f1b0f2b3e524eeba9e8f6428fcb1d1e39235dd042d48defc8";
41
+ var T2000_PACKAGE_ID = process.env.T2000_PACKAGE_ID ?? "0xab92e9f1fe549ad3d6a52924a73181b45791e76120b975138fac9ec9b75db9f3";
42
+ var T2000_CONFIG_ID = process.env.T2000_CONFIG_ID ?? "0x408add9aa9322f93cfd87523d8f603006eb8713894f4c460283c58a6888dae8a";
43
+ var T2000_TREASURY_ID = process.env.T2000_TREASURY_ID ?? "0x3bb501b8300125dca59019247941a42af6b292a150ce3cfcce9449456be2ec91";
43
44
  var DEFAULT_NETWORK = "mainnet";
44
45
  var DEFAULT_RPC_URL = "https://fullnode.mainnet.sui.io:443";
45
46
  var DEFAULT_KEY_PATH = "~/.t2000/wallet.key";
46
47
  var API_BASE_URL = process.env.T2000_API_URL ?? "https://api.t2000.ai";
47
48
  var CETUS_USDC_SUI_POOL = "0x51e883ba7c0b566a26cbc8a94cd33eb0abd418a77cc1e60ad22fd9b1f29cd2ab";
49
+ var SENTINEL = {
50
+ PACKAGE: "0x88b83f36dafcd5f6dcdcf1d2cb5889b03f61264ab3cee9cae35db7aa940a21b7",
51
+ AGENT_REGISTRY: "0xc47564f5f14c12b31e0dfa1a3dc99a6380a1edf8929c28cb0eaa3359c8db36ac",
52
+ ENCLAVE: "0xfb1261aeb9583514cb1341a548a5ec12d1231bd96af22215f1792617a93e1213",
53
+ PROTOCOL_CONFIG: "0x2fa4fa4a1dd0498612304635ff9334e1b922e78af325000e9d9c0e88adea459f",
54
+ TEE_API: "https://app.suisentinel.xyz/api/consume-prompt",
55
+ SENTINELS_API: "https://api.suisentinel.xyz/agents/mainnet",
56
+ RANDOM: "0x8",
57
+ MIN_FEE_MIST: 100000000n,
58
+ // 0.1 SUI
59
+ MAX_PROMPT_TOKENS: 600
60
+ };
48
61
 
49
62
  // src/errors.ts
50
63
  var T2000Error = class extends Error {
@@ -87,7 +100,8 @@ function mapMoveAbortCode(code) {
87
100
  6: "Not authorized",
88
101
  7: "Package version mismatch \u2014 upgrade required",
89
102
  8: "Timelock is active \u2014 wait for expiry",
90
- 9: "No pending change to execute"
103
+ 9: "No pending change to execute",
104
+ 10: "Already at current version"
91
105
  };
92
106
  return abortMessages[code] ?? `Move abort code: ${code}`;
93
107
  }
@@ -358,6 +372,61 @@ function inferAction(txBlock) {
358
372
  if (kind === "ProgrammableTransaction") return "transaction";
359
373
  return kind ?? "unknown";
360
374
  }
375
+
376
+ // src/protocols/protocolFee.ts
377
+ var FEE_RATES = {
378
+ save: SAVE_FEE_BPS,
379
+ swap: SWAP_FEE_BPS,
380
+ borrow: BORROW_FEE_BPS
381
+ };
382
+ var OP_CODES = {
383
+ save: 0,
384
+ swap: 1,
385
+ borrow: 2
386
+ };
387
+ function calculateFee(operation, amount) {
388
+ const bps = FEE_RATES[operation];
389
+ const feeAmount = amount * Number(bps) / Number(BPS_DENOMINATOR);
390
+ const rawAmount = usdcToRaw(feeAmount);
391
+ return {
392
+ amount: feeAmount,
393
+ asset: "USDC",
394
+ rate: Number(bps) / Number(BPS_DENOMINATOR),
395
+ rawAmount
396
+ };
397
+ }
398
+ function addCollectFeeToTx(tx, paymentCoin, operation) {
399
+ const bps = FEE_RATES[operation];
400
+ if (bps <= 0n) return;
401
+ tx.moveCall({
402
+ target: `${T2000_PACKAGE_ID}::treasury::collect_fee`,
403
+ typeArguments: [SUPPORTED_ASSETS.USDC.type],
404
+ arguments: [
405
+ tx.object(T2000_TREASURY_ID),
406
+ tx.object(T2000_CONFIG_ID),
407
+ paymentCoin,
408
+ tx.pure.u8(OP_CODES[operation])
409
+ ]
410
+ });
411
+ }
412
+ async function reportFee(agentAddress, operation, feeAmount, feeRate, txDigest) {
413
+ try {
414
+ await fetch(`${API_BASE_URL}/api/fees`, {
415
+ method: "POST",
416
+ headers: { "Content-Type": "application/json" },
417
+ body: JSON.stringify({
418
+ agentAddress,
419
+ operation,
420
+ feeAmount: feeAmount.toString(),
421
+ feeRate: feeRate.toString(),
422
+ txDigest
423
+ })
424
+ });
425
+ } catch {
426
+ }
427
+ }
428
+
429
+ // src/protocols/navi.ts
361
430
  var ENV = { env: "prod" };
362
431
  var USDC_TYPE = SUPPORTED_ASSETS.USDC.type;
363
432
  var RATE_DECIMALS = 27;
@@ -400,7 +469,7 @@ async function updateOracle(tx, client, address) {
400
469
  } catch {
401
470
  }
402
471
  }
403
- async function buildSaveTx(client, address, amount) {
472
+ async function buildSaveTx(client, address, amount, options = {}) {
404
473
  const rawAmount = Number(usdcToRaw(amount));
405
474
  const coins = await getCoins(address, { coinType: USDC_TYPE, client });
406
475
  if (!coins || coins.length === 0) {
@@ -409,6 +478,9 @@ async function buildSaveTx(client, address, amount) {
409
478
  const tx = new Transaction();
410
479
  tx.setSender(address);
411
480
  const coinObj = mergeCoinsPTB(tx, coins, { balance: rawAmount });
481
+ if (options.collectFee) {
482
+ addCollectFeeToTx(tx, coinObj, "save");
483
+ }
412
484
  await depositCoinPTB(tx, USDC_TYPE, coinObj, ENV);
413
485
  return tx;
414
486
  }
@@ -426,12 +498,15 @@ async function buildWithdrawTx(client, address, amount) {
426
498
  tx.transferObjects([withdrawnCoin], address);
427
499
  return { tx, effectiveAmount };
428
500
  }
429
- async function buildBorrowTx(client, address, amount) {
501
+ async function buildBorrowTx(client, address, amount, options = {}) {
430
502
  const rawAmount = Number(usdcToRaw(amount));
431
503
  const tx = new Transaction();
432
504
  tx.setSender(address);
433
505
  await updateOracle(tx, client, address);
434
506
  const borrowedCoin = await borrowCoinPTB(tx, USDC_TYPE, rawAmount, ENV);
507
+ if (options.collectFee) {
508
+ addCollectFeeToTx(tx, borrowedCoin, "borrow");
509
+ }
435
510
  tx.transferObjects([borrowedCoin], address);
436
511
  return tx;
437
512
  }
@@ -639,40 +714,6 @@ async function getSwapQuote(client, fromAsset, toAsset, amount) {
639
714
  }
640
715
  }
641
716
 
642
- // src/protocols/protocolFee.ts
643
- var FEE_RATES = {
644
- save: SAVE_FEE_BPS,
645
- swap: SWAP_FEE_BPS,
646
- borrow: BORROW_FEE_BPS
647
- };
648
- function calculateFee(operation, amount) {
649
- const bps = FEE_RATES[operation];
650
- const feeAmount = amount * Number(bps) / Number(BPS_DENOMINATOR);
651
- const rawAmount = usdcToRaw(feeAmount);
652
- return {
653
- amount: feeAmount,
654
- asset: "USDC",
655
- rate: Number(bps) / Number(BPS_DENOMINATOR),
656
- rawAmount
657
- };
658
- }
659
- async function reportFee(agentAddress, operation, feeAmount, feeRate, txDigest) {
660
- try {
661
- await fetch(`${API_BASE_URL}/api/fees`, {
662
- method: "POST",
663
- headers: { "Content-Type": "application/json" },
664
- body: JSON.stringify({
665
- agentAddress,
666
- operation,
667
- feeAmount: feeAmount.toString(),
668
- feeRate: feeRate.toString(),
669
- txDigest
670
- })
671
- });
672
- } catch {
673
- }
674
- }
675
-
676
717
  // src/protocols/yieldTracker.ts
677
718
  async function getEarnings(client, keypair) {
678
719
  const hf = await getHealthFactor(client, keypair);
@@ -699,6 +740,190 @@ async function getFundStatus(client, keypair) {
699
740
  projectedMonthly: earnings.dailyEarning * 30
700
741
  };
701
742
  }
743
+ function mapAgent(raw) {
744
+ return {
745
+ id: raw.agent_id,
746
+ objectId: raw.agent_object_id,
747
+ name: raw.agent_name,
748
+ model: raw.model ?? "unknown",
749
+ systemPrompt: raw.prompt,
750
+ attackFee: BigInt(raw.cost_per_message),
751
+ prizePool: BigInt(raw.total_balance),
752
+ totalAttacks: raw.total_attacks,
753
+ successfulBreaches: raw.successful_breaches ?? 0,
754
+ state: raw.state
755
+ };
756
+ }
757
+ async function listSentinels() {
758
+ const res = await fetch(SENTINEL.SENTINELS_API);
759
+ if (!res.ok) {
760
+ throw new T2000Error("SENTINEL_API_ERROR", `Sentinel API returned ${res.status}`);
761
+ }
762
+ const data = await res.json();
763
+ if (!Array.isArray(data.agents)) {
764
+ throw new T2000Error("SENTINEL_API_ERROR", "Unexpected API response shape");
765
+ }
766
+ return data.agents.filter((a) => a.state === "active").map(mapAgent);
767
+ }
768
+ async function getSentinelInfo(client, sentinelObjectId) {
769
+ const agents = await listSentinels();
770
+ const match = agents.find((a) => a.objectId === sentinelObjectId || a.id === sentinelObjectId);
771
+ if (match) return match;
772
+ const obj = await client.getObject({
773
+ id: sentinelObjectId,
774
+ options: { showContent: true, showType: true }
775
+ });
776
+ if (!obj.data) {
777
+ throw new T2000Error("SENTINEL_NOT_FOUND", `Sentinel ${sentinelObjectId} not found on-chain`);
778
+ }
779
+ const content = obj.data.content;
780
+ if (!content || content.dataType !== "moveObject") {
781
+ throw new T2000Error("SENTINEL_NOT_FOUND", `Object ${sentinelObjectId} is not a Move object`);
782
+ }
783
+ const fields = content.fields;
784
+ return {
785
+ id: fields.id?.id ?? sentinelObjectId,
786
+ objectId: sentinelObjectId,
787
+ name: fields.name ?? "Unknown",
788
+ model: fields.model ?? "unknown",
789
+ systemPrompt: fields.system_prompt ?? "",
790
+ attackFee: BigInt(fields.cost_per_message ?? "0"),
791
+ prizePool: BigInt(fields.balance ?? "0"),
792
+ totalAttacks: Number(fields.total_attacks ?? "0"),
793
+ successfulBreaches: Number(fields.successful_breaches ?? "0"),
794
+ state: fields.state ?? "unknown"
795
+ };
796
+ }
797
+ async function requestAttack(client, signer, sentinelObjectId, feeMist) {
798
+ if (feeMist < SENTINEL.MIN_FEE_MIST) {
799
+ throw new T2000Error("INVALID_AMOUNT", `Attack fee must be at least 0.1 SUI (${SENTINEL.MIN_FEE_MIST} MIST)`);
800
+ }
801
+ const tx = new Transaction();
802
+ const [coin] = tx.splitCoins(tx.gas, [Number(feeMist)]);
803
+ const [attack2] = tx.moveCall({
804
+ target: `${SENTINEL.PACKAGE}::sentinel::request_attack`,
805
+ arguments: [
806
+ tx.object(SENTINEL.AGENT_REGISTRY),
807
+ tx.object(sentinelObjectId),
808
+ tx.object(SENTINEL.PROTOCOL_CONFIG),
809
+ coin,
810
+ tx.object(SENTINEL.RANDOM),
811
+ tx.object(CLOCK_ID)
812
+ ]
813
+ });
814
+ const address = signer.toSuiAddress();
815
+ tx.transferObjects([attack2], address);
816
+ const result = await client.signAndExecuteTransaction({
817
+ signer,
818
+ transaction: tx,
819
+ options: { showObjectChanges: true, showEffects: true }
820
+ });
821
+ await client.waitForTransaction({ digest: result.digest });
822
+ const attackObj = result.objectChanges?.find(
823
+ (c) => c.type === "created" && c.objectType?.includes("::sentinel::Attack")
824
+ );
825
+ const attackObjectId = attackObj && "objectId" in attackObj ? attackObj.objectId : void 0;
826
+ if (!attackObjectId) {
827
+ throw new T2000Error("SENTINEL_TX_FAILED", "Attack object was not created \u2014 transaction may have failed");
828
+ }
829
+ return { attackObjectId, digest: result.digest };
830
+ }
831
+ async function submitPrompt(agentId, attackObjectId, prompt) {
832
+ const res = await fetch(SENTINEL.TEE_API, {
833
+ method: "POST",
834
+ headers: { "Content-Type": "application/json" },
835
+ body: JSON.stringify({
836
+ agent_id: agentId,
837
+ attack_object_id: attackObjectId,
838
+ message: prompt
839
+ })
840
+ });
841
+ if (!res.ok) {
842
+ const body = await res.text().catch(() => "");
843
+ throw new T2000Error("SENTINEL_TEE_ERROR", `TEE returned ${res.status}: ${body.slice(0, 200)}`);
844
+ }
845
+ const raw = await res.json();
846
+ const envelope = raw.response ?? raw;
847
+ const data = envelope.data ?? envelope;
848
+ const signature = raw.signature ?? data.signature;
849
+ const timestampMs = envelope.timestamp_ms ?? data.timestamp_ms;
850
+ if (typeof signature !== "string") {
851
+ throw new T2000Error("SENTINEL_TEE_ERROR", "TEE response missing signature");
852
+ }
853
+ return {
854
+ success: data.success ?? data.is_success,
855
+ score: data.score,
856
+ agentResponse: data.agent_response,
857
+ juryResponse: data.jury_response,
858
+ funResponse: data.fun_response ?? "",
859
+ signature,
860
+ timestampMs
861
+ };
862
+ }
863
+ async function settleAttack(client, signer, sentinelObjectId, attackObjectId, prompt, verdict) {
864
+ const sigBytes = Array.from(Buffer.from(verdict.signature.replace(/^0x/, ""), "hex"));
865
+ const tx = new Transaction();
866
+ tx.moveCall({
867
+ target: `${SENTINEL.PACKAGE}::sentinel::consume_prompt`,
868
+ arguments: [
869
+ tx.object(SENTINEL.AGENT_REGISTRY),
870
+ tx.object(SENTINEL.PROTOCOL_CONFIG),
871
+ tx.object(sentinelObjectId),
872
+ tx.pure.bool(verdict.success),
873
+ tx.pure.string(verdict.agentResponse),
874
+ tx.pure.string(verdict.juryResponse),
875
+ tx.pure.string(verdict.funResponse),
876
+ tx.pure.string(prompt),
877
+ tx.pure.u8(verdict.score),
878
+ tx.pure.u64(verdict.timestampMs),
879
+ tx.pure(bcs.vector(bcs.u8()).serialize(sigBytes)),
880
+ tx.object(SENTINEL.ENCLAVE),
881
+ tx.object(attackObjectId),
882
+ tx.object(CLOCK_ID)
883
+ ]
884
+ });
885
+ const result = await client.signAndExecuteTransaction({
886
+ signer,
887
+ transaction: tx,
888
+ options: { showEffects: true }
889
+ });
890
+ await client.waitForTransaction({ digest: result.digest });
891
+ const txSuccess = result.effects?.status?.status === "success";
892
+ return { digest: result.digest, success: txSuccess };
893
+ }
894
+ async function attack(client, signer, sentinelId, prompt, feeMist) {
895
+ const sentinel = await getSentinelInfo(client, sentinelId);
896
+ const fee = feeMist ?? sentinel.attackFee;
897
+ if (fee < SENTINEL.MIN_FEE_MIST) {
898
+ throw new T2000Error("INVALID_AMOUNT", `Attack fee must be at least 0.1 SUI`);
899
+ }
900
+ const { attackObjectId, digest: requestTx } = await requestAttack(
901
+ client,
902
+ signer,
903
+ sentinel.objectId,
904
+ fee
905
+ );
906
+ const verdict = await submitPrompt(sentinel.id, attackObjectId, prompt);
907
+ const { digest: settleTx } = await settleAttack(
908
+ client,
909
+ signer,
910
+ sentinel.objectId,
911
+ attackObjectId,
912
+ prompt,
913
+ verdict
914
+ );
915
+ const won = verdict.success && verdict.score >= 70;
916
+ return {
917
+ attackObjectId,
918
+ sentinelId: sentinel.id,
919
+ prompt,
920
+ verdict,
921
+ requestTx,
922
+ settleTx,
923
+ won,
924
+ feePaid: Number(fee) / Number(MIST_PER_SUI)
925
+ };
926
+ }
702
927
  function hasLeadingZeroBits(hash, bits) {
703
928
  const fullBytes = Math.floor(bits / 8);
704
929
  const remainingBits = bits % 8;
@@ -1081,12 +1306,12 @@ var T2000 = class _T2000 extends EventEmitter {
1081
1306
  const gasResult = await executeWithGas(
1082
1307
  this.client,
1083
1308
  this.keypair,
1084
- () => buildSaveTx(this.client, this._address, saveAmount)
1309
+ () => buildSaveTx(this.client, this._address, saveAmount, { collectFee: true })
1085
1310
  );
1086
1311
  const rates = await getRates(this.client);
1087
1312
  reportFee(this._address, "save", fee.amount, fee.rate, gasResult.digest);
1088
1313
  this.emitBalanceChange("USDC", saveAmount, "save", gasResult.digest);
1089
- let savingsBalance = saveAmount - fee.amount;
1314
+ let savingsBalance = saveAmount;
1090
1315
  try {
1091
1316
  const positions = await this.positions();
1092
1317
  savingsBalance = positions.positions.filter((p) => p.type === "save").reduce((sum, p) => sum + p.amount, 0);
@@ -1170,7 +1395,7 @@ var T2000 = class _T2000 extends EventEmitter {
1170
1395
  const gasResult = await executeWithGas(
1171
1396
  this.client,
1172
1397
  this.keypair,
1173
- () => buildBorrowTx(this.client, this._address, borrowAmount)
1398
+ () => buildBorrowTx(this.client, this._address, borrowAmount, { collectFee: true })
1174
1399
  );
1175
1400
  const hf = await getHealthFactor(this.client, this.keypair);
1176
1401
  reportFee(this._address, "borrow", fee.amount, fee.rate, gasResult.digest);
@@ -1316,6 +1541,16 @@ var T2000 = class _T2000 extends EventEmitter {
1316
1541
  async fundStatus() {
1317
1542
  return getFundStatus(this.client, this.keypair);
1318
1543
  }
1544
+ // -- Sentinel --
1545
+ async sentinelList() {
1546
+ return listSentinels();
1547
+ }
1548
+ async sentinelInfo(id) {
1549
+ return getSentinelInfo(this.client, id);
1550
+ }
1551
+ async sentinelAttack(id, prompt, fee) {
1552
+ return attack(this.client, this.keypair, id, prompt, fee);
1553
+ }
1319
1554
  // -- Helpers --
1320
1555
  emitBalanceChange(asset, amount, cause, tx) {
1321
1556
  this.emit("balanceChange", { asset, previous: 0, current: 0, cause, tx });
@@ -1415,6 +1650,6 @@ function parseMoveAbort(errorStr) {
1415
1650
  return { reason: errorStr };
1416
1651
  }
1417
1652
 
1418
- export { BPS_DENOMINATOR, CLOCK_ID, DEFAULT_NETWORK, MIST_PER_SUI, SUI_DECIMALS, SUPPORTED_ASSETS, T2000, T2000Error, USDC_DECIMALS, calculateFee, executeAutoTopUp, executeWithGas, exportPrivateKey, formatSui, formatUsd, generateKeypair, getAddress, getGasStatus, getPoolPrice, getRates, getSwapQuote, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, rawToUsdc, saveKey, shouldAutoTopUp, simulateTransaction, solveHashcash, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
1653
+ export { BPS_DENOMINATOR, CLOCK_ID, DEFAULT_NETWORK, MIST_PER_SUI, SENTINEL, SUI_DECIMALS, SUPPORTED_ASSETS, T2000, T2000Error, USDC_DECIMALS, addCollectFeeToTx, calculateFee, executeAutoTopUp, executeWithGas, exportPrivateKey, formatSui, formatUsd, generateKeypair, getAddress, getGasStatus, getPoolPrice, getRates, getSentinelInfo, getSwapQuote, keypairFromPrivateKey, listSentinels, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, rawToUsdc, requestAttack, saveKey, attack as sentinelAttack, settleAttack, shouldAutoTopUp, simulateTransaction, solveHashcash, submitPrompt, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
1419
1654
  //# sourceMappingURL=index.js.map
1420
1655
  //# sourceMappingURL=index.js.map