@neardefi/shade-agent-js
Version:
A library for creating Shade Agent agents in JavaScript and TypeScript
199 lines (193 loc) • 8.36 kB
text/typescript
import { Provider } from '@near-js/providers';
import { SerializedReturnValue, BlockReference, TxExecutionStatus } from '@near-js/types';
interface TcbInfo {
mrtd: string;
rtmr0: string;
rtmr1: string;
rtmr2: string;
rtmr3: string;
os_image_hash: string;
compose_hash: string;
device_id: string;
app_compose: string;
event_log: EventLog[];
}
interface EventLog {
imr: number;
event_type: number;
digest: string;
event: string;
event_payload: string;
}
interface DstackAttestationForContract {
quote: number[];
collateral: {
pck_crl_issuer_chain: string;
root_ca_crl: string;
pck_crl: string;
tcb_info_issuer_chain: string;
tcb_info: string;
tcb_info_signature: string;
qe_identity_issuer_chain: string;
qe_identity: string;
qe_identity_signature: string;
};
tcb_info: TcbInfo;
}
interface Measurements {
/** MRTD (Measurement of Root of Trust for Data) - identifies the virtual firmware. */
mrtd: string;
/** RTMR0 (Runtime Measurement Register 0) - typically measures the bootloader, virtual firmware data, and configuration. */
rtmr0: string;
/** RTMR1 (Runtime Measurement Register 1) - typically measures the OS kernel, boot parameters, and initrd (initial ramdisk). */
rtmr1: string;
/** RTMR2 (Runtime Measurement Register 2) - typically measures the OS application. */
rtmr2: string;
}
interface FullMeasurements {
/** Expected RTMRs (Runtime Measurement Registers). */
rtmrs: Measurements;
/** Expected digest for the key-provider event. */
key_provider_event_digest: string;
/** Expected app_compose hash payload. */
app_compose_hash_payload: string;
}
/**
* Configuration object for creating a ShadeClient instance
*/
interface ShadeConfig {
/** Network ID ('testnet' or 'mainnet'), defaults to 'testnet' if not provided */
networkId?: "testnet" | "mainnet";
/** The NEAR contract ID for the agent contract */
agentContractId?: string;
/** Sponsor account configuration for funding the agent account */
sponsor?: {
/** The sponsor's NEAR account ID */
accountId: string;
/** The sponsor's private key */
privateKey: string;
};
/** Custom NEAR RPC provider. If not provided, a default provider will be created based on networkId */
rpc?: Provider;
/** Number of keys to use for the agent (1-100), defaults to 1 if not provided */
numKeys?: number;
/** Derivation path for deterministic key generation for local testing (needs to be a randomly unique string)*/
derivationPath?: string;
}
declare class ShadeClient {
private config;
private dstackClient;
private agentAccountId;
private agentPrivateKeys;
private currentKeyIndex;
private keysDerivedWithTEE;
private keysChecked;
private constructor();
/**
* Creates a new ShadeClient instance asynchronously
* @param config - Configuration object for the Shade client (see ShadeConfig interface for details)
* @returns Promise that resolves to a ShadeClient instance
* @throws Error if configuration is invalid, network ID mismatch, or key generation fails
*/
static create(config: ShadeConfig): Promise<ShadeClient>;
/**
* Gets the NEAR account ID of the agent
* @returns The agent's account ID
*/
accountId(): string;
/**
* Gets the NEAR balance of the agent account in human readable format (e.g. 1 = one NEAR)
* @returns Promise that resolves to the account balance in NEAR tokens, if the agent account does not exist, returns 0
* @throws Error if network request fails
*/
balance(): Promise<number>;
/**
* Registers the agent in the agent contract.
*
* @param params
* @param params.deposit Attached deposit in yoctoNEAR when storage is required or when `forceDeposit` is `true` (defaults to `5000000000000000000000` — 0.005 NEAR)
* @param params.forceDeposit If `true`, always attach `deposit` (or the default) and skip `get_agent`. If `false`, attach no deposit and skip `get_agent`. If omitted, use `get_agent` to decide.
* @returns Promise that resolves to true if registration was successful
* @throws Error if agentContractId is not configured, if fetching attestation fails, or if the contract call fails
*/
register(params?: {
deposit?: bigint | string | number;
forceDeposit?: boolean;
}): Promise<boolean>;
/**
* Call a view function on the agent contract and return the result
* @param params
* @param params.methodName The method that will be called
* @param params.args Arguments as a valid JSON Object
* @param params.blockQuery (optional) Block reference for the query
* @returns A promise that resolves with the result of the view function call
* @throws Error if agentContractId is not configured or if RPC call fails
*/
view<T extends SerializedReturnValue>(params: {
methodName: string;
args: Record<string, unknown>;
blockQuery?: BlockReference;
}): Promise<T>;
/**
* Call a function on the agent contract and return the result
* @param params
* @param params.methodName The method that will be called
* @param params.args Arguments, either as a valid JSON Object or a raw Uint8Array
* @param params.deposit (optional) Amount of NEAR Tokens to attach to the call
* @param params.gas (optional) Amount of GAS to use attach to the call
* @param params.waitUntil (optional) Transaction finality to wait for
* @returns A promise that resolves with the result of the contract function call
* @throws Error if agentContractId is not configured, if key derivation fails, or if transaction fails
*/
call<T extends SerializedReturnValue>(params: {
methodName: string;
args: Uint8Array | Record<string, any>;
deposit?: bigint | string | number;
gas?: bigint | string | number;
waitUntil?: TxExecutionStatus;
}): Promise<T>;
/**
* Gets the TEE attestation for the agent in contract format (ready to be sent to the contract)
* @returns Promise that resolves to the contract-formatted attestation object
* @throws Error if fetching quote collateral fails (network errors, HTTP errors, timeouts)
*/
getAttestation(): Promise<DstackAttestationForContract>;
/**
* Funds the agent account with NEAR tokens from the sponsor account
* @param fundAmount - Amount of NEAR tokens to transfer to the agent account in human readable format (e.g. 1 = one NEAR)
* @returns Promise that resolves when funding is complete
* @throws Error if sponsor is not configured or if transfer fails after retries
*/
fund(fundAmount: number): Promise<void>;
/**
* Gets the agent's private keys (use with caution)
* @param params - Must pass `{ acknowledgeRisk: true }`
* @returns Array of private key strings
*/
getPrivateKeys(params: {
acknowledgeRisk: true;
}): string[];
/**
* Checks if the agent is whitelisted for local mode
* @returns Promise that resolves to true if the agent is whitelisted, false if the agent is not whitelisted, or null if the agent contract requires TEE
* @throws Error if agentContractId is not configured or if view call fails
*/
isWhitelisted(): Promise<boolean | null>;
}
/**
* Sanitization utilities to prevent private key leaks in error messages and logs.
*/
/**
* Sanitizes any value: strings, objects, Errors, and primitives.
* Redacts private key patterns and sensitive keys (privateKey, secretKey, etc.).
* Returns values that cannot contain a private key as-is.
*
* - string → sanitized string
* - Error → new Error with sanitized message
* - object/array → redacted copy
* - null/undefined/number/boolean/symbol/bigint → returned as-is
*/
declare function sanitize(value: unknown): unknown;
/** Returns an Error suitable for throwing. Use: throw toThrowable(caughtError) */
declare function toThrowable(error: unknown): Error;
export { type DstackAttestationForContract, type FullMeasurements, type Measurements, ShadeClient, type ShadeConfig, sanitize, toThrowable };