# 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'),
  wasmFile: new File([wasmBytes], 'function.wasm')
})
```

### **Triggers**

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

```typescript
import type { 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: new Date('2024-01-01'),
  createdBefore: new Date('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 a trigger (requires signer)
const deactivatedTrigger: Trigger = await client.triggers.signAndDeactivate('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 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 (1-4 topics)
  delta: '1h',              // execution window
  endDate: 0                // timestamp or 0 for no end
}
```

#### **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. Each execution includes inputs (oracle responses), outputs (intents), fee breakdown, and validations.

```typescript
import type { Execution } from '@mimicprotocol/sdk'

// List executions (with optional filters)
const executions: Execution[] = await client.executions.get({
  triggerSig: '0x...',                 // by trigger signature
  createdAfter: new Date('2024-01-01'),
  createdBefore: new Date('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)
  for (const input of ex.inputs) {
    console.log('Oracle input:', input)
  }

  // Outputs (intents emitted)
  for (const out of ex.outputs) {
    console.log('Intent hash:', out.hash)
  }

  // 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: Execution = 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 type {
  EvmCallOperation,
  Intent,
  Operation,
  SwapOperation,
  SwapProposal,
  TransferOperation,
} from '@mimicprotocol/sdk'

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

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

// Type guards and decoders
for (const op of intent.operations) {
  if (client.intents.isSwap(op)) {
    const swap: SwapOperation = client.intents.decodeSwapOperation(op)
    console.log(swap.sourceChain, swap.destinationChain, swap.tokensIn, swap.tokensOut)
  } else if (client.intents.isTransfer(op)) {
    const transfer: TransferOperation = client.intents.decodeTransferOperation(op)
    console.log(transfer.chainId, transfer.transfers)
  } else if (client.intents.isEvmCall(op)) {
    const call: EvmCallOperation = client.intents.decodeEvmCallOperation(op)
    console.log(call.chainId, call.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,
  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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mimic.fi/developers/sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
