diff --git a/Readme.md b/Readme.md index b43ab78..3b5871c 100644 --- a/Readme.md +++ b/Readme.md @@ -510,6 +510,9 @@ gmgn-cli portfolio activity --chain sol --wallet # Stats (supports multiple wallets) gmgn-cli portfolio stats --chain sol --wallet --wallet +# P&L (supports 1–100 wallets and 1d/7d/30d/all periods) +gmgn-cli portfolio profits --chain sol --wallet --wallet --period 7d + # Wallets and balances linked to API key gmgn-cli portfolio info diff --git a/Readme.zh.md b/Readme.zh.md index f2047e6..507b777 100644 --- a/Readme.zh.md +++ b/Readme.zh.md @@ -534,6 +534,9 @@ gmgn-cli portfolio activity --chain sol --wallet # 交易统计(支持多钱包) gmgn-cli portfolio stats --chain sol --wallet --wallet +# 盈亏查询(支持 1–100 个钱包及 1d/7d/30d/all 周期) +gmgn-cli portfolio profits --chain sol --wallet --wallet --period 7d + # API Key 绑定的钱包及主币余额 gmgn-cli portfolio info diff --git a/docs/cli-usage.md b/docs/cli-usage.md index c563cb9..40e9457 100644 --- a/docs/cli-usage.md +++ b/docs/cli-usage.md @@ -228,6 +228,28 @@ npx gmgn-cli portfolio stats \ --- +## portfolio profits + +Batch query wallet profit and loss for 1–100 wallets. + +```bash +gmgn-cli portfolio profits \ + --chain \ + --wallet [--wallet ] \ + [--period 1d|7d|30d|all] \ + [--raw] +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` / `arc` / `stable` | +| `--wallet` | Yes | Wallet address (one or more, max 100) | +| `--period` | No | P&L period: `1d` / `7d` / `30d` / `all` (default `7d`) | + +The response contains a `list` array with one result per wallet, including selected-period and all-time realized profit, unrealized profit, total profit, total cost, and buy/sell counts. + +--- + ## portfolio info Query wallets and main currency balances bound to the API Key. diff --git a/skills/gmgn-portfolio/SKILL.md b/skills/gmgn-portfolio/SKILL.md index fe74bac..f42e78f 100644 --- a/skills/gmgn-portfolio/SKILL.md +++ b/skills/gmgn-portfolio/SKILL.md @@ -1,7 +1,7 @@ --- name: gmgn-portfolio -description: Analyze any crypto wallet by address — holdings, realized/unrealized P&L, win rate, trading history, performance stats, specific token balance, and tokens created by a developer wallet (with ATH market cap and DEX graduation status) via GMGN API on Solana, BSC, Base, or Ethereum. Use when user asks about a wallet's holdings, P&L, win rate, what tokens a dev has launched, the highest ATH token a dev ever created, or wants a wallet report to decide whether to copy-trade or follow. -argument-hint: " [--chain ] [--wallet ]" +description: Analyze one or many crypto wallets by address — holdings, batch realized/unrealized P&L, win rate, trading history, performance stats, specific token balance, and tokens created by a developer wallet (with ATH market cap and DEX graduation status) via GMGN API on Solana, BSC, Base, or Ethereum. Use when user asks about wallet holdings, P&L (including comparing up to 100 wallets), win rate, what tokens a dev has launched, the highest ATH token a dev ever created, or wants a wallet report to decide whether to copy-trade or follow. +argument-hint: " [--chain ] [--wallet ]" metadata: cliHelp: "gmgn-cli portfolio --help" --- @@ -40,6 +40,7 @@ Use the `gmgn-cli` tool to query wallet portfolio data based on the user's reque | `portfolio holdings` | Wallet token holdings with P&L | | `portfolio activity` | Transaction history | | `portfolio stats` | Trading statistics (supports batch) | +| `portfolio profits` | Batch wallet P&L for 1–100 wallets | | `portfolio token-balance` | Token balance for a specific token | | `portfolio created-tokens` | Tokens created by a developer wallet, with market cap and ATH info | @@ -69,6 +70,7 @@ All portfolio routes used by this skill go through GMGN's leaky-bucket limiter w | `portfolio info` | `GET /v1/user/info` | 1 | | `portfolio activity` | `GET /v1/user/wallet_activity` | 3 | | `portfolio stats` | `GET /v1/user/wallet_stats` | 3 | +| `portfolio profits` | `POST /v1/user/wallet_profits` | 3 | | `portfolio token-balance` | `GET /v1/user/wallet_token_balance` | 1 | | `portfolio created-tokens` | `GET /v1/user/created_tokens` | 2 | @@ -117,6 +119,14 @@ gmgn-cli portfolio stats --chain sol --wallet --period 30d gmgn-cli portfolio stats --chain sol \ --wallet --wallet +# Batch P&L for multiple wallets (default 7d) +gmgn-cli portfolio profits --chain sol \ + --wallet --wallet + +# All-time P&L for up to 100 wallets +gmgn-cli portfolio profits --chain sol \ + --wallet --wallet --period all + # Token balance gmgn-cli portfolio token-balance \ --chain sol --wallet --token @@ -182,6 +192,13 @@ The activity response includes a `next` field. Pass it to `--cursor` to fetch th |--------|-------------| | `--period ` | Stats period: `7d` / `30d` (default `7d`) | +## `portfolio profits` Options + +| Option | Description | +|--------|-------------| +| `--wallet ` | One or more wallet addresses (required, max 100) | +| `--period ` | P&L period: `1d` / `7d` / `30d` / `all` (default `7d`) | + ## Response Field Reference ### `portfolio holdings` — Key Fields @@ -261,6 +278,22 @@ The response also includes a `common` object when available (absent if the upstr Use `common.tags` and `common.twitter_username` when building a wallet profile narrative. If `common` is absent in the response, omit identity fields silently — do not report it as an error. +### `portfolio profits` — Key Fields + +The response has a `list` array with one item per wallet. Monetary values are decimal strings; parse them with decimal arithmetic rather than binary floating point when exact calculations matter. + +| Field | Description | +|-------|-------------| +| `wallet_address` | Wallet address | +| `realized_profit` | Realized profit in the selected period | +| `realized_profit_cost` | Cost basis associated with selected-period realized profit | +| `buy` / `sell` | Buy and sell counts in the selected period | +| `unrealized_profit` | Unrealized profit on current holdings | +| `total_realized_profit` | All-time realized profit | +| `total_realized_profit_cost` | Cost basis associated with all-time realized profit | +| `total_profit` | Total profit | +| `total_cost` | Total cost basis | + ### `portfolio created-tokens` — Key Fields The response `data` object has a `tokens` array plus aggregate stats. diff --git a/src/client/OpenApiClient.ts b/src/client/OpenApiClient.ts index 0fd6314..8cbda81 100644 --- a/src/client/OpenApiClient.ts +++ b/src/client/OpenApiClient.ts @@ -417,6 +417,14 @@ export class OpenApiClient { }); } + async getWalletProfits(chain: string, walletAddresses: string[], period = "7d"): Promise { + return this.authExistRequest("POST", "/v1/user/wallet_profits", {}, { + chain, + period, + wallet_addresses: walletAddresses, + }); + } + async getWalletTokenBalance( chain: string, walletAddress: string, diff --git a/src/commands/portfolio.ts b/src/commands/portfolio.ts index f45d24e..cd1f1e0 100644 --- a/src/commands/portfolio.ts +++ b/src/commands/portfolio.ts @@ -83,6 +83,28 @@ export function registerPortfolioCommands(program: Command): void { printResult(data, opts.raw); }); + portfolio + .command("profits") + .description("Batch query wallet profit and loss (1–100 wallets)") + .requiredOption("--chain ", "Chain: sol / bsc / base / eth / robinhood / arc / stable") + .requiredOption("--wallet ", "Wallet address(es), up to 100") + .option("--period ", "Profit period: 1d / 7d / 30d / all", "7d") + .option("--raw", "Output raw JSON") + .action(async (opts) => { + validateChain(opts.chain); + const wallets = opts.wallet as string[]; + if (wallets.length > 100) { + throw new Error("--wallet accepts at most 100 addresses"); + } + for (const wallet of wallets) validateAddress(wallet, opts.chain, "--wallet"); + if (!["1d", "7d", "30d", "all"].includes(opts.period)) { + throw new Error("--period must be one of: 1d, 7d, 30d, all"); + } + const client = new OpenApiClient(getConfig()); + const data = await client.getWalletProfits(opts.chain, wallets, opts.period).catch(exitOnError); + printResult(data, opts.raw); + }); + portfolio .command("info") .description("Get wallets and main currency balances bound to the API Key") @@ -131,4 +153,3 @@ export function registerPortfolioCommands(program: Command): void { }); } -