Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
dYdX Python API for Limit Orders
The library is currently tested against Python versions 2.7, 3.4, 3.5, and 3.6
dydx-python
is available on PyPI. Install with pip
:
pip install dydx-python
Check the dYdX developer docs for the API endpoint.
from dydx.client import Client
import dydx.constants as consts
import dydx.util as utils
# create a new client with a private key (string or bytearray)
client = Client(
private_key='0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d',
node='https://mainnet.infura.io/v3/00000000000000000000000000000000'
)
# Get all trading pairs for dydx
pairs = client.get_pairs()
# Get my account balances of margin-trading accounts
my_balances = client.get_my_balances()
# Get my account balances of perpetual accounts
balances = client.get_my_perpetual_balances()
# Get orders created by my account for both sides of the book
my_orders = client.get_my_orders(
market=['WETH-DAI', 'DAI-WETH'],
limit=None,
startingBefore=None
)
# Get all orders for both sides of the book
ten_days_ago = datetime.datetime.now() - datetime.timedelta(days=10)
all_orders = client.get_orders(
market=['WETH-DAI', 'DAI-WETH'],
makerAccountOwner=None, # optional
makerAccountNumber=None, # optional
limit=2, # optional
startingBefore=ten_days_ago # optional
)
# Get fills created by my account for both sides of the orderbook
my_fills = client.get_my_fills(
market=['WETH-DAI', 'DAI-WETH'],
limit=None, # optional
startingBefore=None # optional
)
# Get all fills from one side of the book
all_fills = client.get_fills(
market=['WETH-DAI'], # 'DAI-WETH' side of the book is not included
makerAccountOwner='0x5F5A46a8471F60b1E9F2eD0b8fc21Ba8b48887D8', # optional
makerAccountNumber=0, # optional
limit=2, # optional
startingBefore=None # optional
)
'''
fills = {
"fills": [
{
uuid: "b53ab8c4-465f-4950-add2-dd807c048d68",
createdAt: "2020-03-08T17:42:36.037Z",
transactionHash: "0x39576745c2f030ba04bf4df7bcc64ffaa97421243c53e714bca4161163be9d51",
status: "PENDING",
market: "WETH-DAI",
side: "BUY",
feeAmount: "0",
orderClientId: null,
price: "217.019",
amount: "15000000000000000000",
orderId: "0x8924cdc0d18899d250bfa27d5929967e26e7e676745a28b6ee5b3a8f182ceb9f",
accountOwner: "0x8a9d46d28003673cd4fe7a56ecfcfa2be6372e64",
accountNumber: "63397253610709255086306580859198088914565604507660670583302927962305720029570",
liquidity: "TAKER"
},
...
]
}
'''
# Get one order by id
order = client.get_order(
orderId,
)
'''
order = {
"order" = {
"uuid": "c95c386a-307d-4fbf-bcac-a7ff965a7207",
"id": "0x812f2e71081daa820d08fa25c76c06332cd39282433679a413c03c5d4591bc35",
"clientId": "d046f4db-12a9-48fb-b413-6916a9f0cfff",
"status": "CANCELED",
"accountOwner": "0x862821badb9c5800654015ba9a2d9d7894c83a7a",
"accountNumber": "0",
"orderType": "LIMIT",
"fillOrKill": false,
"postOnly": false,
"triggerPrice": null,
"market": "WETH-DAI",
"side": "BUY",
"baseAmount": "186056800000000000000",
"quoteAmount": "39808712928000001179648",
"filledAmount": "0",
"price": "213.96",
"cancelReason": "USER_CANCELED",
"createdAt": "2020-03-08T17:35:24.694Z",
"updatedAt": "2020-03-08T17:35:25.474Z",
"expiresAt": "2020-03-08T17:55:29.000Z"
}
}
'''
# Get trades created by my account for both sides of the orderbook
my_trades = client.get_my_trades(
market=['WETH-DAI', 'DAI-WETH'],
limit=None, # optional
startingBefore=None # optional
)
# Get all trades from one side of the book
all_trades = client.get_trades(
market=['WETH-DAI'], # 'DAI-WETH' side of the book is not included
makerAccountOwner='0x5F5A46a8471F60b1E9F2eD0b8fc21Ba8b48887D8', # optional
makerAccountNumber=0, # optional
limit=2, # optional
startingBefore=None # optional
)
'''
trades = {
"trades": [
{
"uuid": "7b00efba-5002-4562-b777-0122ede33fec",
"createdAt": "2020-03-08T17:32:35.413Z",
"transactionHash": "0xfd6fe9605114a5d44000b51d126751eee1f38866ebd4d4be7eacf89d8bf264d9",
"status": "CONFIRMED",
"market": "WETH-DAI",
"side": "SELL",
"price": "214.90",
"amount": "2447332508052454104",
"makerOrderId": "0x9e5cf0e5091566651ad33c56fb4e24ce96341b561d31180f0d471163709b098d",
"makerAccountOwner": "0x862821badb9c5800654015ba9a2d9d7894c83a7a",
"makerAccountNumber": "0",
"takerOrderId": "0xc1a71851c62fc132ece0060c46a076cb082741ef6b80f894b20c4351b824dfb7",
"takerAccountOwner": "0xd3069c9e486a8b77add55ae3ceb3a4b138fb76c7",
"takerAccountNumber": "48394678789855236190833155557217125360276244141304950018155758748772338730587"
},
...
]
}
'''
# Create order to LONG ETH with an order quantity of 2,500 ETH-USD contracts
# at a price of 250 USD per ETH.
created_order = client.place_order(
market=consts.PAIR_WETH_PUSD,
side=consts.SIDE_SELL,
amount=utils.usd_to_order_amount(25000),
price=Decimal('250e-12'),
fillOrKill=False,
postOnly=False
)
# Create order to BUY 10 PBTC for 723,400.00 USDC (a price of 7234.00 PBTC/USDC)
created_order = client.place_order(
market=consts.PAIR_PBTC_USDC,
side=consts.SIDE_BUY,
amount=utils.btc_to_sats(10),
price=Decimal('72.34'),
fillOrKill=False,
postOnly=False
)
# Create order to BUY 100 PLINK for 1,500.00 USDC (a price of 15.00 PLINK/USDC)
created_order = client.place_order(
market=consts.PAIR_PLINK_USDC,
side=consts.SIDE_BUY,
amount=utils.link_to_order_amount(100),
price=Decimal('15.00'),
fillOrKill=False,
postOnly=False
)
# Create order to BUY 10 ETH for 2504.90 DAI (a price of 250.49 DAI/ETH)
created_order = client.place_order(
market=consts.PAIR_WETH_DAI,
side=consts.SIDE_BUY,
amount=utils.token_to_wei(10, consts.MARKET_WETH),
price=Decimal('250.49'),
fillOrKill=False,
postOnly=False
)
# Create order to SELL 10 ETH for 1500.10 USDC (a price of 150.01 USDC/ETH)
# 'e-12' is in the price since USDC has 6 decimal places (ETH and DAI have 18)
created_order = client.place_order(
market=consts.PAIR_WETH_USDC,
side=consts.SIDE_SELL,
amount=utils.token_to_wei(10, consts.MARKET_WETH),
price=Decimal('150.01e-12'),
fillOrKill=False,
postOnly=False
)
# Cancel the previously created solo order
order_hash = created_order['order']['id']
canceled_order = client.cancel_order(
hash=order_hash
)
# Cancel the previously created perpetual order
order_hash = created_order['order']['id']
canceled_order = client.cancel_perpetual_order(
hash=order_hash
)
orderbook = client.get_orderbook(
market='WETH-DAI'
)
'''
orderbook = {
"bids": [
{
"id": "0xefa4562c0747a8f2a9aa69abb817474ee9e98c8505a71de6054a610ac744b0cd",
"uuid": "c58be890-6e76-4e98-95d4-27977a91af19",
"amount": "17459277053478281216",
"price": "160.08"
},
{
"id": "0xa2ab9f653106fefef5b1264a509b02eab021ffea442307e995908e5360f3cd4d",
"uuid": "d2dba4c6-6442-46bc-b097-1f37312cf279",
"amount": "149610989871929360384",
"price": "160.07"
},
{
"id": "0xec35d60dd1c5eab86cd7881fcbc1239193ceda695df2815d521a46f54bd90580",
"uuid": "24d5a4e1-195b-43fa-a7d8-1d794619e97e",
"amount": "54494000000000000000",
"price": "160.06"
},
],
"asks": [
{
"id": "0xb242e2006a0d99c390fc7256d10558844a719d580e80eaa5a4f99dd14bd9ce5e",
"uuid": "6fdff2f3-0175-4297-bf23-89526eb9aa36",
"amount": "12074182754430260637",
"price": "160.30"
},
{
"id": "0xe32a00e11b91b6f8daa70fbe03ad0100fa458c0d87e5c59f2e629ce9d5d32921",
"uuid": "3f9b35a8-d843-4ae6-bc8b-b534b07e8093",
"amount": "50000000000000000000",
"price": "160.40"
},
{
"id": "0xcad0c2e92094bd1dd17a694bd25933a8825c6014aaf4ae2925512f62c15ae968",
"uuid": "5aefdfd2-4e4d-4b37-9c99-35e8eec0ed9a",
"amount": "50000000000000000000",
"price": "160.50"
},
]
}
'''
market = client.get_market(
market='WETH-DAI'
)
'''
market = {
"market": {
"WETH-DAI": {
"name": "WETH-DAI",
"baseCurrency": {
"currency": "WETH",
"decimals": 18,
"soloMarketId": 0,
},
"quoteCurrency": {
"currency": "DAI",
"decimals": 18,
"soloMarketId": 3,
},
"minimumTickSize": "0.01",
"minimumOrderSize": "100000000000000000",
"smallOrderThreshold": "500000000000000000",
"makerFee": "0",
"largeTakerFee": "0.005",
"smallTakerFee": "0.0015",
},
}
}
'''
markets = client.get_markets()
'''
markets = {
"markets": {
"WETH-DAI": {
"name": "WETH-DAI",
"baseCurrency": {
"currency": "WETH",
"decimals": 18,
"soloMarketId": 0,
},
"quoteCurrency": {
"currency": "DAI",
"decimals": 18,
"soloMarketId": 3,
},
"minimumTickSize": "0.01",
"minimumOrderSize": "100000000000000000",
"smallOrderThreshold": "500000000000000000",
"makerFee": "0",
"largeTakerFee": "0.005",
"smallTakerFee": "0.0015",
},
"WETH-USDC": {
"name": "WETH-USDC",
"baseCurrency": {
"currency": "WETH",
"decimals": 18,
"soloMarketId": 0,
},
"quoteCurrency": {
"currency": "USDC",
"decimals": 6,
"soloMarketId": 2,
},
"minimumTickSize": "0.00000000000001",
"minimumOrderSize": "100000000000000000",
"smallOrderThreshold": "500000000000000000",
"makerFee": "0",
"largeTakerFee": "0.005",
"smallTakerFee": "0.0015",
},
"DAI-USDC": {
"name": "DAI-USDC",
"baseCurrency": {
"currency": "DAI",
"decimals": 18,
"soloMarketId": 3,
},
"quoteCurrency": {
"currency": "USDC",
"decimals": 6,
"soloMarketId": 1,
},
"minimumTickSize": "0.0000000000000001",
"minimumOrderSize": "20000000000000000000",
"smallOrderThreshold": "100000000000000000000",
"makerFee": "0",
"largeTakerFee": "0.005",
"smallTakerFee": "0.0005",
},
}
}
'''
market = client.get_perpetual_market(
market='PBTC-USDC'
)
'''
market = {
"market": {
"uuid": "f6d20698-32ac-4f3a-a9c4-b6b7528b7b94",
"market": "PBTC-USDC",
"oraclePrice": "68.9615",
"fundingRate": "0",
"minCollateral": "0.1075",
"globalIndexValue": "0",
"globalIndexTimestamp": "1587407069",
"createdAt": "2020-04-09T22:42:35.696Z",
"updatedAt": "2020-04-20T18:48:06.334Z"
}
}
'''
markets = client.get_perpetual_markets()
'''
markets = {
"markets": [
{
"uuid": "f6d20698-32ac-4f3a-a9c4-b6b7528b7b94",
"market": "PBTC-USDC",
"oraclePrice": "68.9615",
"fundingRate": "0",
"minCollateral": "0.1075",
"globalIndexValue": "0",
"globalIndexTimestamp": "1587407069",
"createdAt": "2020-04-09T22:42:35.696Z",
"updatedAt": "2020-04-20T18:47:06.197Z"
}
]
}
'''
# deposit 2 ETH into the ETH-USD Perpetual
tx_hash = client.eth.perp.deposit(
market=consts.PAIR_WETH_PUSD,
amount=utils.token_to_wei(2, consts.MARKET_WETH)
)
receipt = client.eth.get_receipt(tx_hash)
# withdraw 1 ETH from the ETH-USD Perpetual
tx_hash = client.eth.perp.withdraw(
market=consts.PAIR_WETH_PUSD,
amount=utils.token_to_wei(1, consts.MARKET_WETH)
)
receipt = client.eth.get_receipt(tx_hash)
# deposit 100 USDC into the BTC-USD Perpetual
tx_hash = client.eth.perp.set_allowance(consts.PAIR_PBTC_USDC) # must only be called once, ever
receipt = client.eth.get_receipt(tx_hash)
tx_hash = client.eth.perp.deposit(
market=consts.PAIR_PBTC_USDC,
amount=utils.token_to_wei(100, consts.MARKET_USDC)
)
receipt = client.eth.get_receipt(tx_hash)
# withdraw 50 USDC from the BTC-USD Perpetual
tx_hash = client.eth.perp.withdraw(
market=consts.PAIR_PBTC_USDC,
amount=utils.token_to_wei(50, consts.MARKET_USDC)
)
receipt = client.eth.get_receipt(tx_hash)
# deposit 100 USDC into the LINK-USD Perpetual
tx_hash = client.eth.perp.set_allowance(consts.PAIR_PLINK_USDC) # must only be called once, ever
receipt = client.eth.get_receipt(tx_hash)
tx_hash = client.eth.perp.deposit(
market=consts.PAIR_PLINK_USDC,
amount=utils.token_to_wei(100, consts.MARKET_USDC)
)
receipt = client.eth.get_receipt(tx_hash)
# withdraw 50 USDC from the LINK-USD Perpetual
tx_hash = client.eth.perp.withdraw(
market=consts.PAIR_PLINK_USDC,
amount=utils.token_to_wei(50, consts.MARKET_USDC)
)
receipt = client.eth.get_receipt(tx_hash)
# get the USD value of PBTC
# Since PBTC is measured in Satoshis (1e-8 of one BTC) and USDC has 6 decimal places,
# a normal price of $7200 per BTC would return a result of 72.
btc_price = client.eth.perp.get_oracle_price(
market=consts.PAIR_PBTC_USDC
)
# get the USD value of PLINK
# Since PLINK and USDC both have 6 decimal places,
# a normal price of $15 per LINK would return a result of 15.
btc_price = client.eth.perp.get_oracle_price(
market=consts.PAIR_PLINK_USDC
)
# get the ETH value of USD
# Since USD is considered to have 6 decimal places, and ETH has 18 decimals places,
# a normal price of $250 per ETH would have a price of 1 / (250e-12).
eth_price = client.eth.perp.get_oracle_price(
market=consts.PAIR_WETH_PUSD
)
# deposit 10 ETH
# does not require set_allowance
tx_hash = client.eth.solo.deposit(
market=consts.MARKET_WETH,
wei=utils.token_to_wei(10, consts.MARKET_WETH)
)
receipt = client.eth.get_receipt(tx_hash)
# deposit 10 WETH ERC20 tokens without using the WETH payable proxy address
# requires set_allowance
tx_hash = client.eth.solo.deposit(
market=consts.MARKET_WETH,
wei=utils.token_to_wei(10, consts.MARKET_WETH),
asEth=False
)
receipt = client.eth.get_receipt(tx_hash)
# deposit 100 DAI
tx_hash = client.eth.solo.set_allowance(market=consts.MARKET_DAI) # must only be called once, ever
receipt = client.eth.get_receipt(tx_hash)
tx_hash = client.eth.solo.deposit(
market=consts.MARKET_DAI,
wei=utils.token_to_wei(100, consts.MARKET_DAI)
)
receipt = client.eth.get_receipt(tx_hash)
# deposit 100 USDC
tx_hash = client.eth.solo.set_allowance(market=consts.MARKET_USDC) # must only be called once, ever
receipt = client.eth.get_receipt(tx_hash)
tx_hash = client.eth.solo.deposit(
market=consts.MARKET_USDC,
wei=utils.token_to_wei(100, consts.MARKET_USDC)
)
receipt = client.eth.get_receipt(tx_hash)
# withdraw 10 WETH ERC20 tokens without using the WETH payable proxy address
tx_hash = client.eth.solo.deposit(
market=consts.MARKET_WETH,
wei=utils.token_to_wei(10, consts.MARKET_WETH),
asEth=False
)
receipt = client.eth.get_receipt(tx_hash)
# withdraw 50 USDC
tx_hash = client.eth.solo.withdraw(
market=consts.MARKET_USDC,
wei=utils.token_to_wei(50, consts.MARKET_USDC)
)
receipt = client.eth.get_receipt(tx_hash)
# withdraw all DAI (including interest)
tx_hash = client.eth.solo.withdraw_to_zero(market=consts.MARKET_DAI)
receipt = client.eth.get_receipt(tx_hash)
# get the USD value of one atomic unit of DAI
dai_price = client.eth.solo.get_oracle_price(consts.MARKET_DAI)
# get dYdX balances
balances = client.eth.solo.get_my_balances()
'''
balances = [
-91971743707894,
3741715702031854553560,
2613206278
]
'''
# get dYdX account collateralization
collateralization = client.eth.get_my_collateralization()
'''
collateralization = 2.5 or float('inf')
'''
# collateralization must remain above the minimum to prevent liquidation
assert(collateralization > consts.MINIMUM_COLLATERALIZATION)
'''
consts.MINIMUM_COLLATERALIZATION = 1.15
'''
Getting information directly from the blockchain by querying a node
# get Wallet balances
balance = client.eth.get_my_wallet_balance(consts.MARKET_DAI)
'''
balance = 1000000000000000000
'''
## Testing
pip install -r requirements.txt
docker-compose up tox
FAQs
dYdX Python REST API for Limit Orders
We found that dydx-python demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.