# 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 proposals associated to executions.

```typescript
import type { EvmCallIntent, Intent, SwapIntent, SwapProposal, TransferIntent } 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
if (client.intents.isSwap(intent)) {
  const swap: SwapIntent = client.intents.decodeSwapIntent(intent)
  console.log(swap.sourceChain, swap.targetChain)
} else if (client.intents.isTransfer(intent)) {
  const transfer: TransferIntent = client.intents.decodeTransferIntent(intent)
  console.log(transfer.chainId, transfer.token)
} else if (client.intents.isEvmCall(intent)) {
  const call: EvmCallIntent = client.intents.decodeEvmCallIntent(intent)
  console.log(call.chainId, call.target)
}

// ChainId helper
const chainId: number = client.intents.getChainId(intent)

// Proposal decoder (supports swap proposals)
const decoded: SwapProposal = client.intents.decodeProposal(intent.proposals[0])

// Encoders
const encodedIntent = client.intents.encodeIntent({ /* Intent fields */ })
const encodedProposal = client.intents.encodeProposal({ /* Proposal fields */ }, intent)
const swapDataHex = client.intents.encodeSwapIntentData({ /* SwapIntentData */ })
const transferDataHex = client.intents.encodeTransferIntentData({ /* TransferIntentData */ })
const callDataHex = client.intents.encodeEvmCallIntentData({ /* EvmCallIntentData */ })
```

### 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,
  Balance,
  
  // 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.
