-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy path2_MsgExec.py
More file actions
107 lines (89 loc) · 3.5 KB
/
2_MsgExec.py
File metadata and controls
107 lines (89 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import asyncio
import os
import uuid
from decimal import Decimal
import dotenv
from grpc import RpcError
from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import Address, PrivateKey
async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY")
granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS")
# select network: local, testnet, mainnet
network = Network.testnet()
# initialize grpc client
client = AsyncClient(network)
composer = await client.composer()
await client.sync_timeout_height()
# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())
# prepare tx msg
market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
grantee = address.to_acc_bech32()
granter_address = Address.from_acc_bech32(granter_inj_address)
granter_subaccount_id = granter_address.get_subaccount_id(index=0)
msg0 = composer.msg_create_spot_limit_order(
sender=granter_inj_address,
market_id=market_id,
subaccount_id=granter_subaccount_id,
fee_recipient=grantee,
price=Decimal("7.523"),
quantity=Decimal("0.01"),
order_type="BUY",
cid=str(uuid.uuid4()),
)
msg = composer.MsgExec(grantee=grantee, msgs=[msg0])
# build sim tx
tx = (
Transaction()
.with_messages(msg)
.with_sequence(client.get_sequence())
.with_account_num(client.get_number())
.with_chain_id(network.chain_id)
)
sim_sign_doc = tx.get_sign_doc(pub_key)
sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)
# simulate tx
try:
sim_res = await client.simulate(sim_tx_raw_bytes)
except RpcError as ex:
print(ex)
return
sim_res_msgs = sim_res["result"]["msgResponses"]
data = sim_res_msgs[0]
unpacked_msg_res = composer.unpack_msg_exec_response(
underlying_msg_type=msg0.__class__.__name__, msg_exec_response=data
)
print("simulation msg response")
print(unpacked_msg_res)
# build tx
gas_price = await client.current_chain_gas_price()
# adjust gas price to make it valid even if it changes between the time it is requested and the TX is broadcasted
gas_price = int(gas_price * 1.1)
gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation
gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
fee = [
composer.coin(
amount=gas_price * gas_limit,
denom=network.fee_denom,
)
]
tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
sign_doc = tx.get_sign_doc(pub_key)
sig = priv_key.sign(sign_doc.SerializeToString())
tx_raw_bytes = tx.get_tx_data(sig, pub_key)
# broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
print(res)
print("gas wanted: {}".format(gas_limit))
print("gas fee: {} INJ".format(gas_fee))
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())