Get Started

Welcome to the Lighter SDK and API Introduction. Here, we will go through everything from the system setup, to creating and cancelling all types of orders, to fetching exchange data. To keep up to date with Lighter's API, join this Telegram Channel or #api-updates on our Discord.

Install the SDK

Python:

pip install lighter-sdk

Go:

go get https://github.com/elliottech/lighter-go

Find Your Account Index

Your account index is Lighter's integer identifier for your account. If you use sub-accounts, there will be multiple account indexes tied to the same L1 wallet. Query it using your L1 (Ethereum) address:

import asyncio
import lighter

BASE_URL = "https://mainnet.zklighter.elliot.ai"
L1_ADDRESS = "0x123"

async def main():
    client = lighter.ApiClient(lighter.Configuration(host=BASE_URL))
    resp = await lighter.AccountApi(client).accounts_by_l1_address(l1_address=L1_ADDRESS)
    print(resp.sub_accounts[0].index)
    await client.close()

if __name__ == "__main__":
    asyncio.run(main())

Create an API Key

API keys enable SDK signing and authenticated API requests; each is tied to a single account index and has its own nonce. You can create up to 253 keys (indices 2-254). Indices 0-1 are reserved for the web/mobile interfaces. Finally, the 255 index can be used as a value for the api_key_index parameter of the apikeys method of the AccountApi for getting the data about all the API keys. See this page for more details.

Initialize the Signer Client

In order to create a transaction (create/cancel/modify order), you need to use the SignerClient. Initialize with the following code:

 client = lighter.SignerClient(  
        url=BASE_URL,  
        api_private_keys={API_KEY_INDEX:PRIVATE_KEY},  
        account_index=ACCOUNT_INDEX
    )

The code for the signer can be found in the same repo, in the signer_client.py file. You may notice that it uses a binary for the signer: the code for it can be found in the lighter-go public repo, and you can compile it yourself using the justfile.

Nonce

When signing a transaction, you may need to provide a nonce (number used once). A nonce needs to be incremented each time you sign something. You can get the next nonce that you need to use using the TransactionApi’s next_nonce method or take care of incrementing it yourself. Note that each nonce is handled per API_KEY.

Signing a transaction

One can sign a transaction using the SignerClient’s sign_create_order, sign_modify_order, sign_cancel_order and its other similar methods. For actually pushing the transaction, you need to call send_tx or send_tx_batch using the TransactionApi. Here’s an example that includes such an operation. Alternatively, you can use create_order, which will send the tx as well. See more details here.

Note that base_amount, price are to be passed as integers, and client_order_index is a unique (across all markets) identifier you provide for you to be able to reference this order later (e.g. if you want to cancel it). The SDK handles nonce management automatically. For complex systems, you can implement local nonce management.

Price and Size precision

Query the orderBookDetails endpoint to get decimal precision for each market:

GET /api/v1/orderBookDetails

Place Your First Market Order

    tx, tx_hash, err = await client.create_order(
        market_index=0, # ETH perps market
        client_order_index=1234, 
        base_amount=10,  # 0.001 ETH
        price=3100_00,  # $3100 -- worst acceptable price for the order
        is_ask=False, # Bid, i.e. buy order
        order_type=client.ORDER_TYPE_MARKET,
        time_in_force=client.ORDER_TIME_IN_FORCE_IMMEDIATE_OR_CANCEL,
        reduce_only=False,
        order_expiry=client.DEFAULT_IOC_EXPIRY,
    )

Place Your First Limit Order

    tx, tx_hash, err = await client.create_order(
        market_index=0, # ETH perps market
        client_order_index=1234,
        base_amount=100,  # 0.01 ETH
        price=2900_00,  # $2900
        is_ask=False,  # Bid, i.e. buy order
        order_type=client.ORDER_TYPE_LIMIT,
        time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
        reduce_only=False,
        order_expiry=client.DEFAULT_28_DAY_ORDER_EXPIRY,
    )

Cancel an order

    tx, tx_hash, err = await client.cancel_order(
        market_index=market_index,
        order_index=1234
    )

Modify an order

    tx, tx_hash, err = await client.modify_order(
        market_index=0,
        order_index=1234,
        base_amount=100,  # 0.01 ETH
        price=2800_00,  # $2800
    )

Authentication Tokens

For REST API calls and Websocket channels requiring authentication:

        auth_token, err = client.create_auth_token_with_expiry(
            deadline=3600, # seconds. Max is 8 hours, default is 10 minutes
            api_key_index=API_KEY_INDEX,
        )

Alternatively, you can use a read-only auth token. See more details here.

API via SDK

The SDK provides API classes that make calling the Lighter API easier. Here are some of them and the most important of their methods:

  • AccountApi - provides account data
    • account - get account data either by l1_address or index
    • accounts_by_l1_address - get data about all the accounts (master account and subaccounts)
    • apikeys - get data about the api keys of an account (use api_key_index = 255 for getting data about all the api keys)
  • TransactionApi - provides transaction-related data
    • next_nonce - get next nonce to be used for signing a transaction using a certain api key
    • send_tx - push a transaction
    • send_tx_batch - push several transactions at once
  • OrderApi - provides data about orders, trades and the orderbook
    • order_book_details - get data about a specific market’s orderbook
    • order_books - get data about all markets’ orderbooks

You can find the rest here. We also provide an example showing how to use some of these. For the methods that require an auth token, you can generate one using the create_auth_token_with_expiry method of the SignerClient (the same applies to the websockets auth).

WebSockets

Lighter also provides access to essential info using websockets. A simple version of an WsClient for subscribing to account and orderbook updates is implemented here. You can also take it as an example implementation of such a client.

To get access to more data, you will need to connect to the websockets without the provided WsClient. You can find the streams you can connect to, how to connect, and the data they provide in the websockets section.