Skip to content

Commit 781564f

Browse files
authored
Merge pull request #117 from InjectiveLabs/f/refactor_local_order_hash
feat: refactor local order hash computation
2 parents 0db9a92 + 4936f51 commit 781564f

File tree

2 files changed

+103
-47
lines changed

2 files changed

+103
-47
lines changed

examples/chain_client/0_LocalOrderHash.py

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from pyinjective.transaction import Transaction
2121
from pyinjective.constant import Network
2222
from pyinjective.wallet import PrivateKey
23-
from pyinjective.orderhash import compute_order_hashes
23+
from pyinjective.orderhash import OrderHashes
2424

2525

2626
async def main() -> None:
@@ -37,6 +37,7 @@ async def main() -> None:
3737
pub_key = priv_key.to_public_key()
3838
address = await pub_key.to_address().async_init_num_seq(network.lcd_endpoint)
3939
subaccount_id = address.get_subaccount_id(index=0)
40+
OrderHashes.get_subaccount_nonce(network=network, subaccount_id=subaccount_id)
4041

4142
# prepare trade info
4243
spot_market_id = "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
@@ -48,7 +49,7 @@ async def main() -> None:
4849
market_id=spot_market_id,
4950
subaccount_id=subaccount_id,
5051
fee_recipient=fee_recipient,
51-
price=3.524,
52+
price=1.524,
5253
quantity=0.01,
5354
is_buy=True,
5455
is_po=True
@@ -99,12 +100,58 @@ async def main() -> None:
99100
)
100101

101102
# compute order hashes
102-
order_hashes = compute_order_hashes(network, spot_orders=spot_orders, derivative_orders=derivative_orders)
103+
104+
order_hashes = OrderHashes.compute_order_hashes(spot_orders=spot_orders, derivative_orders=derivative_orders)
105+
106+
print("computed spot order hashes", order_hashes.spot)
107+
print("computed derivative order hashes", order_hashes.derivative)
108+
109+
# build sim tx 1
110+
tx = (
111+
Transaction()
112+
.with_messages(spot_msg, deriv_msg)
113+
.with_sequence(address.get_sequence())
114+
.with_account_num(address.get_number())
115+
.with_chain_id(network.chain_id)
116+
)
117+
sim_sign_doc = tx.get_sign_doc(pub_key)
118+
sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
119+
sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)
120+
121+
# simulate tx
122+
(sim_res, success) = await client.simulate_tx(sim_tx_raw_bytes)
123+
if not success:
124+
print(sim_res)
125+
return
126+
127+
# build tx
128+
gas_price = 500000000
129+
gas_limit = sim_res.gas_info.gas_used + 20000 # add 20k for gas, fee computation
130+
gas_fee = '{:.18f}'.format((gas_price * gas_limit) / pow(10, 18)).rstrip('0')
131+
fee = [composer.Coin(
132+
amount=gas_price * gas_limit,
133+
denom=network.fee_denom,
134+
)]
135+
tx = tx.with_gas(gas_limit).with_fee(fee).with_memo('').with_timeout_height(client.timeout_height)
136+
sign_doc = tx.get_sign_doc(pub_key)
137+
sig = priv_key.sign(sign_doc.SerializeToString())
138+
tx_raw_bytes = tx.get_tx_data(sig, pub_key)
139+
140+
# broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
141+
res = await client.send_tx_sync_mode(tx_raw_bytes)
142+
print(res)
143+
print("gas wanted: {}".format(gas_limit))
144+
print("gas fee: {} INJ".format(gas_fee))
145+
146+
147+
# compute order hashes
148+
149+
order_hashes = OrderHashes.compute_order_hashes(spot_orders=spot_orders, derivative_orders=derivative_orders)
103150

104151
print("computed spot order hashes", order_hashes.spot)
105152
print("computed derivative order hashes", order_hashes.derivative)
106153

107-
# build sim tx
154+
# build sim tx 2
108155
tx = (
109156
Transaction()
110157
.with_messages(spot_msg, deriv_msg)

pyinjective/orderhash.py

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,65 @@ class DerivativeOrder(EIP712Struct):
3838
class OrderHashes:
3939
def __init__(
4040
self,
41-
spot: [str],
42-
derivative: [str],
41+
spot: [str] = None,
42+
derivative: [str] = None,
43+
nonce: str = None
4344
):
4445
self.spot = spot
4546
self.derivative = derivative
47+
self.nonce = nonce
48+
49+
@classmethod
50+
def get_subaccount_nonce(self, network, subaccount_id) -> int:
51+
url = network.lcd_endpoint + '/injective/exchange/v1beta1/exchange/' + subaccount_id
52+
res = requests.get(url = url)
53+
nonce = res.json()["nonce"]
54+
self.nonce = nonce + 1
55+
return self.nonce
56+
57+
@classmethod
58+
def compute_order_hashes(self, spot_orders, derivative_orders) -> [str]:
59+
if len(spot_orders) + len(derivative_orders) == 0:
60+
return []
61+
62+
order_hashes = OrderHashes(spot=[], derivative=[])
63+
64+
subaccount_id = None
65+
if len(spot_orders) > 0:
66+
subaccount_id = spot_orders[0].order_info.subaccount_id
67+
else:
68+
subaccount_id = derivative_orders[0].order_info.subaccount_id
69+
70+
for o in spot_orders:
71+
msg = build_eip712_msg(o, self.nonce)
72+
typed_data_hash = msg.hash_struct()
73+
typed_bytes = b'\x19\x01' + domain_separator + typed_data_hash
74+
keccak256 = sha3.keccak_256()
75+
keccak256.update(typed_bytes)
76+
order_hash = keccak256.hexdigest()
77+
order_hashes.spot.append('0x' + order_hash)
78+
self.nonce += 1
79+
80+
for o in derivative_orders:
81+
msg = build_eip712_msg(o, self.nonce)
82+
typed_data_hash = msg.hash_struct()
83+
typed_bytes = b'\x19\x01' + domain_separator + typed_data_hash
84+
keccak256 = sha3.keccak_256()
85+
keccak256.update(typed_bytes)
86+
order_hash = keccak256.hexdigest()
87+
order_hashes.derivative.append('0x' + order_hash)
88+
self.nonce += 1
89+
90+
return order_hashes
4691

4792
def param_to_backend_go(param) -> int:
4893
go_param = Decimal(param) / pow(10, 18)
4994
return format(go_param, '.18f')
5095

51-
def get_subaccount_nonce(network, subaccount_id) -> int:
52-
url = network.lcd_endpoint + '/injective/exchange/v1beta1/exchange/' + subaccount_id
53-
res = requests.get(url = url)
54-
return res.json()["nonce"]
96+
def increment_nonce(self):
97+
current_nonce = self.nonce
98+
self.nonce += 1
99+
return current_nonce
55100

56101
def parse_order_type(order):
57102
return order_type_dict[order.order_type]
@@ -95,40 +140,4 @@ def build_eip712_msg(order, nonce):
95140
)
96141

97142
# only support msgs from single subaccount
98-
def compute_order_hashes(network, spot_orders, derivative_orders) -> [str]:
99-
if len(spot_orders) + len(derivative_orders) == 0:
100-
return []
101-
102-
order_hashes = OrderHashes(spot=[], derivative=[])
103-
104-
subaccount_id = None
105-
if len(spot_orders) > 0:
106-
subaccount_id = spot_orders[0].order_info.subaccount_id
107-
else:
108-
subaccount_id = derivative_orders[0].order_info.subaccount_id
109-
110-
# get starting nonce
111-
nonce = get_subaccount_nonce(network, subaccount_id)
112-
nonce += 1
113-
114-
for o in spot_orders:
115-
msg = build_eip712_msg(o, nonce)
116-
typed_data_hash = msg.hash_struct()
117-
typed_bytes = b'\x19\x01' + domain_separator + typed_data_hash
118-
keccak256 = sha3.keccak_256()
119-
keccak256.update(typed_bytes)
120-
order_hash = keccak256.hexdigest()
121-
order_hashes.spot.append('0x' + order_hash)
122-
nonce += 1
123-
124-
for o in derivative_orders:
125-
msg = build_eip712_msg(o, nonce)
126-
typed_data_hash = msg.hash_struct()
127-
typed_bytes = b'\x19\x01' + domain_separator + typed_data_hash
128-
keccak256 = sha3.keccak_256()
129-
keccak256.update(typed_bytes)
130-
order_hash = keccak256.hexdigest()
131-
order_hashes.derivative.append('0x' + order_hash)
132-
nonce += 1
133-
134-
return order_hashes
143+

0 commit comments

Comments
 (0)