Skip to content

ln-markets/sdk-typescript

Repository files navigation

LN Market's logo

NPM Package Version NPM Package Downloads Follow us on X (Twitter)

LN Markets TypeScript SDK

Website - API Reference - Python SDK

Getting Started

Setup

Install our SDK using your preferred package manager:

npm install @ln-markets/sdk
pnpm install @ln-markets/sdk
yarn add @ln-markets/sdk
bun add @ln-markets/sdk

Network

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.

⚠️ 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.

⚠️ 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:

  • announcements
  • futures/inverse/btc_usd/ticker, .../lastPrice, .../index, .../buckets, .../funding
  • futures/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/withdrawal
  • futures/inverse/btc_usd/isolated/trades
  • futures/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).

Releases

Packages

Used by

Contributors

Languages