Menjalankan bot trading otomatis langsung ke pasar prediksi terdesentralisasi seperti Polymarket membawa risiko finansial instan jika terjadi bug logika atau regresi kode. Kesalahan kecil seperti tipe data tidak valid saat menghitung probabilitas cuaca dapat memicu order on-chain yang menguras likuiditas wallet. Artikel ini membedah implementasi pipeline CI GitHub Actions untuk bot trading berbasis TypeScript (merujuk pada arsitektur bot cuaca Polymarket) dengan memvalidasi kode via static check dan integrasi dry-run menggunakan mock server lokal.
Arsitektur CI Pipeline Bot Trading
Pipeline Continuous Integration (CI) untuk bot trading harus bertindak sebagai gerbang deterministik sebelum kode dideploy ke server VPS atau execution runner. Tiga tahap utama yang wajib dieksekusi adalah:
- Static Code Analysis: Linting dengan ESLint dan static type checking dengan TypeScript compiler (
tsc --noEmit) untuk mendeteksi inferensi tipe salah, pemanggilan method tidak aman, dan dead code. - Mock Services: Server HTTP lokal ringan menggunakan Node.js stdlib (
node:http) untuk meniru respon API Polymarket (CLOB/Gamma API) dan feed cuaca eksternal. - Dry-Run Execution: Menjalankan script bot dalam mode simulasi, memastikan bot menerima feed data, melakukan kalkulasi spread/probabilitas, membuat struktur transaksi order, lalu memverifikasi bahwa wallet balance tidak berkurang dan tidak ada network call yang keluar ke endpoint on-chain sebenarnya.
1. Setup Linting dan Typecheck Ketat
Bot trading tidak boleh mentoleransi tipe any implisit karena berpotensi merusak validasi payload transaksi. Konfigurasi tsconfig.json harus mengaktifkan mode strict, dan script package.json harus memisahkan tahapan verifikasi.
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"lib": ["ES2022"],
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}Tambahkan target eksekusi pada package.json:
{
"scripts": {
"lint": "eslint src/**/*.ts",
"typecheck": "tsc --noEmit",
"test:dry-run": "ts-node test/dry-run.ts"
}
}2. Implementasi Mock Server API Polymarket & Feed Cuaca
Alih-alih menambahkan dependency mock server besar, gunakan native node:http untuk menangani endpoint Polymarket Orderbook dan feed cuaca. Pendekatan ini cepat dan meminimalkan footprint CI runner.
import http from 'node:http';
export function startMockServer(port = 8080): http.Server {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json');
// Mock API Cuaca: Prediksi Suhu
if (req.url === '/weather?city=london') {
res.writeHead(200);
return res.end(JSON.stringify({ city: 'London', temp_c: 24.5, condition: 'Sunny' }));
}
// Mock Polymarket Gamma API: Metadata Market
if (req.url?.startsWith('/markets')) {
res.writeHead(200);
return res.end(JSON.stringify([
{
id: 'market-weather-london-2026',
question: 'Will London temp exceed 24C?',
tokens: [{ token_id: 'tok_yes', price: 0.45 }, { token_id: 'tok_no', price: 0.55 }]
}
]));
}
// Mock Polymarket CLOB: Submit Order
if (req.url === '/order' && req.method === 'POST') {
res.writeHead(200);
return res.end(JSON.stringify({ status: 'OK', orderID: 'mock_tx_9981' }));
}
res.writeHead(404);
res.end(JSON.stringify({ error: 'Endpoint not found' }));
});
return server.listen(port);
}3. Skrip Validasi Dry-Run dan Assertion Tanpa Transaksi On-Chain
Logika trading diuji dengan mengarahkan environment variable ke port mock server. Script memastikan kalkulasi order terpicu, namun signing on-chain diblokir menggunakan flag mode dry-run atau mock wallet provider.
import assert from 'node:assert';
import { startMockServer } from './mock-server';
import { WeatherTradingEngine } from '../src/engine';
async function runDryRunValidation() {
const server = startMockServer(8080);
const initialVirtualBalance = 1000;
try {
const bot = new WeatherTradingEngine({
apiUrl: 'http://localhost:8080',
weatherApiUrl: 'http://localhost:8080/weather?city=london',
dryRun: true,
virtualBalance: initialVirtualBalance,
privateKey: '0x0000000000000000000000000000000000000000000000000000000000000001'
});
// Jalankan siklus eksekusi trading bot sekali
const executionResult = await bot.tick();
// Assertions
assert.strictEqual(executionResult.decision, 'BUY_YES', 'Bot gagal mendeteksi sinyal cuaca');
assert.strictEqual(executionResult.isLiveTx, false, 'Dry run mengeksekusi on-chain tx secara ilegal');
assert.strictEqual(bot.getVirtualBalance(), initialVirtualBalance - executionResult.cost, 'Kalkulasi balance bot tidak presisi');
console.log('Dry-run lulus: Sinyal valid, kalkulasi balance presisi, nol transaksi on-chain.');
} finally {
server.close();
}
}
runDryRunValidation().catch((err) => {
console.error('Dry-run gagal:', err);
process.exit(1);
});4. Workflow GitHub Actions
File workflow menyatukan proses dependensi, linting, typecheck, dan eksekusi dry-run dalam satu job cepat.
name: Bot Validation & Dry-Run
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Run Linting
run: npm run lint
- name: Run Static Typecheck
run: npm run typecheck
- name: Execute Dry-Run Trading Pipeline
run: npm run test:dry-run
env:
NODE_ENV: test
DRY_RUN: 'true'Trade-offs dan Tips Debugging
- Trade-off Mocking vs Integration Test: Mocking endpoint via
node:httptidak menguji kompatibilitas signature EIP-712 yang digunakan pada Polymarket CLOB. Untuk memverifikasi format signature cryptographic, sertakan test assertion terpisah menggunakan public mock key tanpa menghubungkan RPC live. - Slippage & Timing Out: Di lingkungan mock, latency mendekati 0ms. Selalu lakukan assertion bahwa kode penentu harga menangani edge-case limit timeout atau order rejection dari server target.
- Security Boundary: Jangan pernah menyimpan private key asli di repository secrets untuk proses CI linting dan dry-run. Gunakan dummy seed atau throw error otomatis jika variable environment mendeteksi address wallet produksi.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!