mirror of
https://github.com/GMGNAI/gmgn-skills.git
synced 2026-08-25 05:58:06 +00:00
support trenches & kol & smartmoney
This commit is contained in:
@@ -75,10 +75,13 @@ export class OpenApiClient {
|
||||
chain: string,
|
||||
address: string,
|
||||
resolution: string,
|
||||
from: number,
|
||||
to: number
|
||||
from?: number,
|
||||
to?: number
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/market/token_kline", { chain, address, resolution, from, to });
|
||||
const query: Record<string, string | number> = { chain, address, resolution };
|
||||
if (from != null) query["from"] = from;
|
||||
if (to != null) query["to"] = to;
|
||||
return this.normalRequest("GET", "/v1/market/token_kline", query);
|
||||
}
|
||||
|
||||
// ---- Portfolio endpoints (normal auth) ----
|
||||
@@ -123,6 +126,11 @@ export class OpenApiClient {
|
||||
return this.normalRequest("GET", "/v1/user/wallet_token_balance", { chain, wallet_address: walletAddress, token_address: tokenAddress });
|
||||
}
|
||||
|
||||
async getTrenches(chain: string): Promise<unknown> {
|
||||
const body = buildTrenchesBody(chain);
|
||||
return this.normalRequest("POST", "/v1/trenches", { chain }, body);
|
||||
}
|
||||
|
||||
// ---- Market trending endpoints (normal auth) ----
|
||||
|
||||
async getTrendingSwaps(
|
||||
@@ -139,6 +147,35 @@ export class OpenApiClient {
|
||||
return this.normalRequest("GET", "/v1/user/info", {});
|
||||
}
|
||||
|
||||
async getFollowWallet(chain: string, extra: Record<string, string | number | string[]> = {}): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/trade/follow_wallet", { chain, ...extra });
|
||||
}
|
||||
|
||||
async getKol(limit?: number): Promise<unknown> {
|
||||
const query: Record<string, string | number> = {};
|
||||
if (limit != null) query["limit"] = limit;
|
||||
return this.normalRequest("GET", "/v1/user/kol", query);
|
||||
}
|
||||
|
||||
async getSmartMoney(limit?: number): Promise<unknown> {
|
||||
const query: Record<string, string | number> = {};
|
||||
if (limit != null) query["limit"] = limit;
|
||||
return this.normalRequest("GET", "/v1/user/smartmoney", query);
|
||||
}
|
||||
|
||||
async quoteOrder(
|
||||
chain: string,
|
||||
from_address: string,
|
||||
input_token: string,
|
||||
output_token: string,
|
||||
input_amount: string,
|
||||
slippage: number
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/trade/quote", {
|
||||
chain, from_address, input_token, output_token, input_amount, slippage,
|
||||
});
|
||||
}
|
||||
|
||||
// ---- Swap endpoints (critical auth) ----
|
||||
|
||||
async swap(params: SwapParams): Promise<unknown> {
|
||||
@@ -269,6 +306,47 @@ function formatCurl(method: string, url: string, headers: Record<string, string>
|
||||
return `\n[curl]\ncurl -X ${method} '${url}' \\\n${headerArgs}${bodyArg}\n`;
|
||||
}
|
||||
|
||||
const TRENCHES_PLATFORMS: Record<string, string[]> = {
|
||||
sol: [
|
||||
"Pump.fun", "pump_mayhem", "pump_mayhem_agent", "pump_agent",
|
||||
"letsbonk", "bonkers", "bags", "memoo", "liquid", "bankr", "zora",
|
||||
"surge", "anoncoin", "moonshot_app", "wendotdev", "heaven", "sugar",
|
||||
"token_mill", "believe", "trendsfun", "trends_fun", "jup_studio",
|
||||
"Moonshot", "boop", "ray_launchpad", "meteora_virtual_curve", "xstocks",
|
||||
],
|
||||
bsc: [
|
||||
"fourmeme", "fourmeme_agent", "bn_fourmeme", "four_xmode_agent",
|
||||
"flap", "clanker", "lunafun",
|
||||
],
|
||||
base: [
|
||||
"clanker", "bankr", "flaunch", "zora", "zora_creator",
|
||||
"baseapp", "basememe", "virtuals_v2", "klik",
|
||||
],
|
||||
};
|
||||
|
||||
const TRENCHES_QUOTE_ADDRESS_TYPES: Record<string, number[]> = {
|
||||
sol: [4, 5, 3, 1, 13, 0],
|
||||
bsc: [6, 7, 1, 16, 8, 3, 9, 10, 2, 17, 18, 0],
|
||||
base: [11, 3, 12, 13, 0],
|
||||
};
|
||||
|
||||
function buildTrenchesBody(chain: string): Record<string, unknown> {
|
||||
const launchpad_platform = TRENCHES_PLATFORMS[chain] ?? [];
|
||||
const quote_address_type = TRENCHES_QUOTE_ADDRESS_TYPES[chain] ?? [];
|
||||
const section = {
|
||||
filters: ["offchain", "onchain"],
|
||||
launchpad_platform,
|
||||
quote_address_type,
|
||||
launchpad_platform_v2: true,
|
||||
};
|
||||
return {
|
||||
new_creation: { ...section, limit: 60 },
|
||||
near_completion: { ...section, limit: 120 },
|
||||
completed: { ...section, limit: 60 },
|
||||
version: "v2",
|
||||
};
|
||||
}
|
||||
|
||||
function buildUrl(base: string, query: Record<string, string | number | string[]>): string {
|
||||
const params = new URLSearchParams();
|
||||
for (const [k, v] of Object.entries(query)) {
|
||||
|
||||
+21
-3
@@ -13,15 +13,21 @@ export function registerMarketCommands(program: Command): void {
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.requiredOption("--address <address>", "Token contract address")
|
||||
.requiredOption("--resolution <resolution>", "Candlestick resolution: 1m / 5m / 15m / 1h / 4h / 1d")
|
||||
.requiredOption("--from <timestamp>", "Start time (Unix seconds)", parseInt)
|
||||
.requiredOption("--to <timestamp>", "End time (Unix seconds)", parseInt)
|
||||
.option("--from <timestamp>", "Start time (Unix seconds)", parseInt)
|
||||
.option("--to <timestamp>", "End time (Unix seconds)", parseInt)
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
validateAddress(opts.address, opts.chain, "--address");
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client
|
||||
.getTokenKline(opts.chain, opts.address, opts.resolution, opts.from * 1000, opts.to * 1000)
|
||||
.getTokenKline(
|
||||
opts.chain,
|
||||
opts.address,
|
||||
opts.resolution,
|
||||
opts.from != null ? opts.from * 1000 : undefined,
|
||||
opts.to != null ? opts.to * 1000 : undefined
|
||||
)
|
||||
.catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
@@ -50,5 +56,17 @@ export function registerMarketCommands(program: Command): void {
|
||||
const data = await client.getTrendingSwaps(opts.chain, opts.interval, extra).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
market
|
||||
.command("trenches")
|
||||
.description("Get Trenches token data (new creation, near completion, completed)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client.getTrenches(opts.chain).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
validateAddress(opts.wallet, opts.chain, "--wallet");
|
||||
if (opts.token) validateAddress(opts.token, opts.chain, "--token");
|
||||
const extra: Record<string, string | number | string[]> = {};
|
||||
if (opts.token) extra["token"] = opts.token;
|
||||
if (opts.token) extra["token_address"] = opts.token;
|
||||
if (opts.limit != null) extra["limit"] = opts.limit;
|
||||
if (opts.cursor) extra["cursor"] = opts.cursor;
|
||||
if (opts.type?.length) extra["type"] = opts.type;
|
||||
@@ -112,5 +112,64 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
const data = await client.getWalletTokenBalance(opts.chain, opts.wallet, opts.token).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
portfolio
|
||||
.command("follow-wallet")
|
||||
.description("Get follow-wallet trade records")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.option("--wallet <address>", "Filter by wallet address")
|
||||
.option("--base-token <address>", "Filter by base token address")
|
||||
.option("--page-token <cursor>", "Pagination cursor")
|
||||
.option("--limit <n>", "Page size (1–200, default 100)", parseInt)
|
||||
.option("--side <side>", "Trade direction filter")
|
||||
.option("--cost <cost>", "Cost filter")
|
||||
.option("--filter <tag...>", "Filter conditions, repeatable")
|
||||
.option("--with-balance", "Include balance in response")
|
||||
.option("--with-security", "Include security info in response")
|
||||
.option("--min-amount-usd <n>", "Minimum trade amount (USD)", parseFloat)
|
||||
.option("--max-amount-usd <n>", "Maximum trade amount (USD)", parseFloat)
|
||||
.option("--is-gray", "Gray mode filter")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
const extra: Record<string, string | number | string[]> = {};
|
||||
if (opts.wallet) extra["wallet_address"] = opts.wallet;
|
||||
if (opts.baseToken) extra["base_token"] = opts.baseToken;
|
||||
if (opts.pageToken) extra["page_token"] = opts.pageToken;
|
||||
if (opts.limit != null) extra["limit"] = opts.limit;
|
||||
if (opts.side) extra["side"] = opts.side;
|
||||
if (opts.cost) extra["cost"] = opts.cost;
|
||||
if (opts.filter?.length) extra["filters"] = opts.filter;
|
||||
if (opts.withBalance) extra["with_balance"] = "true";
|
||||
if (opts.withSecurity) extra["with_security"] = "true";
|
||||
if (opts.minAmountUsd != null) extra["min_amount_usd"] = opts.minAmountUsd;
|
||||
if (opts.maxAmountUsd != null) extra["max_amount_usd"] = opts.maxAmountUsd;
|
||||
if (opts.isGray) extra["is_gray"] = "true";
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client.getFollowWallet(opts.chain, extra).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
portfolio
|
||||
.command("kol")
|
||||
.description("Get KOL trade records (SOL chain)")
|
||||
.option("--limit <n>", "Page size (1–200, default 100)", parseInt)
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client.getKol(opts.limit).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
portfolio
|
||||
.command("smartmoney")
|
||||
.description("Get Smart Money trade records (SOL chain)")
|
||||
.option("--limit <n>", "Page size (1–200, default 100)", parseInt)
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client.getSmartMoney(opts.limit).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,29 @@ export function registerSwapCommands(program: Command): void {
|
||||
|
||||
const order = program.command("order").description("Order management commands");
|
||||
|
||||
order
|
||||
.command("quote")
|
||||
.description("Get a swap quote without submitting a transaction")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--input-token <address>", "Input token contract address")
|
||||
.requiredOption("--output-token <address>", "Output token contract address")
|
||||
.requiredOption("--amount <amount>", "Input amount (smallest unit)")
|
||||
.requiredOption("--slippage <n>", "Slippage tolerance (e.g. 0.01 = 1%)", parseFloat)
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
validateAddress(opts.from, opts.chain, "--from");
|
||||
validateAddress(opts.inputToken, opts.chain, "--input-token");
|
||||
validateAddress(opts.outputToken, opts.chain, "--output-token");
|
||||
validatePositiveInt(opts.amount, "--amount");
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client
|
||||
.quoteOrder(opts.chain, opts.from, opts.inputToken, opts.outputToken, opts.amount, opts.slippage)
|
||||
.catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
order
|
||||
.command("get")
|
||||
.description("Query order status (requires private key)")
|
||||
|
||||
Reference in New Issue
Block a user