[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6Q46RHGFFYZ4W60EXXEVGPK":3,"skill-same:01M6Q46RHGFFYZ4W60EXXEVGPK":70},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":48,"commitSha":49,"skillDirectory":50,"forksCount":51,"repositoryHtmlUrl":52,"repositoryHomepageUrl":6,"ownerHtmlUrl":53,"ownerBlogUrl":6,"ownerDescription":54,"updatedAt":55,"install":56,"resources":69},"01M6Q46RHGFFYZ4W60EXXEVGPK","jb-multi-currency",null,"Handle Juicebox V5 multi-currency projects (ETH vs USDC accounting).\nUse when: (1) building UI that displays currency labels (ETH vs USDC),\n(2) sending transactions that require currency parameter,\n(3) configuring fund access limits or accounting contexts for new rulesets,\n(4) querying project balance\u002Fsurplus with correct token,\n(5) debugging \"wrong currency\" issues in payout or allowance transactions,\n(6) need currency code constants (NATIVE_CURRENCY=61166, USDC varies by chain),\n(7) cash out modal shows wrong return currency (ETH instead of USDC),\n(8) need shared chain constants (names, explorers) across multiple modals.\nCurrency in JBAccountingContext is uint32(uint160(tokenAddress)), NOT 1 or 2.\nCovers baseCurrency detection, decimal handling, terminal accounting, currency codes,\ndynamic labels, cash out return display, and shared chain constants patterns.","Kernel8901\u002Fai-agent-skills-classification","Kernel8901","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F72647553?v=4","01M6KV388J2H5PNC8D8P940BJD","01M6KV38CS5B3AY63RKZB410YM",7,"MIT","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F视觉与设计\u002Fjuicy\u002Fjb-multi-currency\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000040","财务","PROFESSION","适用职业",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"jb multi currency","multi","currency","token","limits","labels","display","juicebox v5","native","chain","terminal","project","shared","across","projects","access","transactions","issues","code","debugging","2026-11-10 10:12:30",false,"---\nname: jb-multi-currency\ndescription: |\n  Handle Juicebox V5 multi-currency projects (ETH vs USDC accounting).\n  Use when: (1) building UI that displays currency labels (ETH vs USDC),\n  (2) sending transactions that require currency parameter,\n  (3) configuring fund access limits or accounting contexts for new rulesets,\n  (4) querying project balance\u002Fsurplus with correct token,\n  (5) debugging \"wrong currency\" issues in payout or allowance transactions,\n  (6) need currency code constants (NATIVE_CURRENCY=61166, USDC varies by chain),\n  (7) cash out modal shows wrong return currency (ETH instead of USDC),\n  (8) need shared chain constants (names, explorers) across multiple modals.\n  Currency in JBAccountingContext is uint32(uint160(tokenAddress)), NOT 1 or 2.\n  Covers baseCurrency detection, decimal handling, terminal accounting, currency codes,\n  dynamic labels, cash out return display, and shared chain constants patterns.\n---\n\n# Juicebox V5 Multi-Currency Support\n\n## Problem\n\nJuicebox V5 projects can be denominated in either ETH (baseCurrency=1) or USD (baseCurrency=2).\nUI components and transactions must use the correct currency value, token address, and display\nlabels. Hardcoding \"ETH\" or currency=1 causes failures for USDC-based projects.\n\n## Context \u002F Trigger Conditions\n\n- UI shows \"ETH\" when project is USDC-based\n- Payout or allowance transaction fails silently\n- Fund access limits set with wrong currency\n- Currency mismatch between ruleset config and terminal accounting\n- Need to display correct currency symbol in forms\n\n## Solution\n\n### 1. Detect Project Currency from Ruleset\n\n```typescript\n\u002F\u002F baseCurrency is in ruleset metadata\n\u002F\u002F 1 = ETH, 2 = USD (USDC)\nconst baseCurrency = ruleset?.metadata?.baseCurrency || 1\nconst currencyLabel = baseCurrency === 2 ? 'USDC' : 'ETH'\n```\n\n### 2. Use Dynamic Currency in Transactions\n\nWhen calling terminal functions (sendPayoutsOf, useAllowanceOf), use the project's baseCurrency:\n\n```typescript\n\u002F\u002F WRONG - hardcoded\nargs: [projectId, token, amount, 1n, minTokensPaidOut, beneficiary]\n\n\u002F\u002F CORRECT - dynamic\nargs: [projectId, token, amount, BigInt(baseCurrency), minTokensPaidOut, beneficiary]\n```\n\n### 3. Fund Access Limits Currency\n\nWhen queuing new rulesets or displaying limits, match the existing project currency.\n**Use correct decimals**: Query from `ERC20.decimals()` or use 18 for native tokens.\n\n```typescript\nimport { parseUnits } from 'viem'\n\n\u002F\u002F Get currency from existing config\nconst currency = existingConfig?.baseCurrency || 1\n\n\u002F\u002F Get decimals from the token contract (or 18 for native token)\n\u002F\u002F For USDC: 6 decimals. For native token (ETH): 18 decimals.\nconst decimals = await getTokenDecimals(tokenAddress, publicClient)\n\n\u002F\u002F Use in fund access limit configuration\nconst payoutLimits = [{\n  amount: parseUnits(limitAmount, decimals).toString(),\n  currency, \u002F\u002F Match project's base currency (1 or 2)\n}]\n```\n\n### 4. Two Different \"currency\" Concepts (CRITICAL)\n\nJuicebox V5 has TWO different concepts called \"currency\" that are often confused:\n\n| Field | Location | Values | Purpose |\n|-------|----------|--------|---------|\n| `baseCurrency` | Ruleset metadata | 1 = ETH, 2 = USD | Issuance rate calculation |\n| `JBCurrencyAmount.currency` | Fund access limits | 1 = ETH, 2 = USD | Payout\u002Fallowance limits |\n| `JBAccountingContext.currency` | Terminal config | `uint32(uint160(token))` | Terminal accounting |\n\n**The `currency` value in JBAccountingContext is NOT 1 or 2. It's `uint32(uint160(tokenAddress))`.**\n\n```typescript\n\u002F\u002F NATIVE_TOKEN (ETH) - same on all chains - from JBConstants.NATIVE_TOKEN\nconst NATIVE_TOKEN = '0x000000000000000000000000000000000000EEEe'\nconst NATIVE_CURRENCY = 61166 \u002F\u002F uint32(uint160(NATIVE_TOKEN)) = 0x0000EEEe\n\n\u002F\u002F USDC addresses and currency codes per chain\nconst USDC_CONFIG: Record\u003Cnumber, { address: string; currency: number }> = {\n  1: {      \u002F\u002F Ethereum\n    address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n    currency: 909516616,\n  },\n  10: {     \u002F\u002F Optimism\n    address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n    currency: 3530704773,\n  },\n  8453: {   \u002F\u002F Base\n    address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n    currency: 3169378579,\n  },\n  42161: {  \u002F\u002F Arbitrum\n    address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n    currency: 1156540465,\n  },\n}\n```\n\n**How to calculate currency from any token address:**\n```typescript\nconst calculateCurrency = (tokenAddress: string): number => {\n  \u002F\u002F Take last 4 bytes of address as uint32\n  return Number(BigInt(tokenAddress) & BigInt(0xFFFFFFFF))\n}\n```\n\n### 5. Decimal Handling\n\n**General rule:** Get decimals from `ERC20.decimals()` for any token. Native tokens (ETH, MATIC, etc.) always use 18 decimals.\n\nCommon cases:\n- Native token (ETH): 18 decimals\n- USDC: 6 decimals\n- Most ERC-20s: varies - always query `decimals()`\n\n```typescript\nimport { erc20Abi } from 'viem'\n\n\u002F\u002F For native token\nconst NATIVE_DECIMALS = 18\n\n\u002F\u002F For ERC-20 tokens - query the contract\nconst getTokenDecimals = async (tokenAddress: string, publicClient: PublicClient) => {\n  if (tokenAddress === NATIVE_TOKEN) return NATIVE_DECIMALS\n  return await publicClient.readContract({\n    address: tokenAddress as `0x${string}`,\n    abi: erc20Abi,\n    functionName: 'decimals',\n  })\n}\n\n\u002F\u002F Shortcut for known tokens (use with caution)\nconst KNOWN_DECIMALS: Record\u003Cstring, number> = {\n  [NATIVE_TOKEN]: 18,\n  \u002F\u002F USDC on all chains uses 6 decimals\n}\n```\n\n### 6. Terminal Accounting Contexts\n\nWhen configuring terminals, set accounting context to match. **The currency MUST be derived from the token address.**\n\n```typescript\n\u002F\u002F ETH-based project\n{\n  terminal: JB_MULTI_TERMINAL,\n  accountingContextsToAccept: [{\n    token: NATIVE_TOKEN,        \u002F\u002F 0x000000000000000000000000000000000000EEEe\n    decimals: 18,\n    currency: 61166,            \u002F\u002F uint32(uint160(NATIVE_TOKEN)) = 0x0000EEEe\n  }]\n}\n\n\u002F\u002F USDC-based project (example: Ethereum)\n{\n  terminal: JB_MULTI_TERMINAL,\n  accountingContextsToAccept: [{\n    token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n    decimals: 6,\n    currency: 909516616,        \u002F\u002F uint32(uint160(USDC_ADDRESS))\n  }]\n}\n```\n\n**WRONG:** Using currency: 1 for ETH or currency: 2 for USD\n**RIGHT:** Using the calculated uint32 value from the token address\n\n## Component Pattern\n\nFor React components that handle multiple currencies:\n\n```typescript\ninterface ChainData {\n  chainId: number\n  projectId: number\n  baseCurrency: number \u002F\u002F 1 = ETH, 2 = USD\n  \u002F\u002F ... other fields\n}\n\nfunction MyComponent({ chainData }: { chainData: ChainData }) {\n  const baseCurrency = chainData?.baseCurrency || 1\n  const currencyLabel = baseCurrency === 2 ? 'USDC' : 'ETH'\n\n  return (\n    \u003Cdiv>\n      \u003Cspan>Amount: {amount} {currencyLabel}\u003C\u002Fspan>\n      {\u002F* Use currencyLabel throughout, never hardcode \"ETH\" *\u002F}\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n### 7. Cash Out Modal Currency Display\n\nWhen cashing out, users burn project tokens and receive funds **in the project's base currency**.\nThe modal must show the correct currency for the return amount:\n\n```typescript\ninterface CashOutModalProps {\n  projectId: string\n  tokenAmount: string      \u002F\u002F Tokens being burned\n  tokenSymbol: string      \u002F\u002F e.g., \"NANA\", \"REV\"\n  estimatedReturn: number  \u002F\u002F Amount user will receive\n  currencySymbol: 'ETH' | 'USDC'  \u002F\u002F CRITICAL: matches project's base currency\n}\n\nfunction CashOutModal({\n  tokenAmount,\n  tokenSymbol,\n  estimatedReturn,\n  currencySymbol = 'ETH',  \u002F\u002F Default to ETH for backwards compatibility\n}: CashOutModalProps) {\n  \u002F\u002F Format decimals based on currency\n  const decimals = currencySymbol === 'USDC' ? 2 : 4\n\n  return (\n    \u003Cdiv>\n      \u003Cdiv>Burning: {tokenAmount} {tokenSymbol}\u003C\u002Fdiv>\n      \u003Cdiv>You receive: ~{estimatedReturn.toFixed(decimals)} {currencySymbol}\u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n**Key insight**: The component receiving cash out data must pass `currencySymbol` based on the\nproject's `baseCurrency`, not hardcode \"ETH\". For USDC-based projects, show \"~5.00 USDC\" not \"~0.002 ETH\".\n\n### 8. Shared Chain Constants Pattern\n\nAvoid duplicating chain info across modals. Create a shared constants file:\n\n```typescript\n\u002F\u002F constants\u002Findex.ts\nexport const CHAINS: Record\u003Cnumber, {\n  name: string\n  shortName: string\n  explorerTx: string\n  explorerAddress: string\n}> = {\n  1: {\n    name: 'Ethereum',\n    shortName: 'ETH',\n    explorerTx: 'https:\u002F\u002Fetherscan.io\u002Ftx\u002F',\n    explorerAddress: 'https:\u002F\u002Fetherscan.io\u002Faddress\u002F',\n  },\n  10: {\n    name: 'Optimism',\n    shortName: 'OP',\n    explorerTx: 'https:\u002F\u002Foptimistic.etherscan.io\u002Ftx\u002F',\n    explorerAddress: 'https:\u002F\u002Foptimistic.etherscan.io\u002Faddress\u002F',\n  },\n  8453: {\n    name: 'Base',\n    shortName: 'BASE',\n    explorerTx: 'https:\u002F\u002Fbasescan.org\u002Ftx\u002F',\n    explorerAddress: 'https:\u002F\u002Fbasescan.org\u002Faddress\u002F',\n  },\n  42161: {\n    name: 'Arbitrum',\n    shortName: 'ARB',\n    explorerTx: 'https:\u002F\u002Farbiscan.io\u002Ftx\u002F',\n    explorerAddress: 'https:\u002F\u002Farbiscan.io\u002Faddress\u002F',\n  },\n}\n\nexport const NATIVE_TOKEN = '0x000000000000000000000000000000000000EEEe' as const\n```\n\nThen import in modals:\n```typescript\nimport { CHAINS, NATIVE_TOKEN } from '..\u002Fconstants'\n\nconst chainInfo = CHAINS[chainId] || CHAINS[1]\nconst explorerLink = `${chainInfo.explorerTx}${txHash}`\n```\n\n## Verification\n\n- USDC-based projects display \"USDC\" labels (not \"ETH\")\n- Cash out modals show return in correct currency (ETH or USDC)\n- Transactions use correct currency parameter\n- Fund access limits store correct currency\n- Balance queries use correct token address\n\n## Example\n\nFor Artizen (project 6 on Base):\n- baseCurrency = 2 (USD)\n- Display \"USDC\" in all labels\n- Use USDC token address for balance queries: `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`\n- Fund access limits use currency: 2\n\n## Common Mistakes\n\n1. **Hardcoded labels**: Using \"ETH\" string instead of `currencyLabel`\n2. **Hardcoded currency**: Using `1n` instead of `BigInt(baseCurrency)`\n3. **Wrong decimals**: Using 18 decimals for USDC (should be 6)\n4. **Token mismatch**: Querying with NATIVE_TOKEN for USDC project\n\n## Notes\n\n- Default to ETH (baseCurrency=1) if not specified\n- JBSwapTerminal accepts any token and swaps to project's base currency\n- Cash out returns funds in the project's base currency\n- Price feeds convert between currencies when needed\n\n## References\n\n- JBMultiTerminal5_1: `0x52869db3d61dde1e391967f2ce5039ad0ecd371c`\n- JBSwapTerminal: `0x0c02e48e55f4451a499e48a53595de55c40f3574`\n- JBPrices: `0x6e92e3b5ce1e7a4344c6d27c0c54efd00df92fb6`\n","# Juicebox V5 Multi-Currency Support\n\n## Problem\n\nJuicebox V5 projects can be denominated in either ETH (baseCurrency=1) or USD (baseCurrency=2).\nUI components and transactions must use the correct currency value, token address, and display\nlabels. Hardcoding \"ETH\" or currency=1 causes failures for USDC-based projects.\n\n## Context \u002F Trigger Conditions\n\n- UI shows \"ETH\" when project is USDC-based\n- Payout or allowance transaction fails silently\n- Fund access limits set with wrong currency\n- Currency mismatch between ruleset config and terminal accounting\n- Need to display correct currency symbol in forms\n\n## Solution\n\n### 1. Detect Project Currency from Ruleset\n\n```typescript\n\u002F\u002F baseCurrency is in ruleset metadata\n\u002F\u002F 1 = ETH, 2 = USD (USDC)\nconst baseCurrency = ruleset?.metadata?.baseCurrency || 1\nconst currencyLabel = baseCurrency === 2 ? 'USDC' : 'ETH'\n```\n\n### 2. Use Dynamic Currency in Transactions\n\nWhen calling terminal functions (sendPayoutsOf, useAllowanceOf), use the project's baseCurrency:\n\n```typescript\n\u002F\u002F WRONG - hardcoded\nargs: [projectId, token, amount, 1n, minTokensPaidOut, beneficiary]\n\n\u002F\u002F CORRECT - dynamic\nargs: [projectId, token, amount, BigInt(baseCurrency), minTokensPaidOut, beneficiary]\n```\n\n### 3. Fund Access Limits Currency\n\nWhen queuing new rulesets or displaying limits, match the existing project currency.\n**Use correct decimals**: Query from `ERC20.decimals()` or use 18 for native tokens.\n\n```typescript\nimport { parseUnits } from 'viem'\n\n\u002F\u002F Get currency from existing config\nconst currency = existingConfig?.baseCurrency || 1\n\n\u002F\u002F Get decimals from the token contract (or 18 for native token)\n\u002F\u002F For USDC: 6 decimals. For native token (ETH): 18 decimals.\nconst decimals = await getTokenDecimals(tokenAddress, publicClient)\n\n\u002F\u002F Use in fund access limit configuration\nconst payoutLimits = [{\n  amount: parseUnits(limitAmount, decimals).toString(),\n  currency, \u002F\u002F Match project's base currency (1 or 2)\n}]\n```\n\n### 4. Two Different \"currency\" Concepts (CRITICAL)\n\nJuicebox V5 has TWO different concepts called \"currency\" that are often confused:\n\n| Field | Location | Values | Purpose |\n|-------|----------|--------|---------|\n| `baseCurrency` | Ruleset metadata | 1 = ETH, 2 = USD | Issuance rate calculation |\n| `JBCurrencyAmount.currency` | Fund access limits | 1 = ETH, 2 = USD | Payout\u002Fallowance limits |\n| `JBAccountingContext.currency` | Terminal config | `uint32(uint160(token))` | Terminal accounting |\n\n**The `currency` value in JBAccountingContext is NOT 1 or 2. It's `uint32(uint160(tokenAddress))`.**\n\n```typescript\n\u002F\u002F NATIVE_TOKEN (ETH) - same on all chains - from JBConstants.NATIVE_TOKEN\nconst NATIVE_TOKEN = '0x000000000000000000000000000000000000EEEe'\nconst NATIVE_CURRENCY = 61166 \u002F\u002F uint32(uint160(NATIVE_TOKEN)) = 0x0000EEEe\n\n\u002F\u002F USDC addresses and currency codes per chain\nconst USDC_CONFIG: Record\u003Cnumber, { address: string; currency: number }> = {\n  1: {      \u002F\u002F Ethereum\n    address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n    currency: 909516616,\n  },\n  10: {     \u002F\u002F Optimism\n    address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n    currency: 3530704773,\n  },\n  8453: {   \u002F\u002F Base\n    address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n    currency: 3169378579,\n  },\n  42161: {  \u002F\u002F Arbitrum\n    address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n    currency: 1156540465,\n  },\n}\n```\n\n**How to calculate currency from any token address:**\n```typescript\nconst calculateCurrency = (tokenAddress: string): number => {\n  \u002F\u002F Take last 4 bytes of address as uint32\n  return Number(BigInt(tokenAddress) & BigInt(0xFFFFFFFF))\n}\n```\n\n### 5. Decimal Handling\n\n**General rule:** Get decimals from `ERC20.decimals()` for any token. Native tokens (ETH, MATIC, etc.) always use 18 decimals.\n\nCommon cases:\n- Native token (ETH): 18 decimals\n- USDC: 6 decimals\n- Most ERC-20s: varies - always query `decimals()`\n\n```typescript\nimport { erc20Abi } from 'viem'\n\n\u002F\u002F For native token\nconst NATIVE_DECIMALS = 18\n\n\u002F\u002F For ERC-20 tokens - query the contract\nconst getTokenDecimals = async (tokenAddress: string, publicClient: PublicClient) => {\n  if (tokenAddress === NATIVE_TOKEN) return NATIVE_DECIMALS\n  return await publicClient.readContract({\n    address: tokenAddress as `0x${string}`,\n    abi: erc20Abi,\n    functionName: 'decimals',\n  })\n}\n\n\u002F\u002F Shortcut for known tokens (use with caution)\nconst KNOWN_DECIMALS: Record\u003Cstring, number> = {\n  [NATIVE_TOKEN]: 18,\n  \u002F\u002F USDC on all chains uses 6 decimals\n}\n```\n\n### 6. Terminal Accounting Contexts\n\nWhen configuring terminals, set accounting context to match. **The currency MUST be derived from the token address.**\n\n```typescript\n\u002F\u002F ETH-based project\n{\n  terminal: JB_MULTI_TERMINAL,\n  accountingContextsToAccept: [{\n    token: NATIVE_TOKEN,        \u002F\u002F 0x000000000000000000000000000000000000EEEe\n    decimals: 18,\n    currency: 61166,            \u002F\u002F uint32(uint160(NATIVE_TOKEN)) = 0x0000EEEe\n  }]\n}\n\n\u002F\u002F USDC-based project (example: Ethereum)\n{\n  terminal: JB_MULTI_TERMINAL,\n  accountingContextsToAccept: [{\n    token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n    decimals: 6,\n    currency: 909516616,        \u002F\u002F uint32(uint160(USDC_ADDRESS))\n  }]\n}\n```\n\n**WRONG:** Using currency: 1 for ETH or currency: 2 for USD\n**RIGHT:** Using the calculated uint32 value from the token address\n\n## Component Pattern\n\nFor React components that handle multiple currencies:\n\n```typescript\ninterface ChainData {\n  chainId: number\n  projectId: number\n  baseCurrency: number \u002F\u002F 1 = ETH, 2 = USD\n  \u002F\u002F ... other fields\n}\n\nfunction MyComponent({ chainData }: { chainData: ChainData }) {\n  const baseCurrency = chainData?.baseCurrency || 1\n  const currencyLabel = baseCurrency === 2 ? 'USDC' : 'ETH'\n\n  return (\n    \u003Cdiv>\n      \u003Cspan>Amount: {amount} {currencyLabel}\u003C\u002Fspan>\n      {\u002F* Use currencyLabel throughout, never hardcode \"ETH\" *\u002F}\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n### 7. Cash Out Modal Currency Display\n\nWhen cashing out, users burn project tokens and receive funds **in the project's base currency**.\nThe modal must show the correct currency for the return amount:\n\n```typescript\ninterface CashOutModalProps {\n  projectId: string\n  tokenAmount: string      \u002F\u002F Tokens being burned\n  tokenSymbol: string      \u002F\u002F e.g., \"NANA\", \"REV\"\n  estimatedReturn: number  \u002F\u002F Amount user will receive\n  currencySymbol: 'ETH' | 'USDC'  \u002F\u002F CRITICAL: matches project's base currency\n}\n\nfunction CashOutModal({\n  tokenAmount,\n  tokenSymbol,\n  estimatedReturn,\n  currencySymbol = 'ETH',  \u002F\u002F Default to ETH for backwards compatibility\n}: CashOutModalProps) {\n  \u002F\u002F Format decimals based on currency\n  const decimals = currencySymbol === 'USDC' ? 2 : 4\n\n  return (\n    \u003Cdiv>\n      \u003Cdiv>Burning: {tokenAmount} {tokenSymbol}\u003C\u002Fdiv>\n      \u003Cdiv>You receive: ~{estimatedReturn.toFixed(decimals)} {currencySymbol}\u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n**Key insight**: The component receiving cash out data must pass `currencySymbol` based on the\nproject's `baseCurrency`, not hardcode \"ETH\". For USDC-based projects, show \"~5.00 USDC\" not \"~0.002 ETH\".\n\n### 8. Shared Chain Constants Pattern\n\nAvoid duplicating chain info across modals. Create a shared constants file:\n\n```typescript\n\u002F\u002F constants\u002Findex.ts\nexport const CHAINS: Record\u003Cnumber, {\n  name: string\n  shortName: string\n  explorerTx: string\n  explorerAddress: string\n}> = {\n  1: {\n    name: 'Ethereum',\n    shortName: 'ETH',\n    explorerTx: 'https:\u002F\u002Fetherscan.io\u002Ftx\u002F',\n    explorerAddress: 'https:\u002F\u002Fetherscan.io\u002Faddress\u002F',\n  },\n  10: {\n    name: 'Optimism',\n    shortName: 'OP',\n    explorerTx: 'https:\u002F\u002Foptimistic.etherscan.io\u002Ftx\u002F',\n    explorerAddress: 'https:\u002F\u002Foptimistic.etherscan.io\u002Faddress\u002F',\n  },\n  8453: {\n    name: 'Base',\n    shortName: 'BASE',\n    explorerTx: 'https:\u002F\u002Fbasescan.org\u002Ftx\u002F',\n    explorerAddress: 'https:\u002F\u002Fbasescan.org\u002Faddress\u002F',\n  },\n  42161: {\n    name: 'Arbitrum',\n    shortName: 'ARB',\n    explorerTx: 'https:\u002F\u002Farbiscan.io\u002Ftx\u002F',\n    explorerAddress: 'https:\u002F\u002Farbiscan.io\u002Faddress\u002F',\n  },\n}\n\nexport const NATIVE_TOKEN = '0x000000000000000000000000000000000000EEEe' as const\n```\n\nThen import in modals:\n```typescript\nimport { CHAINS, NATIVE_TOKEN } from '..\u002Fconstants'\n\nconst chainInfo = CHAINS[chainId] || CHAINS[1]\nconst explorerLink = `${chainInfo.explorerTx}${txHash}`\n```\n\n## Verification\n\n- USDC-based projects display \"USDC\" labels (not \"ETH\")\n- Cash out modals show return in correct currency (ETH or USDC)\n- Transactions use correct currency parameter\n- Fund access limits store correct currency\n- Balance queries use correct token address\n\n## Example\n\nFor Artizen (project 6 on Base):\n- baseCurrency = 2 (USD)\n- Display \"USDC\" in all labels\n- Use USDC token address for balance queries: `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`\n- Fund access limits use currency: 2\n\n## Common Mistakes\n\n1. **Hardcoded labels**: Using \"ETH\" string instead of `currencyLabel`\n2. **Hardcoded currency**: Using `1n` instead of `BigInt(baseCurrency)`\n3. **Wrong decimals**: Using 18 decimals for USDC (should be 6)\n4. **Token mismatch**: Querying with NATIVE_TOKEN for USDC project\n\n## Notes\n\n- Default to ETH (baseCurrency=1) if not specified\n- JBSwapTerminal accepts any token and swaps to project's base currency\n- Cash out returns funds in the project's base currency\n- Price feeds convert between currencies when needed\n\n## References\n\n- JBMultiTerminal5_1: `0x52869db3d61dde1e391967f2ce5039ad0ecd371c`\n- JBSwapTerminal: `0x0c02e48e55f4451a499e48a53595de55c40f3574`\n- JBPrices: `0x6e92e3b5ce1e7a4344c6d27c0c54efd00df92fb6`\n",{"name":5,"description":7},"main","f4cb2d49f7667e79ef7804f50396d5aaffdf1f56","视觉与设计\u002Fjuicy\u002Fjb-multi-currency",1,"https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification","https:\u002F\u002Fgithub.com\u002FKernel8901","a little little little dobe in life but science geek","2026-04-05 16:43:56",{"source":8,"skillName":5,"commands":57,"prompt":67,"zipAvailable":68},[58,61,64],{"tool":59,"command":60},"npx","npx skills add Kernel8901\u002Fai-agent-skills-classification --skill jb-multi-currency",{"tool":62,"command":63},"bunx","bunx skills add Kernel8901\u002Fai-agent-skills-classification --skill jb-multi-currency",{"tool":65,"command":66},"pnpm","pnpm dlx skills add Kernel8901\u002Fai-agent-skills-classification --skill jb-multi-currency","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F视觉与设计\u002Fjuicy\u002Fjb-multi-currency\u002FSKILL.md",true,[],[71,95,126,137,147,174],{"skillNo":72,"name":73,"nameZh":6,"description":74,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":75,"categories":76,"keywords":77,"publishedAt":43},"01M6Q5R6WZ06RRB9RQTW54B34B","zyfai","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 subaccount (Safe) linked to their EOA, enables automated yield optimization, and lets them deposit\u002Fwithdraw anytime.","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fzyfai-sdk\u002FSKILL.md",[],[73,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94],"safe","ethereum","defi","Optimization","user","use","Wallet","base","deposit","withdraw","yield","arbitrum","non-custodial","passive","defi yield","earn","yield optimization",{"skillNo":96,"name":97,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":98,"categories":99,"keywords":111,"publishedAt":43},"01M6Q5R337B5JSNER4P4YS03TN","zerion-api","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fzerion-api\u002FSKILL.md",[100,105,108],{"categoryNo":101,"categoryName":102,"taxonomyType":103,"taxonomyTypeDesc":104},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":106,"categoryName":107,"taxonomyType":103,"taxonomyTypeDesc":104},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":109,"categoryName":110,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000030","开发工程师",[112,113,114,115,116,117,118,80,39,84,119,120,121,122,123,36,124,26,125],"api","zerion api","zerion","MCP","mcp server","server","blockchain","crypto wallet","crypto","evm","solana","query","positions","prices",{"skillNo":127,"name":128,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":129,"categories":130,"keywords":134,"publishedAt":43},"01M6Q5QZFYTDAZMZ27BN5VZXAR","zerion-api-skill","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fzerion-api-skill\u002FSKILL.md",[131,132,133],{"categoryNo":101,"categoryName":102,"taxonomyType":103,"taxonomyTypeDesc":104},{"categoryNo":106,"categoryName":107,"taxonomyType":103,"taxonomyTypeDesc":104},{"categoryNo":109,"categoryName":110,"taxonomyType":20,"taxonomyTypeDesc":21},[112,135,136,113,114,115,116,117,118,80,39,84,120,121,122,123,36,124,26,125],"api skill","zerion api skill",{"skillNo":138,"name":139,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":145,"publishedAt":43},"01M6Q5QW17QW98RA3FE45E4RD8","zerion-api-mcp","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fzerion-api-mcp\u002FSKILL.md",[142,143,144],{"categoryNo":101,"categoryName":102,"taxonomyType":103,"taxonomyTypeDesc":104},{"categoryNo":106,"categoryName":107,"taxonomyType":103,"taxonomyTypeDesc":104},{"categoryNo":109,"categoryName":110,"taxonomyType":20,"taxonomyTypeDesc":21},[115,112,146,113,114,116,117,80,39,84,119,120,121,122,123,36,124,26,125],"zerion api mcp",{"skillNo":148,"name":149,"nameZh":6,"description":150,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":151,"categories":152,"keywords":154,"publishedAt":43},"01M6Q5QQYZB7A501BDEQWKGSJT","yahoo-finance-forex","Fetches real-time FOREX news and market data from Yahoo Finance for major currency pairs (EUR\u002FUSD, GBP\u002FUSD, USD\u002FJPY, etc.). Analyzes sentiment and provides trading context.","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fyahoo-finance-forex\u002FSKILL.md",[153],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,25,170,171,172,173],"finance","yahoo finance","forex","yahoo","yahoo finance forex","github","https","sentiment","real-time","python3","install","Market","usd","news","time","gbp","pip","market data","for",{"skillNo":175,"name":176,"nameZh":6,"description":177,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":178,"categories":179,"keywords":181,"publishedAt":43},"01M6Q5QM6VS84WZVM7BKXXPF32","yahoo-finance","This skill should be used when the user asks to \"get stock prices\", \"check stock quotes\", \"look up earnings\", \"get financial data\", \"find trending stocks\", or needs stock market data from Yahoo Finance.","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fyahoo-finance-cli\u002FSKILL.md",[180],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[155,156,158,182,183,184,185,186,187,166,188,189,190,191,192,193,194,195,125,172],"cli","homebrew","find","check","brew","up","local","get","stock","link","trending","sf","quotes","ln"]