[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6X8VVAGDMBRCPCAZ5VR3BY2":3,"skill-same:01M6X8VVAGDMBRCPCAZ5VR3BY2":73},{"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":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":50,"commitSha":51,"skillDirectory":52,"forksCount":53,"repositoryHtmlUrl":54,"repositoryHomepageUrl":6,"ownerHtmlUrl":55,"ownerBlogUrl":56,"ownerDescription":57,"updatedAt":58,"install":59,"resources":72},"01M6X8VVAGDMBRCPCAZ5VR3BY2","Bankr Dev - Client Patterns",null,"This skill should be used when the user asks to \"implement Bankr client\", \"write bankr-client.ts\", \"create API client for Bankr\", \"common files for Bankr project\", \"package.json for Bankr\", \"tsconfig for Bankr\", \"Bankr TypeScript patterns\", \"Bankr response types\", or needs the reusable client code and common project files for Bankr API integrations.","enuno\u002Fcrewless-capital","enuno","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6727752?v=4","01M6J09HF6Y74150F7PEMC446X","Elvis Nuno","01M6X86WGZG9RH09ACTSTJ2383",1,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fenuno\u002Fcrewless-capital\u002Fblob\u002Fmain\u002Fmigrate-hyperliquid-firm\u002Fskills\u002Fbankr-skills\u002Fbankr-dev-client-patterns\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"Bankr Dev   Client Patterns","dev","client","bankr","patterns","files","when","for","types","project","reusable","implement","write","common","integrations","json","api","package","code","create","2026-11-10 10:12:30",false,"---\nname: Bankr Dev - Client Patterns\ndescription: This skill should be used when the user asks to \"implement Bankr client\", \"write bankr-client.ts\", \"create API client for Bankr\", \"common files for Bankr project\", \"package.json for Bankr\", \"tsconfig for Bankr\", \"Bankr TypeScript patterns\", \"Bankr response types\", or needs the reusable client code and common project files for Bankr API integrations.\nversion: 1.0.0\n---\n\n# Bankr Client Patterns\n\nReusable client code and common files for Bankr API projects.\n\n## bankr-client.ts\n\nThe core API client module for all Bankr projects:\n\n```typescript\nimport \"dotenv\u002Fconfig\";\n\nconst API_URL = process.env.BANKR_API_URL || \"https:\u002F\u002Fapi.bankr.bot\";\nconst API_KEY = process.env.BANKR_API_KEY;\n\n\u002F\u002F ============================================\n\u002F\u002F Types\n\u002F\u002F ============================================\n\nexport type JobStatus = \"pending\" | \"processing\" | \"completed\" | \"failed\" | \"cancelled\";\n\nexport interface JobStatusResponse {\n  success: boolean;\n  jobId: string;\n  status: JobStatus;\n  prompt: string;\n  response?: string;\n  transactions?: Transaction[];\n  richData?: RichData[];\n  statusUpdates?: StatusUpdate[];\n  error?: string;\n  createdAt: string;\n  startedAt?: string;\n  completedAt?: string;\n  cancelledAt?: string;\n  processingTime?: number;\n  cancellable?: boolean;\n}\n\nexport interface StatusUpdate {\n  message: string;\n  timestamp: string;\n}\n\n\u002F\u002F Transaction types\nexport type Transaction =\n  | SwapTransaction\n  | ApprovalTransaction\n  | TransferErc20Transaction\n  | TransferEthTransaction\n  | ConvertEthToWethTransaction\n  | ConvertWethToEthTransaction\n  | TransferNftTransaction\n  | MintManifoldNftTransaction\n  | MintSeaDropNftTransaction\n  | BuyNftTransaction\n  | AvantisTradeTransaction\n  | SwapCrossChainTransaction\n  | ManageBankrStakingTransaction;\n\ninterface BaseTransactionMetadata {\n  __ORIGINAL_TX_DATA__: {\n    chain: string;\n    humanReadableMessage: string;\n    inputTokenAddress: string;\n    inputTokenAmount: string;\n    inputTokenTicker: string;\n    outputTokenAddress: string;\n    outputTokenTicker: string;\n    receiver: string;\n  };\n  transaction: {\n    chainId: number;\n    to: string;\n    data: string;\n    gas: string;\n    gasPrice: string;\n    value: string;\n  };\n}\n\nexport interface SwapTransaction {\n  type: \"swap\";\n  metadata: BaseTransactionMetadata & {\n    approvalRequired?: boolean;\n    approvalTx?: { to: string; data: string };\n    permit2?: object;\n  };\n}\n\nexport interface ApprovalTransaction {\n  type: \"approval\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface TransferErc20Transaction {\n  type: \"transfer_erc20\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface TransferEthTransaction {\n  type: \"transfer_eth\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface ConvertEthToWethTransaction {\n  type: \"convert_eth_to_weth\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface ConvertWethToEthTransaction {\n  type: \"convert_weth_to_eth\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface TransferNftTransaction {\n  type: \"transfer_nft\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface MintManifoldNftTransaction {\n  type: \"mint_manifold_nft\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface MintSeaDropNftTransaction {\n  type: \"mint_seadrop_nft\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface BuyNftTransaction {\n  type: \"buy_nft\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface AvantisTradeTransaction {\n  type: \"avantisTrade\";\n  metadata: {\n    chainId: number;\n    description: string;\n    to: string;\n    data: string;\n    value?: string;\n  };\n}\n\nexport interface SwapCrossChainTransaction {\n  type: \"swapCrossChain\";\n  metadata: {\n    chainId: number;\n    description: string;\n    to: string;\n    data: string;\n    value: string;\n  };\n}\n\nexport interface ManageBankrStakingTransaction {\n  type: \"manage_bankr_staking\";\n  metadata: {\n    chainId: number;\n    description: string;\n    to: string;\n    data: string;\n    value?: string;\n  };\n}\n\n\u002F\u002F Rich data types\nexport type RichData = SocialCard | Chart;\n\nexport interface SocialCard {\n  type: \"social-card\";\n  variant: \"analysis\";\n  text: string;\n}\n\nexport interface Chart {\n  type: \"chart\";\n  url: string;\n}\n\n\u002F\u002F ============================================\n\u002F\u002F API Functions\n\u002F\u002F ============================================\n\nexport async function submitPrompt(prompt: string): Promise\u003C{ jobId: string }> {\n  if (!API_KEY) {\n    throw new Error(\"BANKR_API_KEY not set. Get one at https:\u002F\u002Fbankr.bot\u002Fapi\");\n  }\n\n  const response = await fetch(`${API_URL}\u002Fagent\u002Fprompt`, {\n    method: \"POST\",\n    headers: {\n      \"x-api-key\": API_KEY,\n      \"Content-Type\": \"application\u002Fjson\",\n    },\n    body: JSON.stringify({ prompt }),\n  });\n\n  if (!response.ok) {\n    const text = await response.text();\n    throw new Error(`API error ${response.status}: ${text}`);\n  }\n\n  const data = await response.json();\n  if (!data.success) {\n    throw new Error(data.error || \"Failed to submit prompt\");\n  }\n\n  return { jobId: data.jobId };\n}\n\nexport async function getJobStatus(jobId: string): Promise\u003CJobStatusResponse> {\n  if (!API_KEY) {\n    throw new Error(\"BANKR_API_KEY not set\");\n  }\n\n  const response = await fetch(`${API_URL}\u002Fagent\u002Fjob\u002F${jobId}`, {\n    headers: { \"x-api-key\": API_KEY },\n  });\n\n  if (!response.ok) {\n    const text = await response.text();\n    throw new Error(`API error ${response.status}: ${text}`);\n  }\n\n  return response.json();\n}\n\nexport async function cancelJob(jobId: string): Promise\u003CJobStatusResponse> {\n  if (!API_KEY) {\n    throw new Error(\"BANKR_API_KEY not set\");\n  }\n\n  const response = await fetch(`${API_URL}\u002Fagent\u002Fjob\u002F${jobId}\u002Fcancel`, {\n    method: \"POST\",\n    headers: {\n      \"x-api-key\": API_KEY,\n      \"Content-Type\": \"application\u002Fjson\",\n    },\n  });\n\n  if (!response.ok) {\n    const text = await response.text();\n    throw new Error(`API error ${response.status}: ${text}`);\n  }\n\n  return response.json();\n}\n\nexport async function waitForCompletion(\n  jobId: string,\n  onProgress?: (message: string) => void,\n  options?: { pollInterval?: number; maxAttempts?: number }\n): Promise\u003CJobStatusResponse> {\n  const pollInterval = options?.pollInterval || 2000;\n  const maxAttempts = options?.maxAttempts || 150; \u002F\u002F 5 minutes max\n  let lastUpdateCount = 0;\n\n  for (let attempt = 0; attempt \u003C maxAttempts; attempt++) {\n    const status = await getJobStatus(jobId);\n\n    \u002F\u002F Report new status updates\n    if (onProgress && status.statusUpdates) {\n      for (let i = lastUpdateCount; i \u003C status.statusUpdates.length; i++) {\n        onProgress(status.statusUpdates[i].message);\n      }\n      lastUpdateCount = status.statusUpdates.length;\n    }\n\n    \u002F\u002F Check for terminal states\n    if ([\"completed\", \"failed\", \"cancelled\"].includes(status.status)) {\n      return status;\n    }\n\n    await new Promise((resolve) => setTimeout(resolve, pollInterval));\n  }\n\n  throw new Error(\"Job timed out after maximum attempts\");\n}\n\n\u002F**\n * Execute a Bankr prompt and wait for completion\n * Convenience function that combines submit + poll\n *\u002F\nexport async function execute(\n  prompt: string,\n  onProgress?: (message: string) => void\n): Promise\u003CJobStatusResponse> {\n  const { jobId } = await submitPrompt(prompt);\n  onProgress?.(`Job submitted: ${jobId}`);\n  return waitForCompletion(jobId, onProgress);\n}\n```\n\n---\n\n## Common Files\n\n### package.json\n\nBase package.json for all Bankr projects:\n\n```json\n{\n  \"name\": \"{project-name}\",\n  \"version\": \"0.1.0\",\n  \"description\": \"{description}\",\n  \"type\": \"module\",\n  \"main\": \"dist\u002Findex.js\",\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"start\": \"node dist\u002Findex.js\",\n    \"dev\": \"tsx src\u002Findex.ts\"\n  },\n  \"dependencies\": {\n    \"dotenv\": \"^16.3.1\"\n  },\n  \"devDependencies\": {\n    \"@types\u002Fnode\": \"^20.10.0\",\n    \"tsx\": \"^4.7.0\",\n    \"typescript\": \"^5.3.0\"\n  }\n}\n```\n\n#### Framework-Specific Dependencies\n\nAdd based on project template:\n\n**Web Service (Express):**\n```json\n\"dependencies\": {\n  \"express\": \"^4.18.0\"\n},\n\"devDependencies\": {\n  \"@types\u002Fexpress\": \"^4.17.21\"\n}\n```\n\n**Web Service (Fastify):**\n```json\n\"dependencies\": {\n  \"fastify\": \"^4.25.0\"\n}\n```\n\n**CLI:**\n```json\n\"dependencies\": {\n  \"commander\": \"^12.0.0\"\n}\n```\n\n---\n\n### tsconfig.json\n\nTypeScript configuration:\n\n```json\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\",\n    \"outDir\": \".\u002Fdist\",\n    \"rootDir\": \".\u002Fsrc\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"declaration\": true\n  },\n  \"include\": [\"src\u002F**\u002F*\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n```\n\n---\n\n### .env.example\n\nEnvironment variables template:\n\n```bash\n# Bankr API Configuration\nBANKR_API_KEY=bk_your_api_key_here\nBANKR_API_URL=https:\u002F\u002Fapi.bankr.bot\n\n# Optional: Wallet address for context\nBANKR_WALLET_ADDRESS=0x...\n```\n\n---\n\n### .gitignore\n\nStandard ignore patterns:\n\n```\n# Dependencies\nnode_modules\u002F\n\n# Build output\ndist\u002F\n\n# Environment\n.env\n.env.local\n.env.*.local\n\n# Logs\n*.log\nnpm-debug.log*\n\n# IDE\n.idea\u002F\n.vscode\u002F\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n\n# Testing\ncoverage\u002F\n```\n\n---\n\n## Usage Patterns\n\n### Basic Usage\n\n```typescript\nimport { execute } from \".\u002Fbankr-client\";\n\nconst result = await execute(\"What is the price of ETH?\", (msg) => {\n  console.log(\"Progress:\", msg);\n});\n\nconsole.log(result.response);\n```\n\n### With Error Handling\n\n```typescript\nimport { execute } from \".\u002Fbankr-client\";\n\ntry {\n  const result = await execute(\"Buy $50 of ETH on Base\");\n\n  if (result.status === \"completed\") {\n    console.log(\"Success:\", result.response);\n\n    \u002F\u002F Handle transactions\n    if (result.transactions) {\n      for (const tx of result.transactions) {\n        console.log(`${tx.type}:`, tx.metadata.__ORIGINAL_TX_DATA__?.humanReadableMessage);\n      }\n    }\n  } else if (result.status === \"failed\") {\n    console.error(\"Failed:\", result.error);\n  }\n} catch (error) {\n  console.error(\"Error:\", error.message);\n}\n```\n\n### Manual Control\n\n```typescript\nimport { submitPrompt, waitForCompletion, cancelJob } from \".\u002Fbankr-client\";\n\n\u002F\u002F Submit\nconst { jobId } = await submitPrompt(\"Analyze ETH market\");\n\n\u002F\u002F Set up timeout\nconst timeout = setTimeout(() => {\n  cancelJob(jobId);\n}, 120000);\n\n\u002F\u002F Wait with custom options\nconst result = await waitForCompletion(jobId, console.log, {\n  pollInterval: 2000,\n  maxAttempts: 60,\n});\n\nclearTimeout(timeout);\n```\n\n---\n\n## API Reference\n\nConsult the `bankr-api-basics` skill for:\n- Complete endpoint documentation\n- Authentication details\n- Response field descriptions\n- Error codes and handling\n","# Bankr Client Patterns\n\nReusable client code and common files for Bankr API projects.\n\n## bankr-client.ts\n\nThe core API client module for all Bankr projects:\n\n```typescript\nimport \"dotenv\u002Fconfig\";\n\nconst API_URL = process.env.BANKR_API_URL || \"https:\u002F\u002Fapi.bankr.bot\";\nconst API_KEY = process.env.BANKR_API_KEY;\n\n\u002F\u002F ============================================\n\u002F\u002F Types\n\u002F\u002F ============================================\n\nexport type JobStatus = \"pending\" | \"processing\" | \"completed\" | \"failed\" | \"cancelled\";\n\nexport interface JobStatusResponse {\n  success: boolean;\n  jobId: string;\n  status: JobStatus;\n  prompt: string;\n  response?: string;\n  transactions?: Transaction[];\n  richData?: RichData[];\n  statusUpdates?: StatusUpdate[];\n  error?: string;\n  createdAt: string;\n  startedAt?: string;\n  completedAt?: string;\n  cancelledAt?: string;\n  processingTime?: number;\n  cancellable?: boolean;\n}\n\nexport interface StatusUpdate {\n  message: string;\n  timestamp: string;\n}\n\n\u002F\u002F Transaction types\nexport type Transaction =\n  | SwapTransaction\n  | ApprovalTransaction\n  | TransferErc20Transaction\n  | TransferEthTransaction\n  | ConvertEthToWethTransaction\n  | ConvertWethToEthTransaction\n  | TransferNftTransaction\n  | MintManifoldNftTransaction\n  | MintSeaDropNftTransaction\n  | BuyNftTransaction\n  | AvantisTradeTransaction\n  | SwapCrossChainTransaction\n  | ManageBankrStakingTransaction;\n\ninterface BaseTransactionMetadata {\n  __ORIGINAL_TX_DATA__: {\n    chain: string;\n    humanReadableMessage: string;\n    inputTokenAddress: string;\n    inputTokenAmount: string;\n    inputTokenTicker: string;\n    outputTokenAddress: string;\n    outputTokenTicker: string;\n    receiver: string;\n  };\n  transaction: {\n    chainId: number;\n    to: string;\n    data: string;\n    gas: string;\n    gasPrice: string;\n    value: string;\n  };\n}\n\nexport interface SwapTransaction {\n  type: \"swap\";\n  metadata: BaseTransactionMetadata & {\n    approvalRequired?: boolean;\n    approvalTx?: { to: string; data: string };\n    permit2?: object;\n  };\n}\n\nexport interface ApprovalTransaction {\n  type: \"approval\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface TransferErc20Transaction {\n  type: \"transfer_erc20\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface TransferEthTransaction {\n  type: \"transfer_eth\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface ConvertEthToWethTransaction {\n  type: \"convert_eth_to_weth\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface ConvertWethToEthTransaction {\n  type: \"convert_weth_to_eth\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface TransferNftTransaction {\n  type: \"transfer_nft\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface MintManifoldNftTransaction {\n  type: \"mint_manifold_nft\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface MintSeaDropNftTransaction {\n  type: \"mint_seadrop_nft\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface BuyNftTransaction {\n  type: \"buy_nft\";\n  metadata: BaseTransactionMetadata;\n}\n\nexport interface AvantisTradeTransaction {\n  type: \"avantisTrade\";\n  metadata: {\n    chainId: number;\n    description: string;\n    to: string;\n    data: string;\n    value?: string;\n  };\n}\n\nexport interface SwapCrossChainTransaction {\n  type: \"swapCrossChain\";\n  metadata: {\n    chainId: number;\n    description: string;\n    to: string;\n    data: string;\n    value: string;\n  };\n}\n\nexport interface ManageBankrStakingTransaction {\n  type: \"manage_bankr_staking\";\n  metadata: {\n    chainId: number;\n    description: string;\n    to: string;\n    data: string;\n    value?: string;\n  };\n}\n\n\u002F\u002F Rich data types\nexport type RichData = SocialCard | Chart;\n\nexport interface SocialCard {\n  type: \"social-card\";\n  variant: \"analysis\";\n  text: string;\n}\n\nexport interface Chart {\n  type: \"chart\";\n  url: string;\n}\n\n\u002F\u002F ============================================\n\u002F\u002F API Functions\n\u002F\u002F ============================================\n\nexport async function submitPrompt(prompt: string): Promise\u003C{ jobId: string }> {\n  if (!API_KEY) {\n    throw new Error(\"BANKR_API_KEY not set. Get one at https:\u002F\u002Fbankr.bot\u002Fapi\");\n  }\n\n  const response = await fetch(`${API_URL}\u002Fagent\u002Fprompt`, {\n    method: \"POST\",\n    headers: {\n      \"x-api-key\": API_KEY,\n      \"Content-Type\": \"application\u002Fjson\",\n    },\n    body: JSON.stringify({ prompt }),\n  });\n\n  if (!response.ok) {\n    const text = await response.text();\n    throw new Error(`API error ${response.status}: ${text}`);\n  }\n\n  const data = await response.json();\n  if (!data.success) {\n    throw new Error(data.error || \"Failed to submit prompt\");\n  }\n\n  return { jobId: data.jobId };\n}\n\nexport async function getJobStatus(jobId: string): Promise\u003CJobStatusResponse> {\n  if (!API_KEY) {\n    throw new Error(\"BANKR_API_KEY not set\");\n  }\n\n  const response = await fetch(`${API_URL}\u002Fagent\u002Fjob\u002F${jobId}`, {\n    headers: { \"x-api-key\": API_KEY },\n  });\n\n  if (!response.ok) {\n    const text = await response.text();\n    throw new Error(`API error ${response.status}: ${text}`);\n  }\n\n  return response.json();\n}\n\nexport async function cancelJob(jobId: string): Promise\u003CJobStatusResponse> {\n  if (!API_KEY) {\n    throw new Error(\"BANKR_API_KEY not set\");\n  }\n\n  const response = await fetch(`${API_URL}\u002Fagent\u002Fjob\u002F${jobId}\u002Fcancel`, {\n    method: \"POST\",\n    headers: {\n      \"x-api-key\": API_KEY,\n      \"Content-Type\": \"application\u002Fjson\",\n    },\n  });\n\n  if (!response.ok) {\n    const text = await response.text();\n    throw new Error(`API error ${response.status}: ${text}`);\n  }\n\n  return response.json();\n}\n\nexport async function waitForCompletion(\n  jobId: string,\n  onProgress?: (message: string) => void,\n  options?: { pollInterval?: number; maxAttempts?: number }\n): Promise\u003CJobStatusResponse> {\n  const pollInterval = options?.pollInterval || 2000;\n  const maxAttempts = options?.maxAttempts || 150; \u002F\u002F 5 minutes max\n  let lastUpdateCount = 0;\n\n  for (let attempt = 0; attempt \u003C maxAttempts; attempt++) {\n    const status = await getJobStatus(jobId);\n\n    \u002F\u002F Report new status updates\n    if (onProgress && status.statusUpdates) {\n      for (let i = lastUpdateCount; i \u003C status.statusUpdates.length; i++) {\n        onProgress(status.statusUpdates[i].message);\n      }\n      lastUpdateCount = status.statusUpdates.length;\n    }\n\n    \u002F\u002F Check for terminal states\n    if ([\"completed\", \"failed\", \"cancelled\"].includes(status.status)) {\n      return status;\n    }\n\n    await new Promise((resolve) => setTimeout(resolve, pollInterval));\n  }\n\n  throw new Error(\"Job timed out after maximum attempts\");\n}\n\n\u002F**\n * Execute a Bankr prompt and wait for completion\n * Convenience function that combines submit + poll\n *\u002F\nexport async function execute(\n  prompt: string,\n  onProgress?: (message: string) => void\n): Promise\u003CJobStatusResponse> {\n  const { jobId } = await submitPrompt(prompt);\n  onProgress?.(`Job submitted: ${jobId}`);\n  return waitForCompletion(jobId, onProgress);\n}\n```\n\n---\n\n## Common Files\n\n### package.json\n\nBase package.json for all Bankr projects:\n\n```json\n{\n  \"name\": \"{project-name}\",\n  \"version\": \"0.1.0\",\n  \"description\": \"{description}\",\n  \"type\": \"module\",\n  \"main\": \"dist\u002Findex.js\",\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"start\": \"node dist\u002Findex.js\",\n    \"dev\": \"tsx src\u002Findex.ts\"\n  },\n  \"dependencies\": {\n    \"dotenv\": \"^16.3.1\"\n  },\n  \"devDependencies\": {\n    \"@types\u002Fnode\": \"^20.10.0\",\n    \"tsx\": \"^4.7.0\",\n    \"typescript\": \"^5.3.0\"\n  }\n}\n```\n\n#### Framework-Specific Dependencies\n\nAdd based on project template:\n\n**Web Service (Express):**\n```json\n\"dependencies\": {\n  \"express\": \"^4.18.0\"\n},\n\"devDependencies\": {\n  \"@types\u002Fexpress\": \"^4.17.21\"\n}\n```\n\n**Web Service (Fastify):**\n```json\n\"dependencies\": {\n  \"fastify\": \"^4.25.0\"\n}\n```\n\n**CLI:**\n```json\n\"dependencies\": {\n  \"commander\": \"^12.0.0\"\n}\n```\n\n---\n\n### tsconfig.json\n\nTypeScript configuration:\n\n```json\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\",\n    \"outDir\": \".\u002Fdist\",\n    \"rootDir\": \".\u002Fsrc\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"declaration\": true\n  },\n  \"include\": [\"src\u002F**\u002F*\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n```\n\n---\n\n### .env.example\n\nEnvironment variables template:\n\n```bash\n# Bankr API Configuration\nBANKR_API_KEY=bk_your_api_key_here\nBANKR_API_URL=https:\u002F\u002Fapi.bankr.bot\n\n# Optional: Wallet address for context\nBANKR_WALLET_ADDRESS=0x...\n```\n\n---\n\n### .gitignore\n\nStandard ignore patterns:\n\n```\n# Dependencies\nnode_modules\u002F\n\n# Build output\ndist\u002F\n\n# Environment\n.env\n.env.local\n.env.*.local\n\n# Logs\n*.log\nnpm-debug.log*\n\n# IDE\n.idea\u002F\n.vscode\u002F\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n\n# Testing\ncoverage\u002F\n```\n\n---\n\n## Usage Patterns\n\n### Basic Usage\n\n```typescript\nimport { execute } from \".\u002Fbankr-client\";\n\nconst result = await execute(\"What is the price of ETH?\", (msg) => {\n  console.log(\"Progress:\", msg);\n});\n\nconsole.log(result.response);\n```\n\n### With Error Handling\n\n```typescript\nimport { execute } from \".\u002Fbankr-client\";\n\ntry {\n  const result = await execute(\"Buy $50 of ETH on Base\");\n\n  if (result.status === \"completed\") {\n    console.log(\"Success:\", result.response);\n\n    \u002F\u002F Handle transactions\n    if (result.transactions) {\n      for (const tx of result.transactions) {\n        console.log(`${tx.type}:`, tx.metadata.__ORIGINAL_TX_DATA__?.humanReadableMessage);\n      }\n    }\n  } else if (result.status === \"failed\") {\n    console.error(\"Failed:\", result.error);\n  }\n} catch (error) {\n  console.error(\"Error:\", error.message);\n}\n```\n\n### Manual Control\n\n```typescript\nimport { submitPrompt, waitForCompletion, cancelJob } from \".\u002Fbankr-client\";\n\n\u002F\u002F Submit\nconst { jobId } = await submitPrompt(\"Analyze ETH market\");\n\n\u002F\u002F Set up timeout\nconst timeout = setTimeout(() => {\n  cancelJob(jobId);\n}, 120000);\n\n\u002F\u002F Wait with custom options\nconst result = await waitForCompletion(jobId, console.log, {\n  pollInterval: 2000,\n  maxAttempts: 60,\n});\n\nclearTimeout(timeout);\n```\n\n---\n\n## API Reference\n\nConsult the `bankr-api-basics` skill for:\n- Complete endpoint documentation\n- Authentication details\n- Response field descriptions\n- Error codes and handling\n",{"name":5,"version":49,"description":7},"1.0.0","main","bfe4e4653cba696a8dc20f70c6006651b997fdef","migrate-hyperliquid-firm\u002Fskills\u002Fbankr-skills\u002Fbankr-dev-client-patterns",0,"https:\u002F\u002Fgithub.com\u002Fenuno\u002Fcrewless-capital","https:\u002F\u002Fgithub.com\u002Fenuno","https:\u002F\u002Fenuno.github.io\u002FDynamicCareerCanvas","Digital Nomad, Blockchain Evangel, and Digital Solutions Architect. \r\nCreator of TerraHash Stack.\r\nCEO of Ryno Crypto Mining Services.","2026-07-02 10:49:15",{"source":8,"skillName":5,"commands":60,"prompt":70,"zipAvailable":71},[61,64,67],{"tool":62,"command":63},"npx","npx skills add enuno\u002Fcrewless-capital --skill \"Bankr Dev - Client Patterns\"",{"tool":65,"command":66},"bunx","bunx skills add enuno\u002Fcrewless-capital --skill \"Bankr Dev - Client Patterns\"",{"tool":68,"command":69},"pnpm","pnpm dlx skills add enuno\u002Fcrewless-capital --skill \"Bankr Dev - Client Patterns\"","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fenuno\u002Fcrewless-capital\u002Fblob\u002Fmain\u002Fmigrate-hyperliquid-firm\u002Fskills\u002Fbankr-skills\u002Fbankr-dev-client-patterns\u002FSKILL.md",true,[],[74,102,129,154,179,201],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":85,"publishedAt":44},"01M6X94YFR1XNANZ321FS661NG","supermemory","Supermemory is a state-of-the-art memory and context infrastructure for AI agents. Use this skill when building applications that need persistent memory, user personalization, long-term context retention, or semantic search across knowledge bases. It provides Memory API for learned user context, User Profiles for static\u002Fdynamic facts, and RAG for semantic search. Perfect for chatbots, assistants, and knowledge-intensive applications.","https:\u002F\u002Fgithub.com\u002Fenuno\u002Fcrewless-capital\u002Fblob\u002Fmain\u002Fmigrate-hyperliquid-firm\u002Fskills\u002Fsupermemory\u002FSKILL.md",[80],{"categoryNo":81,"categoryName":82,"taxonomyType":83,"taxonomyTypeDesc":84},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",[76,86,87,88,89,90,91,92,40,93,94,95,96,97,98,99,31,100,101,30],"ai agents","memory","rag","semantic search","infrastructure","search","applications","knowledge","context","Art","personalization","across","learned","retention","persistent memory","static",{"skillNo":103,"name":104,"nameZh":6,"description":105,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":106,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":109,"publishedAt":44},"01M6X94S3K97CSK7VFF5H85ED2","wolverine-strategy","WOLVERINE v2.0 — HYPE alpha hunter. Entry-only scanner, DSL-exit-only architecture. v1.1 lost -22.7% because the scanner's thesis exit chopped 25\u002F27 trades before DSL could manage them. v2.0 removes thesis exit entirely. Scanner decides entries (score 8+, 4H\u002F1H aligned, SM consensus). DSL manages all exits (wide Phase 1 for HYPE volatility, trailing tiers starting at +15% ROE). Leverage lowered to 7x. Max 4 entries\u002Fday. 3-hour cooldown between entries. DSL exit managed by plugin runtime via runtime.yaml.","MIT","https:\u002F\u002Fgithub.com\u002Fenuno\u002Fcrewless-capital\u002Fblob\u002Fmain\u002Fmigrate-hyperliquid-firm\u002Fskills\u002Fsenpi-skills\u002Fwolverine\u002FSKILL.md",[],[110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,31,126,127,128],"strategy","wolverine strategy","architecture","alpha","Volatility","consensus","only","trading","scanner","manage","max","hyperliquid","runtime","leverage","hunter","at","managed","dsl","phase",{"skillNo":130,"name":131,"nameZh":6,"description":132,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":106,"licenseFileUrl":6,"sourceHtmlUrl":133,"categories":134,"keywords":138,"publishedAt":44},"01M6X94HN3CHBM37GM2C84KT26","wolf-strategy","WOLF v6.3 — Fully autonomous multi-strategy trading for Hyperliquid perps via Senpi MCP. Manages multiple strategies simultaneously, each with independent wallets, budgets, slots, and DSL configs. 5+N cron architecture: 5 shared wolf crons (Emerging Movers 3min, SM Flip 5min, Watchdog 5min, Risk Guardian 5min, Health Check 10min) plus one DSL v5.2 cron per strategy (native Hyperliquid SL sync via dsl-dynamic-stop-loss skill v5.3.1). Same asset can be traded in different strategies simultaneously. Enter early on first jumps, not at confirmed peaks. Dynamic risk-based leverage per strategy. Requires Senpi MCP connection, python3, mcporter CLI, OpenClaw cron system, and dsl-dynamic-stop-loss skill (provides dsl-cli.py + dsl-v5.py).","https:\u002F\u002Fgithub.com\u002Fenuno\u002Fcrewless-capital\u002Fblob\u002Fmain\u002Fmigrate-hyperliquid-firm\u002Fskills\u002Fsenpi-skills\u002Fwolf-strategy\u002FSKILL.md",[135],{"categoryNo":136,"categoryName":137,"taxonomyType":83,"taxonomyTypeDesc":84},"01JBSEEDCAT000000000000023","Skill与智能体开发",[110,139,140,141,112,142,143,144,145,146,147,148,149,123,150,151,125,152,153,31],"wolf strategy","MCP","openclaw","health","system","python3","check","health check","stop","strategies","shared","connection","wallets","stop-loss","hyperliquid perps",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":106,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":161,"publishedAt":44},"01M6X949FBGWWGY3YZ8N3WB3CP","wolf-howl","HOWL v2 — Hunt, Optimize, Win, Learn. Nightly self-improvement loop for the WOLF autonomous trading strategy. Runs once per day (via cron) to review all trades from the last 24 hours, compute win rates, analyze signal quality correlation, evaluate DSL tier performance, identify missed opportunities, and produce concrete improvement suggestions for the wolf-strategy skill. v2 adds fee drag ratio (FDR) analysis, holding period bucketing, LONG vs SHORT regime detection, rotation cost tracking, cumulative drift detection, and gross vs net profit factor separation. Use when setting up daily trade review automation, analyzing trading performance, or improving an autonomous trading strategy through data-driven feedback loops. Requires Senpi MCP connection, mcporter CLI, and OpenClaw cron system.","https:\u002F\u002Fgithub.com\u002Fenuno\u002Fcrewless-capital\u002Fblob\u002Fmain\u002Fmigrate-hyperliquid-firm\u002Fskills\u002Fsenpi-skills\u002Fwolf-howl\u002FSKILL.md",[160],{"categoryNo":136,"categoryName":137,"taxonomyType":83,"taxonomyTypeDesc":84},[162,140,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,127,178,30],"wolf howl","review","performance","learn","analysis","loop","analyze","short","autonomous","up","optimize","drift","self","factor","loops","profit","fdr",{"skillNo":180,"name":181,"nameZh":6,"description":182,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":183,"categories":184,"keywords":185,"publishedAt":44},"01M6X9437CQ55N5AYHCPF71JWG","whale-index","Auto-mirror top Discovery traders on Hyperliquid. Scans top 50 traders, scores on PnL rank (35%), win rate (25%), consistency (20%), hold time (10%), drawdown (10%). Creates 2-5 mirror strategies with overlap checks. Daily rebalance with 2-day watch period before swaps. Use when setting up trader mirroring, copy trading, or portfolio auto-rebalancing based on Discovery leaderboard performance.","https:\u002F\u002Fgithub.com\u002Fenuno\u002Fcrewless-capital\u002Fblob\u002Fmain\u002Fmigrate-hyperliquid-firm\u002Fskills\u002Fsenpi-skills\u002Fwhale-index\u002FSKILL.md",[],[186,187,188,164,189,190,191,192,193,171,194,195,148,196,197,198,199,31,200,30],"index","whale","whale index","auth","monitoring","discovery","use","auto","daily","time","with","consistency","top","mirror","pnl",{"skillNo":202,"name":203,"nameZh":6,"description":204,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":106,"licenseFileUrl":6,"sourceHtmlUrl":205,"categories":206,"keywords":207,"publishedAt":44},"01M6X93YTRGNPYNHZRTW9XNH1E","vixen-strategy","VIXEN v1.0 — Dual-mode emerging movers scanner. Built from FOX v1.6 live trading data (+34.5% ROI). Two entry modes: STALKER (steady accumulation, score 6+, catches the SM buildup BEFORE the explosion) and STRIKER (violent FIRST_JUMP, score 9+, with raw volume confirmation to filter blow-off tops). 2-hour per-asset cooldown after Phase 1 exits. DSL High Water Mode mandatory.","https:\u002F\u002Fgithub.com\u002Fenuno\u002Fcrewless-capital\u002Fblob\u002Fmain\u002Fmigrate-hyperliquid-firm\u002Fskills\u002Fsenpi-skills\u002Fvixen\u002FSKILL.md",[],[110,208,209,210,211,212,118,213,214,215,196,216,217,218,219,220,221,222,127,128],"vixen strategy","roi","data","first","confirmation","volume","filter","asset","explosion","mode","high","v1","modes","emerging movers","entry"]