Back to OScope
oscope/tools/tape.mjs
Code
50 lines (46 loc) · 2.92 KB
// Live trades in your terminal.
//
// npm run tape pump.fun and PumpSwap trades of 0.01 SOL or more (smaller ones are mostly volume bots)
// npm run tape -- 1 only trades of 1 SOL or more
// npm run tape -- 0 every single trade
//
// It reads OScope's firehose when OScope is running on this computer, otherwise the stream itself.
import WebSocket from 'ws';
import { config } from '../src/config.mjs';
const minSol = Math.max(0, Number(process.argv[2] ?? process.env.MIN_SOL ?? 0.01) || 0);
const local = `ws://127.0.0.1:${config.port}/firehose?pools=pump,pump-amm`;
const c = { g: s => `\x1b[32m${s}\x1b[0m`, r: s => `\x1b[31m${s}\x1b[0m`, d: s => `\x1b[2m${s}\x1b[0m`, b: s => `\x1b[1m${s}\x1b[0m`, y: s => `\x1b[33m${s}\x1b[0m` };
let usd = 0;
const price = () => fetch('https://api.coinbase.com/v2/prices/SOL-USD/spot', { signal: AbortSignal.timeout(4000) }).then(r => r.json()).then(j => { usd = +j.data.amount || usd; }).catch(() => {});
setInterval(price, 30000).unref();
const money = v => (v >= 1e6 ? (v / 1e6).toFixed(2) + 'M' : v >= 1e3 ? (v / 1e3).toFixed(1) + 'K' : v.toFixed(0));
let shown = 0, seen = 0;
function open(url, fallback) {
const ws = new WebSocket(url);
let ok = false;
ws.on('open', () => { ok = true; console.log(c.d(`reading ${url.split('?')[0]}${minSol ? `, trades of ${minSol} SOL or more` : ''} (Ctrl+C to stop)\n`)); });
ws.on('message', buf => {
let f;
try { f = JSON.parse(buf.toString()); } catch { return; }
if ((f.pool !== 'pump' && f.pool !== 'pump-amm') || (f.action !== 'buy' && f.action !== 'sell' && f.action !== 'create' && f.action !== 'migrate')) return;
seen++;
const t = new Date(f.timestamp || Date.now()).toTimeString().slice(0, 8);
const sym = String(f.symbol || '').slice(0, 12).padEnd(12);
if (f.action === 'create') return console.log(`${c.d(t)} ${c.y('NEW ')} ${c.b(sym)} ${String(f.name || '').slice(0, 40)} ${c.d(f.mint)}`);
if (f.action === 'migrate') return console.log(`${c.d(t)} ${c.y('MIGR')} ${c.b(sym)} moved to PumpSwap ${c.d(f.mint)}`);
const sol = +f.quoteAmount || 0;
if (sol < minSol) return;
shown++;
const side = f.action === 'buy' ? c.g('BUY ') : c.r('SELL');
const mc = usd && f.marketCapQuote ? '$' + money(f.marketCapQuote * usd) : (f.marketCapQuote || 0).toFixed(0) + ' SOL';
console.log(`${c.d(t)} ${side} ${sol.toFixed(3).padStart(9)} SOL ${c.b(sym)} MC ${mc.padEnd(8)} ${c.d(f.pool === 'pump' ? 'curve' : 'swap ')} ${c.d(String(f.txSigner || '').slice(0, 6) + '…')}`);
});
ws.on('close', () => {
if (!ok && fallback) return open(fallback, null);
console.log(c.d('\nstream closed, reopening in 3 s'));
setTimeout(() => open(url, null), 3000);
});
ws.on('error', () => {});
}
process.on('SIGINT', () => { console.log(c.d(`\n${seen.toLocaleString('en-US')} trades seen, ${shown.toLocaleString('en-US')} shown`)); process.exit(0); });
price().then(() => open(local, config.feedUrl));