Skip to content
Development
Skill

/new-exchange

Scaffold a new CCXT exchange integration in TypeScript, following the certified-exchange template. Walks through describe(), required unified methods, parsers, capability flags, sandbox setup, and static fixtures. Use when adding support for an exchange that does not exist yet

From plugin
ccxt
44k8 skills1 agent
Install
$ npx -y skills add ccxt/ccxt --skill new-exchange --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/new-exchange

Context preview

The summary Claude sees to decide when to auto-load this skill.

Scaffold a new CCXT exchange integration in TypeScript, following the certified-exchange template. Walks through describe(), required unified methods, parsers, capability flags, sandbox setup, and static fixtures. Use when adding support for an exchange that does not exist yet

SKILL.md

new-exchange.SKILL.md
name: new-exchange
description: Scaffold a new CCXT exchange integration in TypeScript, following the certified-exchange template. Walks through describe(), required unified methods, parsers, capability flags, sandbox setup, and static fixtures. Use when adding support for an exchange that does not exist yet under ts/src/.

New Exchange Integration

Scaffold a new exchange in `ts/src/<id>.ts` (REST) and optionally `ts/src/pro/<id>.ts` (WebSocket).

> **Read first:** `wiki/Requirements.md` (mandatory unified methods) and `CONTRIBUTING.md` (transpiler rules). The CCXT root `CLAUDE.md` is the contributor guide.

Inputs

  • `<id>`: lowercase exchange id, no separators (e.g. `mynewex`)
  • `<Name>`: human-readable name (e.g. `My New Exchange`)
  • API docs URL(s)
  • Whether the exchange has a testnet/sandbox

Step 1 — Pick a reference exchange

Don't write from scratch. Copy a similar exchange that's already certified and adapt it.

| Style | Reference | |---|---| | Spot + futures, signed REST | `ts/src/binance.ts`, `ts/src/okx.ts` | | Spot only | `ts/src/kraken.ts`, `ts/src/coinbase.ts` | | Derivatives focus | `ts/src/bybit.ts`, `ts/src/bitmex.ts` | | Decentralised / on-chain signing | `ts/src/hyperliquid.ts`, `ts/src/dydx.ts` | | WebSocket reference | `ts/src/pro/binance.ts`, `ts/src/pro/okx.ts` |

Open the reference next to your new file and pattern-match — never invent new conventions.

Step 2 — Create `ts/src/<id>.ts`

Skeleton:

import Exchange from './abstract/<id>.js';
import { /* errors needed */ } from './base/errors.js';
import { Precise } from './base/Precise.js';
import type { /* types needed */ } from './base/types.js';

export default class <id> extends Exchange {
    describe (): any {
        return this.deepExtend (super.describe (), {
            'id': '<id>',
            'name': '<Name>',
            'countries': [ 'XX' ],
            'rateLimit': 1000,        // ms between requests
            'version': 'v1',
            'certified': false,
            'pro': false,             // flip to true when pro/<id>.ts exists
            'has': {
                // start everything false; flip to true as you implement
                'CORS': undefined,
                'spot': true,
                'margin': false,
                'swap': false,
                'future': false,
                'option': false,
                'fetchMarkets': true,
                'fetchCurrencies': true,
                'fetchTicker': true,
                'fetchTickers': false,
                'fetchOrderBook': true,
                'fetchTrades': true,
                'fetchOHLCV': false,
                'fetchBalance': true,
                'createOrder': true,
                'cancelOrder': true,
                'fetchOrder': true,
                'fetchOpenOrders': true,
                'fetchOrders': false,
                'fetchClosedOrders': false,
                'fetchMyTrades': true,
                'fetchDeposits': false,
                'fetchWithdrawals': false,
                'withdraw': false,
            },
            'urls': {
                'logo': 'https://...',
                'api': {
                    'public': 'https://api.<id>.com',
                    'private': 'https://api.<id>.com',
                },
                'test': {                              // OPTIONAL — only if testnet exists
                    'public': 'https://testnet.<id>.com',
                    'private': 'https://testnet.<id>.com',
                },
                'www': 'https://<id>.com',
                'doc': [ 'https://docs.<id>.com' ],
                'fees': 'https://<id>.com/fees',
            },
            'api': {
                'public': {
                    'get': [
                        'symbols',
                        'ticker/{pair}',
                        'orderbook/{pair}',
                    ],
                },
                'private': {
                    'get': [ 'account', 'orders' ],
                    'post': [ 'order' ],
                    'delete': [ 'order/{id}' ],
                },
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': true,
                // 'password': true,        // for passphrase-based exchanges
                // 'walletAddress': true,   // for on-chain
                // 'privateKey': true,
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.001,
                    'taker': 0.001,
                },
            },
            'precisionMode': /* TICK_SIZE | DECIMAL_PLACES | SIGNIFICANT_DIGITS */,
            'options': {
                // exchange-specific defaults
            },
            'exceptions': {
                'exact': {
                    // 'ERROR_CODE': BadRequest,
                },
                'broad': {
                    // 'invalid signature': AuthenticationError,
                },
            },
        });
    }

    // implement the unified methods you flipped on in `has`
    async fetchMarkets (params = {}): Promise<Market[]> { /* ... */ }
    parseMarket (market: Dict): Market { /* ... */ }
    async fetchTicker (symbol: string, params = {}): Promise<Ticker> { /* ... */ }
    parseTicker (ticker: Dict, market: Market = undefined): Ticker { /* ... */ }
    // ...

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        // build URL, sign request — use this.hmac, this.jwt, this.ecdsa, never external libs
    }

    handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
        // throw the right exception based on response
    }
}

Step 3 — Define implicit API methods

URLs in the `api` block become methods automatically:

  • `'symbols'` → `this.publicGetSymbols(params)`
  • `'ticker/{pair}'`
Read more
Ships withccxt

A crypto trading API with more than 100 exchanges and prediction markets in JavaScript / TypeScript / Python / C# / PHP / Go / Java.

Get the whole plugin
Stats
43,585
Stars
8,802
Forks
Active
Maintenance
Python
Language
MIT
License
19m ago
Last commit
9y ago
Created

Repo: ccxt/ccxt

Other skills on ccxt.