07 · API reference
Every public export of @ballast/sdk, with real signatures from
packages/sdk/src. Two entry points:
@ballast/sdk: the full surface (client + PTB builders + reads). It imports@mysten/suiv1.@ballast/sdk/parse: the dependency-free subset (types, presets, targets, parsers, attestation interface). It has no@mysten/suiimport, so it is safe from any app.
@ballast/sdk re-exports everything in @ballast/sdk/parse, so the full package
is a superset.
BallastClient
new BallastClient(opts: BallastClientOptions)
interface BallastClientOptions {
packageId: string; // Ballast call target (v3)
deepbookPackageId: string; // DeepBook package the live pools accept
client?: SuiClient; // an existing client, or…
rpcUrl?: string; // …an RPC url, or…
network?: 'testnet' | 'mainnet' | 'devnet' | 'localnet'; // …a network (default 'testnet')
signer?: Keypair; // required for writes
attestation?: AttestationProvider; // default: MockAttestationProvider
}
| Member | Signature | Notes |
|---|---|---|
client |
SuiClient |
the underlying read client |
packageId / deepbookPackageId |
string |
as passed |
attestation |
AttestationProvider |
the active provider |
address |
get(): string \| undefined |
the signer’s Sui address |
getCapState |
(capId: string) => Promise<CapState> |
live cap read |
getIdentityState |
(identityId: string) => Promise<IdentityState> |
live identity read |
getReputation |
(identityId: string) => Promise<bigint> |
convenience |
mintIdentity |
(label: string) => Promise<{ identityId: string; digest: string }> |
shared AgentIdentity |
issueCap |
(limits: Limits) => Promise<{ capId: string; digest: string }> |
mint + share a BallastCap |
revokeCap |
(capId: string) => Promise<{ digest: string }> |
owner-only |
depositSui |
(balanceManagerId: string, amount: bigint) => Promise<{ digest: string }> |
DeepBook venue glue |
executeGated |
(p: ExecuteGatedParams) => Promise<GatedResult> |
the headline; act through the cap |
executeGated behavior. It reads the pool’s type args (unless typeArgs is
given), asks the attestation provider to attest(...), builds either
execute_trade (mock) or execute_trade_attested (when the provider exposes an
enclaveId), sets an explicit gas budget so even a rejected action commits a
digest, submits, and returns a typed GatedResult. A capability violation is
{ ok: false }, never a throw.
PTB builders (pure)
Each returns an unsigned Transaction you can sign anywhere (e.g. a wallet).
buildMintIdentityTx(packageId: string, label: string): Transaction
buildIssueCapTx(packageId: string, a: IssueCapArgs): Transaction
buildRevokeTx(packageId: string, capId: string): Transaction
buildExecuteGatedTx(a: ExecuteGatedTxArgs): Transaction
buildExecuteAttestedTx(a: ExecuteAttestedTxArgs): Transaction
buildDepositTx(deepbookPackageId: string, balanceManagerId: string, coinType: string, amount: bigint): Transaction
interface IssueCapArgs {
identityId: string; spendLimit: bigint; maxLeverageBps: bigint;
allowedMarkets: string[]; expiryMs: bigint;
}
interface ExecuteGatedTxArgs {
packageId: string; identityId: string; capId: string; poolId: string;
balanceManagerId: string; typeArgs: [string, string]; amount: bigint;
leverageBps: bigint; isBid: boolean; payWithDeep: boolean;
clientOrderId: bigint; attestation: Attestation;
}
interface ExecuteAttestedTxArgs {
packageId: string; identityId: string; capId: string; poolId: string;
balanceManagerId: string; enclaveId: string; typeArgs: [string, string];
amount: bigint; leverageBps: bigint; isBid: boolean; payWithDeep: boolean;
clientOrderId: bigint; timestampMs: bigint; sig: Uint8Array;
}
Builder arg order mirrors the Move signatures exactly. See
MOVE_TARGETS.
Reads (pure parsers + client reads)
getCapState(client: SuiClient, capId: string): Promise<CapState>
getIdentityState(client: SuiClient, identityId: string): Promise<IdentityState>
readPoolTypeArgs(client: SuiClient, poolId: string): Promise<[string, string]>
// pure (operate on already-fetched JSON):
parseCapState(obj: unknown): CapState
parseIdentityState(obj: unknown): IdentityState
parseTradeExecuted(events: unknown[] | null | undefined): TradeExecutedEvent | undefined
extractAbortCode(errText: string | null | undefined): number | undefined
abortReason(code: number | undefined): string
ABORT_REASONS: Record<number, string>
ABORT_REASONS: 1 capability revoked · 2 capability expired · 3 market not
allowed · 4 leverage exceeds the cap · 5 spend exceeds the cap · 6 caller is
not the owner.
MOVE_TARGETS
Stable call-target strings (the single source of truth for which on-chain functions to call):
MOVE_TARGETS.identityMint(pkg) // `${pkg}::identity::mint`
MOVE_TARGETS.capabilityIssue(pkg) // `${pkg}::capability::issue`
MOVE_TARGETS.capabilityRevoke(pkg) // `${pkg}::capability::revoke`
MOVE_TARGETS.tradingExecute(pkg) // `${pkg}::trading::execute_trade`
MOVE_TARGETS.tradingExecuteAttested(pkg) // `${pkg}::trading::execute_trade_attested`
MOVE_TARGETS.deepbookDeposit(deepbookPkg) // `${deepbookPkg}::balance_manager::deposit`
Presets
TESTNET: BallastNetwork // the reference deployment (mirrors DEPLOYMENTS.md)
TESTNET_ORIGIN_PACKAGE: string // 0xe12fe8ef… — match `${ORIGIN}::trading::TradeExecuted`
SUI_TYPE / DBUSDC_TYPE / DEEP_TYPE: string
SUI: bigint // 1_000_000_000n (one SUI in MIST)
CLOCK_ID: string // '0x6'
Types
interface BallastNetwork { packageId; deepbookPackageId; identityId; balanceManagerId; poolId: string }
interface Limits { identityId: string; spendLimit: bigint; maxLeverage: number; allowedMarkets: string[]; expiryMs: number }
interface CapState { spendLimit; spent; remaining; maxLeverageBps; expiryMs: bigint; allowedMarkets: string[]; revoked: boolean; owner; agent: string }
interface IdentityState { label: string; reputation; actionsOk; actionsBlocked: bigint; owner: string }
interface TradeExecutedEvent { agent; cap; pool; amount; is_bid; leverage_bps; client_order_id; reputation }
interface ExecuteGatedParams { identityId; capId; poolId; balanceManagerId: string; amount: bigint; isBid: boolean; leverage?: number; payWithDeep?: boolean; clientOrderId?: bigint; typeArgs?: [string,string]; gasBudget?: bigint }
type GatedResult =
| { ok: true; digest: string; filled: string; reputation: string; event?: TradeExecutedEvent }
| { ok: false; digest?: string; abortCode?: number; abortReason: string };
The attestation seam
The point of the design: executeGated only ever calls provider.attest(...), so
a real TEE provider drops in with zero call-site change.
interface AttestationContext { agent: string; market: string; amount: bigint; isBid: boolean; ts: number }
interface Attestation { payload: Uint8Array; sig: Uint8Array; timestampMs?: bigint }
interface AttestationProvider { attest(ctx: AttestationContext): Promise<Attestation> | Attestation }
class MockAttestationProvider implements AttestationProvider { /* dev: JSON payload + dummy sig */ }
interface NautilusOptions { enclaveUrl: string; enclaveId: string; fetchImpl?: typeof fetch }
class NautilusAttestationProvider implements AttestationProvider {
readonly enclaveId: string;
constructor(opts: NautilusOptions);
attest(ctx: AttestationContext): Promise<Attestation>; // POSTs to the enclave /process_data
}
The presence of enclaveId on the provider is what marks a client as attested and
routes executeGated to execute_trade_attested.