Signing Transactions
Traders can trade programmatically using the sendTx and sendTxBatch REST endpoints, or json/sendTx and json/sendTxBatch types via Websocket. Creating an API key is required to sign transactions.
Orders that have the correct syntax will be accepted by the API servers, returning code=200. This does not guarantee the execution of your order, as the sequencer could still reject it if parameters are not set properly. To monitor orders execution, you can use websocket channels.
Sign Transactions
Every transaction needs to be signed using the SignerClient. Using the Python SDK, you can initialize it as follows:
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.
Handle Nonces
When signing a transaction, you may need to provide a nonce (number used once). 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. If the transaction throws an error at the API server level, nonce will not increase. But if the syntax is correct and order is only later rejected by the Sequencer (say, because the price was set incorrectly), the order is cancelled and the nonce increases regardless - this holds true except for a few edge cases e.g. when the order isn't executed by the sequencer before the ExpiredAt timestamps. One peculiarity is that maker orders with correct syntax can still fail at the API level if some conditions aren't met (e.g. not enough margin), resulting in nonce not increasing, while taker orders will go through regardless as long as the syntax is correct, and only fail at the sequencer level - increasing the nonce.
Handle price and size
To correctly handle decimals for both price and size, you can refer to the orderBooks and orderBookDetails endpoints. The number of decimals indicates the number of zeros you'll need to use in order to specify a whole unit (e.g. to buy a whole Ethereum coin where supported_size_decimals is 4, you will need to specify size equal to 1*10^4). Additionally, those same endpoints will offer guidance on the minimum base amount and the minimum quota amount. The former indicates the minimum amount you can trade in coin terms, while the latter indicates it using the quote asset (so, USDC). The highest of the two is applied. Note that those minimums only apply to maker orders.
As for prices, note that when specifying a price for a taker order, that is to be interpreted as the worst price you're willing to accept - if the sequencer cannot offer you an equal or better price, the order is cancelled. Additionally, when handling TP/SL orders, you should be mindful that, besides a trigger price, you should indicate a price as well, which indicates the allowed slippage for the execution of said order, with the same logic used for taker orders above.
Handle Client Order Index, and Order Index
When signing new orders, you can specify a client_order_index (uint48) allowing you to better reference your trades. Sometimes, e.g. in cancels, you may see order_index instead as an argument - this is fine and you can use the same value here. If client_order_index is missing (e.g. if you trade from the front-end, that'll be 0), you can use trade_id (assigned by the exchange) to reference the order.
Order types
- ORDER_TYPE_LIMIT (0)
- ORDER_TYPE_MARKET (1)
- ORDER_TYPE_STOP_LOSS (2)
- ORDER_TYPE_STOP_LOSS_LIMIT (3)
- ORDER_TYPE_TAKE_PROFIT (4)
- ORDER_TYPE_TAKE_PROFIT_LIMIT (5)
- ORDER_TYPE_TWAP (6)
Additionally, there are two internal order types:
- TWAPSubOrder (7)
- LiquidationOrder (8)
Time in force
- ORDER_TIME_IN_FORCE_IMMEDIATE_OR_CANCEL (0)
- ORDER_TIME_IN_FORCE_GOOD_TILL_TIME (1)
- ORDER_TIME_IN_FORCE_POST_ONLY (2)
Order types, time in force, and other types of transactions are specified on signer_client.py in the Python SDK, and in constants.go in the GO SDK.
Updated 29 days ago