diff --git a/examples/chain_client/1_LocalOrderHash.py b/examples/chain_client/1_LocalOrderHash.py index 89ca21a4..55574d6d 100644 --- a/examples/chain_client/1_LocalOrderHash.py +++ b/examples/chain_client/1_LocalOrderHash.py @@ -1,4 +1,5 @@ import asyncio +import json import os import uuid from decimal import Decimal @@ -132,7 +133,7 @@ async def main() -> None: # 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(json.dumps(res, indent=2)) print("gas wanted: {}".format(gas_limit)) print("gas fee: {} INJ".format(gas_fee)) @@ -173,7 +174,7 @@ async def main() -> None: # 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(json.dumps(res, indent=2)) print("gas wanted: {}".format(gas_limit)) print("gas fee: {} INJ".format(gas_fee)) @@ -269,7 +270,7 @@ async def main() -> None: # 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(json.dumps(res, indent=2)) print("gas wanted: {}".format(gas_limit)) print("gas fee: {} INJ".format(gas_fee)) diff --git a/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py b/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py index 41d94702..7efd2fde 100644 --- a/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py +++ b/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py @@ -27,7 +27,7 @@ async def main() -> None: # 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) - message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( network=network, private_key=private_key_in_hexa, gas_price=gas_price, diff --git a/examples/chain_client/auction/1_MsgBid.py b/examples/chain_client/auction/1_MsgBid.py index 350d82f6..5b75bd13 100644 --- a/examples/chain_client/auction/1_MsgBid.py +++ b/examples/chain_client/auction/1_MsgBid.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,59 +20,35 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) # prepare tx msg msg = composer.msg_bid(sender=address.to_acc_bech32(), round=16250, bid_amount=1) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/auth/query/1_Account.py b/examples/chain_client/auth/query/1_Account.py index 7a1d7522..d0318646 100644 --- a/examples/chain_client/auth/query/1_Account.py +++ b/examples/chain_client/auth/query/1_Account.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -9,7 +10,7 @@ async def main() -> None: client = AsyncClient(network) address = "inj1knhahceyp57j5x7xh69p7utegnnnfgxavmahjr" acc = await client.fetch_account(address=address) - print(acc) + print(json.dumps(acc, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/authz/1_MsgGrant.py b/examples/chain_client/authz/1_MsgGrant.py index a57bed85..60e87b98 100644 --- a/examples/chain_client/authz/1_MsgGrant.py +++ b/examples/chain_client/authz/1_MsgGrant.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") # select network: local, testnet, mainnet @@ -22,13 +21,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) # subaccount_id = address.get_subaccount_id(index=0) # market_ids = ["0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa"] @@ -52,48 +60,15 @@ async def main() -> None: # market_ids=market_ids # ) - # 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 - - # build tx + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) + 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/authz/2_MsgExec.py b/examples/chain_client/authz/2_MsgExec.py index 691fd830..e32efb4c 100644 --- a/examples/chain_client/authz/2_MsgExec.py +++ b/examples/chain_client/authz/2_MsgExec.py @@ -1,21 +1,20 @@ import asyncio +import json import os import uuid from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk 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") + private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") # select network: local, testnet, mainnet @@ -24,13 +23,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_for_grantee_account_using_gas_heuristics( + network=network, + grantee_private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) 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" @@ -38,7 +46,7 @@ async def main() -> None: 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( + message = composer.msg_create_spot_limit_order( sender=granter_inj_address, market_id=market_id, subaccount_id=granter_subaccount_id, @@ -49,58 +57,15 @@ async def main() -> None: cid=str(uuid.uuid4()), ) - msg = composer.msg_exec(grantee=grantee, msgs=[msg0]) + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/authz/3_MsgRevoke.py b/examples/chain_client/authz/3_MsgRevoke.py index 3e534f7c..83f978ed 100644 --- a/examples/chain_client/authz/3_MsgRevoke.py +++ b/examples/chain_client/authz/3_MsgRevoke.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") # select network: local, testnet, mainnet @@ -22,13 +21,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) # prepare tx msg msg = composer.msg_revoke( @@ -37,48 +45,15 @@ async def main() -> None: msg_type="/injective.exchange.v2.MsgCreateSpotLimitOrder", ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/authz/query/1_Grants.py b/examples/chain_client/authz/query/1_Grants.py index 1f252508..abf12e75 100644 --- a/examples/chain_client/authz/query/1_Grants.py +++ b/examples/chain_client/authz/query/1_Grants.py @@ -1,4 +1,5 @@ import asyncio +import json import os import dotenv @@ -16,7 +17,7 @@ async def main() -> None: client = AsyncClient(network) msg_type_url = "/injective.exchange.v2.MsgCreateDerivativeLimitOrder" authorizations = await client.fetch_grants(granter=granter, grantee=grantee, msg_type_url=msg_type_url) - print(authorizations) + print(json.dumps(authorizations, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/bank/1_MsgSend.py b/examples/chain_client/bank/1_MsgSend.py index 4b34d6f4..6c101a3b 100644 --- a/examples/chain_client/bank/1_MsgSend.py +++ b/examples/chain_client/bank/1_MsgSend.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,13 +20,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) # prepare tx msg msg = composer.msg_send( @@ -37,48 +45,15 @@ async def main() -> None: denom="inj", ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/bank/query/10_SendEnabled.py b/examples/chain_client/bank/query/10_SendEnabled.py index f043e878..6ae82c71 100644 --- a/examples/chain_client/bank/query/10_SendEnabled.py +++ b/examples/chain_client/bank/query/10_SendEnabled.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.client.model.pagination import PaginationOption @@ -13,7 +14,7 @@ async def main() -> None: denoms=[denom], pagination=PaginationOption(limit=10), ) - print(enabled) + print(json.dumps(enabled, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/bank/query/1_BankBalance.py b/examples/chain_client/bank/query/1_BankBalance.py index fa9e5aac..2163ee1e 100644 --- a/examples/chain_client/bank/query/1_BankBalance.py +++ b/examples/chain_client/bank/query/1_BankBalance.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -10,7 +11,7 @@ async def main() -> None: address = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" denom = "inj" bank_balance = await client.fetch_bank_balance(address=address, denom=denom) - print(bank_balance) + print(json.dumps(bank_balance, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/bank/query/2_BankBalances.py b/examples/chain_client/bank/query/2_BankBalances.py index 5fb6d8e0..be03cfc4 100644 --- a/examples/chain_client/bank/query/2_BankBalances.py +++ b/examples/chain_client/bank/query/2_BankBalances.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -9,7 +10,7 @@ async def main() -> None: client = AsyncClient(network) address = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" all_bank_balances = await client.fetch_bank_balances(address=address) - print(all_bank_balances) + print(json.dumps(all_bank_balances, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/bank/query/3_SpendableBalances.py b/examples/chain_client/bank/query/3_SpendableBalances.py index 81f294ff..0536d0c2 100644 --- a/examples/chain_client/bank/query/3_SpendableBalances.py +++ b/examples/chain_client/bank/query/3_SpendableBalances.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -9,7 +10,7 @@ async def main() -> None: client = AsyncClient(network) address = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" spendable_balances = await client.fetch_spendable_balances(address=address) - print(spendable_balances) + print(json.dumps(spendable_balances, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/bank/query/4_SpendableBalancesByDenom.py b/examples/chain_client/bank/query/4_SpendableBalancesByDenom.py index 06d13e6b..d9c5bc1a 100644 --- a/examples/chain_client/bank/query/4_SpendableBalancesByDenom.py +++ b/examples/chain_client/bank/query/4_SpendableBalancesByDenom.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -10,7 +11,7 @@ async def main() -> None: address = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" denom = "inj" spendable_balances = await client.fetch_spendable_balances_by_denom(address=address, denom=denom) - print(spendable_balances) + print(json.dumps(spendable_balances, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/bank/query/5_TotalSupply.py b/examples/chain_client/bank/query/5_TotalSupply.py index adba28cc..c55ec15a 100644 --- a/examples/chain_client/bank/query/5_TotalSupply.py +++ b/examples/chain_client/bank/query/5_TotalSupply.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.client.model.pagination import PaginationOption @@ -11,7 +12,7 @@ async def main() -> None: total_supply = await client.fetch_total_supply( pagination=PaginationOption(limit=10), ) - print(total_supply) + print(json.dumps(total_supply, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/bank/query/6_SupplyOf.py b/examples/chain_client/bank/query/6_SupplyOf.py index 681453a2..472c06f2 100644 --- a/examples/chain_client/bank/query/6_SupplyOf.py +++ b/examples/chain_client/bank/query/6_SupplyOf.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -8,7 +9,7 @@ async def main() -> None: network = Network.testnet() client = AsyncClient(network) supply_of = await client.fetch_supply_of(denom="inj") - print(supply_of) + print(json.dumps(supply_of, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/bank/query/7_DenomMetadata.py b/examples/chain_client/bank/query/7_DenomMetadata.py index 5bf78e71..76ffb25c 100644 --- a/examples/chain_client/bank/query/7_DenomMetadata.py +++ b/examples/chain_client/bank/query/7_DenomMetadata.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -9,7 +10,7 @@ async def main() -> None: client = AsyncClient(network) denom = "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position" metadata = await client.fetch_denom_metadata(denom=denom) - print(metadata) + print(json.dumps(metadata, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/bank/query/8_DenomsMetadata.py b/examples/chain_client/bank/query/8_DenomsMetadata.py index 8540c9cd..3a4b16bc 100644 --- a/examples/chain_client/bank/query/8_DenomsMetadata.py +++ b/examples/chain_client/bank/query/8_DenomsMetadata.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.client.model.pagination import PaginationOption @@ -11,7 +12,7 @@ async def main() -> None: denoms = await client.fetch_denoms_metadata( pagination=PaginationOption(limit=10), ) - print(denoms) + print(json.dumps(denoms, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/bank/query/9_DenomOwners.py b/examples/chain_client/bank/query/9_DenomOwners.py index da8a6538..a170e7fd 100644 --- a/examples/chain_client/bank/query/9_DenomOwners.py +++ b/examples/chain_client/bank/query/9_DenomOwners.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.client.model.pagination import PaginationOption @@ -13,7 +14,7 @@ async def main() -> None: denom=denom, pagination=PaginationOption(limit=10), ) - print(owners) + print(json.dumps(owners, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/distribution/1_SetWithdrawAddress.py b/examples/chain_client/distribution/1_SetWithdrawAddress.py index a8dd3973..261124e1 100644 --- a/examples/chain_client/distribution/1_SetWithdrawAddress.py +++ b/examples/chain_client/distribution/1_SetWithdrawAddress.py @@ -22,7 +22,7 @@ async def main() -> None: # 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) - message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( network=network, private_key=configured_private_key, gas_price=gas_price, diff --git a/examples/chain_client/distribution/2_WithdrawDelegatorReward.py b/examples/chain_client/distribution/2_WithdrawDelegatorReward.py index be2ada42..64041aaa 100644 --- a/examples/chain_client/distribution/2_WithdrawDelegatorReward.py +++ b/examples/chain_client/distribution/2_WithdrawDelegatorReward.py @@ -23,7 +23,7 @@ async def main() -> None: # 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) - message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( network=network, private_key=configured_private_key, gas_price=gas_price, diff --git a/examples/chain_client/distribution/3_WithdrawValidatorCommission.py b/examples/chain_client/distribution/3_WithdrawValidatorCommission.py index 63b37a6d..bd452c57 100644 --- a/examples/chain_client/distribution/3_WithdrawValidatorCommission.py +++ b/examples/chain_client/distribution/3_WithdrawValidatorCommission.py @@ -23,7 +23,7 @@ async def main() -> None: # 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) - message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( network=network, private_key=configured_private_key, gas_price=gas_price, diff --git a/examples/chain_client/distribution/4_FundCommunityPool.py b/examples/chain_client/distribution/4_FundCommunityPool.py index 2b78af9a..10d93c16 100644 --- a/examples/chain_client/distribution/4_FundCommunityPool.py +++ b/examples/chain_client/distribution/4_FundCommunityPool.py @@ -23,7 +23,7 @@ async def main() -> None: # 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) - message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( network=network, private_key=configured_private_key, gas_price=gas_price, diff --git a/examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py b/examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py index 3d8442b7..6be36259 100644 --- a/examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py +++ b/examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -9,7 +10,7 @@ async def main() -> None: client = AsyncClient(network) validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" distribution_info = await client.fetch_validator_distribution_info(validator_address=validator_address) - print(distribution_info) + print(json.dumps(distribution_info, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py b/examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py index 12321f9f..1bd21c12 100644 --- a/examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py +++ b/examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -9,7 +10,7 @@ async def main() -> None: client = AsyncClient(network) validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" rewards = await client.fetch_validator_outstanding_rewards(validator_address=validator_address) - print(rewards) + print(json.dumps(rewards, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/distribution/query/3_ValidatorCommission.py b/examples/chain_client/distribution/query/3_ValidatorCommission.py index 7ce6104b..f6054ae0 100644 --- a/examples/chain_client/distribution/query/3_ValidatorCommission.py +++ b/examples/chain_client/distribution/query/3_ValidatorCommission.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -9,7 +10,7 @@ async def main() -> None: client = AsyncClient(network) validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" commission = await client.fetch_validator_commission(validator_address=validator_address) - print(commission) + print(json.dumps(commission, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/distribution/query/4_ValidatorSlashes.py b/examples/chain_client/distribution/query/4_ValidatorSlashes.py index 198327f4..00b7a8e2 100644 --- a/examples/chain_client/distribution/query/4_ValidatorSlashes.py +++ b/examples/chain_client/distribution/query/4_ValidatorSlashes.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.client.model.pagination import PaginationOption @@ -13,7 +14,7 @@ async def main() -> None: pagination = PaginationOption(limit=limit) validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" contracts = await client.fetch_validator_slashes(validator_address=validator_address, pagination=pagination) - print(contracts) + print(json.dumps(contracts, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/distribution/query/5_DelegationRewards.py b/examples/chain_client/distribution/query/5_DelegationRewards.py index f0c822d2..71e36cad 100644 --- a/examples/chain_client/distribution/query/5_DelegationRewards.py +++ b/examples/chain_client/distribution/query/5_DelegationRewards.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -12,7 +13,7 @@ async def main() -> None: rewards = await client.fetch_delegation_rewards( delegator_address=delegator_address, validator_address=validator_address ) - print(rewards) + print(json.dumps(rewards, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/distribution/query/6_DelegationTotalRewards.py b/examples/chain_client/distribution/query/6_DelegationTotalRewards.py index 0945ae26..06d5c84a 100644 --- a/examples/chain_client/distribution/query/6_DelegationTotalRewards.py +++ b/examples/chain_client/distribution/query/6_DelegationTotalRewards.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -11,7 +12,7 @@ async def main() -> None: rewards = await client.fetch_delegation_total_rewards( delegator_address=delegator_address, ) - print(rewards) + print(json.dumps(rewards, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/distribution/query/7_DelegatorValidators.py b/examples/chain_client/distribution/query/7_DelegatorValidators.py index b27373d9..7cf7634e 100644 --- a/examples/chain_client/distribution/query/7_DelegatorValidators.py +++ b/examples/chain_client/distribution/query/7_DelegatorValidators.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -11,7 +12,7 @@ async def main() -> None: validators = await client.fetch_delegator_validators( delegator_address=delegator_address, ) - print(validators) + print(json.dumps(validators, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py b/examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py index bcc5a732..90378bef 100644 --- a/examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py +++ b/examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -11,7 +12,7 @@ async def main() -> None: withdraw_address = await client.fetch_delegator_withdraw_address( delegator_address=delegator_address, ) - print(withdraw_address) + print(json.dumps(withdraw_address, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/distribution/query/9_CommunityPool.py b/examples/chain_client/distribution/query/9_CommunityPool.py index 190d3b95..f4a14dfd 100644 --- a/examples/chain_client/distribution/query/9_CommunityPool.py +++ b/examples/chain_client/distribution/query/9_CommunityPool.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -8,7 +9,7 @@ async def main() -> None: network = Network.testnet() client = AsyncClient(network) community_pool = await client.fetch_community_pool() - print(community_pool) + print(json.dumps(community_pool, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py index ea1f3afd..aed41c73 100644 --- a/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py @@ -1,21 +1,20 @@ import asyncio +import json import os import uuid from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -23,13 +22,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -51,53 +59,15 @@ async def main() -> None: cid=str(uuid.uuid4()), ) - # 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_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py index 84bf1ff1..4e86e724 100644 --- a/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py @@ -1,21 +1,20 @@ import asyncio +import json import os import uuid from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -23,13 +22,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -51,53 +59,15 @@ async def main() -> None: cid=str(uuid.uuid4()), ) - # 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_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py index 01e5778c..7ff56a05 100644 --- a/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,13 +20,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -45,48 +53,15 @@ async def main() -> None: is_conditional=False, ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py index 4f83e4f3..9532d3bb 100644 --- a/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py @@ -1,21 +1,20 @@ import asyncio +import json import os import uuid from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -23,13 +22,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -49,53 +57,15 @@ async def main() -> None: cid=str(uuid.uuid4()), ) - # 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_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py index 42142538..78ab4a38 100644 --- a/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py @@ -1,21 +1,20 @@ import asyncio +import json import os import uuid from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -23,13 +22,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -49,53 +57,16 @@ async def main() -> None: ), cid=str(uuid.uuid4()), ) - # 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_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py index 26e8a984..5ba84019 100644 --- a/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,13 +20,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -44,53 +52,16 @@ async def main() -> None: is_market_order=False, is_conditional=False, ) - # 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_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/17_MsgSubaccountTransfer.py b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py index 878befc7..25ee7ebd 100644 --- a/examples/chain_client/exchange/17_MsgSubaccountTransfer.py +++ b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,13 +20,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) dest_subaccount_id = address.get_subaccount_id(index=1) @@ -40,48 +48,15 @@ async def main() -> None: denom="inj", ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/18_MsgExternalTransfer.py b/examples/chain_client/exchange/18_MsgExternalTransfer.py index b4720310..e0edc731 100644 --- a/examples/chain_client/exchange/18_MsgExternalTransfer.py +++ b/examples/chain_client/exchange/18_MsgExternalTransfer.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,13 +20,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) dest_subaccount_id = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000" @@ -40,48 +48,15 @@ async def main() -> None: denom="inj", ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/19_MsgLiquidatePosition.py b/examples/chain_client/exchange/19_MsgLiquidatePosition.py index 3e9054e9..376b87d4 100644 --- a/examples/chain_client/exchange/19_MsgLiquidatePosition.py +++ b/examples/chain_client/exchange/19_MsgLiquidatePosition.py @@ -1,21 +1,20 @@ import asyncio +import json import os import uuid from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -23,13 +22,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -58,54 +66,15 @@ async def main() -> None: order=order, ) - # 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_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) - - # build tx + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) + 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("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - print(f"\n\ncid: {cid}") + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/1_MsgDeposit.py b/examples/chain_client/exchange/1_MsgDeposit.py index efc6144e..a01a9717 100644 --- a/examples/chain_client/exchange/1_MsgDeposit.py +++ b/examples/chain_client/exchange/1_MsgDeposit.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,60 +20,36 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare tx msg msg = composer.msg_deposit(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="inj") - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py b/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py index c5c3d006..2a2f5108 100644 --- a/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py +++ b/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py @@ -1,20 +1,19 @@ import asyncio +import json import os from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -22,13 +21,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -43,48 +51,15 @@ async def main() -> None: amount=Decimal(2), ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/21_MsgRewardsOptOut.py b/examples/chain_client/exchange/21_MsgRewardsOptOut.py index a7be5b27..3d7f1772 100644 --- a/examples/chain_client/exchange/21_MsgRewardsOptOut.py +++ b/examples/chain_client/exchange/21_MsgRewardsOptOut.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,59 +20,35 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) # prepare tx msg msg = composer.msg_rewards_opt_out(sender=address.to_acc_bech32()) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py index 748c4459..f37cb08b 100644 --- a/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py @@ -1,20 +1,19 @@ import asyncio +import json import os from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -22,13 +21,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) # prepare trade info market_id = "0xfafec40a7b93331c1fc89c23f66d11fbb48f38dfdd78f7f4fc4031fad90f6896" @@ -47,53 +55,15 @@ async def main() -> None: status=status, ) - # 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_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/2_MsgWithdraw.py b/examples/chain_client/exchange/2_MsgWithdraw.py index 72d69668..4372a124 100644 --- a/examples/chain_client/exchange/2_MsgWithdraw.py +++ b/examples/chain_client/exchange/2_MsgWithdraw.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,61 +20,37 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) denom = "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5" # prepare tx msg msg = composer.msg_withdraw(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom=denom) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py index 89423499..f95d55d6 100644 --- a/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py @@ -1,21 +1,20 @@ import asyncio +import json import os import uuid from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -23,13 +22,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -48,53 +56,15 @@ async def main() -> None: cid=str(uuid.uuid4()), ) - # 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_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/8_MsgCancelSpotOrder.py b/examples/chain_client/exchange/8_MsgCancelSpotOrder.py index ab1381db..66a31fb3 100644 --- a/examples/chain_client/exchange/8_MsgCancelSpotOrder.py +++ b/examples/chain_client/exchange/8_MsgCancelSpotOrder.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,13 +20,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -39,48 +47,15 @@ async def main() -> None: sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py index f6703cbe..553cf0ba 100644 --- a/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py +++ b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py @@ -1,21 +1,20 @@ import asyncio +import json import os import uuid from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -23,13 +22,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) subaccount_id = address.get_subaccount_id(index=0) # prepare trade info @@ -126,53 +134,15 @@ async def main() -> None: spot_orders_to_cancel=spot_orders_to_cancel, ) - # 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_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) - - # build tx + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) + 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("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/query/1_SubaccountDeposits.py b/examples/chain_client/exchange/query/1_SubaccountDeposits.py index e4f07c30..24a0f362 100644 --- a/examples/chain_client/exchange/query/1_SubaccountDeposits.py +++ b/examples/chain_client/exchange/query/1_SubaccountDeposits.py @@ -1,4 +1,5 @@ import asyncio +import json import os import dotenv @@ -27,7 +28,7 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) deposits = await client.fetch_subaccount_deposits(subaccount_id=subaccount_id) - print(deposits) + print(json.dumps(deposits, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/query/2_SubaccountDeposit.py b/examples/chain_client/exchange/query/2_SubaccountDeposit.py index 28df1ab0..274d393b 100644 --- a/examples/chain_client/exchange/query/2_SubaccountDeposit.py +++ b/examples/chain_client/exchange/query/2_SubaccountDeposit.py @@ -1,4 +1,5 @@ import asyncio +import json import os import dotenv @@ -27,7 +28,7 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) deposit = await client.fetch_subaccount_deposit(subaccount_id=subaccount_id, denom="inj") - print(deposit) + print(json.dumps(deposit, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/query/3_ExchangeBalances.py b/examples/chain_client/exchange/query/3_ExchangeBalances.py index 86cd43a7..15ade507 100644 --- a/examples/chain_client/exchange/query/3_ExchangeBalances.py +++ b/examples/chain_client/exchange/query/3_ExchangeBalances.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -11,7 +12,7 @@ async def main() -> None: client = AsyncClient(network) balances = await client.fetch_exchange_balances() - print(balances) + print(json.dumps(balances, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/query/4_AggregateVolume.py b/examples/chain_client/exchange/query/4_AggregateVolume.py index 66c5b12f..1c284e79 100644 --- a/examples/chain_client/exchange/query/4_AggregateVolume.py +++ b/examples/chain_client/exchange/query/4_AggregateVolume.py @@ -1,4 +1,5 @@ import asyncio +import json import os import dotenv @@ -26,10 +27,10 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) volume = await client.fetch_aggregate_volume(account=address.to_acc_bech32()) - print(volume) + print(json.dumps(volume, indent=2)) volume = await client.fetch_aggregate_volume(account=subaccount_id) - print(volume) + print(json.dumps(volume, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/query/52_MarketVolatility.py b/examples/chain_client/exchange/query/52_MarketVolatility.py index 50d50991..c1e0900c 100644 --- a/examples/chain_client/exchange/query/52_MarketVolatility.py +++ b/examples/chain_client/exchange/query/52_MarketVolatility.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -23,7 +24,7 @@ async def main() -> None: include_raw_history=include_raw_history, include_metadata=include_metadata, ) - print(volatility) + print(json.dumps(volatility, indent=4)) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/query/58_GrantAuthorizations.py b/examples/chain_client/exchange/query/58_GrantAuthorizations.py index 5ca0009c..0a930e81 100644 --- a/examples/chain_client/exchange/query/58_GrantAuthorizations.py +++ b/examples/chain_client/exchange/query/58_GrantAuthorizations.py @@ -1,4 +1,5 @@ import asyncio +import json import os import dotenv @@ -25,7 +26,7 @@ async def main() -> None: active_grant = await client.fetch_grant_authorizations( granter=address.to_acc_bech32(), ) - print(active_grant) + print(json.dumps(active_grant, indent=4)) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/query/59_L3DerivativeOrderBook.py b/examples/chain_client/exchange/query/59_L3DerivativeOrderBook.py deleted file mode 100644 index 38f10f92..00000000 --- a/examples/chain_client/exchange/query/59_L3DerivativeOrderBook.py +++ /dev/null @@ -1,21 +0,0 @@ -import asyncio - -from pyinjective.async_client_v2 import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - orderbook = await client.fetch_l3_derivative_orderbook( - market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", - ) - print(orderbook) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/58_MarketBalance.py b/examples/chain_client/exchange/query/59_MarketBalance.py similarity index 59% rename from examples/chain_client/exchange/query/58_MarketBalance.py rename to examples/chain_client/exchange/query/59_MarketBalance.py index fc8a8df1..4fe4c760 100644 --- a/examples/chain_client/exchange/query/58_MarketBalance.py +++ b/examples/chain_client/exchange/query/59_MarketBalance.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -6,7 +7,7 @@ async def main() -> None: """ - Demonstrate fetching market balance using AsyncClient. + Demonstrate fetching market balances using AsyncClient. """ # Select network: choose between Network.mainnet(), Network.testnet(), or Network.devnet() network = Network.testnet() @@ -15,13 +16,12 @@ async def main() -> None: client = AsyncClient(network) try: - # Example market ID (replace with an actual market ID from the network) - market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" - - # Fetch market balance - market_balance = await client.fetch_market_balance(market_id=market_id) + # Fetch market balances + market_balance = await client.fetch_market_balance( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + ) print("Market Balance:") - print(market_balance) + print(json.dumps(market_balance, indent=4)) except Exception as ex: print(f"Error occurred: {ex}") diff --git a/examples/chain_client/exchange/query/5_AggregateVolumes.py b/examples/chain_client/exchange/query/5_AggregateVolumes.py index 06fe8152..66b1acd7 100644 --- a/examples/chain_client/exchange/query/5_AggregateVolumes.py +++ b/examples/chain_client/exchange/query/5_AggregateVolumes.py @@ -1,4 +1,5 @@ import asyncio +import json import os import dotenv @@ -27,7 +28,7 @@ async def main() -> None: accounts=[address.to_acc_bech32()], market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], ) - print(volume) + print(json.dumps(volume, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/exchange/query/60_L3SpotOrderBook.py b/examples/chain_client/exchange/query/60_L3SpotOrderBook.py deleted file mode 100644 index f2fee345..00000000 --- a/examples/chain_client/exchange/query/60_L3SpotOrderBook.py +++ /dev/null @@ -1,21 +0,0 @@ -import asyncio - -from pyinjective.async_client_v2 import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - orderbook = await client.fetch_l3_spot_orderbook( - market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", - ) - print(orderbook) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/59_MarketBalances.py b/examples/chain_client/exchange/query/60_MarketBalances.py similarity index 91% rename from examples/chain_client/exchange/query/59_MarketBalances.py rename to examples/chain_client/exchange/query/60_MarketBalances.py index 219a5f62..59981f40 100644 --- a/examples/chain_client/exchange/query/59_MarketBalances.py +++ b/examples/chain_client/exchange/query/60_MarketBalances.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -18,7 +19,7 @@ async def main() -> None: # Fetch market balances market_balances = await client.fetch_market_balances() print("Market Balances:") - print(market_balances) + print(json.dumps(market_balances, indent=4)) except Exception as ex: print(f"Error occurred: {ex}") diff --git a/examples/chain_client/exchange/query/60_DenomMinNotional.py b/examples/chain_client/exchange/query/61_DenomMinNotional.py similarity index 100% rename from examples/chain_client/exchange/query/60_DenomMinNotional.py rename to examples/chain_client/exchange/query/61_DenomMinNotional.py diff --git a/examples/chain_client/exchange/query/61_DenomMinNotionals.py b/examples/chain_client/exchange/query/62_DenomMinNotionals.py similarity index 100% rename from examples/chain_client/exchange/query/61_DenomMinNotionals.py rename to examples/chain_client/exchange/query/62_DenomMinNotionals.py diff --git a/examples/chain_client/exchange/query/56_L3DerivativeOrderBook.py b/examples/chain_client/exchange/query/63_L3DerivativeOrderBook.py similarity index 100% rename from examples/chain_client/exchange/query/56_L3DerivativeOrderBook.py rename to examples/chain_client/exchange/query/63_L3DerivativeOrderBook.py diff --git a/examples/chain_client/exchange/query/57_L3SpotOrderBook.py b/examples/chain_client/exchange/query/64_L3SpotOrderBook.py similarity index 100% rename from examples/chain_client/exchange/query/57_L3SpotOrderBook.py rename to examples/chain_client/exchange/query/64_L3SpotOrderBook.py diff --git a/examples/chain_client/exchange/query/6_AggregateMarketVolume.py b/examples/chain_client/exchange/query/6_AggregateMarketVolume.py index d1ce6c8b..fef7714c 100644 --- a/examples/chain_client/exchange/query/6_AggregateMarketVolume.py +++ b/examples/chain_client/exchange/query/6_AggregateMarketVolume.py @@ -1,4 +1,5 @@ import asyncio +import json from pyinjective.async_client_v2 import AsyncClient from pyinjective.core.network import Network @@ -14,7 +15,7 @@ async def main() -> None: market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" volume = await client.fetch_aggregate_market_volume(market_id=market_id) - print(volume) + print(json.dumps(volume, indent=2)) if __name__ == "__main__": diff --git a/examples/chain_client/insurance/1_MsgCreateInsuranceFund.py b/examples/chain_client/insurance/1_MsgCreateInsuranceFund.py index 5aec1df7..9eb0156f 100644 --- a/examples/chain_client/insurance/1_MsgCreateInsuranceFund.py +++ b/examples/chain_client/insurance/1_MsgCreateInsuranceFund.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -22,13 +21,22 @@ async def main() -> None: # set custom cookie location (optional) - defaults to current dir client = AsyncClient(network) composer = await client.composer() - await client.sync_timeout_height() - # load account - priv_key = PrivateKey.from_hex(configured_private_key) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) msg = composer.msg_create_insurance_fund( sender=address.to_acc_bech32(), @@ -41,48 +49,15 @@ async def main() -> None: initial_deposit=1000, ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/insurance/2_MsgUnderwrite.py b/examples/chain_client/insurance/2_MsgUnderwrite.py index 000625f7..d717d798 100644 --- a/examples/chain_client/insurance/2_MsgUnderwrite.py +++ b/examples/chain_client/insurance/2_MsgUnderwrite.py @@ -1,20 +1,19 @@ import asyncio +import json import os from decimal import Decimal import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -23,13 +22,22 @@ async def main() -> None: # set custom cookie location (optional) - defaults to current dir client = AsyncClient(network) composer = await client.composer() - await client.sync_timeout_height() - # load account - priv_key = PrivateKey.from_hex(configured_private_key) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) token_decimals = 6 amount = 100 @@ -42,48 +50,15 @@ async def main() -> None: amount=int(chain_amount), ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/insurance/3_MsgRequestRedemption.py b/examples/chain_client/insurance/3_MsgRequestRedemption.py index 7f39c7e9..6bd79ab2 100644 --- a/examples/chain_client/insurance/3_MsgRequestRedemption.py +++ b/examples/chain_client/insurance/3_MsgRequestRedemption.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -22,13 +21,22 @@ async def main() -> None: # set custom cookie location (optional) - defaults to current dir client = AsyncClient(network) composer = await client.composer() - await client.sync_timeout_height() - # load account - priv_key = PrivateKey.from_hex(configured_private_key) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) msg = composer.msg_request_redemption( sender=address.to_acc_bech32(), @@ -37,48 +45,15 @@ async def main() -> None: amount=100, # raw chain value ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py b/examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py index 885ffcb2..003e7972 100644 --- a/examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py +++ b/examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,13 +20,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) price = 100 price_to_send = [str(int(price * 10**18))] @@ -39,48 +47,15 @@ async def main() -> None: sender=address.to_acc_bech32(), price=price_to_send, base=base, quote=quote ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/oracle/2_MsgRelayProviderPrices.py b/examples/chain_client/oracle/2_MsgRelayProviderPrices.py index c681d777..950d77aa 100644 --- a/examples/chain_client/oracle/2_MsgRelayProviderPrices.py +++ b/examples/chain_client/oracle/2_MsgRelayProviderPrices.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,13 +20,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) provider = "ufc" symbols = ["KHABIB-TKO-05/30/2023", "KHABIB-TKO-05/26/2023"] @@ -38,53 +46,15 @@ async def main() -> None: sender=address.to_acc_bech32(), provider=provider, symbols=symbols, prices=prices ) - # 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_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/peggy/1_MsgSendToEth.py b/examples/chain_client/peggy/1_MsgSendToEth.py index 4f369a8a..e1e38d7b 100644 --- a/examples/chain_client/peggy/1_MsgSendToEth.py +++ b/examples/chain_client/peggy/1_MsgSendToEth.py @@ -1,21 +1,20 @@ import asyncio +import json import os from decimal import Decimal import dotenv import requests -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -23,13 +22,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) # prepare msg asset = "injective-protocol" @@ -49,48 +57,15 @@ async def main() -> None: bridge_fee=chain_bridge_fee, ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/staking/1_MsgDelegate.py b/examples/chain_client/staking/1_MsgDelegate.py index 33b13889..93472d80 100644 --- a/examples/chain_client/staking/1_MsgDelegate.py +++ b/examples/chain_client/staking/1_MsgDelegate.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -21,13 +20,22 @@ async def main() -> None: # 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) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) # prepare tx msg validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" @@ -37,48 +45,15 @@ async def main() -> None: delegator_address=address.to_acc_bech32(), validator_address=validator_address, amount=amount ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/tokenfactory/4_MsgChangeAdmin.py b/examples/chain_client/tokenfactory/4_MsgChangeAdmin.py index 3a311586..566ab321 100644 --- a/examples/chain_client/tokenfactory/4_MsgChangeAdmin.py +++ b/examples/chain_client/tokenfactory/4_MsgChangeAdmin.py @@ -24,7 +24,7 @@ async def main() -> None: # 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) - message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( network=network, private_key=private_key_in_hexa, gas_price=gas_price, diff --git a/examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py b/examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py index 993dc953..24549c1b 100644 --- a/examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py +++ b/examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py @@ -24,7 +24,7 @@ async def main() -> None: # 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) - message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( network=network, private_key=private_key_in_hexa, gas_price=gas_price, diff --git a/examples/chain_client/wasm/1_MsgExecuteContract.py b/examples/chain_client/wasm/1_MsgExecuteContract.py index ce939f6c..8d6081eb 100644 --- a/examples/chain_client/wasm/1_MsgExecuteContract.py +++ b/examples/chain_client/wasm/1_MsgExecuteContract.py @@ -1,19 +1,18 @@ import asyncio +import json import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() @@ -22,13 +21,22 @@ async def main() -> None: # set custom cookie location (optional) - defaults to current dir client = AsyncClient(network) composer = await client.composer() - await client.sync_timeout_height() - # load account - priv_key = PrivateKey.from_hex(configured_private_key) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) # prepare tx msg # NOTE: COIN MUST BE SORTED IN ALPHABETICAL ORDER BY DENOMS @@ -47,48 +55,15 @@ async def main() -> None: funds=funds, ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/examples/chain_client/wasmx/1_MsgExecuteContractCompat.py b/examples/chain_client/wasmx/1_MsgExecuteContractCompat.py index 7c413fd5..6d845045 100644 --- a/examples/chain_client/wasmx/1_MsgExecuteContractCompat.py +++ b/examples/chain_client/wasmx/1_MsgExecuteContractCompat.py @@ -3,31 +3,38 @@ import os import dotenv -from grpc import RpcError from pyinjective.async_client_v2 import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT +from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network -from pyinjective.transaction import Transaction from pyinjective.wallet import PrivateKey async def main() -> None: dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") # select network: local, testnet, mainnet network = Network.testnet() client = AsyncClient(network) composer = await client.composer() - await client.sync_timeout_height() - # load account - priv_key = PrivateKey.from_hex(configured_private_key) + 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) + + message_broadcaster = MsgBroadcasterWithPk.new_using_gas_heuristics( + network=network, + private_key=private_key_in_hexa, + gas_price=gas_price, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) # prepare tx msg # NOTE: COIN MUST BE SORTED IN ALPHABETICAL ORDER BY DENOMS @@ -44,48 +51,15 @@ async def main() -> None: funds=funds, ) - # 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 + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(json.dumps(result, indent=2)) - # 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)) + message_broadcaster.update_gas_price(gas_price=gas_price) if __name__ == "__main__": diff --git a/pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py b/pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py index d931701b..fd9df5fd 100644 --- a/pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py +++ b/pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py @@ -575,6 +575,51 @@ async def fetch_market_atomic_execution_fee_multiplier( return response + async def fetch_l3_derivative_orderbook( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFullDerivativeOrderbookRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.L3DerivativeOrderBook, request=request) + + return response + + async def fetch_l3_spot_orderbook( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFullSpotOrderbookRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.L3SpotOrderBook, request=request) + + return response + + async def fetch_market_balance(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryMarketBalanceRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.MarketBalance, request=request) + + return response + + async def fetch_market_balances(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryMarketBalancesRequest() + response = await self._execute_call(call=self._stub.MarketBalances, request=request) + + return response + + async def fetch_denom_min_notional(self, denom: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryDenomMinNotionalRequest(denom=denom) + response = await self._execute_call(call=self._stub.DenomMinNotional, request=request) + + return response + + async def fetch_denom_min_notionals(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryDenomMinNotionalsRequest() + response = await self._execute_call(call=self._stub.DenomMinNotionals, request=request) + return response + async def fetch_active_stake_grant(self, grantee: str) -> Dict[str, Any]: request = exchange_query_pb.QueryActiveStakeGrantRequest(grantee=grantee) response = await self._execute_call(call=self._stub.ActiveStakeGrant, request=request) @@ -600,27 +645,5 @@ async def fetch_grant_authorizations(self, granter: str) -> Dict[str, Any]: return response - async def fetch_l3_derivative_orderbook( - self, - market_id: str, - ) -> Dict[str, Any]: - request = exchange_query_pb.QueryFullDerivativeOrderbookRequest( - market_id=market_id, - ) - response = await self._execute_call(call=self._stub.L3DerivativeOrderBook, request=request) - - return response - - async def fetch_l3_spot_orderbook( - self, - market_id: str, - ) -> Dict[str, Any]: - request = exchange_query_pb.QueryFullSpotOrderbookRequest( - market_id=market_id, - ) - response = await self._execute_call(call=self._stub.L3SpotOrderBook, request=request) - - return response - async def _execute_call(self, call: Callable, request) -> Dict[str, Any]: return await self._assistant.execute_call(call=call, request=request) diff --git a/tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py b/tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py index c3da9415..fa361011 100644 --- a/tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py +++ b/tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py @@ -70,6 +70,10 @@ def __init__(self): self.grant_authorizations_responses = deque() self.l3_derivative_orderbook_responses = deque() self.l3_spot_orderbook_responses = deque() + self.market_balance_responses = deque() + self.market_balances_responses = deque() + self.denom_min_notional_responses = deque() + self.denom_min_notionals_responses = deque() async def QueryExchangeParams( self, request: exchange_query_pb.QueryExchangeParamsRequest, context=None, metadata=None @@ -359,3 +363,19 @@ async def L3SpotOrderBook( self, request: exchange_query_pb.QueryFullSpotOrderbookRequest, context=None, metadata=None ): return self.l3_spot_orderbook_responses.pop() + + async def MarketBalance(self, request: exchange_query_pb.QueryMarketBalanceRequest, context=None, metadata=None): + return self.market_balance_responses.pop() + + async def MarketBalances(self, request: exchange_query_pb.QueryMarketBalancesRequest, context=None, metadata=None): + return self.market_balances_responses.pop() + + async def DenomMinNotional( + self, request: exchange_query_pb.QueryDenomMinNotionalRequest, context=None, metadata=None + ): + return self.denom_min_notional_responses.pop() + + async def DenomMinNotionals( + self, request: exchange_query_pb.QueryDenomMinNotionalsRequest, context=None, metadata=None + ): + return self.denom_min_notionals_responses.pop() diff --git a/tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py b/tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py index c7e10286..ab049edf 100644 --- a/tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py +++ b/tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py @@ -2647,6 +2647,116 @@ async def test_fetch_l3_spot_orderbook( assert orderbook == expected_orderbook + @pytest.mark.asyncio + async def test_fetch_market_balance( + self, + exchange_servicer, + ): + market_balance = exchange_query_pb.MarketBalance( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + balance="1000000000000000000", + ) + response = exchange_query_pb.QueryMarketBalanceResponse( + balance=market_balance, + ) + exchange_servicer.market_balance_responses.append(response) + + api = self._api_instance(servicer=exchange_servicer) + + market_balance_response = await api.fetch_market_balance( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + ) + expected_market_balance = { + "balance": { + "marketId": market_balance.market_id, + "balance": market_balance.balance, + } + } + + assert market_balance_response == expected_market_balance + + @pytest.mark.asyncio + async def test_fetch_market_balances( + self, + exchange_servicer, + ): + balance1 = exchange_query_pb.MarketBalance( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + balance="1000000000000000000", + ) + balance2 = exchange_query_pb.MarketBalance( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + balance="2000000000000000000", + ) + response = exchange_query_pb.QueryMarketBalancesResponse(balances=[balance1, balance2]) + exchange_servicer.market_balances_responses.append(response) + + api = self._api_instance(servicer=exchange_servicer) + + market_balances_response = await api.fetch_market_balances() + expected_market_balances = { + "balances": [ + { + "marketId": balance1.market_id, + "balance": balance1.balance, + }, + { + "marketId": balance2.market_id, + "balance": balance2.balance, + }, + ] + } + + assert market_balances_response == expected_market_balances + + @pytest.mark.asyncio + async def test_fetch_denom_min_notional( + self, + exchange_servicer, + ): + amount = "1" # Decimal as a string + response = exchange_query_pb.QueryDenomMinNotionalResponse( + amount=amount, + ) + exchange_servicer.denom_min_notional_responses.append(response) + + api = self._api_instance(servicer=exchange_servicer) + + denom_min_notional_response = await api.fetch_denom_min_notional( + denom="peggy0xf9152067989BDc8783fF586624124C05A529A5D1" + ) + expected_denom_min_notional = {"amount": amount} + + assert denom_min_notional_response == expected_denom_min_notional + + @pytest.mark.asyncio + async def test_fetch_denom_min_notionals( + self, + exchange_servicer, + ): + denom_min_notional = exchange_pb.DenomMinNotional( + denom="inj", + min_notional="5000000000000000000", + ) + response = exchange_query_pb.QueryDenomMinNotionalsResponse( + denom_min_notionals=[denom_min_notional], + ) + exchange_servicer.denom_min_notionals_responses.append(response) + + api = self._api_instance(servicer=exchange_servicer) + + denom_min_notionals_response = await api.fetch_denom_min_notionals() + expected_denom_min_notionals = { + "denomMinNotionals": [ + { + "denom": denom_min_notional.denom, + "minNotional": denom_min_notional.min_notional, + } + ] + } + + assert denom_min_notionals_response == expected_denom_min_notionals + def _api_instance(self, servicer): network = Network.devnet() channel = grpc.aio.insecure_channel(network.grpc_endpoint)