[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6ET5MHC01R668JHR5N0HGA1":3,"skill-same:01M6ET5MHC01R668JHR5N0HGA1":63},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":34,"linkOnly":35,"markdownContent":36,"markdownBody":37,"frontMatter":38,"refName":39,"commitSha":40,"skillDirectory":41,"forksCount":42,"repositoryHtmlUrl":43,"repositoryHomepageUrl":44,"ownerHtmlUrl":45,"ownerBlogUrl":46,"ownerDescription":47,"updatedAt":48,"install":49,"resources":62},"01M6ET5MHC01R668JHR5N0HGA1","zyfai",null,"Earn yield on any Ethereum wallet on Base, Arbitrum, and Plasma. Use when a user wants passive DeFi yield on their funds. Deploys a non-custodial deterministic subaccount (Safe) linked to their EOA, enables automated yield optimization, and lets them deposit\u002Fwithdraw anytime.","Eskyee\u002Fagentbot-opensource","Eskyee","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F30862925?v=4","01M6ESSG1VB0FYP310V08SY08K","Esky33","01M6ESSG5ZR55BV28APEN3Y2P6",17,"MIT","https:\u002F\u002Fgithub.com\u002FEskyee\u002Fagentbot-opensource\u002Fblob\u002Fmain\u002Fskills\u002Fzyfai\u002FSKILL.md",[],[5,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33],"safe","ethereum","defi","Optimization","user","use","Wallet","base","deterministic","deposit","withdraw","yield","arbitrum","non-custodial","passive","2026-11-10 10:12:30",false,"---\nname: zyfai\ndescription: Earn yield on any Ethereum wallet on Base, Arbitrum, and Plasma. Use when a user wants passive DeFi yield on their funds. Deploys a non-custodial deterministic subaccount (Safe) linked to their EOA, enables automated yield optimization, and lets them deposit\u002Fwithdraw anytime.\n---\n\n# Zyfai — Yield for Any Wallet\n\nTurn any Ethereum wallet into a yield-generating account.\n\n## What This Does\n\nWhen a user wants to **earn yield** on their crypto, Zyfai creates a **deterministic subaccount** (Safe smart wallet) linked to their existing wallet (EOA). Funds deposited into this subaccount are automatically optimized across DeFi protocols. The user stays in full control and can withdraw anytime.\n\n```\n┌─────────────────┐      ┌──────────────────────┐\n│   User's EOA    │ ───► │  Zyfai Subaccount    │\n│  (their wallet) │      │  (Safe smart wallet) │\n│                 │      │                      │\n│  Owns & controls│      │  • Auto-rebalancing  │\n│                 │      │  • Yield optimization│\n│                 │      │  • Non-custodial     │\n└─────────────────┘      └──────────────────────┘\n```\n\n**Key points:**\n- The subaccount is **owned by the user's EOA** — only they can withdraw\n- Session keys allow **automated rebalancing** but cannot withdraw to other addresses\n- Same EOA = same subaccount address across all chains\n\n## The Flow\n\n```\n1. DEPLOY    →  Create a deterministic subaccount linked to user's wallet\n2. SESSION   →  Enable automated yield optimization  \n3. DEPOSIT   →  Send funds to subaccount (starts earning)\n4. WITHDRAW  →  Pull funds back to wallet (anytime)\n```\n\n## Prerequisites\n\n- **API Key** — Get one programmatically (see below) or manually at [sdk.zyf.ai](https:\u002F\u002Fsdk.zyf.ai)\n- **Wallet Connection** — Either a wallet provider (browser) or secure key management (server)\n- **Node.js 18+**\n\n```bash\nnpm install @zyfai\u002Fsdk viem\n```\n\n### Programmatic API Key Creation (Agent-Native)\n\nAgents can create their own API key without human intervention. You need the wallet address (public key) of the agent.\n\n```bash\nPOST https:\u002F\u002Fsdk.zyf.ai\u002Fapi\u002Fsdk-api-keys\u002Fcreate\nContent-Type: application\u002Fjson\n\n{\n  \"clientName\": \"my-agent\",\n  \"walletAddress\": \"0x...\",\n  \"email\": \"agent@example.com\"\n}\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"message\": \"SDK API key created successfully. Store the apiKey securely - it cannot be retrieved later!\",\n  \"data\": {\n    \"id\": \"936...\",\n    \"apiKey\": \"zyfai_361ad41d083c2fe.....\",\n    \"keyPrefix\": \"zyfai_361ad4\",\n    \"clientName\": \"my-agent\",\n    \"ownerWalletAddress\": \"0x...\"\n  }\n}\n```\n\n> **Important:** Store the `apiKey` securely — it cannot be retrieved later. The key is linked to the provided wallet address.\n\n## Supported Chains\n\n| Chain    | ID    |\n|----------|-------|\n| Arbitrum | 42161 |\n| Base     | 8453  |\n| Plasma   | 9745  |\n\n## Important: Always Use EOA Address\n\nWhen calling SDK methods, **always pass the EOA address** (the user's wallet address) as `userAddress` — never the subaccount\u002FSafe address. The SDK derives the subaccount address automatically from the EOA.\n\n## Wallet Connection Options\n\nThe SDK supports multiple ways to connect a wallet. Choose based on your security requirements and deployment context.\n\n### Option 1: Wallet Provider (Recommended for Browser\u002FdApps)\n\nUse an injected wallet provider like MetaMask. The private key never leaves the user's wallet.\n\n```typescript\nimport { ZyfaiSDK } from \"@zyfai\u002Fsdk\";\n\nconst sdk = new ZyfaiSDK({ apiKey: \"your-api-key\", referralSource: \"openclaw-skill\" });\n\n\u002F\u002F Connect using injected wallet provider (MetaMask, WalletConnect, etc.)\nawait sdk.connectAccount(window.ethereum, 8453);\n```\n\n**Security:** The private key stays in the user's wallet. The SDK only requests signatures when needed.\n\n### Option 2: Viem WalletClient (Recommended for Server Agents)\n\nUse a pre-configured viem WalletClient. This is the recommended approach for server-side agents as it allows integration with secure key management solutions.\n\n```typescript\nimport { ZyfaiSDK } from \"@zyfai\u002Fsdk\";\nimport { createWalletClient, http } from \"viem\";\nimport { base } from \"viem\u002Fchains\";\nimport { privateKeyToAccount } from \"viem\u002Faccounts\";\n\n\u002F\u002F Create wallet client with your preferred key management\n\u002F\u002F Option A: From environment variable (simple but requires secure env management)\nconst account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);\n\n\u002F\u002F Option B: From KMS (AWS, GCP, etc.) - recommended for production\n\u002F\u002F const account = await getAccountFromKMS();\n\n\u002F\u002F Option C: From Wallet-as-a-Service (Turnkey, Privy, etc.)\n\u002F\u002F const account = await turnkeyClient.getAccount();\n\nconst walletClient = createWalletClient({\n  account,\n  chain: base,\n  transport: http(),\n});\n\nconst sdk = new ZyfaiSDK({ apiKey: \"your-api-key\", referralSource: \"openclaw-skill\" });\n\n\u002F\u002F Connect using the WalletClient\nawait sdk.connectAccount(walletClient, 8453);\n```\n\n**Security:** The WalletClient abstraction allows you to integrate with secure key management solutions like:\n- **AWS KMS** \u002F **GCP Cloud KMS** — Hardware-backed key storage\n- **Turnkey** \u002F **Privy** \u002F **Dynamic** — Wallet-as-a-Service providers\n- **Hardware wallets** — Via WalletConnect or similar\n\n### Option 3: Private Key String (Development Only)\n\nDirect private key usage.\n\n```typescript\nimport { ZyfaiSDK } from \"@zyfai\u002Fsdk\";\n\nconst sdk = new ZyfaiSDK({ apiKey: \"your-api-key\", referralSource: \"openclaw-skill\" });\n\n\u002F\u002F WARNING: Only use for development. Never hardcode private keys in production.\nawait sdk.connectAccount(process.env.PRIVATE_KEY, 8453);\n```\n\n**Security Warning:** Raw private keys in environment variables are a security risk. For production autonomous agents, use Option 2 with a proper key management solution.\n\n### Security Comparison\n\n| Method | Security Level | Use Case |\n|--------|---------------|----------|\n| Wallet Provider | High | Browser dApps, user-facing apps |\n| WalletClient + KMS | High | Production server agents |\n| WalletClient + WaaS | High | Production server agents |\n| Private Key String | Low | Development\u002Ftesting only |\n\n## Step-by-Step\n\n### 1. Connect to Zyfai\n\n```typescript\nimport { ZyfaiSDK } from \"@zyfai\u002Fsdk\";\nimport { createWalletClient, http } from \"viem\";\nimport { base } from \"viem\u002Fchains\";\nimport { privateKeyToAccount } from \"viem\u002Faccounts\";\n\nconst sdk = new ZyfaiSDK({ apiKey: \"your-api-key\", referralSource: \"openclaw-skill\" });\n\n\u002F\u002F For browser: use wallet provider\nawait sdk.connectAccount(window.ethereum, 8453);\n\n\u002F\u002F For server: use WalletClient (see Wallet Connection Options above)\nconst walletClient = createWalletClient({\n  account: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`),\n  chain: base,\n  transport: http(),\n});\nawait sdk.connectAccount(walletClient, 8453);\n```\n\n### 2. Deploy Subaccount\n\n```typescript\nconst userAddress = \"0x...\"; \u002F\u002F User's EOA (NOT the subaccount address!)\nconst chainId = 8453; \u002F\u002F Base\n\n\u002F\u002F Check if subaccount exists\nconst wallet = await sdk.getSmartWalletAddress(userAddress, chainId);\nconsole.log(`Subaccount: ${wallet.address}`);\nconsole.log(`Deployed: ${wallet.isDeployed}`);\n\n\u002F\u002F Deploy if needed\nif (!wallet.isDeployed) {\n  const result = await sdk.deploySafe(userAddress, chainId, \"conservative\");\n  console.log(\"Subaccount deployed:\", result.safeAddress);\n}\n```\n\n**Strategies:**\n- `\"conservative\"` — Stable yield, lower risk\n- `\"aggressive\"` — Higher yield, higher risk\n\n### 3. Enable Yield Optimization\n\n```typescript\nawait sdk.createSessionKey(userAddress, chainId);\n\n\u002F\u002F Always verify the session key was activated\nconst user = await sdk.getUserDetails();\nif (!user.hasActiveSessionKey) {\n  \u002F\u002F Session key not active — retry the process\n  console.log(\"Session key not active, retrying...\");\n  await sdk.createSessionKey(userAddress, chainId);\n  \n  \u002F\u002F Verify again\n  const userRetry = await sdk.getUserDetails();\n  if (!userRetry.hasActiveSessionKey) {\n    throw new Error(\"Session key activation failed after retry. Contact support.\");\n  }\n}\nconsole.log(\"Session key active:\", user.hasActiveSessionKey);\n```\n\nThis allows Zyfai to rebalance funds automatically. Session keys **cannot** withdraw to arbitrary addresses — only optimize within the protocol.\n\n> **Important:** Always verify the session key is active by checking `getUserDetails().hasActiveSessionKey` after calling `createSessionKey`. If it returns `false`, retry the process. A session key must be active for automated yield optimization to work.\n\n### 4. Deposit Funds\n\n```typescript\n\u002F\u002F Deposit 10 USDC (6 decimals) - default asset\nawait sdk.depositFunds(userAddress, chainId, \"10000000\");\n\n\u002F\u002F Deposit 0.5 WETH (18 decimals)\n\u002F\u002F IMPORTANT: User must have WETH, not ETH. Wrap ETH to WETH first if needed.\nawait sdk.depositFunds(userAddress, chainId, \"500000000000000000\", \"WETH\");\n```\n\nFunds move from EOA -> Subaccount and start earning yield immediately.\n\n### 5. Withdraw Funds\n\n```typescript\n\u002F\u002F Withdraw all USDC (default)\nawait sdk.withdrawFunds(userAddress, chainId);\n\n\u002F\u002F Partial USDC withdrawal (5 USDC)\nawait sdk.withdrawFunds(userAddress, chainId, \"5000000\");\n\n\u002F\u002F Withdraw all WETH\nawait sdk.withdrawFunds(userAddress, chainId, undefined, \"WETH\");\n```\n\nFunds return to the user's EOA. Withdrawals are processed asynchronously.\n\n### 6. Disconnect\n\n```typescript\nawait sdk.disconnectAccount();\n```\n\n## Complete Example\n\n```typescript\nimport { ZyfaiSDK } from \"@zyfai\u002Fsdk\";\nimport { createWalletClient, http } from \"viem\";\nimport { base } from \"viem\u002Fchains\";\nimport { privateKeyToAccount } from \"viem\u002Faccounts\";\n\nasync function startEarningYield(userAddress: string) {\n  const sdk = new ZyfaiSDK({ apiKey: process.env.ZYFAI_API_KEY! });\n  const chainId = 8453; \u002F\u002F Base\n  \n  \u002F\u002F Connect using WalletClient (recommended for server agents)\n  const walletClient = createWalletClient({\n    account: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`),\n    chain: base,\n    transport: http(),\n  });\n  await sdk.connectAccount(walletClient, chainId);\n  \n  \u002F\u002F Deploy subaccount if needed (always pass EOA as userAddress)\n  const wallet = await sdk.getSmartWalletAddress(userAddress, chainId);\n  if (!wallet.isDeployed) {\n    await sdk.deploySafe(userAddress, chainId, \"conservative\");\n    console.log(\"Subaccount created:\", wallet.address);\n  }\n  \n  \u002F\u002F Enable automated optimization\n  await sdk.createSessionKey(userAddress, chainId);\n  \n  \u002F\u002F Verify session key is active\n  const user = await sdk.getUserDetails();\n  if (!user.hasActiveSessionKey) {\n    console.log(\"Session key not active, retrying...\");\n    await sdk.createSessionKey(userAddress, chainId);\n    const userRetry = await sdk.getUserDetails();\n    if (!userRetry.hasActiveSessionKey) {\n      throw new Error(\"Session key activation failed. Contact support.\");\n    }\n  }\n  \n  \u002F\u002F Deposit 100 USDC\n  await sdk.depositFunds(userAddress, chainId, \"100000000\");\n  console.log(\"Deposited! Now earning yield.\");\n  \n  await sdk.disconnectAccount();\n}\n\nasync function withdrawYield(userAddress: string, amount?: string) {\n  const sdk = new ZyfaiSDK({ apiKey: process.env.ZYFAI_API_KEY! });\n  const chainId = 8453; \u002F\u002F Base\n  \n  \u002F\u002F Connect using WalletClient\n  const walletClient = createWalletClient({\n    account: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`),\n    chain: base,\n    transport: http(),\n  });\n  await sdk.connectAccount(walletClient, chainId);\n  \n  \u002F\u002F Withdraw funds (pass EOA as userAddress)\n  if (amount) {\n    \u002F\u002F Partial withdrawal\n    await sdk.withdrawFunds(userAddress, chainId, amount);\n    console.log(`Withdrawn ${amount} (6 decimals) to EOA`);\n  } else {\n    \u002F\u002F Full withdrawal\n    await sdk.withdrawFunds(userAddress, chainId);\n    console.log(\"Withdrawn all funds to EOA\");\n  }\n  \n  await sdk.disconnectAccount();\n}\n```\n\n## API Reference\n\n| Method | Params | Description |\n|--------|--------|-------------|\n| `connectAccount` | `(walletClientOrProvider, chainId)` | Authenticate with Zyfai |\n| `getSmartWalletAddress` | `(userAddress, chainId)` | Get subaccount address & status |\n| `deploySafe` | `(userAddress, chainId, strategy)` | Create subaccount |\n| `createSessionKey` | `(userAddress, chainId)` | Enable auto-optimization |\n| `depositFunds` | `(userAddress, chainId, amount, asset?)` | Deposit USDC or WETH |\n| `withdrawFunds` | `(userAddress, chainId, amount?, assetType?)` | Withdraw USDC or WETH |\n| `getPositions` | `(userAddress, chainId?)` | Get active DeFi positions |\n| `getAvailableProtocols` | `(chainId)` | Get available protocols & pools |\n| `getAPYPerStrategy` | `(crossChain?, days?, strategy?, chainId?, tokenSymbol?)` | Get APY by strategy and token |\n| `getUserDetails` | `()` | Get authenticated user details |\n| `getOnchainEarnings` | `(walletAddress)` | Get earnings data |\n| `updateUserProfile` | `(params)` | Update strategy, protocols, splitting, cross-chain settings |\n| `registerAgentOnIdentityRegistry` | `(smartWallet, chainId)` | Register agent on ERC-8004 Identity Registry |\n| `disconnectAccount` | `()` | End session |\n\n**Note:** All methods that take `userAddress` expect the **EOA address**, not the subaccount\u002FSafe address.\n\n## Data Methods\n\n### getPositions\n\nGet all active DeFi positions for a user across protocols. Optionally filter by chain.\n\n**Parameters:**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| userAddress | string | Yes | User's EOA address |\n| chainId | SupportedChainId | No | Optional: Filter by specific chain ID |\n\n**Example:**\n\n```typescript\n\u002F\u002F Get all positions across all chains\nconst positions = await sdk.getPositions(\"0xUser...\");\n\n\u002F\u002F Get positions on Arbitrum only\nconst arbPositions = await sdk.getPositions(\"0xUser...\", 42161);\n```\n\n**Returns:**\n\n```typescript\ninterface PositionsResponse {\n  success: boolean;\n  userAddress: string;\n  positions: Position[];\n}\n```\n\n### getAvailableProtocols\n\nGet available DeFi protocols and pools for a specific chain with APY data.\n\n```typescript\nconst protocols = await sdk.getAvailableProtocols(42161); \u002F\u002F Arbitrum\n\nprotocols.protocols.forEach((protocol) => {\n  console.log(`${protocol.name} (ID: ${protocol.id})`);\n  if (protocol.pools) {\n    protocol.pools.forEach((pool) => {\n      console.log(`  Pool: ${pool.name} - APY: ${pool.apy || \"N\u002FA\"}%`);\n    });\n  }\n});\n```\n\nReturns:\n```typescript\ninterface ProtocolsResponse {\n  success: boolean;\n  chainId: SupportedChainId;\n  protocols: Protocol[];\n}\n```\n\n### getUserDetails\n\nGet current authenticated user details including smart wallet, chains, protocols, and settings. Requires SIWE authentication.\n\n```typescript\nawait sdk.connectAccount(walletClient, chainId);\nconst user = await sdk.getUserDetails();\n\nconsole.log(\"Smart Wallet:\", user.smartWallet);\nconsole.log(\"Chains:\", user.chains);\nconsole.log(\"Has Active Session:\", user.hasActiveSessionKey);\n```\n\nReturns `UpdateUserProfileResponse` (same as `updateUserProfile`).\n\n### updateUserProfile\n\nUpdate the authenticated user's profile settings including strategy, protocols, splitting, and cross-chain options. Requires SIWE authentication.\n\n```typescript\nsdk.updateUserProfile(params: UpdateUserProfileRequest): Promise\u003CUpdateUserProfileResponse>\n```\n\n**Parameters:**\n\n```typescript\ninterface UpdateUserProfileRequest {\n  \u002F** Investment strategy: \"conservative\" or \"aggressive\" *\u002F\n  strategy?: string;\n  \u002F** Array of protocol IDs to use *\u002F\n  protocols?: string[];\n  \u002F** Enable auto-selection of protocols *\u002F\n  autoSelectProtocols?: boolean;\n  \u002F** Enable omni-account for cross-chain operations *\u002F\n  omniAccount?: boolean;\n  \u002F** Array of chain IDs to operate on *\u002F\n  chains?: number[];\n  \u002F** Enable automatic compounding (default: true) *\u002F\n  autocompounding?: boolean;\n  \u002F** Custom name for your agent *\u002F\n  agentName?: string;\n  \u002F** Enable cross-chain strategy execution *\u002F\n  crosschainStrategy?: boolean;\n  \u002F** Enable position splitting across multiple protocols *\u002F\n  splitting?: boolean;\n  \u002F** Minimum number of splits (1-4) *\u002F\n  minSplits?: number;\n  \u002F** Asset to update: \"usdc\" (default) or \"eth\" *\u002F\n  asset?: \"USDC\" | \"WETH\";\n}\n```\n\n**Note on `asset`:** Each asset has its own configuration. Use `asset: \"WETH\"` to update WETH settings separately from USDC.\n\n**Returns:**\n\n```typescript\ninterface UpdateUserProfileResponse {\n  success: boolean;\n  smartWallet?: string;\n  chains?: number[];\n  strategy?: string;\n  protocols?: string[];\n  autoSelectProtocols?: boolean;\n  omniAccount?: boolean;\n  autocompounding?: boolean;\n  agentName?: string;\n  crosschainStrategy?: boolean;\n  executorProxy?: boolean;\n  hasActiveSessionKey?: boolean;\n  splitting?: boolean;\n  minSplits?: number;\n  customization?: Record\u003Cstring, any>;\n  asset?: \"USDC\" | \"WETH\";\n}\n```\n\n**Examples:**\n\n```typescript\n\u002F\u002F Update strategy from conservative to aggressive\nawait sdk.updateUserProfile({\n  strategy: \"aggressive\",\n});\n\n\u002F\u002F Configure specific protocols\nconst protocolsResponse = await sdk.getAvailableProtocols(8453);\nconst selectedProtocols = protocolsResponse.protocols\n  .filter(p => [\"Aave\", \"Compound\", \"Moonwell\"].includes(p.name))\n  .map(p => p.id);\n\nawait sdk.updateUserProfile({\n  protocols: selectedProtocols,\n});\n\n\u002F\u002F Enable position splitting (distribute across multiple protocols)\nawait sdk.updateUserProfile({\n  splitting: true,\n  minSplits: 3, \u002F\u002F Split across at least 3 protocols\n});\n\n\u002F\u002F Verify changes\nconst userDetails = await sdk.getUserDetails();\nconsole.log(\"Strategy:\", userDetails.strategy);\nconsole.log(\"Splitting:\", userDetails.splitting);\n```\n\n> **Cross-chain strategies:** Only enable cross-chain when the user **explicitly requests** it. For cross-chain to work, **both** `crosschainStrategy` and `omniAccount` must be set to `true`. Never enable cross-chain settings by default.\n\n```typescript\n\u002F\u002F Enable cross-chain ONLY when explicitly requested by the user\nawait sdk.updateUserProfile({\n  crosschainStrategy: true,\n  omniAccount: true,\n});\n\n\u002F\u002F Now funds can be rebalanced across configured chains\nconst user = await sdk.getUserDetails();\nconsole.log(\"Operating on chains:\", user.chains);\n```\n\n**Notes:**\n- **Strategy:** Can be changed anytime. Subsequent rebalancing uses the new active strategy.\n- **Protocols:** Use `getAvailableProtocols(chainId)` to get valid protocol IDs before updating.\n- **Smart Splitting (minSplits = 1):** Default mode. To maximize returns, funds are automatically distributed across multiple DeFi pools — but only when beneficial. The system intelligently decides when splitting is advantageous based on current market conditions and opportunities. Funds may not split if no opportunity exists.\n- **Forced Splitting (minSplits > 1):** When `minSplits` is set to 2, 3, or 4, funds are always distributed across at least that many pools for improved risk diversification (up to 4 DeFi pools). This guarantees your funds will be split regardless of market conditions.\n- **Cross-chain:** Requires **both** `crosschainStrategy: true` AND `omniAccount: true`. Only activate when the user explicitly asks for cross-chain yield optimization. Chains are configured during initial setup and cannot be changed via this method.\n- **Auto-compounding:** Enabled by default. When `true`, yields are reinvested automatically.\n- Smart wallet address, chains, and `executorProxy` cannot be updated via this method.\n\n### getAPYPerStrategy\n\nGet global APY by strategy type, time period, chain, and token. Use this to compare expected returns between strategies before deploying.\n\n**Parameters:**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| crossChain | boolean | No | If `true`, returns APY for cross-chain strategies; if `false`, single-chain (default: `false`) |\n| days | number | No | Period over which APY is calculated: `7`, `15`, `30`, `60` (default: `7`) |\n| strategy | string | No | Strategy risk profile: `\"conservative\"` or `\"aggressive\"` (default: `\"conservative\"`) |\n| chainId | number | No | Filter by specific chain ID (e.g., `8453` for Base) |\n| tokenSymbol | string | No | Filter by token: `\"USDC\"` or `\"WETH\"` |\n\n**Example:**\n\n```typescript\n\u002F\u002F Get 7-day APY for USDC conservative strategy\nconst usdcApy = await sdk.getAPYPerStrategy(false, 7, \"conservative\", undefined, \"USDC\");\nconsole.log(\"USDC APY:\", usdcApy.data);\n\n\u002F\u002F Get 30-day APY for WETH aggressive strategy on Base\nconst wethApy = await sdk.getAPYPerStrategy(false, 30, \"aggressive\", 8453, \"WETH\");\nconsole.log(\"WETH APY on Base:\", wethApy.data);\n\n\u002F\u002F Compare strategies\nconst conservative = await sdk.getAPYPerStrategy(false, 30, \"conservative\");\nconst aggressive = await sdk.getAPYPerStrategy(false, 30, \"aggressive\");\nconsole.log(`Conservative 30d APY: ${conservative.data[0]?.average_apy}%`);\nconsole.log(`Aggressive 30d APY: ${aggressive.data[0]?.average_apy}%`);\n```\n\n**Returns:**\n\n```typescript\ninterface APYPerStrategyResponse {\n  success: boolean;\n  count: number;\n  data: APYPerStrategy[];\n}\n\ninterface APYPerStrategy {\n  id: string;\n  timestamp: string;\n  amount: number;\n  fee_threshold: number;\n  days: number;\n  chain_id: number;\n  is_cross_chain: boolean;\n  average_apy: number;\n  average_apy_with_rzfi: number;\n  total_rebalances: number;\n  created_at: string;\n  strategy: string;\n  token_symbol?: string;\n  average_apy_with_fee: number;\n  average_apy_with_rzfi_with_fee: number;\n  average_apy_without_fee?: number;\n  average_apy_with_rzfi_without_fee?: number;\n  events_average_apy?: Record\u003Cstring, number>;\n}\n```\n\n### getOnchainEarnings\n\nGet onchain earnings for a wallet with per-token breakdown (USDC, WETH).\n\n```typescript\nconst earnings = await sdk.getOnchainEarnings(smartWalletAddress);\n\nconsole.log(\"Total earnings by token:\", earnings.data.totalEarningsByToken);\n\u002F\u002F { \"USDC\": 150.50, \"WETH\": 0.05 }\n\nconsole.log(\"USDC earnings:\", earnings.data.totalEarningsByToken[\"USDC\"]);\nconsole.log(\"WETH earnings:\", earnings.data.totalEarningsByToken[\"WETH\"]);\n```\n\nReturns:\n```typescript\n\u002F\u002F TokenEarnings is a record of token symbols to amounts\ntype TokenEarnings = Record\u003Cstring, number>;  \u002F\u002F e.g., { \"USDC\": 100.5, \"WETH\": 0.025 }\n\ninterface OnchainEarningsResponse {\n  success: boolean;\n  data: {\n    walletAddress: string;\n    totalEarningsByToken: TokenEarnings;\n    lifetimeEarningsByToken: TokenEarnings;\n    currentEarningsByChain: Record\u003Cstring, TokenEarnings>;\n    unrealizedEarningsByChain: Record\u003Cstring, TokenEarnings>;\n    lastCheckTimestamp?: string;\n  };\n}\n```\n\n### registerAgentOnIdentityRegistry (ERC-8004)\n\nRegister your Zyfai deployed agent on the Identity Registry following the ERC-8004 standard. This is used for OpenClaw agent registration. The method fetches a tokenUri containing the agent's metadata stored on IPFS, then registers it on-chain.\n\n**Supported Chains:**\n\n| Chain | Chain ID |\n|-------|----------|\n| Base | 8453 |\n| Arbitrum | 42161 |\n\n**Parameters:**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| smartWallet | string | Yes | The Zyfai deployed smart wallet address to register as an agent |\n| chainId | SupportedChainId | Yes | Chain ID (only 8453 or 42161) |\n\n**Example:**\n\n```typescript\nconst sdk = new ZyfaiSDK({ apiKey: \"your-api-key\" });\nawait sdk.connectAccount(walletClient, 8453);\n\n\u002F\u002F Get smart wallet address\nconst walletInfo = await sdk.getSmartWalletAddress(userAddress, 8453);\nconst smartWallet = walletInfo.address;\n\n\u002F\u002F Register agent on Identity Registry\nconst result = await sdk.registerAgentOnIdentityRegistry(smartWallet, 8453);\n\nconsole.log(\"Registration successful:\");\nconsole.log(\"  Tx Hash:\", result.txHash);\nconsole.log(\"  Chain ID:\", result.chainId);\nconsole.log(\"  Smart Wallet:\", result.smartWallet);\n```\n\n**Returns:**\n\n```typescript\ninterface RegisterAgentResponse {\n  success: boolean;\n  txHash: string;\n  chainId: number;\n  smartWallet: string;\n}\n```\n\n**How It Works:**\n\n1. Fetches a `tokenUri` from the Zyfai API (agent metadata stored on IPFS)\n2. Encodes the `register(tokenUri)` call for the Identity Registry contract\n3. Sends the transaction from the connected wallet\n4. Waits for on-chain confirmation\n\n## Security\n\n- **Non-custodial** — User's EOA owns the subaccount\n- **Session keys are limited** — Can rebalance, cannot withdraw elsewhere\n- **Deterministic** — Same EOA = same subaccount on every chain\n- **Flexible key management** — Use wallet providers, WalletClients, or KMS integrations\n\n### Key Management Best Practices\n\nFor **production autonomous agents**, we recommend:\n\n1. **Use a WalletClient** with a secure key source (not raw private keys)\n2. **Integrate with KMS** (AWS KMS, GCP Cloud KMS) for hardware-backed key storage\n3. **Consider Wallet-as-a-Service** providers like Turnkey, Privy, or Dynamic\n4. **Never hardcode** private keys in source code\n5. **Rotate keys** periodically and implement key revocation procedures\n\n## Troubleshooting\n\n### Subaccount address mismatch across chains\n\nThe subaccount address should be **identical** across all chains for the same EOA. If you see different addresses:\n\n```typescript\n\u002F\u002F Check addresses on both chains\nconst baseWallet = await sdk.getSmartWalletAddress(userAddress, 8453);\nconst arbWallet = await sdk.getSmartWalletAddress(userAddress, 42161);\n\nif (baseWallet.address !== arbWallet.address) {\n  console.error(\"Address mismatch! Contact support.\");\n}\n```\n\n**If addresses don't match:**\n1. Try redeploying on the affected chain\n2. If the issue persists, contact support on Telegram: [@paul_zyfai](https:\u002F\u002Ft.me\u002Fpaul_zyfai)\n\n### \"Deposit address not found\" error\n\nThis means the wallet isn't registered in the backend. Solution:\n1. Call `deploySafe()` first — even if the Safe is already deployed on-chain, this registers it with the backend\n2. Then retry `createSessionKey()`\n\n### \"Invalid signature\" error\n\nThis typically means:\n- The wallet\u002Fsigner doesn't match the EOA you're passing\n- The Safe address on-chain doesn't match what the SDK expects\n\nVerify you're using the correct wallet for the EOA.\n\n## Resources\n\n- **Get API Key:** [sdk.zyf.ai](https:\u002F\u002Fsdk.zyf.ai) or programmatically via `POST \u002Fapi\u002Fsdk-api-keys\u002Fcreate`\n- **Docs:** [docs.zyf.ai](https:\u002F\u002Fdocs.zyf.ai)\n- **Demo:** [github.com\u002Fondefy\u002Fzyfai-sdk-demo](https:\u002F\u002Fgithub.com\u002Fondefy\u002Fzyfai-sdk-demo)\n- **MCP Server:** [mcp.zyf.ai](https:\u002F\u002Fmcp.zyf.ai\u002Fmcp) — Use with Claude or other MCP-compatible agents\n- **Agent Registration:** [zyf.ai\u002F.well-known\u002Fagent-registration.json](https:\u002F\u002Fwww.zyf.ai\u002F.well-known\u002Fagent-registration.json)\n\n## License\n\nMIT License\n\nCopyright (c) 2026 Zyfai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and\u002For sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","# Zyfai — Yield for Any Wallet\n\nTurn any Ethereum wallet into a yield-generating account.\n\n## What This Does\n\nWhen a user wants to **earn yield** on their crypto, Zyfai creates a **deterministic subaccount** (Safe smart wallet) linked to their existing wallet (EOA). Funds deposited into this subaccount are automatically optimized across DeFi protocols. The user stays in full control and can withdraw anytime.\n\n```\n┌─────────────────┐      ┌──────────────────────┐\n│   User's EOA    │ ───► │  Zyfai Subaccount    │\n│  (their wallet) │      │  (Safe smart wallet) │\n│                 │      │                      │\n│  Owns & controls│      │  • Auto-rebalancing  │\n│                 │      │  • Yield optimization│\n│                 │      │  • Non-custodial     │\n└─────────────────┘      └──────────────────────┘\n```\n\n**Key points:**\n- The subaccount is **owned by the user's EOA** — only they can withdraw\n- Session keys allow **automated rebalancing** but cannot withdraw to other addresses\n- Same EOA = same subaccount address across all chains\n\n## The Flow\n\n```\n1. DEPLOY    →  Create a deterministic subaccount linked to user's wallet\n2. SESSION   →  Enable automated yield optimization  \n3. DEPOSIT   →  Send funds to subaccount (starts earning)\n4. WITHDRAW  →  Pull funds back to wallet (anytime)\n```\n\n## Prerequisites\n\n- **API Key** — Get one programmatically (see below) or manually at [sdk.zyf.ai](https:\u002F\u002Fsdk.zyf.ai)\n- **Wallet Connection** — Either a wallet provider (browser) or secure key management (server)\n- **Node.js 18+**\n\n```bash\nnpm install @zyfai\u002Fsdk viem\n```\n\n### Programmatic API Key Creation (Agent-Native)\n\nAgents can create their own API key without human intervention. You need the wallet address (public key) of the agent.\n\n```bash\nPOST https:\u002F\u002Fsdk.zyf.ai\u002Fapi\u002Fsdk-api-keys\u002Fcreate\nContent-Type: application\u002Fjson\n\n{\n  \"clientName\": \"my-agent\",\n  \"walletAddress\": \"0x...\",\n  \"email\": \"agent@example.com\"\n}\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"message\": \"SDK API key created successfully. Store the apiKey securely - it cannot be retrieved later!\",\n  \"data\": {\n    \"id\": \"936...\",\n    \"apiKey\": \"zyfai_361ad41d083c2fe.....\",\n    \"keyPrefix\": \"zyfai_361ad4\",\n    \"clientName\": \"my-agent\",\n    \"ownerWalletAddress\": \"0x...\"\n  }\n}\n```\n\n> **Important:** Store the `apiKey` securely — it cannot be retrieved later. The key is linked to the provided wallet address.\n\n## Supported Chains\n\n| Chain    | ID    |\n|----------|-------|\n| Arbitrum | 42161 |\n| Base     | 8453  |\n| Plasma   | 9745  |\n\n## Important: Always Use EOA Address\n\nWhen calling SDK methods, **always pass the EOA address** (the user's wallet address) as `userAddress` — never the subaccount\u002FSafe address. The SDK derives the subaccount address automatically from the EOA.\n\n## Wallet Connection Options\n\nThe SDK supports multiple ways to connect a wallet. Choose based on your security requirements and deployment context.\n\n### Option 1: Wallet Provider (Recommended for Browser\u002FdApps)\n\nUse an injected wallet provider like MetaMask. The private key never leaves the user's wallet.\n\n```typescript\nimport { ZyfaiSDK } from \"@zyfai\u002Fsdk\";\n\nconst sdk = new ZyfaiSDK({ apiKey: \"your-api-key\", referralSource: \"openclaw-skill\" });\n\n\u002F\u002F Connect using injected wallet provider (MetaMask, WalletConnect, etc.)\nawait sdk.connectAccount(window.ethereum, 8453);\n```\n\n**Security:** The private key stays in the user's wallet. The SDK only requests signatures when needed.\n\n### Option 2: Viem WalletClient (Recommended for Server Agents)\n\nUse a pre-configured viem WalletClient. This is the recommended approach for server-side agents as it allows integration with secure key management solutions.\n\n```typescript\nimport { ZyfaiSDK } from \"@zyfai\u002Fsdk\";\nimport { createWalletClient, http } from \"viem\";\nimport { base } from \"viem\u002Fchains\";\nimport { privateKeyToAccount } from \"viem\u002Faccounts\";\n\n\u002F\u002F Create wallet client with your preferred key management\n\u002F\u002F Option A: From environment variable (simple but requires secure env management)\nconst account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);\n\n\u002F\u002F Option B: From KMS (AWS, GCP, etc.) - recommended for production\n\u002F\u002F const account = await getAccountFromKMS();\n\n\u002F\u002F Option C: From Wallet-as-a-Service (Turnkey, Privy, etc.)\n\u002F\u002F const account = await turnkeyClient.getAccount();\n\nconst walletClient = createWalletClient({\n  account,\n  chain: base,\n  transport: http(),\n});\n\nconst sdk = new ZyfaiSDK({ apiKey: \"your-api-key\", referralSource: \"openclaw-skill\" });\n\n\u002F\u002F Connect using the WalletClient\nawait sdk.connectAccount(walletClient, 8453);\n```\n\n**Security:** The WalletClient abstraction allows you to integrate with secure key management solutions like:\n- **AWS KMS** \u002F **GCP Cloud KMS** — Hardware-backed key storage\n- **Turnkey** \u002F **Privy** \u002F **Dynamic** — Wallet-as-a-Service providers\n- **Hardware wallets** — Via WalletConnect or similar\n\n### Option 3: Private Key String (Development Only)\n\nDirect private key usage.\n\n```typescript\nimport { ZyfaiSDK } from \"@zyfai\u002Fsdk\";\n\nconst sdk = new ZyfaiSDK({ apiKey: \"your-api-key\", referralSource: \"openclaw-skill\" });\n\n\u002F\u002F WARNING: Only use for development. Never hardcode private keys in production.\nawait sdk.connectAccount(process.env.PRIVATE_KEY, 8453);\n```\n\n**Security Warning:** Raw private keys in environment variables are a security risk. For production autonomous agents, use Option 2 with a proper key management solution.\n\n### Security Comparison\n\n| Method | Security Level | Use Case |\n|--------|---------------|----------|\n| Wallet Provider | High | Browser dApps, user-facing apps |\n| WalletClient + KMS | High | Production server agents |\n| WalletClient + WaaS | High | Production server agents |\n| Private Key String | Low | Development\u002Ftesting only |\n\n## Step-by-Step\n\n### 1. Connect to Zyfai\n\n```typescript\nimport { ZyfaiSDK } from \"@zyfai\u002Fsdk\";\nimport { createWalletClient, http } from \"viem\";\nimport { base } from \"viem\u002Fchains\";\nimport { privateKeyToAccount } from \"viem\u002Faccounts\";\n\nconst sdk = new ZyfaiSDK({ apiKey: \"your-api-key\", referralSource: \"openclaw-skill\" });\n\n\u002F\u002F For browser: use wallet provider\nawait sdk.connectAccount(window.ethereum, 8453);\n\n\u002F\u002F For server: use WalletClient (see Wallet Connection Options above)\nconst walletClient = createWalletClient({\n  account: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`),\n  chain: base,\n  transport: http(),\n});\nawait sdk.connectAccount(walletClient, 8453);\n```\n\n### 2. Deploy Subaccount\n\n```typescript\nconst userAddress = \"0x...\"; \u002F\u002F User's EOA (NOT the subaccount address!)\nconst chainId = 8453; \u002F\u002F Base\n\n\u002F\u002F Check if subaccount exists\nconst wallet = await sdk.getSmartWalletAddress(userAddress, chainId);\nconsole.log(`Subaccount: ${wallet.address}`);\nconsole.log(`Deployed: ${wallet.isDeployed}`);\n\n\u002F\u002F Deploy if needed\nif (!wallet.isDeployed) {\n  const result = await sdk.deploySafe(userAddress, chainId, \"conservative\");\n  console.log(\"Subaccount deployed:\", result.safeAddress);\n}\n```\n\n**Strategies:**\n- `\"conservative\"` — Stable yield, lower risk\n- `\"aggressive\"` — Higher yield, higher risk\n\n### 3. Enable Yield Optimization\n\n```typescript\nawait sdk.createSessionKey(userAddress, chainId);\n\n\u002F\u002F Always verify the session key was activated\nconst user = await sdk.getUserDetails();\nif (!user.hasActiveSessionKey) {\n  \u002F\u002F Session key not active — retry the process\n  console.log(\"Session key not active, retrying...\");\n  await sdk.createSessionKey(userAddress, chainId);\n  \n  \u002F\u002F Verify again\n  const userRetry = await sdk.getUserDetails();\n  if (!userRetry.hasActiveSessionKey) {\n    throw new Error(\"Session key activation failed after retry. Contact support.\");\n  }\n}\nconsole.log(\"Session key active:\", user.hasActiveSessionKey);\n```\n\nThis allows Zyfai to rebalance funds automatically. Session keys **cannot** withdraw to arbitrary addresses — only optimize within the protocol.\n\n> **Important:** Always verify the session key is active by checking `getUserDetails().hasActiveSessionKey` after calling `createSessionKey`. If it returns `false`, retry the process. A session key must be active for automated yield optimization to work.\n\n### 4. Deposit Funds\n\n```typescript\n\u002F\u002F Deposit 10 USDC (6 decimals) - default asset\nawait sdk.depositFunds(userAddress, chainId, \"10000000\");\n\n\u002F\u002F Deposit 0.5 WETH (18 decimals)\n\u002F\u002F IMPORTANT: User must have WETH, not ETH. Wrap ETH to WETH first if needed.\nawait sdk.depositFunds(userAddress, chainId, \"500000000000000000\", \"WETH\");\n```\n\nFunds move from EOA -> Subaccount and start earning yield immediately.\n\n### 5. Withdraw Funds\n\n```typescript\n\u002F\u002F Withdraw all USDC (default)\nawait sdk.withdrawFunds(userAddress, chainId);\n\n\u002F\u002F Partial USDC withdrawal (5 USDC)\nawait sdk.withdrawFunds(userAddress, chainId, \"5000000\");\n\n\u002F\u002F Withdraw all WETH\nawait sdk.withdrawFunds(userAddress, chainId, undefined, \"WETH\");\n```\n\nFunds return to the user's EOA. Withdrawals are processed asynchronously.\n\n### 6. Disconnect\n\n```typescript\nawait sdk.disconnectAccount();\n```\n\n## Complete Example\n\n```typescript\nimport { ZyfaiSDK } from \"@zyfai\u002Fsdk\";\nimport { createWalletClient, http } from \"viem\";\nimport { base } from \"viem\u002Fchains\";\nimport { privateKeyToAccount } from \"viem\u002Faccounts\";\n\nasync function startEarningYield(userAddress: string) {\n  const sdk = new ZyfaiSDK({ apiKey: process.env.ZYFAI_API_KEY! });\n  const chainId = 8453; \u002F\u002F Base\n  \n  \u002F\u002F Connect using WalletClient (recommended for server agents)\n  const walletClient = createWalletClient({\n    account: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`),\n    chain: base,\n    transport: http(),\n  });\n  await sdk.connectAccount(walletClient, chainId);\n  \n  \u002F\u002F Deploy subaccount if needed (always pass EOA as userAddress)\n  const wallet = await sdk.getSmartWalletAddress(userAddress, chainId);\n  if (!wallet.isDeployed) {\n    await sdk.deploySafe(userAddress, chainId, \"conservative\");\n    console.log(\"Subaccount created:\", wallet.address);\n  }\n  \n  \u002F\u002F Enable automated optimization\n  await sdk.createSessionKey(userAddress, chainId);\n  \n  \u002F\u002F Verify session key is active\n  const user = await sdk.getUserDetails();\n  if (!user.hasActiveSessionKey) {\n    console.log(\"Session key not active, retrying...\");\n    await sdk.createSessionKey(userAddress, chainId);\n    const userRetry = await sdk.getUserDetails();\n    if (!userRetry.hasActiveSessionKey) {\n      throw new Error(\"Session key activation failed. Contact support.\");\n    }\n  }\n  \n  \u002F\u002F Deposit 100 USDC\n  await sdk.depositFunds(userAddress, chainId, \"100000000\");\n  console.log(\"Deposited! Now earning yield.\");\n  \n  await sdk.disconnectAccount();\n}\n\nasync function withdrawYield(userAddress: string, amount?: string) {\n  const sdk = new ZyfaiSDK({ apiKey: process.env.ZYFAI_API_KEY! });\n  const chainId = 8453; \u002F\u002F Base\n  \n  \u002F\u002F Connect using WalletClient\n  const walletClient = createWalletClient({\n    account: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`),\n    chain: base,\n    transport: http(),\n  });\n  await sdk.connectAccount(walletClient, chainId);\n  \n  \u002F\u002F Withdraw funds (pass EOA as userAddress)\n  if (amount) {\n    \u002F\u002F Partial withdrawal\n    await sdk.withdrawFunds(userAddress, chainId, amount);\n    console.log(`Withdrawn ${amount} (6 decimals) to EOA`);\n  } else {\n    \u002F\u002F Full withdrawal\n    await sdk.withdrawFunds(userAddress, chainId);\n    console.log(\"Withdrawn all funds to EOA\");\n  }\n  \n  await sdk.disconnectAccount();\n}\n```\n\n## API Reference\n\n| Method | Params | Description |\n|--------|--------|-------------|\n| `connectAccount` | `(walletClientOrProvider, chainId)` | Authenticate with Zyfai |\n| `getSmartWalletAddress` | `(userAddress, chainId)` | Get subaccount address & status |\n| `deploySafe` | `(userAddress, chainId, strategy)` | Create subaccount |\n| `createSessionKey` | `(userAddress, chainId)` | Enable auto-optimization |\n| `depositFunds` | `(userAddress, chainId, amount, asset?)` | Deposit USDC or WETH |\n| `withdrawFunds` | `(userAddress, chainId, amount?, assetType?)` | Withdraw USDC or WETH |\n| `getPositions` | `(userAddress, chainId?)` | Get active DeFi positions |\n| `getAvailableProtocols` | `(chainId)` | Get available protocols & pools |\n| `getAPYPerStrategy` | `(crossChain?, days?, strategy?, chainId?, tokenSymbol?)` | Get APY by strategy and token |\n| `getUserDetails` | `()` | Get authenticated user details |\n| `getOnchainEarnings` | `(walletAddress)` | Get earnings data |\n| `updateUserProfile` | `(params)` | Update strategy, protocols, splitting, cross-chain settings |\n| `registerAgentOnIdentityRegistry` | `(smartWallet, chainId)` | Register agent on ERC-8004 Identity Registry |\n| `disconnectAccount` | `()` | End session |\n\n**Note:** All methods that take `userAddress` expect the **EOA address**, not the subaccount\u002FSafe address.\n\n## Data Methods\n\n### getPositions\n\nGet all active DeFi positions for a user across protocols. Optionally filter by chain.\n\n**Parameters:**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| userAddress | string | Yes | User's EOA address |\n| chainId | SupportedChainId | No | Optional: Filter by specific chain ID |\n\n**Example:**\n\n```typescript\n\u002F\u002F Get all positions across all chains\nconst positions = await sdk.getPositions(\"0xUser...\");\n\n\u002F\u002F Get positions on Arbitrum only\nconst arbPositions = await sdk.getPositions(\"0xUser...\", 42161);\n```\n\n**Returns:**\n\n```typescript\ninterface PositionsResponse {\n  success: boolean;\n  userAddress: string;\n  positions: Position[];\n}\n```\n\n### getAvailableProtocols\n\nGet available DeFi protocols and pools for a specific chain with APY data.\n\n```typescript\nconst protocols = await sdk.getAvailableProtocols(42161); \u002F\u002F Arbitrum\n\nprotocols.protocols.forEach((protocol) => {\n  console.log(`${protocol.name} (ID: ${protocol.id})`);\n  if (protocol.pools) {\n    protocol.pools.forEach((pool) => {\n      console.log(`  Pool: ${pool.name} - APY: ${pool.apy || \"N\u002FA\"}%`);\n    });\n  }\n});\n```\n\nReturns:\n```typescript\ninterface ProtocolsResponse {\n  success: boolean;\n  chainId: SupportedChainId;\n  protocols: Protocol[];\n}\n```\n\n### getUserDetails\n\nGet current authenticated user details including smart wallet, chains, protocols, and settings. Requires SIWE authentication.\n\n```typescript\nawait sdk.connectAccount(walletClient, chainId);\nconst user = await sdk.getUserDetails();\n\nconsole.log(\"Smart Wallet:\", user.smartWallet);\nconsole.log(\"Chains:\", user.chains);\nconsole.log(\"Has Active Session:\", user.hasActiveSessionKey);\n```\n\nReturns `UpdateUserProfileResponse` (same as `updateUserProfile`).\n\n### updateUserProfile\n\nUpdate the authenticated user's profile settings including strategy, protocols, splitting, and cross-chain options. Requires SIWE authentication.\n\n```typescript\nsdk.updateUserProfile(params: UpdateUserProfileRequest): Promise\u003CUpdateUserProfileResponse>\n```\n\n**Parameters:**\n\n```typescript\ninterface UpdateUserProfileRequest {\n  \u002F** Investment strategy: \"conservative\" or \"aggressive\" *\u002F\n  strategy?: string;\n  \u002F** Array of protocol IDs to use *\u002F\n  protocols?: string[];\n  \u002F** Enable auto-selection of protocols *\u002F\n  autoSelectProtocols?: boolean;\n  \u002F** Enable omni-account for cross-chain operations *\u002F\n  omniAccount?: boolean;\n  \u002F** Array of chain IDs to operate on *\u002F\n  chains?: number[];\n  \u002F** Enable automatic compounding (default: true) *\u002F\n  autocompounding?: boolean;\n  \u002F** Custom name for your agent *\u002F\n  agentName?: string;\n  \u002F** Enable cross-chain strategy execution *\u002F\n  crosschainStrategy?: boolean;\n  \u002F** Enable position splitting across multiple protocols *\u002F\n  splitting?: boolean;\n  \u002F** Minimum number of splits (1-4) *\u002F\n  minSplits?: number;\n  \u002F** Asset to update: \"usdc\" (default) or \"eth\" *\u002F\n  asset?: \"USDC\" | \"WETH\";\n}\n```\n\n**Note on `asset`:** Each asset has its own configuration. Use `asset: \"WETH\"` to update WETH settings separately from USDC.\n\n**Returns:**\n\n```typescript\ninterface UpdateUserProfileResponse {\n  success: boolean;\n  smartWallet?: string;\n  chains?: number[];\n  strategy?: string;\n  protocols?: string[];\n  autoSelectProtocols?: boolean;\n  omniAccount?: boolean;\n  autocompounding?: boolean;\n  agentName?: string;\n  crosschainStrategy?: boolean;\n  executorProxy?: boolean;\n  hasActiveSessionKey?: boolean;\n  splitting?: boolean;\n  minSplits?: number;\n  customization?: Record\u003Cstring, any>;\n  asset?: \"USDC\" | \"WETH\";\n}\n```\n\n**Examples:**\n\n```typescript\n\u002F\u002F Update strategy from conservative to aggressive\nawait sdk.updateUserProfile({\n  strategy: \"aggressive\",\n});\n\n\u002F\u002F Configure specific protocols\nconst protocolsResponse = await sdk.getAvailableProtocols(8453);\nconst selectedProtocols = protocolsResponse.protocols\n  .filter(p => [\"Aave\", \"Compound\", \"Moonwell\"].includes(p.name))\n  .map(p => p.id);\n\nawait sdk.updateUserProfile({\n  protocols: selectedProtocols,\n});\n\n\u002F\u002F Enable position splitting (distribute across multiple protocols)\nawait sdk.updateUserProfile({\n  splitting: true,\n  minSplits: 3, \u002F\u002F Split across at least 3 protocols\n});\n\n\u002F\u002F Verify changes\nconst userDetails = await sdk.getUserDetails();\nconsole.log(\"Strategy:\", userDetails.strategy);\nconsole.log(\"Splitting:\", userDetails.splitting);\n```\n\n> **Cross-chain strategies:** Only enable cross-chain when the user **explicitly requests** it. For cross-chain to work, **both** `crosschainStrategy` and `omniAccount` must be set to `true`. Never enable cross-chain settings by default.\n\n```typescript\n\u002F\u002F Enable cross-chain ONLY when explicitly requested by the user\nawait sdk.updateUserProfile({\n  crosschainStrategy: true,\n  omniAccount: true,\n});\n\n\u002F\u002F Now funds can be rebalanced across configured chains\nconst user = await sdk.getUserDetails();\nconsole.log(\"Operating on chains:\", user.chains);\n```\n\n**Notes:**\n- **Strategy:** Can be changed anytime. Subsequent rebalancing uses the new active strategy.\n- **Protocols:** Use `getAvailableProtocols(chainId)` to get valid protocol IDs before updating.\n- **Smart Splitting (minSplits = 1):** Default mode. To maximize returns, funds are automatically distributed across multiple DeFi pools — but only when beneficial. The system intelligently decides when splitting is advantageous based on current market conditions and opportunities. Funds may not split if no opportunity exists.\n- **Forced Splitting (minSplits > 1):** When `minSplits` is set to 2, 3, or 4, funds are always distributed across at least that many pools for improved risk diversification (up to 4 DeFi pools). This guarantees your funds will be split regardless of market conditions.\n- **Cross-chain:** Requires **both** `crosschainStrategy: true` AND `omniAccount: true`. Only activate when the user explicitly asks for cross-chain yield optimization. Chains are configured during initial setup and cannot be changed via this method.\n- **Auto-compounding:** Enabled by default. When `true`, yields are reinvested automatically.\n- Smart wallet address, chains, and `executorProxy` cannot be updated via this method.\n\n### getAPYPerStrategy\n\nGet global APY by strategy type, time period, chain, and token. Use this to compare expected returns between strategies before deploying.\n\n**Parameters:**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| crossChain | boolean | No | If `true`, returns APY for cross-chain strategies; if `false`, single-chain (default: `false`) |\n| days | number | No | Period over which APY is calculated: `7`, `15`, `30`, `60` (default: `7`) |\n| strategy | string | No | Strategy risk profile: `\"conservative\"` or `\"aggressive\"` (default: `\"conservative\"`) |\n| chainId | number | No | Filter by specific chain ID (e.g., `8453` for Base) |\n| tokenSymbol | string | No | Filter by token: `\"USDC\"` or `\"WETH\"` |\n\n**Example:**\n\n```typescript\n\u002F\u002F Get 7-day APY for USDC conservative strategy\nconst usdcApy = await sdk.getAPYPerStrategy(false, 7, \"conservative\", undefined, \"USDC\");\nconsole.log(\"USDC APY:\", usdcApy.data);\n\n\u002F\u002F Get 30-day APY for WETH aggressive strategy on Base\nconst wethApy = await sdk.getAPYPerStrategy(false, 30, \"aggressive\", 8453, \"WETH\");\nconsole.log(\"WETH APY on Base:\", wethApy.data);\n\n\u002F\u002F Compare strategies\nconst conservative = await sdk.getAPYPerStrategy(false, 30, \"conservative\");\nconst aggressive = await sdk.getAPYPerStrategy(false, 30, \"aggressive\");\nconsole.log(`Conservative 30d APY: ${conservative.data[0]?.average_apy}%`);\nconsole.log(`Aggressive 30d APY: ${aggressive.data[0]?.average_apy}%`);\n```\n\n**Returns:**\n\n```typescript\ninterface APYPerStrategyResponse {\n  success: boolean;\n  count: number;\n  data: APYPerStrategy[];\n}\n\ninterface APYPerStrategy {\n  id: string;\n  timestamp: string;\n  amount: number;\n  fee_threshold: number;\n  days: number;\n  chain_id: number;\n  is_cross_chain: boolean;\n  average_apy: number;\n  average_apy_with_rzfi: number;\n  total_rebalances: number;\n  created_at: string;\n  strategy: string;\n  token_symbol?: string;\n  average_apy_with_fee: number;\n  average_apy_with_rzfi_with_fee: number;\n  average_apy_without_fee?: number;\n  average_apy_with_rzfi_without_fee?: number;\n  events_average_apy?: Record\u003Cstring, number>;\n}\n```\n\n### getOnchainEarnings\n\nGet onchain earnings for a wallet with per-token breakdown (USDC, WETH).\n\n```typescript\nconst earnings = await sdk.getOnchainEarnings(smartWalletAddress);\n\nconsole.log(\"Total earnings by token:\", earnings.data.totalEarningsByToken);\n\u002F\u002F { \"USDC\": 150.50, \"WETH\": 0.05 }\n\nconsole.log(\"USDC earnings:\", earnings.data.totalEarningsByToken[\"USDC\"]);\nconsole.log(\"WETH earnings:\", earnings.data.totalEarningsByToken[\"WETH\"]);\n```\n\nReturns:\n```typescript\n\u002F\u002F TokenEarnings is a record of token symbols to amounts\ntype TokenEarnings = Record\u003Cstring, number>;  \u002F\u002F e.g., { \"USDC\": 100.5, \"WETH\": 0.025 }\n\ninterface OnchainEarningsResponse {\n  success: boolean;\n  data: {\n    walletAddress: string;\n    totalEarningsByToken: TokenEarnings;\n    lifetimeEarningsByToken: TokenEarnings;\n    currentEarningsByChain: Record\u003Cstring, TokenEarnings>;\n    unrealizedEarningsByChain: Record\u003Cstring, TokenEarnings>;\n    lastCheckTimestamp?: string;\n  };\n}\n```\n\n### registerAgentOnIdentityRegistry (ERC-8004)\n\nRegister your Zyfai deployed agent on the Identity Registry following the ERC-8004 standard. This is used for OpenClaw agent registration. The method fetches a tokenUri containing the agent's metadata stored on IPFS, then registers it on-chain.\n\n**Supported Chains:**\n\n| Chain | Chain ID |\n|-------|----------|\n| Base | 8453 |\n| Arbitrum | 42161 |\n\n**Parameters:**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| smartWallet | string | Yes | The Zyfai deployed smart wallet address to register as an agent |\n| chainId | SupportedChainId | Yes | Chain ID (only 8453 or 42161) |\n\n**Example:**\n\n```typescript\nconst sdk = new ZyfaiSDK({ apiKey: \"your-api-key\" });\nawait sdk.connectAccount(walletClient, 8453);\n\n\u002F\u002F Get smart wallet address\nconst walletInfo = await sdk.getSmartWalletAddress(userAddress, 8453);\nconst smartWallet = walletInfo.address;\n\n\u002F\u002F Register agent on Identity Registry\nconst result = await sdk.registerAgentOnIdentityRegistry(smartWallet, 8453);\n\nconsole.log(\"Registration successful:\");\nconsole.log(\"  Tx Hash:\", result.txHash);\nconsole.log(\"  Chain ID:\", result.chainId);\nconsole.log(\"  Smart Wallet:\", result.smartWallet);\n```\n\n**Returns:**\n\n```typescript\ninterface RegisterAgentResponse {\n  success: boolean;\n  txHash: string;\n  chainId: number;\n  smartWallet: string;\n}\n```\n\n**How It Works:**\n\n1. Fetches a `tokenUri` from the Zyfai API (agent metadata stored on IPFS)\n2. Encodes the `register(tokenUri)` call for the Identity Registry contract\n3. Sends the transaction from the connected wallet\n4. Waits for on-chain confirmation\n\n## Security\n\n- **Non-custodial** — User's EOA owns the subaccount\n- **Session keys are limited** — Can rebalance, cannot withdraw elsewhere\n- **Deterministic** — Same EOA = same subaccount on every chain\n- **Flexible key management** — Use wallet providers, WalletClients, or KMS integrations\n\n### Key Management Best Practices\n\nFor **production autonomous agents**, we recommend:\n\n1. **Use a WalletClient** with a secure key source (not raw private keys)\n2. **Integrate with KMS** (AWS KMS, GCP Cloud KMS) for hardware-backed key storage\n3. **Consider Wallet-as-a-Service** providers like Turnkey, Privy, or Dynamic\n4. **Never hardcode** private keys in source code\n5. **Rotate keys** periodically and implement key revocation procedures\n\n## Troubleshooting\n\n### Subaccount address mismatch across chains\n\nThe subaccount address should be **identical** across all chains for the same EOA. If you see different addresses:\n\n```typescript\n\u002F\u002F Check addresses on both chains\nconst baseWallet = await sdk.getSmartWalletAddress(userAddress, 8453);\nconst arbWallet = await sdk.getSmartWalletAddress(userAddress, 42161);\n\nif (baseWallet.address !== arbWallet.address) {\n  console.error(\"Address mismatch! Contact support.\");\n}\n```\n\n**If addresses don't match:**\n1. Try redeploying on the affected chain\n2. If the issue persists, contact support on Telegram: [@paul_zyfai](https:\u002F\u002Ft.me\u002Fpaul_zyfai)\n\n### \"Deposit address not found\" error\n\nThis means the wallet isn't registered in the backend. Solution:\n1. Call `deploySafe()` first — even if the Safe is already deployed on-chain, this registers it with the backend\n2. Then retry `createSessionKey()`\n\n### \"Invalid signature\" error\n\nThis typically means:\n- The wallet\u002Fsigner doesn't match the EOA you're passing\n- The Safe address on-chain doesn't match what the SDK expects\n\nVerify you're using the correct wallet for the EOA.\n\n## Resources\n\n- **Get API Key:** [sdk.zyf.ai](https:\u002F\u002Fsdk.zyf.ai) or programmatically via `POST \u002Fapi\u002Fsdk-api-keys\u002Fcreate`\n- **Docs:** [docs.zyf.ai](https:\u002F\u002Fdocs.zyf.ai)\n- **Demo:** [github.com\u002Fondefy\u002Fzyfai-sdk-demo](https:\u002F\u002Fgithub.com\u002Fondefy\u002Fzyfai-sdk-demo)\n- **MCP Server:** [mcp.zyf.ai](https:\u002F\u002Fmcp.zyf.ai\u002Fmcp) — Use with Claude or other MCP-compatible agents\n- **Agent Registration:** [zyf.ai\u002F.well-known\u002Fagent-registration.json](https:\u002F\u002Fwww.zyf.ai\u002F.well-known\u002Fagent-registration.json)\n\n## License\n\nMIT License\n\nCopyright (c) 2026 Zyfai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and\u002For sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n",{"name":5,"description":7},"main","82fb6583c8457bf1cbf87293c95642f184e9dbaf","skills\u002Fzyfai",2,"https:\u002F\u002Fgithub.com\u002FEskyee\u002Fagentbot-opensource","https:\u002F\u002Fagentbot-studio.vercel.app","https:\u002F\u002Fgithub.com\u002FEskyee","https:\u002F\u002Fagentbot.sh","London-based indie founder. \r\nCreator of Agentbot.sh - BaseFM.space","2026-11-05 10:56:50",{"source":8,"skillName":5,"commands":50,"prompt":60,"zipAvailable":61},[51,54,57],{"tool":52,"command":53},"npx","npx skills add Eskyee\u002Fagentbot-opensource --skill zyfai",{"tool":55,"command":56},"bunx","bunx skills add Eskyee\u002Fagentbot-opensource --skill zyfai",{"tool":58,"command":59},"pnpm","pnpm dlx skills add Eskyee\u002Fagentbot-opensource --skill zyfai","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FEskyee\u002Fagentbot-opensource\u002Fblob\u002Fmain\u002Fskills\u002Fzyfai\u002FSKILL.md",true,[],[64,77,112,137,145,167],{"skillNo":65,"name":66,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":67,"categories":68,"keywords":74,"publishedAt":34},"01M6ET5WZACASAB0WXF3RWEA00","provisioning-v1","https:\u002F\u002Fgithub.com\u002FEskyee\u002Fagentbot-opensource\u002Fblob\u002Fmain\u002Fweb\u002Fskills\u002Fprovisioning-v1\u002FSKILL.md",[69],{"categoryNo":70,"categoryName":71,"taxonomyType":72,"taxonomyTypeDesc":73},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[75,76],"provisioning v1","provisioning",{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":91,"publishedAt":34},"01M6ET5R7WW7NHX7BBH6RR41SH","get-api-docs","Use this skill when you need documentation for a third-party library, SDK, or API before writing code that uses it — for example, \"use the OpenAI API\", \"call the Stripe API\", \"use the Anthropic SDK\", \"query Pinecone\", or any time the user asks you to write code against an external service and you need current API reference. Fetch the docs with chub before answering, rather than relying on training knowledge.","https:\u002F\u002Fgithub.com\u002FEskyee\u002Fagentbot-opensource\u002Fblob\u002Fmain\u002Fweb\u002Fskills\u002Fget-api-docs\u002FSKILL.md",[83,86],{"categoryNo":84,"categoryName":85,"taxonomyType":72,"taxonomyTypeDesc":73},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111],"api","docs","get","get api docs","knowledge","anthropic sdk","time","query","stripe","pinecone","example","fetch","write","library","openai api","openai","code","training","documentation","writing",{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":119,"publishedAt":34},"01M6ET5FA594JNMY39RN003ANW","zerion","Interpreted crypto wallet data for AI agents. Use when an agent needs portfolio values, token positions, DeFi positions, NFT holdings, transaction history, PnL data, token prices, charts, gas prices, swap quotes, or DApp information across 41+ chains. Zerion transforms raw blockchain data into agent-ready JSON with USD values, protocol labels, and enriched metadata. Supports x402 pay-per-request ($0.01 USDC on Base) and API key access. Triggers on mentions of portfolio, wallet analysis, positions, transactions, PnL, profit\u002Floss, DeFi, token balances, NFTs, swap quotes, gas prices, or Zerion.","https:\u002F\u002Fgithub.com\u002FEskyee\u002Fagentbot-opensource\u002Fblob\u002Fmain\u002Fskills\u002Fzerion\u002FSKILL.md",[118],{"categoryNo":84,"categoryName":85,"taxonomyType":72,"taxonomyTypeDesc":73},[114,120,121,122,123,124,125,126,127,25,128,129,130,131,132,133,92,134,135,136],"nfts","token","nft","across","transactions","transforms","usd","x402","ready","portfolio","gas","access","data","information","analysis","ai agents","Charts",{"skillNo":138,"name":139,"nameZh":6,"description":140,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":141,"categories":142,"keywords":143,"publishedAt":34},"01M6ET5C758AY90H4E0AWAJ9JR","zapper","Placeholder for Zapper skill.","https:\u002F\u002Fgithub.com\u002FEskyee\u002Fagentbot-opensource\u002Fblob\u002Fmain\u002Fskills\u002Fzapper\u002FSKILL.md",[],[139,144],"placeholder",{"skillNo":146,"name":147,"nameZh":6,"description":148,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":149,"categories":150,"keywords":151,"publishedAt":34},"01M6ET5965RAA4BZNSWEVK3MGW","yoink","Play Yoink, an onchain capture-the-flag game on Base. Yoink the flag from the current holder, check game stats and leaderboards, view player scores, and compete for the trophy. Uses Bankr for transaction execution.","https:\u002F\u002Fgithub.com\u002FEskyee\u002Fagentbot-opensource\u002Fblob\u002Fmain\u002Fskills\u002Fyoink\u002FSKILL.md",[],[147,152,153,154,26,155,156,157,158,159,160,161,162,163,164,165,166],"https","play","stats","org","compete","transaction","bankr","onchain","view","check","capture","jq","curl","game","execution",{"skillNo":168,"name":169,"nameZh":6,"description":170,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":171,"categories":172,"keywords":174,"publishedAt":34},"01M6ET54MPC9VNMTKF5ZVG5XM7","wake-token-spotter-analysis","Get the WAKE engine's analysis of any Base token by contract address. Returns a transparent 0-100 score across five criteria (deployer quality, liquidity health, contract safety, market signals, social signals), launch protocol classification (Bankr\u002FClanker\u002Fdirect), security flags from GoPlus, controlled-vocabulary tags, and a brief narrative interpretation. Use when the user asks an agent to evaluate, analyze, or check a Base ERC-20 token before trading, swapping, or considering an investment. Read-only intelligence — not financial advice.","https:\u002F\u002Fgithub.com\u002FEskyee\u002Fagentbot-opensource\u002Fblob\u002Fmain\u002Fskills\u002Fwake-token-spotter-analysis\u002FSKILL.md",[173],{"categoryNo":70,"categoryName":71,"taxonomyType":72,"taxonomyTypeDesc":73},[121,175,134,176,177,94,178,123,179,158,180,181,182,183,184,185,186,187,188,189],"wake token spotter analysis","social","narrative","signals","clanker","intelligence","flags","only","read","direct","analyze","Safety","brief","interpretation","security"]