docs: 更新 lighter-python-main 文档,添加示例代码和 API 说明,重构部分内容以提高可读性

This commit is contained in:
discountry
2025-09-30 18:35:14 +08:00
parent d6533733c9
commit e83bdfccf9
337 changed files with 50410 additions and 0 deletions
@@ -0,0 +1,24 @@
## Setup steps for testnet
- Go to https://testnet.app.lighter.xyz/ and connect a wallet to receive $500
- run `system_setup.py` with the correct ETH Private key configured
- set an API key index which is not 0, so you won't override the one used by [app.lighter.xyz](https://app.lighter.xyz/)
- this will require you to enter your Ethereum private key
- the eth private key will only be used in the Py SDK to sign a message
- the eth private key is not required in order to trade on the platform
- the eth private key is not passed to the binary
- copy the output of the script and post it into `create_cancel_order.py`
- the output should look like
```
BASE_URL = 'https://testnet.zklighter.elliot.ai'
API_KEY_PRIVATE_KEY = '0xea5d2eca5be67eca056752eaf27b173518b8a5550117c09d2b58c7ea7d306cc4426f913ccf27ab19'
ACCOUNT_INDEX = 595
API_KEY_INDEX = 1
```
- start trading using
- `create_cancel_order.py` has an example which created an order on testnet & cancels it
- you'll need to set up both your account index, api key index & API Key private key
## Setup steps for mainnet
- deposit money on Lighter to create an account first
- change the URL to `mainnet.zklighter.elliot.ai`
- repeat setup step
@@ -0,0 +1,70 @@
import asyncio
import logging
import lighter
logging.basicConfig(level=logging.DEBUG)
# The API_KEY_PRIVATE_KEY provided belongs to a dummy account registered on Testnet.
# It was generated using the setup_system.py script, and servers as an example.
# Alternatively, you can go to https://app.lighter.xyz/apikeys for mainnet api keys
BASE_URL = "https://testnet.zklighter.elliot.ai"
API_KEY_PRIVATE_KEY = "0xed636277f3753b6c0275f7a28c2678a7f3a95655e09deaebec15179b50c5da7f903152e50f594f7b"
ACCOUNT_INDEX = 65
API_KEY_INDEX = 1
def trim_exception(e: Exception) -> str:
return str(e).strip().split("\n")[-1]
async def main():
api_client = lighter.ApiClient(configuration=lighter.Configuration(host=BASE_URL))
client = lighter.SignerClient(
url=BASE_URL,
private_key=API_KEY_PRIVATE_KEY,
account_index=ACCOUNT_INDEX,
api_key_index=API_KEY_INDEX,
)
err = client.check_client()
if err is not None:
print(f"CheckClient error: {trim_exception(err)}")
return
# create order
tx, tx_hash, err = await client.create_order(
market_index=0,
client_order_index=123,
base_amount=100000,
price=405000,
is_ask=True,
order_type=lighter.SignerClient.ORDER_TYPE_LIMIT,
time_in_force=lighter.SignerClient.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
reduce_only=0,
trigger_price=0,
)
print(f"Create Order {tx=} {tx_hash=} {err=}")
if err is not None:
raise Exception(err)
auth, err = client.create_auth_token_with_expiry(lighter.SignerClient.DEFAULT_10_MIN_AUTH_EXPIRY)
print(f"{auth=}")
if err is not None:
raise Exception(err)
# cancel order
tx, tx_hash, err = await client.cancel_order(
market_index=0,
order_index=123,
)
print(f"Cancel Order {tx=} {tx_hash=} {err=}")
if err is not None:
raise Exception(err)
await client.close()
await api_client.close()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,39 @@
import asyncio
import logging
import lighter
logging.basicConfig(level=logging.DEBUG)
# The API_KEY_PRIVATE_KEY provided belongs to a dummy account registered on Testnet.
# It was generated using the setup_system.py script, and serves as an example.
BASE_URL = "https://testnet.zklighter.elliot.ai"
API_KEY_PRIVATE_KEY = "0xed636277f3753b6c0275f7a28c2678a7f3a95655e09deaebec15179b50c5da7f903152e50f594f7b"
ACCOUNT_INDEX = 65
API_KEY_INDEX = 3
def trim_exception(e: Exception) -> str:
return str(e).strip().split("\n")[-1]
async def main():
client = lighter.SignerClient(
url=BASE_URL,
private_key=API_KEY_PRIVATE_KEY,
account_index=ACCOUNT_INDEX,
api_key_index=API_KEY_INDEX,
)
tx = await client.create_market_order(
market_index=0,
client_order_index=0,
base_amount=1000, # 0.1 ETH
avg_execution_price=170000, # $1700 -- worst acceptable price for the order
is_ask=True,
)
print("Create Order Tx:", tx)
await client.close()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,36 @@
import asyncio
import logging
import lighter
logging.basicConfig(level=logging.DEBUG)
# The API_KEY_PRIVATE_KEY provided belongs to a dummy account registered on Testnet.
# It was generated using the setup_system.py script, and serves as an example.
BASE_URL = "https://testnet.zklighter.elliot.ai"
API_KEY_PRIVATE_KEY = "0xe0fa55e11d6b5575d54c0500bd2f3b240221ae90241e3b573f2307e27de20c04ea628de3f1936e56"
ACCOUNT_INDEX = 22
API_KEY_INDEX = 3
def trim_exception(e: Exception) -> str:
return str(e).strip().split("\n")[-1]
async def main():
client = lighter.SignerClient(
url=BASE_URL,
private_key=API_KEY_PRIVATE_KEY,
account_index=ACCOUNT_INDEX,
api_key_index=API_KEY_INDEX,
)
# tx = await client.create_market_order_limited_slippage(market_index=0, client_order_index=0, base_amount=30000000,
# max_slippage=0.001, is_ask=True)
tx = await client.create_market_order_if_slippage(market_index=0, client_order_index=0, base_amount=30000000,
max_slippage=0.01, is_ask=True, ideal_price=300000)
print("Create Order Tx:", tx)
await client.close()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,70 @@
import asyncio
import logging
import lighter
logging.basicConfig(level=logging.DEBUG)
# The API_KEY_PRIVATE_KEY provided belongs to a dummy account registered on Testnet.
# It was generated using the setup_system.py script, and servers as an example.
BASE_URL = "https://testnet.zklighter.elliot.ai"
API_KEY_PRIVATE_KEY = "0xe0fa55e11d6b5575d54c0500bd2f3b240221ae90241e3b573f2307e27de20c04ea628de3f1936e56"
ACCOUNT_INDEX = 22
API_KEY_INDEX = 3
def trim_exception(e: Exception) -> str:
return str(e).strip().split("\n")[-1]
async def main():
client = lighter.SignerClient(
url=BASE_URL,
private_key=API_KEY_PRIVATE_KEY,
account_index=ACCOUNT_INDEX,
api_key_index=API_KEY_INDEX,
)
tx = await client.create_tp_order(
market_index=0,
client_order_index=0,
base_amount=1000, # 0.1 ETH
trigger_price=500000,
price=500000,
is_ask=False
)
print("Create Order Tx:", tx)
tx = await client.create_sl_order(
market_index=0,
client_order_index=0,
base_amount=1000, # 0.1 ETH
trigger_price=500000,
price=500000,
is_ask=False
)
print("Create Order Tx:", tx)
tx = await client.create_tp_limit_order(
market_index=0,
client_order_index=0,
base_amount=1000, # 0.1 ETH
trigger_price=500000,
price=500000,
is_ask=False
)
tx = await client.create_sl_limit_order(
market_index=0,
client_order_index=0,
base_amount=1000, # 0.1 ETH
trigger_price=500000,
price=500000,
is_ask=False
)
print("Create Order Tx:", tx)
await client.close()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,48 @@
import asyncio
import lighter
BASE_URL = "https://testnet.zklighter.elliot.ai"
# use examples/system_setup.py or the apikeys page (for mainnet) to generate new api keys
KEYS = {
5: "API_PRIVATE_KEY_5",
6: "API_PRIVATE_KEY_6",
7: "API_PRIVATE_KEY_7",
}
ACCOUNT_INDEX = 100 # replace with your account_index
async def main():
client = lighter.SignerClient(
url=BASE_URL,
private_key=KEYS[5],
account_index=ACCOUNT_INDEX,
api_key_index=5,
max_api_key_index=7,
private_keys=KEYS,
)
err = client.check_client()
if err is not None:
print(f"CheckClient error: {err}")
return
for i in range(20):
res_tuple = await client.create_order(
market_index=0,
client_order_index=123 + i,
base_amount=100000 + i,
price=385000 + i,
is_ask=True,
order_type=lighter.SignerClient.ORDER_TYPE_LIMIT,
time_in_force=lighter.SignerClient.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
reduce_only=0,
trigger_price=0,
)
print(res_tuple)
await client.cancel_all_orders(time_in_force=client.CANCEL_ALL_TIF_IMMEDIATE, time=0)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,91 @@
import asyncio
import datetime
import lighter
import logging
logging.basicConfig(level=logging.INFO)
# The address provided belongs to a dummy account registered on Testnet.
L1_ADDRESS = "0x8D7f03FdE1A626223364E592740a233b72395235"
ACCOUNT_INDEX = 65
async def print_api(method, *args, **kwargs):
logging.info(f"{method.__name__}: {await method(*args, **kwargs)}")
async def account_apis(client: lighter.ApiClient):
logging.info("ACCOUNT APIS")
account_instance = lighter.AccountApi(client)
await print_api(account_instance.account, by="l1_address", value=L1_ADDRESS)
await print_api(account_instance.account, by="index", value=str(ACCOUNT_INDEX))
await print_api(account_instance.accounts_by_l1_address, l1_address=L1_ADDRESS)
await print_api(account_instance.apikeys, account_index=ACCOUNT_INDEX, api_key_index=1)
await print_api(account_instance.public_pools, filter="all", limit=1, index=0)
async def block_apis(client: lighter.ApiClient):
logging.info("BLOCK APIS")
block_instance = lighter.BlockApi(client)
await print_api(block_instance.block, by="height", value="1")
await print_api(block_instance.blocks, index=0, limit=2, sort="asc")
await print_api(block_instance.current_height)
async def candlestick_apis(client: lighter.ApiClient):
logging.info("CANDLESTICK APIS")
candlestick_instance = lighter.CandlestickApi(client)
await print_api(
candlestick_instance.candlesticks,
market_id=0,
resolution="1h",
start_timestamp=int(datetime.datetime.now().timestamp() - 60 * 60 * 24),
end_timestamp=int(datetime.datetime.now().timestamp()),
count_back=2,
)
await print_api(
candlestick_instance.fundings,
market_id=0,
resolution="1h",
start_timestamp=int(datetime.datetime.now().timestamp() - 60 * 60 * 24),
end_timestamp=int(datetime.datetime.now().timestamp()),
count_back=2,
)
async def order_apis(client: lighter.ApiClient):
logging.info("ORDER APIS")
order_instance = lighter.OrderApi(client)
await print_api(order_instance.exchange_stats)
await print_api(order_instance.order_book_details, market_id=0)
await print_api(order_instance.order_books)
await print_api(order_instance.recent_trades, market_id=0, limit=2)
async def transaction_apis(client: lighter.ApiClient):
logging.info("TRANSACTION APIS")
transaction_instance = lighter.TransactionApi(client)
await print_api(transaction_instance.block_txs, by="block_height", value="1")
await print_api(
transaction_instance.next_nonce,
account_index=int(ACCOUNT_INDEX),
api_key_index=0,
)
# use with a valid sequence index
# await print_api(transaction_instance.tx, by="sequence_index", value="5")
await print_api(transaction_instance.txs, index=0, limit=2)
async def main():
client = lighter.ApiClient(configuration=lighter.Configuration(host="https://testnet.zklighter.elliot.ai"))
await account_apis(client)
await block_apis(client)
await candlestick_apis(client)
await order_apis(client)
await transaction_apis(client)
await client.close()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,138 @@
import asyncio
import logging
import lighter
import json
logging.basicConfig(level=logging.DEBUG)
# The API_KEY_PRIVATE_KEY provided belongs to a dummy account registered on Testnet.
# It was generated using the setup_system.py script, and servers as an example.
BASE_URL = "https://testnet.zklighter.elliot.ai"
API_KEY_PRIVATE_KEY = "0xed636277f3753b6c0275f7a28c2678a7f3a95655e09deaebec15179b50c5da7f903152e50f594f7b"
ACCOUNT_INDEX = 65
API_KEY_INDEX = 1
def trim_exception(e: Exception) -> str:
return str(e).strip().split("\n")[-1]
async def main():
# Initialize configuration and clients
configuration = lighter.Configuration(BASE_URL)
api_client = lighter.ApiClient(configuration)
transaction_api = lighter.TransactionApi(api_client)
# Initialize signer client
client = lighter.SignerClient(
url=BASE_URL,
private_key=API_KEY_PRIVATE_KEY,
account_index=ACCOUNT_INDEX,
api_key_index=API_KEY_INDEX
)
# Check client connection
err = client.check_client()
if err is not None:
print(f"CheckClient error: {trim_exception(err)}")
return
# use next nonce for getting nonces
next_nonce = await transaction_api.next_nonce(account_index=ACCOUNT_INDEX, api_key_index=API_KEY_INDEX)
nonce_value = next_nonce.nonce
ask_tx_info, error = client.sign_create_order(
market_index=0,
client_order_index=1001, # Unique identifier for this order
base_amount=100000,
price=280000,
is_ask=True,
order_type=client.ORDER_TYPE_LIMIT,
time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
reduce_only=False,
trigger_price=0,
nonce=nonce_value
)
nonce_value += 1
if error is not None:
print(f"Error signing first order (first batch): {trim_exception(error)}")
return
# Sign second order
bid_tx_info, error = client.sign_create_order(
market_index=0,
client_order_index=1002, # Different unique identifier
base_amount=200000,
price=200000,
is_ask=False,
order_type=client.ORDER_TYPE_LIMIT,
time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
reduce_only=False,
trigger_price=0,
nonce=nonce_value
)
nonce_value += 1
if error is not None:
print(f"Error signing second order (first batch): {trim_exception(error)}")
return
tx_types = json.dumps([client.TX_TYPE_CREATE_ORDER, client.TX_TYPE_CREATE_ORDER])
tx_infos = json.dumps([ask_tx_info, bid_tx_info])
try:
tx_hashes = await transaction_api.send_tx_batch(tx_types=tx_types, tx_infos=tx_infos)
print(f"Batch transaction successful: {tx_hashes}")
except Exception as e:
print(f"Error sending batch transaction: {trim_exception(e)}")
# In case we want to see the changes in the UI, sleep a bit
import time
time.sleep(5)
cancel_tx_info, error = client.sign_cancel_order(
market_index=0,
order_index=1001, # the index of the order we want cancelled
nonce=nonce_value
)
nonce_value += 1
if error is not None:
print(f"Error signing first order (second batch): {trim_exception(error)}")
return
# Sign second order
new_ask_tx_info, error = client.sign_create_order(
market_index=0,
client_order_index=1003, # Different unique identifier
base_amount=300000,
price=310000,
is_ask=True,
order_type=client.ORDER_TYPE_LIMIT,
time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
reduce_only=False,
trigger_price=0,
nonce=nonce_value
)
nonce_value += 1
if error is not None:
print(f"Error signing second order (second batch): {trim_exception(error)}")
return
tx_types = json.dumps([client.TX_TYPE_CANCEL_ORDER, client.TX_TYPE_CREATE_ORDER])
tx_infos = json.dumps([cancel_tx_info, new_ask_tx_info])
try:
tx_hashes = await transaction_api.send_tx_batch(tx_types=tx_types, tx_infos=tx_infos)
print(f"Batch 2 transaction successful: {tx_hashes}")
except Exception as e:
print(f"Error sending batch transaction 2: {trim_exception(e)}")
# Clean up
await client.close()
await api_client.close()
# Run the async main function
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,86 @@
import asyncio
import logging
import time
import eth_account
import lighter
logging.basicConfig(level=logging.DEBUG)
# this is a dummy private key which is registered on Testnet.
# It serves as a good example
BASE_URL = "https://testnet.zklighter.elliot.ai"
ETH_PRIVATE_KEY = "1234567812345678123456781234567812345678123456781234567812345678"
API_KEY_INDEX = 3
async def main():
# verify that the account exists & fetch account index
api_client = lighter.ApiClient(configuration=lighter.Configuration(host=BASE_URL))
eth_acc = eth_account.Account.from_key(ETH_PRIVATE_KEY)
eth_address = eth_acc.address
try:
response = await lighter.AccountApi(api_client).accounts_by_l1_address(
l1_address=eth_address
)
except lighter.ApiException as e:
if e.data.message == "account not found":
print(f"error: account not found for {eth_address}")
return
else:
raise e
if len(response.sub_accounts) > 1:
for sub_account in response.sub_accounts:
print(f"found accountIndex: {sub_account.index}")
print("multiple accounts found, using the first one")
account_index = response.sub_accounts[0].index
else:
account_index = response.sub_accounts[0].index
# create a private/public key pair for the new API key
# pass any string to be used as seed for create_api_key like
# create_api_key("Hello world random seed to make things more secure")
private_key, public_key, err = lighter.create_api_key()
if err is not None:
raise Exception(err)
tx_client = lighter.SignerClient(
url=BASE_URL,
private_key=private_key,
account_index=account_index,
api_key_index=API_KEY_INDEX,
)
# change the API key
response, err = await tx_client.change_api_key(
eth_private_key=ETH_PRIVATE_KEY,
new_pubkey=public_key,
)
if err is not None:
raise Exception(err)
# wait some time so that we receive the new API key in the response
time.sleep(10)
# check that the API key changed on the server
err = tx_client.check_client()
if err is not None:
raise Exception(err)
print(
f"""
BASE_URL = '{BASE_URL}'
API_KEY_PRIVATE_KEY = '{private_key}'
ACCOUNT_INDEX = {account_index}
API_KEY_INDEX = {API_KEY_INDEX}
"""
)
await tx_client.close()
await api_client.close()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,47 @@
import asyncio
import lighter
from examples.secrets import BASE_URL, API_KEY_PRIVATE_KEY, ETH_PRIVATE_KEY
API_KEY_INDEX = 10
TO_ACCOUNT_INDEX = 9
ACCOUNT_INDEX = 10 # replace with your account_index
async def main():
client = lighter.SignerClient(
url=BASE_URL,
private_key=API_KEY_PRIVATE_KEY,
account_index=ACCOUNT_INDEX,
api_key_index=API_KEY_INDEX,
)
api_client = lighter.ApiClient(configuration=lighter.Configuration(host=BASE_URL))
info_api = lighter.InfoApi(api_client)
order_api = lighter.OrderApi(api_client)
auth_token, _ = client.create_auth_token_with_expiry()
fee_info = await info_api.transfer_fee_info(ACCOUNT_INDEX, authorization=auth_token, auth=auth_token, to_account_index=TO_ACCOUNT_INDEX)
print(fee_info)
err = client.check_client()
if err is not None:
print(f"CheckClient error: {err}")
return
memo = "a"*32 # memo is a user message and it has to be exactly 32 bytes long
transfer_tx, response, err = await client.transfer(
ETH_PRIVATE_KEY,
usdc_amount=100, # decimals are added by sdk
to_account_index=TO_ACCOUNT_INDEX,
fee=fee_info.transfer_fee_usdc,
memo=memo,
)
if err != None:
raise Exception(f"error transferring {err}")
print(transfer_tx, response)
lev_tx, response, err = await client.update_leverage(4, client.CROSS_MARGIN_MODE, 3)
print(lev_tx, response, err)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,23 @@
import json
import logging
import lighter
logging.basicConfig(level=logging.INFO)
def on_order_book_update(market_id, order_book):
logging.info(f"Order book {market_id}:\n{json.dumps(order_book, indent=2)}")
def on_account_update(account_id, account):
logging.info(f"Account {account_id}:\n{json.dumps(account, indent=2)}")
client = lighter.WsClient(
order_book_ids=[0, 1],
account_ids=[1, 2],
on_order_book_update=on_order_book_update,
on_account_update=on_account_update,
)
client.run()
@@ -0,0 +1,24 @@
import json
import logging
import asyncio
import lighter
logging.basicConfig(level=logging.INFO)
def on_order_book_update(market_id, order_book):
logging.info(f"Order book {market_id}:\n{json.dumps(order_book, indent=2)}")
def on_account_update(account_id, account):
logging.info(f"Account {account_id}:\n{json.dumps(account, indent=2)}")
client = lighter.WsClient(
order_book_ids=[0, 1],
account_ids=[1, 2],
on_order_book_update=on_order_book_update,
on_account_update=on_account_update,
)
asyncio.run(client.run_async())
@@ -0,0 +1,101 @@
import lighter
import json
import websockets
import asyncio
# The API_KEY_PRIVATE_KEY provided belongs to a dummy account registered on Testnet.
# It was generated using the setup_system.py script, and servers as an example.
# Alternatively, you can go to https://app.lighter.xyz/apikeys for mainnet api keys
BASE_URL = "https://testnet.zklighter.elliot.ai"
API_KEY_PRIVATE_KEY = (
"0xed636277f3753b6c0275f7a28c2678a7f3a95655e09deaebec15179b50c5da7f903152e50f594f7b"
)
ACCOUNT_INDEX = 65
API_KEY_INDEX = 1
async def ws_flow(tx_types, tx_infos):
async with websockets.connect(f"{BASE_URL.replace('https', 'wss')}/stream") as ws:
msg = await ws.recv()
print("Received:", msg)
await ws.send(
json.dumps(
{
"type": "jsonapi/sendtxbatch",
"data": {
"id": f"my_random_batch_id_{12345678}", # optional, helps id the response
"tx_types": json.dumps(tx_types),
"tx_infos": json.dumps(tx_infos),
},
}
)
)
print("Response:", await ws.recv())
async def main():
client = lighter.SignerClient(
url=BASE_URL,
private_key=API_KEY_PRIVATE_KEY,
account_index=ACCOUNT_INDEX,
api_key_index=API_KEY_INDEX,
)
configuration = lighter.Configuration(BASE_URL)
api_client = lighter.ApiClient(configuration)
transaction_api = lighter.TransactionApi(api_client)
# use next nonce for getting nonces
next_nonce = await transaction_api.next_nonce(
account_index=ACCOUNT_INDEX, api_key_index=API_KEY_INDEX
)
nonce_value = next_nonce.nonce
ask_tx_info, error = client.sign_create_order(
market_index=0,
client_order_index=1001, # Unique identifier for this order
base_amount=100000,
price=280000,
is_ask=True,
order_type=client.ORDER_TYPE_LIMIT,
time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
reduce_only=False,
trigger_price=0,
nonce=nonce_value,
)
nonce_value += 1
if error is not None:
print(f"Error signing first order (first batch): {error}")
return
# Sign second order
bid_tx_info, error = client.sign_create_order(
market_index=0,
client_order_index=1002, # Different unique identifier
base_amount=200000,
price=200000,
is_ask=False,
order_type=client.ORDER_TYPE_LIMIT,
time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
reduce_only=False,
trigger_price=0,
nonce=nonce_value,
)
if error is not None:
print(f"Error signing second order (first batch): {error}")
return
tx_types = [
lighter.SignerClient.TX_TYPE_CREATE_ORDER,
lighter.SignerClient.TX_TYPE_CREATE_ORDER,
]
tx_infos = [ask_tx_info, bid_tx_info]
await ws_flow(tx_types, tx_infos)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,74 @@
import lighter
import json
import websockets
import asyncio
# The API_KEY_PRIVATE_KEY provided belongs to a dummy account registered on Testnet.
# It was generated using the setup_system.py script, and servers as an example.
# Alternatively, you can go to https://app.lighter.xyz/apikeys for mainnet api keys
BASE_URL = "https://testnet.zklighter.elliot.ai"
API_KEY_PRIVATE_KEY = (
"0xed636277f3753b6c0275f7a28c2678a7f3a95655e09deaebec15179b50c5da7f903152e50f594f7b"
)
ACCOUNT_INDEX = 65
API_KEY_INDEX = 3
async def ws_flow(tx_type, tx_info):
async with websockets.connect(f"{BASE_URL.replace('https', 'wss')}/stream") as ws:
msg = await ws.recv()
print("Received:", msg)
await ws.send(
json.dumps(
{
"type": "jsonapi/sendtx",
"data": {
"id": f"my_random_id_{12345678}", # optional, helps id the response
"tx_type": tx_type,
"tx_info": json.loads(tx_info),
},
}
)
)
print("Response:", await ws.recv())
async def main():
client = lighter.SignerClient(
url=BASE_URL,
private_key=API_KEY_PRIVATE_KEY,
account_index=ACCOUNT_INDEX,
api_key_index=API_KEY_INDEX,
)
configuration = lighter.Configuration(BASE_URL)
api_client = lighter.ApiClient(configuration)
transaction_api = lighter.TransactionApi(api_client)
next_nonce = await transaction_api.next_nonce(
account_index=ACCOUNT_INDEX, api_key_index=API_KEY_INDEX
)
nonce_value = next_nonce.nonce
tx_info, error = client.sign_create_order(
market_index=0,
client_order_index=1002, # Different unique identifier
base_amount=200000,
price=200000,
is_ask=False,
order_type=client.ORDER_TYPE_LIMIT,
time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
reduce_only=False,
trigger_price=0,
nonce=nonce_value,
)
if error is not None:
print(f"Error signing order: {error}")
return
await ws_flow(lighter.SignerClient.TX_TYPE_CREATE_ORDER, tx_info)
if __name__ == "__main__":
asyncio.run(main())