> For the complete documentation index, see [llms.txt](https://docs.mimic.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.mimic.fi/developers/sdk.md).

# SDK

The Mimic Protocol SDK provides a TypeScript client to interact with the Mimic Protocol blockchain automation platform. It offers a developer-friendly interface for managing functions, triggers, executions, and intents.

## Getting Started

You can install Mimic Protocol's SDK by running the following command line:

```bash
yarn add @mimicprotocol/sdk
```

### **Basic Client Initialization**

```typescript
import { Client } from '@mimicprotocol/sdk'

// Basic client with default configuration
const client = new Client()

// Client with custom base URL
const client = new Client({
  baseUrl: 'https://api-protocol.mimic.fi'
})
```

### **Client with Authentication**

```typescript
import { Client, ApiKeyAuth, BearerAuth } from '@mimicprotocol/sdk'

// Using API key authentication
const client = new Client({
  auth: new ApiKeyAuth('your-api-key')
})

// Using Bearer token authentication
const client = new Client({
  auth: new BearerAuth('your-bearer-token')
})
```

### **Client with Signer**

```typescript
import { Client, EthersSigner } from '@mimicprotocol/sdk'
import { ethers } from 'ethers'

// Using private key
const signer = EthersSigner.fromPrivateKey('0x...')
const client = new Client({
  signer
})

// Using JSON-RPC signer (e.g., MetaMask)
const provider = new ethers.BrowserProvider(window.ethereum)
const jsonRpcSigner = await provider.getSigner()
const signer = EthersSigner.fromJsonRpcSigner(jsonRpcSigner)
const client = new Client({
  signer
})

// Using browser wallet directly
import { WindowEthereumSigner } from '@mimicprotocol/sdk'

const signer = new WindowEthereumSigner('0x...') // wallet address
const client = new Client({
  signer
})
```

## Domain Clients

The SDK is organized into domain-specific clients, each handling a specific aspect of the protocol.

### **Balances**

Query balance entries and compute totals.

```typescript
import type { Balances, BalanceTotal } from '@mimicprotocol/sdk'

// List balances (optionally filter by address)
const balances: Balances = await client.balances.get({
  address: '0x...',
  limit: 20,
  offset: 0,
})

// Get total balance for a specific address
const total: BalanceTotal = await client.balances.getTotal('0x...')
console.log(total.address, total.balance)

// Pagination
const nextPage: Balances = await client.balances.get({ offset: 20, limit: 20 })
```

### **Functions**

Manage WASM functions and their manifests.

```typescript
import type { Function, Functions, Manifest } from '@mimicprotocol/sdk'

// List all functions
const functions: Functions = await client.functions.get()

// List functions with filters
const functionsFiltered: Functions = await client.functions.get({
  creator: '0x...',
  limit: 10,
  offset: 0
})

// Get specific function by CID
const function: Function = await client.functions.getByCid('Qm...')

// Get function manifest
const manifest: Manifest = await client.functions.getManifest('Qm...')

// Download WASM binary
const wasmBlob: Blob = await client.functions.getWasm('Qm...')

// Create new function (requires API key authentication)
const newFunction: Function = await client.functions.create({
  manifestFile: new File([manifestJson], 'manifest.json', { type: 'application/json' }),
  wasmFile: new File([wasmBytes], 'function.wasm', { type: 'application/wasm' })
})
```

### **Triggers**

Manage function triggers and their lifecycle. Triggers define how and when functions should be executed.

```typescript
import { Trigger, TriggerType } from '@mimicprotocol/sdk'

// List all triggers
const triggers: Trigger[] = await client.triggers.get()

// List triggers with filters
const triggers = await client.triggers.get({
  sigs: ['0x...', '0x...'],           // specific signatures
  functionCid: 'Qm...',               // filter by function
  signer: '0x...',                    // filter by creator
  active: true,                       // filter by status
  createdAfter: Date.parse('2024-01-01'),
  createdBefore: Date.parse('2024-12-31'),
  offset: 0,
  limit: 20,
})

// Get specific trigger by signature
const trigger: Trigger = await client.triggers.getBySignature('0x...')

// Create and sign a new trigger (requires signer)
const newTrigger: Trigger = await client.triggers.signAndCreate({
  description: 'Daily DCA automation',
  functionCid: 'Qm...',
  version: '1.0.0',
  manifest: { /* function manifest with inputs definition */ },
  config: {
    type: TriggerType.Cron,           // or TriggerType.Event or TriggerType.Once
    schedule: '0 0 * * *',            // cron expression (daily at midnight)
    delta: '1h',                      // execution window
    endDate: 0                        // 0 = no end date
  },
  input: { 
    token: '0x...', 
    amount: '1000000000000000000'     // must match manifest inputs
  },
  executionFeeLimit: '1000000000000000000',  // max fee in wei
  minValidations: 1                   // minimum validations required
})

// Deactivate one or more triggers (requires signer)
await client.triggers.signAndDeactivate(['0x...'])
await client.triggers.signAndDeactivate(['0x...', '0x...'])

// Check if trigger is expired
const isExpired: boolean = client.triggers.isExpired(trigger)

// Get next execution timestamp for cron triggers
const nextExecution: number = client.triggers.getNextExecutionTimestamp('0 0 * * *', Date.now())
```

Trigger deactivation supports batching. A single signature can deactivate multiple triggers as long as they belong to the same signer.

### **Trigger Config Types**

#### **Cron Trigger Config**

```typescript
{
  type: TriggerType.Cron,
  schedule: '0 0 * * *',    // cron expression
  delta: '1h',              // execution window (e.g., '30m', '2h', '1d')
  endDate: 0                // timestamp or 0 for no end
}
```

#### **Event Trigger Config**

```typescript
{
  type: TriggerType.Event,
  chainId: 1,               // blockchain chain ID
  contract: '0x...',        // contract address to monitor
  topics: [['0x...']],      // event topics by indexed position (1-4 topic arrays)
  delta: '1h',              // execution window
  endDate: 0                // timestamp or 0 for no end
}
```

For example, if you want to track:

```typescript
topic0: '0x1'
topic1: any
topic2: '0x2' OR '0x3'
```

you should set `topics` to:

```typescript
[
  ['0x1'],
  [],
  ['0x2', '0x3'],
]
```

#### **Once Trigger Config**

```typescript
{
  type: TriggerType.Once,
  startDate: 1769615762929, // timestamp
  delta: '10m',             // execution window
  endDate: 1769616362929    // start date + delta
}
```

You can also use `createExecuteOnceTriggerConfig()` to create an execute once trigger config.

### **Executions**

Query function execution history and results. The list and detail endpoints return execution metadata, fee breakdown, and validations. Inputs, outputs, and logs are fetched separately through dedicated methods.

```typescript
import type { ExecutionInput, ExecutionOutput, ExecutionResponse } from '@mimicprotocol/sdk'

// List executions (with optional filters)
const executions: ExecutionResponse[] = await client.executions.get({
  triggerSig: '0x...',                 // by trigger signature
  createdAfter: Date.parse('2024-01-01'),
  createdBefore: Date.parse('2024-12-31'),
  offset: 0,
  limit: 50,
})

// Inspect an execution
for (const ex of executions) {
  console.log(ex.hash, ex.timestamp, ex.status)
  console.log('Result:', ex.result)             // succeeded | failed
  console.log('Relayer:', ex.relayer)
  console.log('Fuel used:', ex.fuelUsed)

  // Optional fee breakdown
  if (ex.fee) {
    console.log('Fee total:', ex.fee.total)
  }

  // Inputs (oracle responses)
  const inputs: ExecutionInput[] = await client.executions.getInputs(ex.hash)
  for (const input of inputs) {
    console.log('Oracle input:', input)
  }

  // Outputs (intents emitted)
  const outputs: ExecutionOutput[] = await client.executions.getOutputs(ex.hash)
  for (const out of outputs) {
    console.log('Intent hash:', out.hash)
  }

  // Logs
  const logs: string[] = await client.executions.getLogs(ex.hash)
  for (const log of logs) {
    console.log('Log: ', log)
  }

  // Optional validations
  if (ex.validations) {
    for (const v of ex.validations) {
      console.log('Validation:', v.succeeded, v.signature)
    }
  }
}

// Get specific execution by hash
const execution: ExecutionResponse = await client.executions.getByHash('0x...')
```

### **Intents**

Query, encode, and decode intents and their operations. An intent contains one or more operations (`intent.operations`); each operation has an `opType` that identifies what it does.

```typescript
import { isEvmCall, isSwap, isTransfer, OpType } from '@mimicprotocol/sdk'
import type {
  AxiaIntent,
  EvmCallOperation,
  EvmDynamicCallOperation,
  Operation,
  SwapOperation,
  SwapProposal,
  TransferOperation,
} from '@mimicprotocol/sdk'

// List intents (filters are optional)
const intents: AxiaIntent[] = await client.intents.get({
  feePayer: '0x...',             // fee payer address
  settler: '0x...',              // settler address
  deadlineAfter: BigInt(1714600000),
  deadlineBefore: BigInt(1735600000),
  offset: 0,
  limit: 20,
})

// Get a specific intent by hash
const intent: AxiaIntent = await client.intents.getByHash('0x...')

// Type guards and decoders
for (const op of intent.operations) {
  if (isSwap(op)) {
    const swap: SwapOperation = client.intents.decodeSwapOperation(op)
    console.log(swap.sourceChain, swap.destinationChain, swap.tokensIn, swap.tokensOut)
  } else if (isTransfer(op)) {
    const transfer: TransferOperation = client.intents.decodeTransferOperation(op)
    console.log(transfer.chainId, transfer.transfers)
  } else if (isEvmCall(op)) {
    const call: EvmCallOperation = client.intents.decodeEvmCallOperation(op)
    console.log(call.chainId, call.calls)
  } else if (op.opType === OpType.EvmDynamicCall) { // Alternative to `isEvmDynamicCall(op)`
    const dynamicCall: EvmDynamicCallOperation = client.intents.decodeEvmDynamicCallOperation(op)
    console.log(dynamicCall.chainId, dynamicCall.calls)
  }
}

// ChainId helper — reads chainId from a single operation
const chainId: number = client.intents.getChainId(intent.operations[0])

// Proposal decoder — pass the proposal and the index of the operation it belongs to
const decoded: SwapProposal = client.intents.decodeProposal(intent.proposals[0], 0)

// Encoders
const encodedIntent = client.intents.encodeIntent({ /* Intent fields */ })
const encodedProposal = client.intents.encodeProposal({ /* Proposal fields */ }, intent)
const swapDataHex = client.intents.encodeSwapOperationData({ /* SwapOperationData */ })
const transferDataHex = client.intents.encodeTransferOperationData({ /* TransferOperationData */ })
const callDataHex = client.intents.encodeEvmCallOperationData({ /* EvmCallOperationData */ })
```

### Error Handling

The SDK uses structured error handling with the `ApiError` class.

```typescript
import { ApiError } from '@mimicprotocol/sdk'

try {
  const trigger = await client.triggers.getBySignature('invalid-signature')
} catch (error) {
  if (error instanceof ApiError) {
    console.error('API Error:', error.message)
    console.error('Status:', error.status)
    console.error('Code:', error.code)
    console.error('Details:', error.details)
  } else {
    console.error('Unexpected error:', error)
  }
}
```

### TypeScript Types

The SDK exports comprehensive TypeScript types for all data structures:

```typescript
import type {
  // Core types
  Client,
  InitOptions,

  // Domain types
  Trigger,
  Function,
  Execution,
  Intent,
  Operation,
  Balance,

  // Operation subtypes
  SwapOperation,
  TransferOperation,
  EvmCallOperation,
  EvmDynamicCallOperation,
  SwapProposal,

  // Authentication types
  Signer,
  EthersSigner,
  WindowEthereumSigner,
  ApiKeyAuth,
  BearerAuth,

  // Utility types
  Address,
  Signature,
  ChainId,
  Hash
} from '@mimicprotocol/sdk'
```

### Configuration Options

#### **Client Configuration**

```typescript
interface InitOptions {
  domains?: Partial<CoreConfig>  // Per-domain configuration
  baseUrl?: string              // Global base URL
  auth?: AuthStrategy           // Global authentication
  signer?: Signer              // Global signer
}
```

#### **Per-Domain Configuration**

```typescript
const client = new Client({
  domains: {
    triggers: {
      baseUrl: 'https://...',
      auth: new ApiKeyAuth('configs-key'),
      timeoutMs: 30000
    },
    functions: {
      baseUrl: 'https://...',
      auth: new BearerAuth('functions-token')
    }
  }
})
```

## Best Practices

1. **Error Handling**: Always wrap SDK calls in try-catch blocks and handle `ApiError` instances appropriately.
2. **Type Safety**: Leverage TypeScript types for better development experience and compile-time error checking.
3. **Configuration Management**: Use environment variables for sensitive data like API keys and private keys.
4. **Signer Management**: In production, use secure signer implementations and never expose private keys in client-side code.
