Merge pull request #202 from dylanzhong662-max/feat/batch-wallet-profits

feat(portfolio): add batch wallet profits command
This commit is contained in:
GMGN.AI
2026-08-20 16:31:33 +08:00
committed by GitHub
6 changed files with 93 additions and 3 deletions
+3
View File
@@ -510,6 +510,9 @@ gmgn-cli portfolio activity --chain sol --wallet <addr>
# Stats (supports multiple wallets)
gmgn-cli portfolio stats --chain sol --wallet <addr1> --wallet <addr2>
# P&L (supports 1100 wallets and 1d/7d/30d/all periods)
gmgn-cli portfolio profits --chain sol --wallet <addr1> --wallet <addr2> --period 7d
# Wallets and balances linked to API key
gmgn-cli portfolio info
+3
View File
@@ -534,6 +534,9 @@ gmgn-cli portfolio activity --chain sol --wallet <addr>
# 交易统计(支持多钱包)
gmgn-cli portfolio stats --chain sol --wallet <addr1> --wallet <addr2>
# 盈亏查询(支持 1100 个钱包及 1d/7d/30d/all 周期)
gmgn-cli portfolio profits --chain sol --wallet <addr1> --wallet <addr2> --period 7d
# API Key 绑定的钱包及主币余额
gmgn-cli portfolio info
+22
View File
@@ -228,6 +228,28 @@ npx gmgn-cli portfolio stats \
---
## portfolio profits
Batch query wallet profit and loss for 1100 wallets.
```bash
gmgn-cli portfolio profits \
--chain <chain> \
--wallet <wallet_address_1> [--wallet <wallet_address_2>] \
[--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.
+35 -2
View File
@@ -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: "<info|holdings|activity|stats|token-balance|created-tokens> [--chain <sol|bsc|base|eth|robinhood|arc|stable>] [--wallet <wallet_address>]"
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: "<info|holdings|activity|stats|profits|token-balance|created-tokens> [--chain <sol|bsc|base|eth|robinhood|arc|stable>] [--wallet <wallet_address...>]"
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 1100 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 <wallet_address> --period 30d
gmgn-cli portfolio stats --chain sol \
--wallet <wallet_1> --wallet <wallet_2>
# Batch P&L for multiple wallets (default 7d)
gmgn-cli portfolio profits --chain sol \
--wallet <wallet_1> --wallet <wallet_2>
# All-time P&L for up to 100 wallets
gmgn-cli portfolio profits --chain sol \
--wallet <wallet_1> --wallet <wallet_2> --period all
# Token balance
gmgn-cli portfolio token-balance \
--chain sol --wallet <wallet_address> --token <token_address>
@@ -182,6 +192,13 @@ The activity response includes a `next` field. Pass it to `--cursor` to fetch th
|--------|-------------|
| `--period <period>` | Stats period: `7d` / `30d` (default `7d`) |
## `portfolio profits` Options
| Option | Description |
|--------|-------------|
| `--wallet <address...>` | One or more wallet addresses (required, max 100) |
| `--period <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.
+8
View File
@@ -417,6 +417,14 @@ export class OpenApiClient {
});
}
async getWalletProfits(chain: string, walletAddresses: string[], period = "7d"): Promise<unknown> {
return this.authExistRequest("POST", "/v1/user/wallet_profits", {}, {
chain,
period,
wallet_addresses: walletAddresses,
});
}
async getWalletTokenBalance(
chain: string,
walletAddress: string,
+22 -1
View File
@@ -83,6 +83,28 @@ export function registerPortfolioCommands(program: Command): void {
printResult(data, opts.raw);
});
portfolio
.command("profits")
.description("Batch query wallet profit and loss (1100 wallets)")
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood / arc / stable")
.requiredOption("--wallet <address...>", "Wallet address(es), up to 100")
.option("--period <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 {
});
}