[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GWHFTT3ZGX0XWHXJ2K2RT0":3,"skill-same:01M6GWHFTT3ZGX0XWHXJ2K2RT0":82},{"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":16,"sourceHtmlUrl":17,"categories":18,"keywords":19,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":48,"repositoryHtmlUrl":49,"repositoryHomepageUrl":6,"ownerHtmlUrl":50,"ownerBlogUrl":51,"ownerDescription":52,"updatedAt":53,"install":54,"resources":67},"01M6GWHFTT3ZGX0XWHXJ2K2RT0","gdex-copy-trading",null,"Copy trade setup — discover top wallets, create\u002Fmanage copy trades, view transaction history, and browse supported DEXes. Solana only for write operations.","jiayaoqijia\u002Fcryptoskill","jiayaoqijia","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1453879?v=4","01M6GMYTX7Q7S504VC6E756ENR","YQ","01M6GMYV1QKJ1CC75MTTGT9PR0",81,"MIT","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fmcp-servers\u002Fgemachdao-gdex-copy-trading\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fmcp-servers\u002Fgemachdao-gdex-copy-trading\u002FSKILL.md",[],[20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"gdex copy trading","copy","trading","solana","for","copy trade","wallets","top","discover","trade","transaction","setup","manage","only","operations","view","write","history","browse","create","2026-11-10 10:12:30",false,"---\nname: gdex-copy-trading\ndescription: Copy trade setup — discover top wallets, create\u002Fmanage copy trades, view transaction history, and browse supported DEXes. Solana only for write operations.\n---\n\n# GDEX: Copy Trading\n\nAutomatically mirror trades from top-performing Solana wallets. Includes wallet leaderboards, hot token gems, backed by a background process that copies buys\u002Fsells in real-time.\n\n## When to Use\n\n- Browsing the top wallet leaderboard (by PnL or net profit)\n- Discovering hot new tokens from top wallets\n- Creating a copy trade to follow a specific trader\n- Updating, toggling, or deleting a copy trade\n- Viewing copy trade transaction history with PnL\n- Listing supported DEXes for exclusion\n\n## Prerequisites\n\n- `@gemachdao\u002Fgdex-skill` installed\n- For discovery: `loginWithApiKey()` only\n- For read (list\u002Ftx_list): Full sign-in with session key\n- For write (create\u002Fupdate): Full sign-in + computedData\n\n## Auth Tiers\n\n| Tier | Endpoints | Auth Needed |\n|------|-----------|-------------|\n| Discovery | `wallets`, `custom_wallets`, `gems`, `dexes_list`, `top_traders` | API key only |\n| Read | `list`, `tx_list` | Session-key auth (`userId` + encrypted `data`) |\n| Write | `create`, `update` | computedData (ABI-encode + sign + AES-encrypt) |\n\n> **Write operations are Solana-only.** All create\u002Fupdate calls reject non-Solana chain IDs.\n\n## Discovery Endpoints (No Auth)\n\n### Top Wallets by PnL\n\n```typescript\nconst wallets = await skill.getCopyTradeWallets();\n\u002F\u002F Returns 300 wallets sorted by totalPnl, cached 2 minutes\n```\n\n### Top Wallets by Net Received\n\n```typescript\nconst custom = await skill.getCopyTradeCustomWallets();\n\u002F\u002F Returns 300 wallets sorted by receivedMinusSpent, cached 2 minutes\n```\n\n### CopyTradeWallet Response Shape\n\n```typescript\ninterface CopyTradeWallet {\n  _id: string;\n  chainId: number;             \u002F\u002F 622112261 for Solana\n  address: string;             \u002F\u002F Solana wallet address\n  lastTxTimestamp: number;     \u002F\u002F Unix timestamp\n  receivedMinusSpent: number;  \u002F\u002F Net USD profit\n  spent: number;               \u002F\u002F Total USD spent\n  lastCalculateUnrealizedPnl: number;\n  totalPnl: number;            \u002F\u002F Total PnL (incl. unrealized)\n  unrealizedValue: number;     \u002F\u002F Current unrealized USD\n  received: number;            \u002F\u002F Total USD received\n}\n```\n\n### Hot Token Gems\n\n```typescript\nconst gems = await skill.getCopyTradeGems();\n\u002F\u002F Tokens heavily traded by 3+ hot wallets with >$10 total value\n\u002F\u002F Cached 20 seconds; may return empty array\n```\n\n### Supported DEXes\n\n```typescript\nconst dexes = await skill.getCopyTradeDexes(622112261); \u002F\u002F Solana chain ID\n\u002F\u002F { success: true, dexes: [{ chainId, dexNumber, dexName, programId }] }\n```\n\nLive DEX list (Solana):\n\n| # | DEX | Program ID |\n|---|-----|-----------|\n| 1 | pumpfun | `6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P` |\n| 2 | pumpswap | `pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA` |\n| 3 | raydium | `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8` |\n| 4 | raydiumCpmm | `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C` |\n| 5 | meteoraDlmm | `LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo` |\n\n## Read Endpoints (Session-Key Auth)\n\nRequire `userId` and `data` (AES-encrypted session key from `buildGdexUserSessionData`).\n\n### List User's Copy Trades\n\n```typescript\nimport { buildGdexUserSessionData } from '@gemachdao\u002Fgdex-skill';\n\nconst data = buildGdexUserSessionData(sessionKey, apiKey);\nconst list = await skill.getCopyTradeList({ userId, data });\n\u002F\u002F { isSuccess: true, count: 2, allCopyTrades: [...], dexes: [...] }\n```\n\n### CopyTradeConfig Shape\n\n```typescript\ninterface CopyTradeConfig {\n  copyTradeId: string;\n  copyTradeName: string;\n  buyMode: number;          \u002F\u002F 1 = fixed SOL, 2 = % of trader's amount\n  chainId: number;\n  isActive: boolean;\n  userId: string;\n  userWallet: string;\n  traderWallet: string;\n  lossPercent: number;      \u002F\u002F stop-loss %\n  profitPercent: number;    \u002F\u002F take-profit %\n  gasPrice: string;\n  copyBuyFixedAmount: string;\n  copyBuyPercent: number;\n  isBuyExistingToken: boolean;\n  copySell: boolean;\n  excludedProgramIds: string[];\n  excludedDexNumbers: number[];\n  txCount?: number;\n  lastTxTimestamp?: number;\n}\n```\n\n### Transaction History\n\n```typescript\nconst txList = await skill.getCopyTradeTxList({ userId, data });\n\u002F\u002F { isSuccess: true, count: 5, txes: [...] }\n```\n\nEach `CopyTradeTx` includes:\n- `isBuy`, `priceUsd`, `boughtPrice`, `pnlPercentage`\n- `tokenInfo`: `{ address, symbol, name, decimals, dexId, marketCap, logoUrl }`\n\n## Write Endpoints (ComputedData Auth, Solana Only)\n\n### Create a Copy Trade\n\n```typescript\nawait skill.createCopyTrade({\n  apiKey,\n  userId,\n  sessionPrivateKey,\n  chainId: 622112261,\n  traderWallet: 'SolanaWalletAddress',\n  copyTradeName: 'My Alpha Trader',\n  buyMode: 1,               \u002F\u002F 1 = fixed SOL amount\n  copyBuyAmount: '0.5',     \u002F\u002F 0.5 SOL per copied trade\n  lossPercent: '50',         \u002F\u002F 50% stop-loss\n  profitPercent: '100',      \u002F\u002F 100% take-profit\n  copySell: true,\n  isBuyExistingToken: true,\n  excludedDexNumbers: [],    \u002F\u002F empty = allow all DEXes\n});\n```\n\n### Update, Pause, Resume, Delete\n\nUse the explicit operations. Each reads the current configuration from the list\nendpoint first (the backend rewrites every field on update), so you only pass\nwhat you want to change.\n\n```typescript\nconst ids = { apiKey, userId, sessionPrivateKey, copyTradeId: 'a1b2c3...' };\n\n\u002F\u002F Change settings only. Never deletes, never pauses. Omitted fields keep current values.\nawait skill.updateCopyTradeSettings({ ...ids, buyMode: 2, copyBuyAmount: '50', lossPercent: '30' });\n\n\u002F\u002F Pause without deleting (isActive=false). No-op if already paused.\nawait skill.pauseCopyTrade(ids);\n\u002F\u002F Resume (isActive=true). No-op if already active.\nawait skill.resumeCopyTrade(ids);\n\n\u002F\u002F Permanent delete.\nawait skill.deleteCopyTrade(ids);\n```\n\nWhat each does on the backend (`ServiceCopyTrade.update`):\n\n| Operation | Backend effect | Open positions \u002F TP-SL orders |\n|---|---|---|\n| `updateCopyTradeSettings` | rewrites the config fields | unchanged, not resized |\n| `pauseCopyTrade` | `isChangeStatus` toggle → `isActive=false`; the copier skips inactive configs for buys AND sells | stay open, TP\u002FSL limit orders stay |\n| `resumeCopyTrade` | toggle → `isActive=true` | trades made while paused are not replayed |\n| `deleteCopyTrade` | `CopyTradeSetting.deleteOne` (+ the trader tracking row if nobody else follows them) | NOT sold, TP\u002FSL limit orders NOT cancelled |\n\n`isChangeStatus` is a relative toggle, so pause\u002Fresume refuse to act when the\nstate cannot be confirmed (`PAUSE_STATE_UNVERIFIED`; also raised for a second\ntoggle within 25 s because the list is cached for 20 s). `PAUSE_UNSUPPORTED`\nmeans the stored config holds an invalid `buyMode`: fix it with\n`updateCopyTradeSettings` first, or delete (positions stay open).\n\nThe low-level `updateCopyTrade` still exists: `isDelete` deletes, `isChangeStatus`\ntoggles, and setting both is rejected.\n\n## Backend Validation Rules\n\n- **Solana only**: chainId must be the Solana chain ID (622112261)\n- **Valid wallet**: traderWallet must be a valid Solana address\n- **TP\u002FSL**: lossPercent > 0 and \u003C 100, profitPercent > 0\n- **buyMode 2**: percentage must be > 0 and \u003C= 100\n- **No duplicates**: Can't copy the same wallet+chain+user twice\n- **Max limit**: Backend enforces max copy trades per user\n- **Circular dependency**: Prevents A→B→C→A copy chains (checked to depth 50)\n\n## How Copies Execute\n\nTrades are NOT executed at API call time. A background process monitors tracked wallets in real-time:\n1. Detects trader buy\u002Fsell transactions\n2. Checks excluded DEXes and deduplication\n3. Calculates buy amount (fixed or percentage)\n4. Executes the copy trade\n5. Places automatic TP\u002FSL orders based on your settings\n\n## Example: Full Copy Trading Flow\n\n```typescript\nimport {\n  GdexSkill,\n  buildGdexUserSessionData,\n  generateGdexSessionKeyPair,\n  buildGdexSignInMessage,\n  buildGdexSignInComputedData,\n} from '@gemachdao\u002Fgdex-skill';\nimport { ethers } from 'ethers';\n\nconst skill = new GdexSkill();\nskill.loginWithApiKey(apiKey);\n\n\u002F\u002F 1. Sign in with session key\nconst wallet = ethers.Wallet.fromPhrase(mnemonic);\nconst { sessionPrivateKey, sessionKey } = generateGdexSessionKeyPair();\nconst nonce = String(Date.now());\nconst msg = buildGdexSignInMessage(wallet.address, nonce, sessionKey);\nconst sig = await wallet.signMessage(msg);\nconst payload = buildGdexSignInComputedData({ apiKey, userId: wallet.address, sessionKey, nonce, signature: sig });\nawait skill.signInWithComputedData({ computedData: payload.computedData, chainId: 1 }, { sessionPrivateKey });\nconst data = buildGdexUserSessionData(sessionKey, apiKey);\nconst userId = wallet.address.toLowerCase();\n\n\u002F\u002F 2. Browse top wallets\nconst wallets = await skill.getCopyTradeWallets();\nconst best = wallets[0];\nconsole.log(`Top wallet: ${best.address}, PnL: $${best.totalPnl.toFixed(2)}`);\n\n\u002F\u002F 3. Check DEXes\nconst { dexes } = await skill.getCopyTradeDexes(622112261);\n\n\u002F\u002F 4. Create a copy trade\nawait skill.createCopyTrade({\n  apiKey,\n  userId,\n  sessionPrivateKey,\n  chainId: 622112261,\n  traderWallet: best.address,\n  copyTradeName: `Top PnL: ${best.address.slice(0, 8)}`,\n  buyMode: 1,\n  copyBuyAmount: '0.1',\n  lossPercent: '50',\n  profitPercent: '100',\n  copySell: true,\n});\n\n\u002F\u002F 5. Monitor\nconst list = await skill.getCopyTradeList({ userId, data });\nfor (const ct of list.allCopyTrades) {\n  console.log(`${ct.copyTradeName}: active=${ct.isActive}, ${ct.txCount ?? 0} trades`);\n}\n```\n\n## Autonomous Agent Notes (Live-Tested)\n\n1. **All 4 discovery endpoints work with API key only (E2E verified):** `getCopyTradeWallets()`, `getCopyTradeCustomWallets()`, `getCopyTradeGems()`, `getCopyTradeDexes()`.\n2. **`getCopyTradeGems()` may return empty array** — this is normal (cached 20 seconds, depends on hot wallet activity).\n3. **Sign-in for Solana copy trading must use `chainId: 622112261`** (Solana), not `chainId: 1` (EVM). This is the opposite of HL perp copy trading.\n4. **`isChangeStatus` toggles `isActive`; only `isDelete` deletes.** SDK versions up to 4.12 encoded every field as an ABI string, which the backend decoded with `isDelete=true`, so every update deleted. The SDK now encodes the typed ABI the backend expects (`uint64` chainId\u002FbuyMode, real `bool`s, `uint64[]` excludedDexNumbers).\n5. **Pause with `pauseCopyTrade`, never with delete.** Pausing or deleting never closes positions.\n6. **`copySell: true`** means the copy will also mirror sell transactions, not just buys.\n\n## Related Skills\n\n- **gdex-authentication** — Auth setup and sign-in required for read\u002Fwrite\n- **gdex-token-discovery** — Top trader rankings (`getTopTraders`)\n- **gdex-portfolio** — Monitor portfolio including copied positions\n- **gdex-spot-trading** — Understand the trades being copied\n","# GDEX: Copy Trading\n\nAutomatically mirror trades from top-performing Solana wallets. Includes wallet leaderboards, hot token gems, backed by a background process that copies buys\u002Fsells in real-time.\n\n## When to Use\n\n- Browsing the top wallet leaderboard (by PnL or net profit)\n- Discovering hot new tokens from top wallets\n- Creating a copy trade to follow a specific trader\n- Updating, toggling, or deleting a copy trade\n- Viewing copy trade transaction history with PnL\n- Listing supported DEXes for exclusion\n\n## Prerequisites\n\n- `@gemachdao\u002Fgdex-skill` installed\n- For discovery: `loginWithApiKey()` only\n- For read (list\u002Ftx_list): Full sign-in with session key\n- For write (create\u002Fupdate): Full sign-in + computedData\n\n## Auth Tiers\n\n| Tier | Endpoints | Auth Needed |\n|------|-----------|-------------|\n| Discovery | `wallets`, `custom_wallets`, `gems`, `dexes_list`, `top_traders` | API key only |\n| Read | `list`, `tx_list` | Session-key auth (`userId` + encrypted `data`) |\n| Write | `create`, `update` | computedData (ABI-encode + sign + AES-encrypt) |\n\n> **Write operations are Solana-only.** All create\u002Fupdate calls reject non-Solana chain IDs.\n\n## Discovery Endpoints (No Auth)\n\n### Top Wallets by PnL\n\n```typescript\nconst wallets = await skill.getCopyTradeWallets();\n\u002F\u002F Returns 300 wallets sorted by totalPnl, cached 2 minutes\n```\n\n### Top Wallets by Net Received\n\n```typescript\nconst custom = await skill.getCopyTradeCustomWallets();\n\u002F\u002F Returns 300 wallets sorted by receivedMinusSpent, cached 2 minutes\n```\n\n### CopyTradeWallet Response Shape\n\n```typescript\ninterface CopyTradeWallet {\n  _id: string;\n  chainId: number;             \u002F\u002F 622112261 for Solana\n  address: string;             \u002F\u002F Solana wallet address\n  lastTxTimestamp: number;     \u002F\u002F Unix timestamp\n  receivedMinusSpent: number;  \u002F\u002F Net USD profit\n  spent: number;               \u002F\u002F Total USD spent\n  lastCalculateUnrealizedPnl: number;\n  totalPnl: number;            \u002F\u002F Total PnL (incl. unrealized)\n  unrealizedValue: number;     \u002F\u002F Current unrealized USD\n  received: number;            \u002F\u002F Total USD received\n}\n```\n\n### Hot Token Gems\n\n```typescript\nconst gems = await skill.getCopyTradeGems();\n\u002F\u002F Tokens heavily traded by 3+ hot wallets with >$10 total value\n\u002F\u002F Cached 20 seconds; may return empty array\n```\n\n### Supported DEXes\n\n```typescript\nconst dexes = await skill.getCopyTradeDexes(622112261); \u002F\u002F Solana chain ID\n\u002F\u002F { success: true, dexes: [{ chainId, dexNumber, dexName, programId }] }\n```\n\nLive DEX list (Solana):\n\n| # | DEX | Program ID |\n|---|-----|-----------|\n| 1 | pumpfun | `6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P` |\n| 2 | pumpswap | `pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA` |\n| 3 | raydium | `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8` |\n| 4 | raydiumCpmm | `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C` |\n| 5 | meteoraDlmm | `LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo` |\n\n## Read Endpoints (Session-Key Auth)\n\nRequire `userId` and `data` (AES-encrypted session key from `buildGdexUserSessionData`).\n\n### List User's Copy Trades\n\n```typescript\nimport { buildGdexUserSessionData } from '@gemachdao\u002Fgdex-skill';\n\nconst data = buildGdexUserSessionData(sessionKey, apiKey);\nconst list = await skill.getCopyTradeList({ userId, data });\n\u002F\u002F { isSuccess: true, count: 2, allCopyTrades: [...], dexes: [...] }\n```\n\n### CopyTradeConfig Shape\n\n```typescript\ninterface CopyTradeConfig {\n  copyTradeId: string;\n  copyTradeName: string;\n  buyMode: number;          \u002F\u002F 1 = fixed SOL, 2 = % of trader's amount\n  chainId: number;\n  isActive: boolean;\n  userId: string;\n  userWallet: string;\n  traderWallet: string;\n  lossPercent: number;      \u002F\u002F stop-loss %\n  profitPercent: number;    \u002F\u002F take-profit %\n  gasPrice: string;\n  copyBuyFixedAmount: string;\n  copyBuyPercent: number;\n  isBuyExistingToken: boolean;\n  copySell: boolean;\n  excludedProgramIds: string[];\n  excludedDexNumbers: number[];\n  txCount?: number;\n  lastTxTimestamp?: number;\n}\n```\n\n### Transaction History\n\n```typescript\nconst txList = await skill.getCopyTradeTxList({ userId, data });\n\u002F\u002F { isSuccess: true, count: 5, txes: [...] }\n```\n\nEach `CopyTradeTx` includes:\n- `isBuy`, `priceUsd`, `boughtPrice`, `pnlPercentage`\n- `tokenInfo`: `{ address, symbol, name, decimals, dexId, marketCap, logoUrl }`\n\n## Write Endpoints (ComputedData Auth, Solana Only)\n\n### Create a Copy Trade\n\n```typescript\nawait skill.createCopyTrade({\n  apiKey,\n  userId,\n  sessionPrivateKey,\n  chainId: 622112261,\n  traderWallet: 'SolanaWalletAddress',\n  copyTradeName: 'My Alpha Trader',\n  buyMode: 1,               \u002F\u002F 1 = fixed SOL amount\n  copyBuyAmount: '0.5',     \u002F\u002F 0.5 SOL per copied trade\n  lossPercent: '50',         \u002F\u002F 50% stop-loss\n  profitPercent: '100',      \u002F\u002F 100% take-profit\n  copySell: true,\n  isBuyExistingToken: true,\n  excludedDexNumbers: [],    \u002F\u002F empty = allow all DEXes\n});\n```\n\n### Update, Pause, Resume, Delete\n\nUse the explicit operations. Each reads the current configuration from the list\nendpoint first (the backend rewrites every field on update), so you only pass\nwhat you want to change.\n\n```typescript\nconst ids = { apiKey, userId, sessionPrivateKey, copyTradeId: 'a1b2c3...' };\n\n\u002F\u002F Change settings only. Never deletes, never pauses. Omitted fields keep current values.\nawait skill.updateCopyTradeSettings({ ...ids, buyMode: 2, copyBuyAmount: '50', lossPercent: '30' });\n\n\u002F\u002F Pause without deleting (isActive=false). No-op if already paused.\nawait skill.pauseCopyTrade(ids);\n\u002F\u002F Resume (isActive=true). No-op if already active.\nawait skill.resumeCopyTrade(ids);\n\n\u002F\u002F Permanent delete.\nawait skill.deleteCopyTrade(ids);\n```\n\nWhat each does on the backend (`ServiceCopyTrade.update`):\n\n| Operation | Backend effect | Open positions \u002F TP-SL orders |\n|---|---|---|\n| `updateCopyTradeSettings` | rewrites the config fields | unchanged, not resized |\n| `pauseCopyTrade` | `isChangeStatus` toggle → `isActive=false`; the copier skips inactive configs for buys AND sells | stay open, TP\u002FSL limit orders stay |\n| `resumeCopyTrade` | toggle → `isActive=true` | trades made while paused are not replayed |\n| `deleteCopyTrade` | `CopyTradeSetting.deleteOne` (+ the trader tracking row if nobody else follows them) | NOT sold, TP\u002FSL limit orders NOT cancelled |\n\n`isChangeStatus` is a relative toggle, so pause\u002Fresume refuse to act when the\nstate cannot be confirmed (`PAUSE_STATE_UNVERIFIED`; also raised for a second\ntoggle within 25 s because the list is cached for 20 s). `PAUSE_UNSUPPORTED`\nmeans the stored config holds an invalid `buyMode`: fix it with\n`updateCopyTradeSettings` first, or delete (positions stay open).\n\nThe low-level `updateCopyTrade` still exists: `isDelete` deletes, `isChangeStatus`\ntoggles, and setting both is rejected.\n\n## Backend Validation Rules\n\n- **Solana only**: chainId must be the Solana chain ID (622112261)\n- **Valid wallet**: traderWallet must be a valid Solana address\n- **TP\u002FSL**: lossPercent > 0 and \u003C 100, profitPercent > 0\n- **buyMode 2**: percentage must be > 0 and \u003C= 100\n- **No duplicates**: Can't copy the same wallet+chain+user twice\n- **Max limit**: Backend enforces max copy trades per user\n- **Circular dependency**: Prevents A→B→C→A copy chains (checked to depth 50)\n\n## How Copies Execute\n\nTrades are NOT executed at API call time. A background process monitors tracked wallets in real-time:\n1. Detects trader buy\u002Fsell transactions\n2. Checks excluded DEXes and deduplication\n3. Calculates buy amount (fixed or percentage)\n4. Executes the copy trade\n5. Places automatic TP\u002FSL orders based on your settings\n\n## Example: Full Copy Trading Flow\n\n```typescript\nimport {\n  GdexSkill,\n  buildGdexUserSessionData,\n  generateGdexSessionKeyPair,\n  buildGdexSignInMessage,\n  buildGdexSignInComputedData,\n} from '@gemachdao\u002Fgdex-skill';\nimport { ethers } from 'ethers';\n\nconst skill = new GdexSkill();\nskill.loginWithApiKey(apiKey);\n\n\u002F\u002F 1. Sign in with session key\nconst wallet = ethers.Wallet.fromPhrase(mnemonic);\nconst { sessionPrivateKey, sessionKey } = generateGdexSessionKeyPair();\nconst nonce = String(Date.now());\nconst msg = buildGdexSignInMessage(wallet.address, nonce, sessionKey);\nconst sig = await wallet.signMessage(msg);\nconst payload = buildGdexSignInComputedData({ apiKey, userId: wallet.address, sessionKey, nonce, signature: sig });\nawait skill.signInWithComputedData({ computedData: payload.computedData, chainId: 1 }, { sessionPrivateKey });\nconst data = buildGdexUserSessionData(sessionKey, apiKey);\nconst userId = wallet.address.toLowerCase();\n\n\u002F\u002F 2. Browse top wallets\nconst wallets = await skill.getCopyTradeWallets();\nconst best = wallets[0];\nconsole.log(`Top wallet: ${best.address}, PnL: $${best.totalPnl.toFixed(2)}`);\n\n\u002F\u002F 3. Check DEXes\nconst { dexes } = await skill.getCopyTradeDexes(622112261);\n\n\u002F\u002F 4. Create a copy trade\nawait skill.createCopyTrade({\n  apiKey,\n  userId,\n  sessionPrivateKey,\n  chainId: 622112261,\n  traderWallet: best.address,\n  copyTradeName: `Top PnL: ${best.address.slice(0, 8)}`,\n  buyMode: 1,\n  copyBuyAmount: '0.1',\n  lossPercent: '50',\n  profitPercent: '100',\n  copySell: true,\n});\n\n\u002F\u002F 5. Monitor\nconst list = await skill.getCopyTradeList({ userId, data });\nfor (const ct of list.allCopyTrades) {\n  console.log(`${ct.copyTradeName}: active=${ct.isActive}, ${ct.txCount ?? 0} trades`);\n}\n```\n\n## Autonomous Agent Notes (Live-Tested)\n\n1. **All 4 discovery endpoints work with API key only (E2E verified):** `getCopyTradeWallets()`, `getCopyTradeCustomWallets()`, `getCopyTradeGems()`, `getCopyTradeDexes()`.\n2. **`getCopyTradeGems()` may return empty array** — this is normal (cached 20 seconds, depends on hot wallet activity).\n3. **Sign-in for Solana copy trading must use `chainId: 622112261`** (Solana), not `chainId: 1` (EVM). This is the opposite of HL perp copy trading.\n4. **`isChangeStatus` toggles `isActive`; only `isDelete` deletes.** SDK versions up to 4.12 encoded every field as an ABI string, which the backend decoded with `isDelete=true`, so every update deleted. The SDK now encodes the typed ABI the backend expects (`uint64` chainId\u002FbuyMode, real `bool`s, `uint64[]` excludedDexNumbers).\n5. **Pause with `pauseCopyTrade`, never with delete.** Pausing or deleting never closes positions.\n6. **`copySell: true`** means the copy will also mirror sell transactions, not just buys.\n\n## Related Skills\n\n- **gdex-authentication** — Auth setup and sign-in required for read\u002Fwrite\n- **gdex-token-discovery** — Top trader rankings (`getTopTraders`)\n- **gdex-portfolio** — Monitor portfolio including copied positions\n- **gdex-spot-trading** — Understand the trades being copied\n",{"name":5,"description":7},"main","3df1d0d67b30ff15236561f8c0f9f06d33f42dfd","skills\u002Fmcp-servers\u002Fgemachdao-gdex-copy-trading",17,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia","https:\u002F\u002Feth2030.com","Hardcore infra. Building @alt-research and applied cryptography.","2026-11-14 02:27:51",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":66},[56,59,62],{"tool":57,"command":58},"npx","npx skills add jiayaoqijia\u002Fcryptoskill --skill gdex-copy-trading",{"tool":60,"command":61},"bunx","bunx skills add jiayaoqijia\u002Fcryptoskill --skill gdex-copy-trading",{"tool":63,"command":64},"pnpm","pnpm dlx skills add jiayaoqijia\u002Fcryptoskill --skill gdex-copy-trading","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fmcp-servers\u002Fgemachdao-gdex-copy-trading\u002FSKILL.md",true,[68,72,78],{"path":69,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":71,"sourceHtmlUrl":16},"LICENSE","许可证",1066,{"path":73,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":76,"sourceHtmlUrl":77},"SOURCE.md","REFERENCE","参考文档",346,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fmcp-servers\u002Fgemachdao-gdex-copy-trading\u002FSOURCE.md",{"path":79,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":80,"sourceHtmlUrl":81},"TRUST.auto.yaml",2071,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fmcp-servers\u002Fgemachdao-gdex-copy-trading\u002FTRUST.auto.yaml",[83,111,133,151,164,174],{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":87,"sourceHtmlUrl":88,"categories":89,"keywords":90,"publishedAt":40},"01M712C436EQYE43342Q4E7GG1","recipe-performance","Diagnose a specific MetaMask user flow's real-app performance and Sentry critical-user-flow telemetry with deterministic mm-harness recipes. Use for CUF boundaries, cold\u002Fwarm\u002Fbackground-resume behavior, latency regressions, lifecycle tags, duplicate or blocking network requests, long tasks, layout\u002Fpaint cost, screen redraws, React rerenders, or browser trace analysis where tests alone cannot prove the real app.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FSKILL.md",[],[91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110],"performance","recipe performance","recipe","mm","sentry","harness","app","deterministic","recipes","flow","cold","critical","analysis","tasks","react","browser","layout","screen","network","metamask",{"skillNo":112,"name":113,"nameZh":6,"description":114,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":115,"licenseFileUrl":116,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":40},"01M70XT2F8A5CQZ81JBP98KSW3","mexc-spot-websocket","MEXC Spot WebSocket workflows for public streams, protobuf handling, depth maintenance, listen keys, and private streams without exposing API keys.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FSKILL.md",[],[120,121,122,123,124,125,126,127,128,129,24,130,131,132],"mexc spot websocket","spot","websocket","api","workflows","public","listen","streams","depth","keys","api keys","maintenance","protobuf",{"skillNo":134,"name":135,"nameZh":6,"description":136,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":115,"licenseFileUrl":137,"sourceHtmlUrl":138,"categories":139,"keywords":140,"publishedAt":40},"01M70XT0MBXN3WZY1BKN0CPNKR","mexc-spot-rest","MEXC Spot REST workflows for public data, signed account requests, orders, wallet\u002Fadmin actions, and secure signing without exposing API keys.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FSKILL.md",[],[141,121,142,143,144,145,146,130,24,129,147,148,149,125,150,124,123],"mexc spot rest","REST","admin","signing","Wallet","requests","actions","secure","data","orders",{"skillNo":152,"name":153,"nameZh":6,"description":154,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":115,"licenseFileUrl":155,"sourceHtmlUrl":156,"categories":157,"keywords":158,"publishedAt":40},"01M70XSYSVZ2N0N91XCAR2CAK0","mexc-futures-websocket","MEXC Futures WebSocket workflows for public streams, private account\u002Forder\u002Fposition streams, ping\u002Fpong, subscriptions, and depth maintenance.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FSKILL.md",[],[159,160,122,161,162,131,24,163,128,127,125,124],"mexc futures websocket","futures","position","ping","subscriptions",{"skillNo":165,"name":166,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":167,"sourceHtmlUrl":168,"categories":169,"keywords":170,"publishedAt":40},"01M6H0ZWHVE5W04WG2DKQE2SQC","0xklen-version-and-refresh-sanctions-lists","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FSKILL.md",[],[171,172,173],"refresh","0xklen version and refresh sanctions lists","version",{"skillNo":175,"name":176,"nameZh":6,"description":177,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":178,"sourceHtmlUrl":179,"categories":180,"keywords":181,"publishedAt":40},"01M6H0Z28Q3R8J0S799GJQWXM3","verify-tests-cover-changed-lines","Use when a PR adds code that the existing suite may not exercise. Measures patch coverage — the share of newly changed lines hit by tests — before approving.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FSKILL.md",[],[182,183,184,185,186,187,188,189,190,191,192],"tests","cover","verify tests cover changed lines","verify","coverage","pr","exercise","use","patch","code","share"]