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 tasks, configurations, exe
Installation
yarn add @mimicprotocol/sdk
Getting Started
Basic Client Initialization
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
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
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.
// List balances (optionally filter by address)
const balances = await client.balances.get({
address: '0x...',
limit: 20,
offset: 0,
})
// Example item
// {
// address: '0x...',
// amount: 12.34,
// description: 'Monthly quota top-up',
// createdAt: new Date(),
// expiresAt: new Date() // optional
// }
// Get total balance for a specific address
const total = await client.balances.getTotal('0x...')
console.log(total.address, total.balance)
// Pagination
const nextPage = await client.balances.get({ offset: 20, limit: 20 })
Tasks
Manage WASM tasks and their manifests.
// List all tasks
const tasks = await client.tasks.get()
// List tasks with filters
const tasks = await client.tasks.get({
creator: '0x...',
limit: 10,
offset: 0
})
// Get specific task by CID
const task = await client.tasks.getByCid('Qm...')
// Get task manifest
const manifest = await client.tasks.getManifest('Qm...')
// Download WASM binary
const wasmBlob = await client.tasks.getWasm('Qm...')
// Create new task (requires API key authentication)
const newTask = await client.tasks.create({
manifestFile: new File([manifestJson], 'manifest.json'),
wasmFile: new File([wasmBytes], 'wasm.wasm')
})
Configs
Manage task configurations and their lifecycle. Configs define how and when tasks should be executed.
// List all configurations
const configs = await client.configs.get()
// List configs with filters
const configs = await client.configs.get({
sigs: ['0x...', '0x...'], // specific signatures
taskCid: 'Qm...', // filter by task
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 configuration by signature
const config = await client.configs.getBySignature('0x...')
// Example config structure:
// {
// sig: '0x...',
// taskCid: 'Qm...',
// signer: '0x...',
// version: '1.0.0',
// active: true,
// description: 'My automation task',
// createdAt: new Date(),
// input: { token: '0x...', amount: '1000000000000000000' },
// trigger: { type: 'cron', schedule: '0 0 * * *', delta: '1h', endDate: 0 },
// executionFeeLimit: '1000000000000000000',
// minValidations: 1,
// types: { Input: [...], Trigger: [...], Config: [...] }
// }
// Create and sign a new configuration (requires signer)
const newConfig = await client.configs.signAndCreate({
description: 'Daily DCA automation',
taskCid: 'Qm...',
version: '1.0.0',
manifest: { /* task manifest with inputs definition */ },
trigger: {
type: 'cron', // or 'event'
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 configuration (requires signer)
const deactivatedConfig = await client.configs.signAndDeactivate('0x...')
// Check if configuration is expired
const isExpired = client.configs.isExpired(config)
// Get next execution timestamp for cron triggers
const nextExecution = client.configs.getNextExecutionTimestamp('0 0 * * *', Date.now())
Trigger Types
Cron Trigger:
{
type: '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:
{
type: '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
}
Executions
Query task execution history and results. Each execution includes inputs (oracle responses), outputs (intents), fee breakdown, and validations.
// List executions (with optional filters)
const executions = await client.executions.get({
configSig: '0x...', // by configuration 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 = await client.executions.getByHash('0x...')
// Example execution structure:
// {
// hash: '0x...',
// configSig: '0x...',
// timestamp: new Date(),
// fuelUsed: 1234,
// logs: ['...'],
// inputs: [ /* oracle responses */ ],
// outputs: [ { hash: '0x...', /* intent fields */ } ],
// signature: '0x...',
// result: 'succeeded' | 'failed',
// relayer: '0x...',
// status: 'enqueued' | 'submitted' | 'succeeded' | 'failed',
// createdAt: new Date(),
// fee?: { trigger, relayer, oracles, validator, intents, protocol, total },
// validations?: [ { signature: '0x...', succeeded: true, description?: string } ]
// }
Intents
Query, encode and decode intents and proposals associated to executions.
// List intents (filters are optional)
const intents = 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 = await client.intents.getByHash('0x...')
// Intent structure example:
// {
// hash: '0x...',
// executionHash: '0x...',
// op: 0 | 1 | 2, // swap | transfer | call
// user: '0x...',
// settler: '0x...',
// nonce: '0x...',
// deadline: '1699999999', // epoch seconds (string)
// data: '0x...', // ABI-encoded data
// status: 'enqueued' | 'discarded' | 'submitted' | 'succeeded' | 'failed' | 'expired',
// proposals: [
// {
// solver: '0x...',
// data: '0x...',
// deadline: '1699999999',
// fees: ['100', '200'], // raw bigint strings
// feeUsd: 12.34,
// signatures: ['0x...'],
// transactionHash?: '0x...',
// destTransactionHash?: '0x...',
// status: 'received' | 'discarded' | 'submitted' | 'succeeded' | 'failed',
// description?: string,
// },
// ],
// logs: [ { level: 'info' | 'success' | 'error', data: '0x...', createdAt: Date } ]
// }
// Type guards and decoders
if (client.intents.isSwap(intent)) {
const swap = client.intents.decodeSwapIntent(intent)
console.log(swap.sourceChain, swap.targetChain)
} else if (client.intents.isTransfer(intent)) {
const transfer = client.intents.decodeTransferIntent(intent)
console.log(transfer.chainId, transfer.token)
} else if (client.intents.isCall(intent)) {
const call = client.intents.decodeCallIntent(intent)
console.log(call.chainId, call.target)
}
// ChainId helper
const chainId = client.intents.getChainId(intent)
// Proposal decoder (supports swap proposals)
const decoded = 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.encodeCallIntentData({ /* CallIntentData */ })
Error Handling
The SDK uses structured error handling with the ApiError
class.
import { ApiError } from '@mimicprotocol/sdk'
try {
const config = await client.configs.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:
import type {
// Core types
Client,
InitOptions,
// Domain types
Config,
Task,
Execution,
Intent,
Balance,
// Authentication types
Signer,
EthersSigner,
WindowEthereumSigner,
ApiKeyAuth,
BearerAuth,
// Utility types
Address,
Signature,
ChainId,
Hash
} from '@mimicprotocol/sdk'
Configuration Options
Client Configuration
interface InitOptions {
domains?: Partial<CoreConfig> // Per-domain configuration
baseUrl?: string // Global base URL
auth?: AuthStrategy // Global authentication
signer?: Signer // Global signer
}
Per-Domain Configuration
const client = new Client({
domains: {
configs: {
baseUrl: 'https://...',
auth: new ApiKeyAuth('configs-key'),
timeoutMs: 30000
},
tasks: {
baseUrl: 'https://...',
auth: new BearerAuth('tasks-token')
}
}
})
Best Practices
Error Handling: Always wrap SDK calls in try-catch blocks and handle
ApiError
instances appropriately.Type Safety: Leverage TypeScript types for better development experience and compile-time error checking.
Configuration Management: Use environment variables for sensitive data like API keys and private keys.
Signer Management: In production, use secure signer implementations and never expose private keys in client-side code.
Last updated