TypeScript
@orderfill/sdk: Bun, Node 20+, browsers and Workers. No dependencies.
bun add @orderfill/sdk # or: npm install @orderfill/sdk
import { OrderFill } from "@orderfill/sdk";
const client = new OrderFill({ token: process.env.ORDERFILL_API_KEY! });
const [account] = await client.accounts();
const gold = client.account(account.id);
console.log(await gold.info());
await gold.placeOrder({ symbol: "XAUUSD", side: "buy", volume: 0.1 });
Accounts
const { account, notice } = await client.connect({
platform: "mt5", login: "477072059", password: "…", server: "Exness-MT5Trial9",
});
const all = await client.accounts();
const handle = client.account(account.id);
Trading
await handle.placeOrder({ symbol: "XAUUSD", side: "buy", volume: 0.1, stopLoss: 2395 });
await handle.placeOrder(order, "my-stable-key"); // your own idempotency key
await handle.modifyPosition(ticket, { takeProfit: 2440 });
await handle.modifyOrder(orderTicket, { price: 1.075 }); // a pending order; the rest is kept
await handle.closePosition(ticket);
await handle.closeLosing(); // or closeAll(), closeProfitable()
const positions = await handle.positions();
const orders = await handle.orders();
Sizing and health
const { margin } = await handle.marginFor({ symbol: "XAUUSD", side: "buy", volume: 0.1 });
const { profit } = await handle.profitFor({ symbol: "XAUUSD", side: "buy", volume: 0.1, open: 2400, close: 2390 });
const last100 = await handle.candles("XAUUSD", { timeframe: "M1", count: 100 });
const { connected, tradeAllowed } = await handle.health();
instruments() carries contractSize, tickSize and tickValue for sizing from a risk
amount; fills from executions() carry commission, swap and fee.
Pass your own idempotency key when you might retry after a restart; otherwise the SDK makes one per call.
Symbols
const { affix, symbols, unresolved } = await handle.symbols();
await handle.resolveSymbol("XAUUSD"); // { brokerSymbol: "XAUUSDm", … }
await handle.setSymbolOverride("XAUUSD", "GOLD"); // pin
await handle.setSymbolOverride("XAUUSD", null); // unpin
Streaming
import { OrderFillStream } from "@orderfill/sdk";
const stream = new OrderFillStream({ token: process.env.ORDERFILL_API_KEY! });
const stop = await stream.watch(account.id, "positions", (positions) => console.log(positions));
It reconnects with backoff and re-subscribes on its own. A rejected token is the one thing it does not retry.
Errors
import { OrderFillError } from "@orderfill/sdk";
try {
await handle.placeOrder({ symbol: "NZDCAD", side: "buy", volume: 0.1 });
} catch (error) {
if (error instanceof OrderFillError) {
console.error(error.code, error.message, error.hint, error.requestId);
}
}