Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Monitor and act on crypto trading signals via Binance Skills Hub for AI agents (natural language interface).
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/cli.mjs
1#!/usr/bin/env node2// trading-signal CLI — self-contained, zero-dep, Node >= 223// Usage: node cli.mjs <command> '<json_params>'4//5// Commands:6// smart-money POST on-chain Smart Money trading signals (BSC + Solana)78// ---- inline HTTP helper (self-contained, zero dependency) ----9const TIMEOUT_MS = 10_000;10const UA = { 'Accept-Encoding': 'identity', 'User-Agent': 'binance-web3/2.0 (Skill)' };1112const qs = (p) => Object.entries(p)13.filter(([, v]) => v != null)14.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)15.join('&');1617async function call({ url, method = 'GET', body, headers = {} }) {18const ctrl = new AbortController();19const timer = setTimeout(() => ctrl.abort(), TIMEOUT_MS);20const opts = { method, headers: { ...UA, ...headers }, signal: ctrl.signal };21if (method === 'POST') { opts.headers['content-type'] = 'application/json'; opts.body = JSON.stringify(body || {}); }22let res;23try { res = await fetch(url, opts); }24catch { clearTimeout(timer); throw Object.assign(new Error('Network request failed'), { exitCode: 3 }); }25clearTimeout(timer);26const data = await res.json();27if (res.status >= 400) throw Object.assign(new Error(`HTTP ${res.status}`), { exitCode: 1, body: data });28return data;29}3031// ---- per-command supported chains (client-side fail-fast) ----32const CHAINS = {33'smart-money': new Set(['56', 'CT_501']),34};3536function validateChainId(cmd, chainId) {37const allowed = CHAINS[cmd];38if (!allowed) return;39const id = String(chainId ?? '');40if (!allowed.has(id)) {41const supported = [...allowed].map((c) => `"${c}"`).join(', ');42throw Object.assign(43new Error(`${cmd}: unsupported chainId "${chainId}". Supported: ${supported}`),44{ exitCode: 1 },45);46}47}4849// ---- commands: (params) => { url, method?, body?, headers? } ----50const COMMANDS = {51'smart-money': (p) => {52validateChainId('smart-money', p.chainId);53return {54url: 'https://web3.binance.com/bapi/defi/v1/public/wallet-direct/buw/wallet/web/signal/smart-money/ai',55method: 'POST',56body: p,57};58},59};6061// ---- exports (for unit testing; direct execution still works — see dispatch below) ----62export { COMMANDS, call, qs, UA, TIMEOUT_MS, CHAINS, validateChainId };6364// ---- CLI dispatch (only runs when executed directly, not when imported) ----65if (import.meta.url === `file://${process.argv[1]}`) {66const [cmd, paramsStr] = process.argv.slice(2);6768if (!cmd || cmd === '--help' || cmd === '-h') {69console.log("Usage: node cli.mjs <command> '<json_params>'\n\nCommands:");70for (const name of Object.keys(COMMANDS)) console.log(` ${name}`);71process.exit(0);72}7374const builder = COMMANDS[cmd];75if (!builder) { console.error(`Unknown command: ${cmd}\nRun with --help to see available commands.`); process.exit(1); }7677let params = {};78if (paramsStr) {79try { params = JSON.parse(paramsStr); }80catch { console.error('Invalid JSON params'); process.exit(1); }81}8283try {84const result = await call(builder(params));85console.log(JSON.stringify(result, null, 2));86} catch (err) {87console.error(err.message);88if (err.body) console.log(JSON.stringify(err.body, null, 2));89process.exit(err.exitCode || 1);90}91}92