@ln-markets/sdk
v2.0.2
Published
TypeScript SDK for LNMarkets API
Maintainers
Readme
Getting Started
Setup
Install our SDK using your preferred package manager:
npm install @ln-markets/sdkpnpm install @ln-markets/sdkyarn add @ln-markets/sdkbun add @ln-markets/sdkNetwork
By default, the SDK will connect to the LN Markets mainnet environment. You can change this by passing the network option to the createHttpClient function.
import { createHttpClient } from '@ln-markets/sdk/rest/v3'
const client = createHttpClient({
network: 'signet', // 'mainnet' or 'signet'
})Unauthenticated client
You can use an unauthenticated client to access public endpoints.
import { createHttpClient } from '@ln-markets/sdk/rest/v3'
const client = createHttpClient()
// Check server time
const time = await client.time()
// => { time: 1698765432 }
// Ping the server
const pong = await client.ping()
// => 'pong'
// Get current ticker information
const ticker = await client.futures.getTicker()
// => { index: 67500, lastPrice: 67520, ... }
// Get candles data
const candles = await client.futures.getCandles({
from: '2023-10-31T00:00:00Z',
to: '2023-11-01T00:00:00Z',
range: '1h',
})
// Get leaderboard
const leaderboard = await client.futures.getLeaderboard()
// Get oracle price data
const lastPrice = await client.oracle.getLastPrice()
const index = await client.oracle.getIndex()Authenticated client
You can authenticate using your API key, secret and passphrase directly passed to the createHttpClient function.
You can get your API key, secret and passphrase from the API Keys section of your LN Markets account.
:warning: Important: Your API key, secret and passphrase are sensitive and should be kept secure. Do not expose them in your client-side code, nor share them with anyone. Any leakage of your API key, secret or passphrase may lead to unauthorized access to your account and irreversible loss of funds.
import { createHttpClient } from '@ln-markets/sdk/rest/v3'
const client = createHttpClient({
key: 'your-api-key',
secret: 'your-api-secret',
passphrase: 'your-api-key-passphrase',
})
// Get account information
const account = await client.account.get()
// => { balance: 100000, syntheticUsdBalance: 50, username: 'trader123', ... }
// Get lightning deposits history
const deposits = await client.account.getLightningDeposits()
// Get lightning withdrawals history
const withdrawals = await client.account.getLightningWithdrawals()API v3 Examples
Futures Trading - Isolated Margin
Isolated margin mode allows you to limit the risk to a specific position. Each position has its own margin.
import { createHttpClient } from '@ln-markets/sdk/rest/v3'
const client = createHttpClient({
key: 'your-api-key',
secret: 'your-api-secret',
passphrase: 'your-api-key-passphrase',
})
// Open a new long position with market order
const marketTrade = await client.futures.isolated.newTrade({
type: 'market',
side: 'buy',
quantity: 10000,
leverage: 25,
})
// Open a long position with limit order
const limitTrade = await client.futures.isolated.newTrade({
type: 'limit',
side: 'buy',
price: 67000, // Limit price
margin: 20000,
leverage: 10,
})
// Get all open trades (orders waiting to be filled)
const openTrades = await client.futures.isolated.getOpenTrades()
// Get all running trades (filled positions)
const runningTrades = await client.futures.isolated.getRunningTrades()
// Get closed trades history
const closedTrades = await client.futures.isolated.getClosedTrades()
// Add margin to an existing position
await client.futures.isolated.addMargin({
id: 'trade-id',
amount: 5000,
})
// Update take-profit
await client.futures.isolated.updateTakeprofit({
id: 'trade-id',
value: 72000,
})
// Update stop-loss
await client.futures.isolated.updateStoploss({
id: 'trade-id',
value: 66000,
})
// Close a specific position
await client.futures.isolated.close({
id: 'trade-id',
})
// Cancel a pending order
await client.futures.isolated.cancel({
id: 'trade-id',
})
// Cancel all pending orders
await client.futures.isolated.cancelAll()
// Get funding fees history
const fundingFees = await client.futures.isolated.getFundingFees({
from: '2023-10-31T00:00:00Z',
to: '2023-11-01T00:00:00Z',
})
// Cash in profits from a running position (partial close)
await client.futures.isolated.cashIn({
id: 'trade-id',
amount: 5000, // Amount in satoshis to cash in
})Futures Trading - Cross Margin
Cross margin mode shares margin across all positions. This allows for more efficient margin usage but increases risk as losses from one position can affect others.
import { createHttpClient } from '@ln-markets/sdk/rest/v3'
const client = createHttpClient({
key: 'your-api-key',
secret: 'your-api-secret',
passphrase: 'your-api-key-passphrase',
})
// First, deposit funds into cross margin account.
// Returns the updated FuturesCrossPosition.
await client.futures.cross.deposit({
amount: 100000, // Amount in satoshis
})
// Set leverage for cross margin trading
await client.futures.cross.setLeverage({
leverage: 25,
})
// Place a market order
const marketOrder = await client.futures.cross.newOrder({
type: 'market',
side: 'buy', // 'buy' for buy/long, 'sell' for sell/short
quantity: 1000, // Quantity in USD
})
// Place a limit order
const limitOrder = await client.futures.cross.newOrder({
type: 'limit',
side: 'sell',
quantity: 500,
price: 68000,
})
// Get current position
const position = await client.futures.cross.getPosition()
// Get open orders
const openOrders = await client.futures.cross.getOpenOrders()
// Get filled orders history
const filledOrders = await client.futures.cross.getFilledOrders({
from: '2023-10-31T00:00:00Z',
to: '2023-11-01T00:00:00Z',
})
// Cancel a specific order
await client.futures.cross.cancel({
id: 'order-id',
})
// Cancel all open orders
await client.futures.cross.cancelAll()
// Close entire position
await client.futures.cross.close()
// Get funding fees history
const fundingFees = await client.futures.cross.getFundingFees({
from: '2023-10-31T00:00:00Z',
to: '2023-11-01T00:00:00Z',
})
// Get transfers history (deposits/withdrawals)
const transfers = await client.futures.cross.getTransfers({
from: '2023-10-31T00:00:00Z',
to: '2023-11-01T00:00:00Z',
})
// Withdraw funds from cross margin account.
// Returns the updated FuturesCrossPosition.
await client.futures.cross.withdraw({
amount: 50000,
})Account Management
import { createHttpClient } from '@ln-markets/sdk/rest/v3'
const client = createHttpClient({
key: 'your-api-key',
secret: 'your-api-secret',
passphrase: 'your-api-key-passphrase',
})
// Get account information
const account = await client.account.get()
console.log(`Balance: ${account.balance} sats`)
console.log(`Synthetic USD Balance: ${account.syntheticUsdBalance}`)
// Create a Lightning deposit invoice
const depositInvoice = await client.account.depositLightning({
amount: 100000, // Amount in satoshis
})
console.log(`Pay this invoice: ${depositInvoice.invoice}`)
// Withdraw via Lightning
const withdrawal = await client.account.withdrawLightning({
invoice: 'lnbc...', // Lightning invoice to pay
})
// Get or add Bitcoin on-chain address
const address = await client.account.getBitcoinAddress()
// or generate a new one (server-side). Optionally choose the script format.
const newAddress = await client.account.addBitcoinAddress({
format: 'p2tr', // 'p2tr' (default) or 'p2wpkh'
})
// Withdraw on-chain
const onChainWithdrawal = await client.account.withdrawOnChain({
address: 'bc1q...',
amount: 100000,
})
// Get transaction histories
const lightningDeposits = await client.account.getLightningDeposits()
const lightningWithdrawals = await client.account.getLightningWithdrawals()
const onChainDeposits = await client.account.getOnChainDeposits()
const onChainWithdrawals = await client.account.getOnChainWithdrawals()Synthetic USD
Synthetic USD allows you to swap between BTC and USD-denominated positions.
import { createHttpClient } from '@ln-markets/sdk/rest/v3'
const client = createHttpClient({
key: 'your-api-key',
secret: 'your-api-secret',
passphrase: 'your-api-key-passphrase',
})
// Get best price for swap (current ask/bid)
const bestPrice = await client.syntheticUsd.getBestPrice()
// Create a new swap by specifying input amount + assets
const swap = await client.syntheticUsd.newSwap({
inAmount: 100,
inAsset: 'USD',
outAsset: 'BTC',
})
// Get swap history
const swaps = await client.syntheticUsd.getSwaps()Oracle Price Data
import { createHttpClient } from '@ln-markets/sdk/rest/v3'
const client = createHttpClient()
// Get latest price
const lastPrice = await client.oracle.getLastPrice()
console.log(`Current BTC price: $${lastPrice.price}`)
// Get index price
const index = await client.oracle.getIndex()API v3 Features
The v3 API provides the following routes:
- account: Account management (balance, info, deposits, withdrawals)
- futures: Futures trading (positions, orders, market data)
- oracle: Price oracle data
- syntheticUsd: Synthetic USD operations
- time: Server time
- ping: Health check endpoint
Stream API (stream/v1)
The Stream API delivers realtime market data and private events over a single WebSocket connection (JSON-RPC 2.0). Subscribe to topics like futures/inverse/btc_usd/ticker, OHLC candles per resolution, and (when authenticated) wallet + position events.
Stream Setup
Create a stream client and connect. By default the client targets mainnet and reconnects automatically.
import { createStreamClient } from '@ln-markets/sdk/stream/v1'
const client = createStreamClient({
network: 'mainnet', // 'mainnet' or 'signet'
reconnectInterval: 5000,
reconnectEnabled: true,
maxReconnectAttempts: 5,
})
await client.connect()Connect and authenticate
Public topics (ticker, lastPrice, index, buckets, funding, OHLC, announcements) require no authentication. Private topics (wallet/*, futures/inverse/btc_usd/cross/*, futures/inverse/btc_usd/isolated/trades) require an authenticated session.
:warning: Important: Your API key, secret and passphrase are sensitive. Treat them like the REST credentials documented above.
import { createStreamClient } from '@ln-markets/sdk/stream/v1'
const client = createStreamClient({ network: 'mainnet' })
await client.connect()
const auth = await client.authenticate({
key: 'your-api-key',
secret: 'your-api-secret',
passphrase: 'your-api-key-passphrase',
})
// => { authenticated: true, permissions: ['futures:isolated:read', ...] }
const me = await client.whoami()
// => { apiKey: '...', userId: '...', permissions: [...] }Subscribe to topics
subscribe takes a Topic[] and rejects unknown strings at compile time. The on(topic, callback) overload narrows the callback's argument type by topic literal — no runtime type assertions needed.
import { createStreamClient } from '@ln-markets/sdk/stream/v1'
const client = createStreamClient()
await client.connect()
// Public ticker stream
client.on('futures/inverse/btc_usd/ticker', (data) => {
// data is FuturesTickerData — typed by topic literal
console.log(data.time, data.lastPrice, data.funding.rate)
})
// OHLC candles — every resolution from '1m' to '3months' is a valid topic
client.on('futures/inverse/btc_usd/ohlc/1m', (candle) => {
// candle is OhlcData
console.log(candle.open, candle.high, candle.low, candle.close, candle.volume)
})
// Private isolated-trade events — discriminated union narrows on `event`
client.on('futures/inverse/btc_usd/isolated/trades', (event) => {
if (event.event === 'open') {
console.log('opened trade', event.trade.id, event.trade.price)
} else if (event.event === 'closed') {
console.log('closed trade', event.trade.id, event.trade.pl)
}
})
const result = await client.subscribe({
topics: [
'futures/inverse/btc_usd/ticker',
'futures/inverse/btc_usd/ohlc/1m',
'futures/inverse/btc_usd/isolated/trades',
],
})
// => { subscribed: ['futures/inverse/btc_usd/ticker', ...] }Lifecycle events
The client emits standard lifecycle events alongside topic events. Listeners are typed.
import { createStreamClient } from '@ln-markets/sdk/stream/v1'
const client = createStreamClient()
await client.connect()
client.on('open', () => {
console.log('connected')
})
client.on('close', (code, reason) => {
console.log('closed', code, reason)
})
client.on('error', (err) => {
console.error('stream error', err)
})
client.on('reconnected', ({ attempts }) => {
console.log('reconnected after', attempts, 'attempts')
// No auto-resubscribe: replay your subscriptions here.
})Unsubscribe and close
// Unsubscribe from specific topics
await client.unsubscribe({
topics: ['futures/inverse/btc_usd/ticker'],
})
// Or drop all subscriptions in one call
await client.unsubscribeAll()
// Clean disconnect
client.close()Available topics
Public:
announcementsfutures/inverse/btc_usd/ticker,.../lastPrice,.../index,.../buckets,.../fundingfutures/inverse/btc_usd/ohlc/{1m,3m,5m,10m,15m,30m,45m,1h,2h,3h,4h,1d,1w,1month,3months}
Private (require authenticate):
wallet/deposit,wallet/withdrawalfutures/inverse/btc_usd/isolated/tradesfutures/inverse/btc_usd/cross/orders,.../cross/position
Each topic carries a typed payload (see SubscriptionData and the per-topic interfaces exported from @ln-markets/sdk/stream/v1).
