@jackwener/opencli 1.7.1 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/cli-manifest.json +386 -1
- package/clis/binance/asks.js +21 -0
- package/clis/binance/commands.test.js +70 -0
- package/clis/binance/depth.js +21 -0
- package/clis/binance/gainers.js +22 -0
- package/clis/binance/klines.js +21 -0
- package/clis/binance/losers.js +22 -0
- package/clis/binance/pairs.js +21 -0
- package/clis/binance/price.js +18 -0
- package/clis/binance/prices.js +19 -0
- package/clis/binance/ticker.js +21 -0
- package/clis/binance/top.js +21 -0
- package/clis/binance/trades.js +20 -0
- package/clis/twitter/lists-parser.js +77 -0
- package/clis/twitter/lists.d.ts +5 -0
- package/clis/twitter/lists.js +62 -0
- package/clis/twitter/lists.test.js +50 -0
- package/clis/weibo/feed.js +18 -5
- package/clis/zsxq/topic.js +5 -3
- package/clis/zsxq/topic.test.js +4 -3
- package/clis/zsxq/utils.js +1 -1
- package/dist/src/cli.js +108 -0
- package/dist/src/discovery.d.ts +5 -2
- package/dist/src/discovery.js +7 -35
- package/dist/src/engine.test.js +29 -1
- package/dist/src/main.js +6 -5
- package/package.json +3 -3
- package/scripts/fetch-adapters.js +59 -28
- package/dist/src/clis/binance/asks.d.ts +0 -1
- package/dist/src/clis/binance/asks.js +0 -20
- package/dist/src/clis/binance/commands.test.d.ts +0 -3
- package/dist/src/clis/binance/commands.test.js +0 -58
- package/dist/src/clis/binance/depth.d.ts +0 -1
- package/dist/src/clis/binance/depth.js +0 -20
- package/dist/src/clis/binance/gainers.d.ts +0 -1
- package/dist/src/clis/binance/gainers.js +0 -21
- package/dist/src/clis/binance/klines.d.ts +0 -1
- package/dist/src/clis/binance/klines.js +0 -20
- package/dist/src/clis/binance/losers.d.ts +0 -1
- package/dist/src/clis/binance/losers.js +0 -21
- package/dist/src/clis/binance/pairs.d.ts +0 -1
- package/dist/src/clis/binance/pairs.js +0 -20
- package/dist/src/clis/binance/price.d.ts +0 -1
- package/dist/src/clis/binance/price.js +0 -17
- package/dist/src/clis/binance/prices.d.ts +0 -1
- package/dist/src/clis/binance/prices.js +0 -18
- package/dist/src/clis/binance/ticker.d.ts +0 -1
- package/dist/src/clis/binance/ticker.js +0 -20
- package/dist/src/clis/binance/top.d.ts +0 -1
- package/dist/src/clis/binance/top.js +0 -20
- package/dist/src/clis/binance/trades.d.ts +0 -1
- package/dist/src/clis/binance/trades.js +0 -19
package/dist/src/main.js
CHANGED
|
@@ -45,14 +45,15 @@ if (argv[0] === 'completion' && argv.length >= 2) {
|
|
|
45
45
|
// Fast path: --get-completions — read from manifest, skip discovery
|
|
46
46
|
const getCompIdx = process.argv.indexOf('--get-completions');
|
|
47
47
|
if (getCompIdx !== -1) {
|
|
48
|
-
// Only
|
|
49
|
-
//
|
|
48
|
+
// Only include manifests that actually exist on disk.
|
|
49
|
+
// With sparse override, the user clis dir may exist but have no manifest.
|
|
50
50
|
const manifestPaths = [getCliManifestPath(BUILTIN_CLIS)];
|
|
51
|
+
const userManifest = getCliManifestPath(USER_CLIS);
|
|
51
52
|
try {
|
|
52
|
-
fs.accessSync(
|
|
53
|
-
manifestPaths.push(
|
|
53
|
+
fs.accessSync(userManifest);
|
|
54
|
+
manifestPaths.push(userManifest);
|
|
54
55
|
}
|
|
55
|
-
catch { /* no user
|
|
56
|
+
catch { /* no user manifest */ }
|
|
56
57
|
if (hasAllManifests(manifestPaths)) {
|
|
57
58
|
const rest = process.argv.slice(getCompIdx + 1);
|
|
58
59
|
let cursor;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jackwener/opencli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"typecheck": "tsc --noEmit",
|
|
53
53
|
"prepare": "[ -d src ] && npm run build || true",
|
|
54
54
|
"prepublishOnly": "npm run build",
|
|
55
|
-
"test": "vitest run --project unit --project extension",
|
|
56
|
-
"test:bun": "bun vitest run --project unit --project extension",
|
|
55
|
+
"test": "vitest run --project unit --project extension --project adapter",
|
|
56
|
+
"test:bun": "bun vitest run --project unit --project extension --project adapter",
|
|
57
57
|
"test:adapter": "vitest run --project adapter",
|
|
58
58
|
"test:all": "vitest run",
|
|
59
59
|
"test:e2e": "vitest run --project e2e",
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Sparse adapter sync: keeps ~/.opencli/clis/ clean by removing stale overrides.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
6
|
+
* Strategy (hash-based, site-level granularity):
|
|
7
|
+
* - When an official site has upstream changes: DELETE the local override
|
|
8
|
+
* (do NOT copy new version — runtime falls back to package baseline)
|
|
9
|
+
* - When an official site has no changes: leave local override intact
|
|
10
|
+
* - User-created custom sites (not in package): always preserved
|
|
11
|
+
* - Skips entirely if already synced at the same version
|
|
12
|
+
*
|
|
13
|
+
* ~/.opencli/clis/ is a sparse override layer, not a full copy.
|
|
14
|
+
* Only eject-ed or user-modified sites appear here.
|
|
11
15
|
*
|
|
12
16
|
* Only runs on global install (npm install -g) or explicit OPENCLI_FETCH=1.
|
|
13
|
-
* No network calls —
|
|
17
|
+
* No network calls — reads hashes from clis/ in the installed package.
|
|
14
18
|
*
|
|
15
19
|
* This is an ESM script (package.json type: module). No TypeScript, no src/ imports.
|
|
16
20
|
*/
|
|
17
21
|
|
|
18
|
-
import { existsSync, mkdirSync, rmSync,
|
|
22
|
+
import { existsSync, mkdirSync, rmSync, readFileSync, writeFileSync, readdirSync, statSync, unlinkSync } from 'node:fs';
|
|
23
|
+
import { createHash } from 'node:crypto';
|
|
19
24
|
import { join, resolve, dirname } from 'node:path';
|
|
20
25
|
import { homedir } from 'node:os';
|
|
21
26
|
|
|
@@ -38,7 +43,14 @@ function getPackageVersion() {
|
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
/**
|
|
41
|
-
*
|
|
46
|
+
* Compute SHA-256 hash of file content.
|
|
47
|
+
*/
|
|
48
|
+
function fileHash(filePath) {
|
|
49
|
+
return createHash('sha256').update(readFileSync(filePath)).digest('hex');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Read existing manifest. Returns { version, files, hashes } or null.
|
|
42
54
|
*/
|
|
43
55
|
function readManifest() {
|
|
44
56
|
try {
|
|
@@ -101,30 +113,48 @@ export function fetchAdapters() {
|
|
|
101
113
|
|
|
102
114
|
const newOfficialFiles = new Set(walkFiles(BUILTIN_CLIS));
|
|
103
115
|
const oldOfficialFiles = new Set(oldManifest?.files ?? []);
|
|
116
|
+
const oldHashes = oldManifest?.hashes ?? {};
|
|
104
117
|
mkdirSync(USER_CLIS_DIR, { recursive: true });
|
|
105
118
|
|
|
106
|
-
// 1.
|
|
107
|
-
|
|
119
|
+
// 1. Compute new hashes and detect which sites have changes
|
|
120
|
+
const newHashes = {};
|
|
121
|
+
const siteFiles = new Map(); // site -> [relPath, ...]
|
|
108
122
|
for (const relPath of newOfficialFiles) {
|
|
109
123
|
const src = join(BUILTIN_CLIS, relPath);
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
124
|
+
const srcHash = fileHash(src);
|
|
125
|
+
newHashes[relPath] = srcHash;
|
|
126
|
+
|
|
127
|
+
const site = relPath.split('/')[0];
|
|
128
|
+
if (!siteFiles.has(site)) siteFiles.set(site, []);
|
|
129
|
+
siteFiles.get(site).push(relPath);
|
|
114
130
|
}
|
|
115
131
|
|
|
116
|
-
//
|
|
117
|
-
|
|
132
|
+
// Determine which sites have any changed/new/removed files
|
|
133
|
+
const changedSites = new Set();
|
|
134
|
+
for (const [site, files] of siteFiles) {
|
|
135
|
+
for (const relPath of files) {
|
|
136
|
+
if (oldHashes[relPath] !== newHashes[relPath]) {
|
|
137
|
+
changedSites.add(site);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Also mark sites that had files removed
|
|
118
143
|
for (const relPath of oldOfficialFiles) {
|
|
119
144
|
if (!newOfficialFiles.has(relPath)) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
145
|
+
changedSites.add(relPath.split('/')[0]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 2. Sparse cleanup: for changed/removed official sites, delete local overrides.
|
|
150
|
+
// Do NOT copy new versions — runtime falls back to package baseline.
|
|
151
|
+
// Only eject-ed sites live in ~/.opencli/clis/.
|
|
152
|
+
let cleared = 0;
|
|
153
|
+
for (const site of changedSites) {
|
|
154
|
+
const siteDir = join(USER_CLIS_DIR, site);
|
|
155
|
+
if (existsSync(siteDir)) {
|
|
156
|
+
rmSync(siteDir, { recursive: true, force: true });
|
|
157
|
+
cleared++;
|
|
128
158
|
}
|
|
129
159
|
}
|
|
130
160
|
|
|
@@ -206,15 +236,16 @@ export function fetchAdapters() {
|
|
|
206
236
|
log(`Cleaned up${legacyCleaned > 0 ? ` ${legacyCleaned} legacy shim files` : ''}${tmpCleaned > 0 ? `${legacyCleaned > 0 ? ',' : ''} ${tmpCleaned} stale tmp files` : ''}`);
|
|
207
237
|
}
|
|
208
238
|
|
|
209
|
-
// 6. Write updated manifest
|
|
239
|
+
// 6. Write updated manifest (with per-file hashes for smart sync)
|
|
210
240
|
writeFileSync(MANIFEST_PATH, JSON.stringify({
|
|
211
241
|
version: currentVersion,
|
|
212
242
|
files: [...newOfficialFiles].sort(),
|
|
243
|
+
hashes: newHashes,
|
|
213
244
|
updatedAt: new Date().toISOString(),
|
|
214
245
|
}, null, 2));
|
|
215
246
|
|
|
216
|
-
log(`
|
|
217
|
-
(
|
|
247
|
+
log(`Synced adapters: ${cleared} local override(s) cleared` +
|
|
248
|
+
(tsCleaned > 0 ? `, ${tsCleaned} stale .ts files removed` : ''));
|
|
218
249
|
}
|
|
219
250
|
|
|
220
251
|
function main() {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'asks',
|
|
5
|
-
description: 'Order book ask prices for a trading pair',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'symbol', type: 'str', required: true, positional: true, help: 'Trading pair symbol (e.g. BTCUSDT, ETHUSDT)' },
|
|
11
|
-
{ name: 'limit', type: 'int', default: 10, help: 'Number of price levels (5, 10, 20, 50, 100)' },
|
|
12
|
-
],
|
|
13
|
-
columns: ['rank', 'ask_price', 'ask_qty'],
|
|
14
|
-
pipeline: [
|
|
15
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/depth?symbol=${{ args.symbol }}&limit=${{ args.limit }}' } },
|
|
16
|
-
{ select: 'asks' },
|
|
17
|
-
{ map: { rank: '${{ index + 1 }}', ask_price: '${{ item.0 }}', ask_qty: '${{ item.1 }}' } },
|
|
18
|
-
{ limit: '${{ args.limit }}' },
|
|
19
|
-
],
|
|
20
|
-
});
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { getRegistry } from '@jackwener/opencli/registry';
|
|
2
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
import { executePipeline } from '../../pipeline/index.js';
|
|
4
|
-
// Import all binance adapters to register them
|
|
5
|
-
import './top.js';
|
|
6
|
-
import './gainers.js';
|
|
7
|
-
import './pairs.js';
|
|
8
|
-
function loadPipeline(name) {
|
|
9
|
-
const cmd = getRegistry().get(`binance/${name}`);
|
|
10
|
-
if (!cmd?.pipeline)
|
|
11
|
-
throw new Error(`Command binance/${name} not found or has no pipeline`);
|
|
12
|
-
return cmd.pipeline;
|
|
13
|
-
}
|
|
14
|
-
function mockJsonOnce(payload) {
|
|
15
|
-
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
|
|
16
|
-
ok: true,
|
|
17
|
-
status: 200,
|
|
18
|
-
statusText: 'OK',
|
|
19
|
-
json: vi.fn().mockResolvedValue(payload),
|
|
20
|
-
}));
|
|
21
|
-
}
|
|
22
|
-
afterEach(() => {
|
|
23
|
-
vi.unstubAllGlobals();
|
|
24
|
-
vi.restoreAllMocks();
|
|
25
|
-
});
|
|
26
|
-
describe('binance adapters', () => {
|
|
27
|
-
it('sorts top pairs by numeric quote volume', async () => {
|
|
28
|
-
mockJsonOnce([
|
|
29
|
-
{ symbol: 'SMALL', lastPrice: '1', priceChangePercent: '1.2', highPrice: '1', lowPrice: '1', quoteVolume: '9.9' },
|
|
30
|
-
{ symbol: 'LARGE', lastPrice: '2', priceChangePercent: '2.3', highPrice: '2', lowPrice: '2', quoteVolume: '100.0' },
|
|
31
|
-
{ symbol: 'MID', lastPrice: '3', priceChangePercent: '3.4', highPrice: '3', lowPrice: '3', quoteVolume: '11.0' },
|
|
32
|
-
]);
|
|
33
|
-
const result = await executePipeline(null, loadPipeline('top'), { args: { limit: 3 } });
|
|
34
|
-
expect(result.map((item) => item.symbol)).toEqual(['LARGE', 'MID', 'SMALL']);
|
|
35
|
-
expect(result.map((item) => item.rank)).toEqual([1, 2, 3]);
|
|
36
|
-
});
|
|
37
|
-
it('sorts gainers by numeric percent change', async () => {
|
|
38
|
-
mockJsonOnce([
|
|
39
|
-
{ symbol: 'TEN', lastPrice: '1', priceChangePercent: '10.0', quoteVolume: '100' },
|
|
40
|
-
{ symbol: 'NINE', lastPrice: '1', priceChangePercent: '9.5', quoteVolume: '100' },
|
|
41
|
-
{ symbol: 'HUNDRED', lastPrice: '1', priceChangePercent: '100.0', quoteVolume: '100' },
|
|
42
|
-
]);
|
|
43
|
-
const result = await executePipeline(null, loadPipeline('gainers'), { args: { limit: 3 } });
|
|
44
|
-
expect(result.map((item) => item.symbol)).toEqual(['HUNDRED', 'TEN', 'NINE']);
|
|
45
|
-
});
|
|
46
|
-
it('keeps only TRADING pairs', async () => {
|
|
47
|
-
mockJsonOnce({
|
|
48
|
-
symbols: [
|
|
49
|
-
{ symbol: 'BTCUSDT', baseAsset: 'BTC', quoteAsset: 'USDT', status: 'TRADING' },
|
|
50
|
-
{ symbol: 'OLDPAIR', baseAsset: 'OLD', quoteAsset: 'USDT', status: 'BREAK' },
|
|
51
|
-
],
|
|
52
|
-
});
|
|
53
|
-
const result = await executePipeline(null, loadPipeline('pairs'), { args: { limit: 10 } });
|
|
54
|
-
expect(result).toEqual([
|
|
55
|
-
{ symbol: 'BTCUSDT', base: 'BTC', quote: 'USDT', status: 'TRADING' },
|
|
56
|
-
]);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'depth',
|
|
5
|
-
description: 'Order book bid prices for a trading pair',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'symbol', type: 'str', required: true, positional: true, help: 'Trading pair symbol (e.g. BTCUSDT, ETHUSDT)' },
|
|
11
|
-
{ name: 'limit', type: 'int', default: 10, help: 'Number of price levels (5, 10, 20, 50, 100)' },
|
|
12
|
-
],
|
|
13
|
-
columns: ['rank', 'bid_price', 'bid_qty'],
|
|
14
|
-
pipeline: [
|
|
15
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/depth?symbol=${{ args.symbol }}&limit=${{ args.limit }}' } },
|
|
16
|
-
{ select: 'bids' },
|
|
17
|
-
{ map: { rank: '${{ index + 1 }}', bid_price: '${{ item.0 }}', bid_qty: '${{ item.1 }}' } },
|
|
18
|
-
{ limit: '${{ args.limit }}' },
|
|
19
|
-
],
|
|
20
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'gainers',
|
|
5
|
-
description: 'Top gaining trading pairs by 24h price change',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'limit', type: 'int', default: 10, help: 'Number of trading pairs' },
|
|
11
|
-
],
|
|
12
|
-
columns: ['rank', 'symbol', 'price', 'change_24h', 'volume'],
|
|
13
|
-
pipeline: [
|
|
14
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/24hr' } },
|
|
15
|
-
{ filter: 'item.priceChangePercent' },
|
|
16
|
-
{ map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_24h: '${{ item.priceChangePercent }}', volume: '${{ item.quoteVolume }}', sort_change: '${{ Number(item.priceChangePercent) }}' } },
|
|
17
|
-
{ sort: { by: 'sort_change', order: 'desc' } },
|
|
18
|
-
{ map: { rank: '${{ index + 1 }}', symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_24h: '${{ item.priceChangePercent }}', volume: '${{ item.quoteVolume }}' } },
|
|
19
|
-
{ limit: '${{ args.limit }}' },
|
|
20
|
-
],
|
|
21
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'klines',
|
|
5
|
-
description: 'Candlestick/kline data for a trading pair',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'symbol', type: 'str', required: true, positional: true, help: 'Trading pair symbol (e.g. BTCUSDT, ETHUSDT)' },
|
|
11
|
-
{ name: 'interval', type: 'str', default: '1d', help: 'Kline interval (1m, 5m, 15m, 1h, 4h, 1d, 1w, 1M)' },
|
|
12
|
-
{ name: 'limit', type: 'int', default: 10, help: 'Number of klines (max 1000)' },
|
|
13
|
-
],
|
|
14
|
-
columns: ['open', 'high', 'low', 'close', 'volume'],
|
|
15
|
-
pipeline: [
|
|
16
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/klines?symbol=${{ args.symbol }}&interval=${{ args.interval }}&limit=${{ args.limit }}' } },
|
|
17
|
-
{ map: { open: '${{ item.1 }}', high: '${{ item.2 }}', low: '${{ item.3 }}', close: '${{ item.4 }}', volume: '${{ item.5 }}' } },
|
|
18
|
-
{ limit: '${{ args.limit }}' },
|
|
19
|
-
],
|
|
20
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'losers',
|
|
5
|
-
description: 'Top losing trading pairs by 24h price change',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'limit', type: 'int', default: 10, help: 'Number of trading pairs' },
|
|
11
|
-
],
|
|
12
|
-
columns: ['rank', 'symbol', 'price', 'change_24h', 'volume'],
|
|
13
|
-
pipeline: [
|
|
14
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/24hr' } },
|
|
15
|
-
{ filter: 'item.priceChangePercent' },
|
|
16
|
-
{ map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_24h: '${{ item.priceChangePercent }}', volume: '${{ item.quoteVolume }}', sort_change: '${{ Number(item.priceChangePercent) }}' } },
|
|
17
|
-
{ sort: { by: 'sort_change' } },
|
|
18
|
-
{ map: { rank: '${{ index + 1 }}', symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_24h: '${{ item.priceChangePercent }}', volume: '${{ item.quoteVolume }}' } },
|
|
19
|
-
{ limit: '${{ args.limit }}' },
|
|
20
|
-
],
|
|
21
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'pairs',
|
|
5
|
-
description: 'List active trading pairs on Binance',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'limit', type: 'int', default: 20, help: 'Number of trading pairs' },
|
|
11
|
-
],
|
|
12
|
-
columns: ['symbol', 'base', 'quote', 'status'],
|
|
13
|
-
pipeline: [
|
|
14
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/exchangeInfo' } },
|
|
15
|
-
{ select: 'symbols' },
|
|
16
|
-
{ filter: 'item.status === \'TRADING\'' },
|
|
17
|
-
{ map: { symbol: '${{ item.symbol }}', base: '${{ item.baseAsset }}', quote: '${{ item.quoteAsset }}', status: '${{ item.status }}' } },
|
|
18
|
-
{ limit: '${{ args.limit }}' },
|
|
19
|
-
],
|
|
20
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'price',
|
|
5
|
-
description: 'Quick price check for a trading pair',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'symbol', type: 'str', required: true, positional: true, help: 'Trading pair symbol (e.g. BTCUSDT, ETHUSDT)' },
|
|
11
|
-
],
|
|
12
|
-
columns: ['symbol', 'price', 'change', 'change_pct', 'high', 'low', 'volume', 'quote_volume', 'trades'],
|
|
13
|
-
pipeline: [
|
|
14
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/24hr?symbol=${{ args.symbol }}' } },
|
|
15
|
-
{ map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change: '${{ item.priceChange }}', change_pct: '${{ item.priceChangePercent }}', high: '${{ item.highPrice }}', low: '${{ item.lowPrice }}', volume: '${{ item.volume }}', quote_volume: '${{ item.quoteVolume }}', trades: '${{ item.count }}' } },
|
|
16
|
-
],
|
|
17
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'prices',
|
|
5
|
-
description: 'Latest prices for all trading pairs',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'limit', type: 'int', default: 20, help: 'Number of prices' },
|
|
11
|
-
],
|
|
12
|
-
columns: ['rank', 'symbol', 'price'],
|
|
13
|
-
pipeline: [
|
|
14
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/price' } },
|
|
15
|
-
{ map: { rank: '${{ index + 1 }}', symbol: '${{ item.symbol }}', price: '${{ item.price }}' } },
|
|
16
|
-
{ limit: '${{ args.limit }}' },
|
|
17
|
-
],
|
|
18
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'ticker',
|
|
5
|
-
description: '24h ticker statistics for top trading pairs by volume',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'limit', type: 'int', default: 20, help: 'Number of tickers' },
|
|
11
|
-
],
|
|
12
|
-
columns: ['symbol', 'price', 'change_pct', 'high', 'low', 'volume', 'quote_vol', 'trades'],
|
|
13
|
-
pipeline: [
|
|
14
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/24hr' } },
|
|
15
|
-
{ map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_pct: '${{ item.priceChangePercent }}', high: '${{ item.highPrice }}', low: '${{ item.lowPrice }}', volume: '${{ item.volume }}', quote_vol: '${{ item.quoteVolume }}', trades: '${{ item.count }}', sort_volume: '${{ Number(item.quoteVolume) }}' } },
|
|
16
|
-
{ sort: { by: 'sort_volume', order: 'desc' } },
|
|
17
|
-
{ map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_pct: '${{ item.priceChangePercent }}', high: '${{ item.highPrice }}', low: '${{ item.lowPrice }}', volume: '${{ item.volume }}', quote_vol: '${{ item.quoteVolume }}', trades: '${{ item.count }}' } },
|
|
18
|
-
{ limit: '${{ args.limit }}' },
|
|
19
|
-
],
|
|
20
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'top',
|
|
5
|
-
description: 'Top trading pairs by 24h volume on Binance',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'limit', type: 'int', default: 20, help: 'Number of trading pairs' },
|
|
11
|
-
],
|
|
12
|
-
columns: ['rank', 'symbol', 'price', 'change_24h', 'high', 'low', 'volume'],
|
|
13
|
-
pipeline: [
|
|
14
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/24hr' } },
|
|
15
|
-
{ map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_24h: '${{ item.priceChangePercent }}', high: '${{ item.highPrice }}', low: '${{ item.lowPrice }}', volume: '${{ item.quoteVolume }}', sort_volume: '${{ Number(item.quoteVolume) }}' } },
|
|
16
|
-
{ sort: { by: 'sort_volume', order: 'desc' } },
|
|
17
|
-
{ map: { rank: '${{ index + 1 }}', symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_24h: '${{ item.priceChangePercent }}', high: '${{ item.highPrice }}', low: '${{ item.lowPrice }}', volume: '${{ item.quoteVolume }}' } },
|
|
18
|
-
{ limit: '${{ args.limit }}' },
|
|
19
|
-
],
|
|
20
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
2
|
-
cli({
|
|
3
|
-
site: 'binance',
|
|
4
|
-
name: 'trades',
|
|
5
|
-
description: 'Recent trades for a trading pair',
|
|
6
|
-
domain: 'data-api.binance.vision',
|
|
7
|
-
strategy: Strategy.PUBLIC,
|
|
8
|
-
browser: false,
|
|
9
|
-
args: [
|
|
10
|
-
{ name: 'symbol', type: 'str', required: true, positional: true, help: 'Trading pair symbol (e.g. BTCUSDT, ETHUSDT)' },
|
|
11
|
-
{ name: 'limit', type: 'int', default: 20, help: 'Number of trades (max 1000)' },
|
|
12
|
-
],
|
|
13
|
-
columns: ['id', 'price', 'qty', 'quote_qty', 'buyer_maker'],
|
|
14
|
-
pipeline: [
|
|
15
|
-
{ fetch: { url: 'https://data-api.binance.vision/api/v3/trades?symbol=${{ args.symbol }}&limit=${{ args.limit }}' } },
|
|
16
|
-
{ map: { id: '${{ item.id }}', price: '${{ item.price }}', qty: '${{ item.qty }}', quote_qty: '${{ item.quoteQty }}', buyer_maker: '${{ item.isBuyerMaker }}' } },
|
|
17
|
-
{ limit: '${{ args.limit }}' },
|
|
18
|
-
],
|
|
19
|
-
});
|