mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-09 08:18:07 +00:00
docs: 更新 lighter-python-main 文档,添加示例代码和 API 说明,重构部分内容以提高可读性
This commit is contained in:
@@ -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())
|
||||
Reference in New Issue
Block a user