Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
0feac91
add starknet order signing
ex10ded Apr 16, 2025
31a2e90
Merge remote-tracking branch 'origin/main' into starknet
ex10ded Apr 16, 2025
ba08fc2
fix merge conflicts
ex10ded Apr 16, 2025
e2eb461
update lockfile
ex10ded Apr 16, 2025
9dbefda
fix linting
ex10ded Apr 16, 2025
b6bc150
fix linter II
ex10ded Apr 16, 2025
5c0f684
update README windows support for rust library
ex10ded Apr 16, 2025
32847b3
tidy up for starknet
ex10ded May 23, 2025
aba727c
review comments I
ex10ded May 27, 2025
1b11e15
review comments II
ex10ded May 27, 2025
d9f6b57
review comments III
ex10ded May 27, 2025
f737522
fix linter
ex10ded May 27, 2025
c813aa8
Merge pull request #40 from x10xchange/starknet_tidy_up
ex10ded May 28, 2025
b61ef40
prepare for 0.0.1 release
ex10ded May 29, 2025
bd2bfc1
Merge pull request #41 from x10xchange/starknet_tidy_up
ex10ded May 29, 2025
a77c41f
add tenacity to dependency list
ex10ded Jun 12, 2025
2d9fca5
fix linter
ex10ded Jun 12, 2025
d353ac8
fix test runner
ex10ded Jun 12, 2025
13f061d
Fixed asset id in transfer settlement
sergeibulavintsev Jun 12, 2025
9cbbb58
Fixed asset id in transfer settlement
sergeibulavintsev Jun 12, 2025
3618c8d
Merge pull request #42 from x10xchange/fixed-transfer-settlement
ex10ded Jun 12, 2025
9166876
fix transfer asset used for hash calculation
ex10ded Jun 12, 2025
93886ae
fix transfer tests
ex10ded Jun 12, 2025
bef1dbf
bump version
ex10ded Jun 12, 2025
d8b41fb
add stupid market maker
ex10ded Jun 12, 2025
6cccd0a
Fix positions history & candles optional fields definition (#44)
alexex10 Jun 23, 2025
f8dbee0
Merge pull request #45 from x10xchange/fix-candles-positions-history-…
ex10ded Jun 23, 2025
5608c38
add example liquidity script
ex10ded Jun 19, 2025
c606bc7
remove async constructor
ex10ded Jul 15, 2025
1e7039f
Merge pull request #46 from x10xchange/add_simple_liquidity_bot
ex10ded Jul 15, 2025
913bf17
bump version
ex10ded Jul 15, 2025
e145571
add withdrawal functionality
ex10ded Jul 30, 2025
db515a2
Merge branch 'main' into starknet
ex10ded Jul 30, 2025
2e24d4e
fix linter
ex10ded Jul 30, 2025
ff7bb6d
Merge remote-tracking branch 'origin/starknet' into starknet
ex10ded Jul 30, 2025
3626a56
fix price rounding
ex10ded Aug 6, 2025
19d3c1d
Update README.md
ex10ded Aug 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,6 @@ format:
black --target-version py310 --line-length 120 ./examples ./tests ./x10

lint:
safety check \
-i 51457 \
-i 64227 \
-i 64396 \
-i 64459 \
-i 64642 \
-i 65693 \
-i 66742 \
-i 67599 \
-i 67895 \
-i 70612 \
-i 70630 \
-i 71064 \
-i 71545 \
-i 71591 \
-i 71608 \
-i 73456 \
-i 74251 \
-i 76752
black --check --diff --target-version py310 --line-length 120 ./examples ./tests ./x10
flake8 ./examples ./tests ./x10
mypy
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Minimum Python version required to use this library is `3.10` (you can use [pyen
## Installation

```shell
pip install x10-python-trading
pip install x10-python-trading-starknet
```

Our SDK makes use of a [Rust Library](https://github.com/x10xchange/stark-crypto-wrapper) to accelerate signing and hashing of stark components. Currently this library supports the following environments
Expand All @@ -19,7 +19,7 @@ Our SDK makes use of a [Rust Library](https://github.com/x10xchange/stark-crypto
| linux (glibc) - arm64 | ✅ | ✅ | ✅ | ✅ |
| linux (musl) - arm64 | ✅ | ✅ | ✅ | ✅ |
| OSX - arm64 | ✅ | ✅ | ✅ | ✅ |
| windows - x86 | ⚠️ | ⚠️ | ⚠️ | ⚠️ |
| windows - x86 | | | | |
| windows - arm64 | ⚠️ | ⚠️ | ⚠️ | ⚠️ |


Expand Down
117 changes: 117 additions & 0 deletions examples/market_maker_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import asyncio
import math
from decimal import Decimal

from eth_account import Account
from eth_account.signers.local import LocalAccount

from x10.perpetual.accounts import StarkPerpetualAccount
from x10.perpetual.configuration import STARKNET_TESTNET_CONFIG
from x10.perpetual.orders import OrderSide
from x10.perpetual.trading_client.trading_client import PerpetualTradingClient
from x10.perpetual.user_client.user_client import UserClient


async def build_markets_cache(trading_client: PerpetualTradingClient):
markets = await trading_client.markets_info.get_markets()
assert markets.data is not None
return {m.name: m for m in markets.data}


# flake8: noqa
async def on_board_example():
environment_config = STARKNET_TESTNET_CONFIG
eth_account_1: LocalAccount = Account.from_key("<YOUR_ETH_PRIVATE_KEY>")
onboarding_client = UserClient(endpoint_config=environment_config, l1_private_key=eth_account_1.key.hex)
root_account = await onboarding_client.onboard()

trading_key = await onboarding_client.create_account_api_key(root_account.account, "trading_key")

root_trading_client = PerpetualTradingClient(
environment_config,
StarkPerpetualAccount(
vault=root_account.account.l2_vault,
private_key=root_account.l2_key_pair.private_hex,
public_key=root_account.l2_key_pair.public_hex,
api_key=trading_key,
),
)

print(f"User 1 v: {root_account.account.l2_vault}")
print(f"User 1 pub: {root_account.l2_key_pair.public_hex}")
print(f"User 1 priv: {root_account.l2_key_pair.private_hex}")

while True:
markets = await build_markets_cache(root_trading_client)
try:
for market in markets.values():
print(f"Market: {market.name}")
price_offset = (Decimal(hash(market.name) % 3 - 1) / Decimal(100)) * Decimal(1)
await root_trading_client.orders.mass_cancel(
markets=[market.name],
)

if "BTC" not in market.name: # Example for a specific market
print(f"Skipping {market.name} market")
continue

mark_price = market.market_stats.mark_price
print(f"Mark Price: {mark_price}")
print(f"price offset: {price_offset}")
print(f"Min order size: {market.trading_config.min_order_size}")
base_target = market.trading_config.max_position_value / Decimal(1000)
sell_prices = [
(
Decimal(base_target * (i + 1)),
round(
mark_price + mark_price * Decimal((i * 0.2) / 100.0) + price_offset * mark_price,
market.trading_config.price_precision,
),
)
for i in range(10)
]
buy_prices = [
(
Decimal(base_target * (i + 1)),
round(
mark_price - mark_price * Decimal((i * 0.2) / 100.0) + price_offset * mark_price,
market.trading_config.price_precision,
),
)
for i in range(10)
]

for target_value, sell_price in sell_prices:
order_size = order_size = market.trading_config.calculate_order_size_from_value(
order_value=target_value, order_price=sell_price
)
print(f"Sell Price: {sell_price}, order size: {order_size}")
try:
order_response_1 = await root_trading_client.place_order(
market_name=market.name,
amount_of_synthetic=order_size,
price=sell_price,
side=OrderSide.SELL,
)
except Exception as e:
print(f"Error: {e}")
for target_value, buy_price in buy_prices:
order_size = market.trading_config.calculate_order_size_from_value(
order_value=target_value, order_price=buy_price
)
print(f"Buy Price: {buy_price}, order size: {order_size}")
try:
order_response_2 = await root_trading_client.place_order(
market_name=market.name,
amount_of_synthetic=order_size,
price=buy_price,
side=OrderSide.BUY,
)
except Exception as e:
print(f"Error: {e}")
await asyncio.sleep(30)
except Exception as e:
print(f"Error: {e}")


asyncio.run(on_board_example())
76 changes: 19 additions & 57 deletions examples/onboarding_example.py
Original file line number Diff line number Diff line change
@@ -1,79 +1,41 @@
import asyncio
from decimal import Decimal

from eth_account import Account
from eth_account.signers.local import LocalAccount

from x10.perpetual.accounts import StarkPerpetualAccount
from x10.perpetual.assets import AssetOperationType
from x10.perpetual.configuration import TESTNET_CONFIG
from x10.perpetual.contract import call_erc20_approve, call_stark_perpetual_deposit
from x10.perpetual.configuration import STARKNET_TESTNET_CONFIG
from x10.perpetual.trading_client.trading_client import PerpetualTradingClient
from x10.perpetual.user_client.user_client import UserClient


# flake8: noqa
async def on_board_example():
environment_config = TESTNET_CONFIG
eth_account: LocalAccount = Account.from_key("<your private key>")
user_client = UserClient(endpoint_config=environment_config, l1_private_key=eth_account.key.hex)
onboarded_user = await user_client.onboard()
sub_account_1 = await user_client.onboard_subaccount(1, "sub account 1")
environment_config = STARKNET_TESTNET_CONFIG
eth_account_1: LocalAccount = Account.from_key("YOUR_ETH_PRIVATE_KEY")
onboarding_client = UserClient(endpoint_config=environment_config, l1_private_key=eth_account_1.key.hex)
root_account = await onboarding_client.onboard()

default_api_key = await user_client.create_account_api_key(onboarded_user.account, "trading api key")
account_1_api_key = await user_client.create_account_api_key(sub_account_1.account, "sub account 1 api key")
trading_key = await onboarding_client.create_account_api_key(root_account.account, "trading_key")

default_account_trading_client = PerpetualTradingClient(
root_trading_client = PerpetualTradingClient(
environment_config,
StarkPerpetualAccount(
vault=onboarded_user.account.l2_vault,
private_key=onboarded_user.l2_key_pair.private_hex,
public_key=onboarded_user.l2_key_pair.public_hex,
api_key=default_api_key,
vault=root_account.account.l2_vault,
private_key=root_account.l2_key_pair.private_hex,
public_key=root_account.l2_key_pair.public_hex,
api_key=trading_key,
),
)

sub_account_1_trading_client = PerpetualTradingClient(
environment_config,
StarkPerpetualAccount(
vault=sub_account_1.account.l2_vault,
private_key=sub_account_1.l2_key_pair.private_hex,
public_key=sub_account_1.l2_key_pair.public_hex,
api_key=account_1_api_key,
),
)

call_erc20_approve(
human_readable_amount=Decimal("1000"), get_eth_private_key=eth_account.key.hex, config=environment_config
)

await default_account_trading_client.account.deposit(
human_readable_amount=Decimal("1000"),
get_eth_private_key=eth_account.key.hex,
)

default_account_trading_client.account.transfer(
to_vault=int(sub_account_1.account.l2_vault),
to_l2_key=sub_account_1.l2_key_pair.public_hex,
amount=Decimal("10"),
)

created_withdrawal_id = await default_account_trading_client.account.slow_withdrawal(
amount=Decimal("10"),
eth_address=eth_account.address,
)

withdrawals = await default_account_trading_client.account.asset_operations(
operations_type=[AssetOperationType.SLOW_WITHDRAWAL],
)

#### wait until withdrawal is in status READY_FOR_CLAIM

available_withdrawal_balance = await user_client.available_l1_withdrawal_balance()

withdrawal_tx_hash = await user_client.perform_l1_withdrawal()
print(f"User 1 v: {root_account.account.l2_vault}")
print(f"User 1 pub: {root_account.l2_key_pair.public_hex}")
print(f"User 1 priv: {root_account.l2_key_pair.private_hex}")
claim_response = await root_trading_client.testnet.claim_testing_funds()
claim_id = claim_response.data.id if claim_response.data else None
print(f"Claim ID: {claim_id}")

print()
resp = await root_trading_client.account.asset_operations(id=claim_id)
print(f"Asset Operations: {resp.data}")


asyncio.run(on_board_example())
4 changes: 3 additions & 1 deletion examples/placed_order_example_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ async def place_order(
price = Decimal("0.660") - Decimal("0.00" + str(i)) if should_buy else Decimal("0.6601") + Decimal("0.00" + str(i))
order_side = OrderSide.BUY if should_buy else OrderSide.SELL
market = markets_cache[ADA_USD_MARKET]
new_order = create_order_object(stark_account, market, Decimal("100"), price, order_side)
new_order = create_order_object(
stark_account, market, Decimal("100"), price, order_side, starknet_domain=TESTNET_CONFIG.starknet_domain
)
order_condtions[new_order.id] = asyncio.Condition()
return new_order.id, await trading_client.orders.place_order(order=new_order)

Expand Down
5 changes: 3 additions & 2 deletions examples/simple_client_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,20 @@ async def setup_and_run():
api_key=api_key,
)

client = BlockingTradingClient(endpoint_config=TESTNET_CONFIG, account=stark_account)
client = await BlockingTradingClient.create(endpoint_config=TESTNET_CONFIG, account=stark_account)

placed_order = await client.create_and_place_order(
amount_of_synthetic=Decimal("1"),
price=Decimal("62133.6"),
market_name="BTC-USD",
side=OrderSide.BUY,
post_only=False,
external_id="test_order_123",
)

print(placed_order)

await client.cancel_order(placed_order.id)
await client.cancel_order(order_external_id=placed_order.external_id)


if __name__ == "__main__":
Expand Down
Loading
Loading