-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/add support exchange v2 #354
base: dev
Are you sure you want to change the base?
Conversation
…xed all failing tests
…include new V2 chain stream protos. Fixed all failing tests
…ies and messages. Added tests for the deprecated V1 methods. Updated all example scripts related to Exchange module
…lient to get markets from the chain. Removed logic in Composer to load markets and tokens from the denom INI files
…e not going to include that in chain core
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThis pull request encompasses a wide-ranging update across various modules in the Injective ecosystem. Key changes include modifications to the Changes
Possibly related PRs
Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.
🛑 Comments failed to post (38)
examples/chain_client/tx/query/1_GetTx.py (1)
8-8: 💡 Codebase verification
Based on the search results, I can now generate the final response since I have enough information to verify the network configuration change:
Network configuration change requires attention
The switch from
testnet()
todevnet()
in this example file is inconsistent with the rest of the codebase. The search results show that almost all example files (180+ files) useNetwork.testnet()
, with only 7 files usingdevnet()
and these are specifically in the permissions module examples.
examples/chain_client/tx/query/1_GetTx.py
should maintain consistency with other example files by usingNetwork.testnet()
🔗 Analysis chain
Verify the network configuration change.
The switch from
testnet()
todevnet()
might impact example execution and documentation. Given that this PR is about Exchange V2 support, we should ensure this environment change aligns with where V2 features are currently deployed.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check if other example files consistently use devnet # and verify if there's documentation about the network requirement # Check network configuration across all example files echo "Checking network configuration in example files..." rg -l "Network\." examples/ | xargs rg "Network\.(testnet|devnet|mainnet)" # Check if there's documentation about network requirements echo "Checking for network documentation..." fd -t f "README" examples/ | xargs rg -i "network|devnet|testnet"Length of output: 174929
examples/chain_client/exchange/query/60_L3SpotOrderBook.py (2)
20-21: 🛠️ Refactor suggestion
Use modern asyncio patterns.
Replace the deprecated
get_event_loop().run_until_complete()
with the modernasyncio.run()
.if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) + asyncio.run(main())📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if __name__ == "__main__": asyncio.run(main())
7-17: 🛠️ Refactor suggestion
Add error handling and documentation.
The example would benefit from:
- Error handling for potential network/gRPC failures
- Documentation explaining the market ID and response format
- Proper cleanup of client resources
Consider this improved implementation:
async def main() -> None: + """ + Example demonstrating how to fetch L3 spot orderbook using Exchange V2. + + Market ID represents INJ/USDT spot market on testnet. + Response includes buy/sell orders with price levels and quantities. + """ # select network: local, testnet, mainnet network = Network.testnet() # initialize grpc client client = AsyncClient(network) + try: + orderbook = await client.fetch_l3_spot_orderbook_v2( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(orderbook) + except Exception as e: + print(f"Failed to fetch orderbook: {e}") + finally: + await client.close() - orderbook = await client.fetch_l3_spot_orderbook_v2( - market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", - ) - print(orderbook)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async def main() -> None: """ Example demonstrating how to fetch L3 spot orderbook using Exchange V2. Market ID represents INJ/USDT spot market on testnet. Response includes buy/sell orders with price levels and quantities. """ # select network: local, testnet, mainnet network = Network.testnet() # initialize grpc client client = AsyncClient(network) try: orderbook = await client.fetch_l3_spot_orderbook_v2( market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", ) print(orderbook) except Exception as e: print(f"Failed to fetch orderbook: {e}") finally: await client.close()
examples/chain_client/exchange/query/59_L3DerivativeOrderBook.py (1)
7-17: 🛠️ Refactor suggestion
Add error handling and improve documentation.
As this is an example script, it should demonstrate proper error handling and provide clear documentation for users.
Consider applying these improvements:
-async def main() -> None: +async def main() -> None: + """Fetch and display L3 derivative orderbook data. + + Market ID represents INJ/USDT perpetual futures market on testnet. + The orderbook response includes buy and sell orders with price levels. + """ # select network: local, testnet, mainnet network = Network.testnet() # initialize grpc client client = AsyncClient(network) - orderbook = await client.fetch_l3_derivative_orderbook_v2( - market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", - ) - print(orderbook) + try: + orderbook = await client.fetch_l3_derivative_orderbook_v2( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print("L3 Derivative Orderbook:") + print(f"Market ID: {orderbook.market_id}") + print("\nBuy Orders:") + for order in orderbook.buys: + print(f" Price: {order.price}, Quantity: {order.quantity}") + print("\nSell Orders:") + for order in orderbook.sells: + print(f" Price: {order.price}, Quantity: {order.quantity}") + except Exception as e: + print(f"Error fetching orderbook: {str(e)}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async def main() -> None: """Fetch and display L3 derivative orderbook data. Market ID represents INJ/USDT perpetual futures market on testnet. The orderbook response includes buy and sell orders with price levels. """ # select network: local, testnet, mainnet network = Network.testnet() # initialize grpc client client = AsyncClient(network) try: orderbook = await client.fetch_l3_derivative_orderbook_v2( market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", ) print("L3 Derivative Orderbook:") print(f"Market ID: {orderbook.market_id}") print("\nBuy Orders:") for order in orderbook.buys: print(f" Price: {order.price}, Quantity: {order.quantity}") print("\nSell Orders:") for order in orderbook.sells: print(f" Price: {order.price}, Quantity: {order.quantity}") except Exception as e: print(f"Error fetching orderbook: {str(e)}")
examples/chain_client/exchange/query/56_ActiveStakeGrant.py (2)
26-27: 🛠️ Refactor suggestion
Use modern asyncio patterns.
The current event loop pattern is deprecated. Use
asyncio.run()
instead for better error handling and cleaner code.if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) + asyncio.run(main())📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if __name__ == "__main__": asyncio.run(main())
10-23:
⚠️ Potential issueAdd error handling and input validation.
The implementation needs several improvements for robustness:
- Add error handling for missing environment variables
- Validate the grantee address format
- Properly close the AsyncClient
Here's the suggested implementation:
async def main() -> None: dotenv.load_dotenv() - grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + if not grantee_public_address: + raise ValueError("INJECTIVE_GRANTEE_PUBLIC_ADDRESS environment variable is required") + + # Basic address format validation + if not grantee_public_address.startswith("inj"): + raise ValueError("Invalid Injective address format") # select network: local, testnet, mainnet network = Network.testnet() # initialize grpc client client = AsyncClient(network) + try: + active_grant = await client.fetch_active_stake_grant( + grantee=grantee_public_address, + ) + print(active_grant) + finally: + await client.close() - active_grant = await client.fetch_active_stake_grant( - grantee=grantee_public_address, - ) - print(active_grant)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async def main() -> None: dotenv.load_dotenv() grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") if not grantee_public_address: raise ValueError("INJECTIVE_GRANTEE_PUBLIC_ADDRESS environment variable is required") # Basic address format validation if not grantee_public_address.startswith("inj"): raise ValueError("Invalid Injective address format") # select network: local, testnet, mainnet network = Network.testnet() # initialize grpc client client = AsyncClient(network) try: active_grant = await client.fetch_active_stake_grant( grantee=grantee_public_address, ) print(active_grant) finally: await client.close()
examples/chain_client/exchange/query/5_AggregateVolumes.py (1)
26-29: 🛠️ Refactor suggestion
Add error handling for the API call.
The example should demonstrate proper error handling for production use.
- volume = await client.fetch_aggregate_volumes_v2( - accounts=[address.to_acc_bech32()], - market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], - ) - print(volume) + try: + volume = await client.fetch_aggregate_volumes_v2( + accounts=[address.to_acc_bech32()], + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(volume) + except Exception as e: + print(f"Failed to fetch aggregate volumes: {str(e)}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try: volume = await client.fetch_aggregate_volumes_v2( accounts=[address.to_acc_bech32()], market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], ) print(volume) except Exception as e: print(f"Failed to fetch aggregate volumes: {str(e)}")
examples/chain_client/exchange/query/58_GrantAuthorizations.py (4)
12-14:
⚠️ Potential issueAdd error handling for environment variables.
The script should gracefully handle missing or invalid environment variables.
- dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + if not dotenv.load_dotenv(): + raise RuntimeError("Failed to load .env file") + + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + if not configured_private_key: + raise ValueError("INJECTIVE_PRIVATE_KEY environment variable is not set")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if not dotenv.load_dotenv(): raise RuntimeError("Failed to load .env file") configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") if not configured_private_key: raise ValueError("INJECTIVE_PRIVATE_KEY environment variable is not set")
21-23:
⚠️ Potential issueAdd error handling for private key conversion.
The private key conversion should be wrapped in a try-catch block to handle invalid keys gracefully.
- priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() + try: + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + except ValueError as e: + raise ValueError(f"Invalid private key format: {e}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try: priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() except ValueError as e: raise ValueError(f"Invalid private key format: {e}")
31-32: 🛠️ Refactor suggestion
Update to modern asyncio pattern.
Replace the deprecated event loop pattern with
asyncio.run()
for better compatibility with Python 3.7+.if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) + asyncio.run(main())📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if __name__ == "__main__": asyncio.run(main())
25-28:
⚠️ Potential issueAdd error handling for API call and cleanup resources.
The API call should handle potential exceptions, and the client should be properly cleaned up after use.
- active_grant = await client.fetch_grant_authorizations( - granter=address.to_acc_bech32(), - ) - print(active_grant) + try: + active_grant = await client.fetch_grant_authorizations( + granter=address.to_acc_bech32(), + ) + print(active_grant) + except Exception as e: + print(f"Failed to fetch grant authorizations: {e}") + raise + finally: + await client.close()📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try: active_grant = await client.fetch_grant_authorizations( granter=address.to_acc_bech32(), ) print(active_grant) except Exception as e: print(f"Failed to fetch grant authorizations: {e}") raise finally: await client.close()
buf.gen.yaml (1)
26-28:
⚠️ Potential issueReplace feature branch with official release tag.
Using a feature branch (
feat/update_chain_stream_for_exchange_v2
) in production dependencies is risky as they're unstable and can change unexpectedly. According to the PR objectives, this PR should not be merged until the Exchange V2 protobufs are in an official chain release and this file references an official tag.Wait for the official release and then apply this change:
- git_repo: https://github.com/InjectiveLabs/injective-core - branch: feat/update_chain_stream_for_exchange_v2 + tag: <official-release-tag> subdir: protoCommittable suggestion skipped: line range outside the PR's diff.
examples/chain_client/exchange/query/57_GrantAuthorization.py (4)
33-34: 🛠️ Refactor suggestion
Update asyncio usage to modern pattern.
The
get_event_loop().run_until_complete()
pattern is deprecated. Useasyncio.run()
instead.Apply this improvement:
if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) + asyncio.run(main())📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if __name__ == "__main__": asyncio.run(main())
22-24: 🛠️ Refactor suggestion
Add error handling for key conversion.
The private key conversion could fail if the input format is invalid. Consider adding try-catch block to handle potential errors gracefully.
Consider this improvement:
- priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() + try: + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + except ValueError as e: + raise ValueError(f"Invalid private key format: {e}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try: priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() except ValueError as e: raise ValueError(f"Invalid private key format: {e}")
26-30: 🛠️ Refactor suggestion
Enhance error handling and response formatting.
The current implementation could benefit from proper error handling and formatted output.
Consider these improvements:
- active_grant = await client.fetch_grant_authorization( - granter=address.to_acc_bech32(), - grantee=grantee_public_address, - ) - print(active_grant) + try: + active_grant = await client.fetch_grant_authorization( + granter=address.to_acc_bech32(), + grantee=grantee_public_address, + ) + print("Grant Authorization Details:") + print(f"Granter: {address.to_acc_bech32()}") + print(f"Grantee: {grantee_public_address}") + print(f"Authorization: {active_grant}") + except Exception as e: + print(f"Error fetching grant authorization: {e}") + raise📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try: active_grant = await client.fetch_grant_authorization( granter=address.to_acc_bech32(), grantee=grantee_public_address, ) print("Grant Authorization Details:") print(f"Granter: {address.to_acc_bech32()}") print(f"Grantee: {grantee_public_address}") print(f"Authorization: {active_grant}") except Exception as e: print(f"Error fetching grant authorization: {e}") raise
11-15: 🛠️ Refactor suggestion
Add environment variable validation and error handling.
The script should validate that required environment variables are present and contain valid values before proceeding.
Consider applying this improvement:
async def main() -> None: dotenv.load_dotenv() configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + + if not configured_private_key or not grantee_public_address: + raise ValueError( + "Missing required environment variables. Please ensure INJECTIVE_PRIVATE_KEY " + "and INJECTIVE_GRANTEE_PUBLIC_ADDRESS are set in your .env file" + )📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async def main() -> None: dotenv.load_dotenv() configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") if not configured_private_key or not grantee_public_address: raise ValueError( "Missing required environment variables. Please ensure INJECTIVE_PRIVATE_KEY " "and INJECTIVE_GRANTEE_PUBLIC_ADDRESS are set in your .env file" )
examples/chain_client/2_StreamEventOrderFail.py (1)
35-36: 🛠️ Refactor suggestion
Add error handling for event processing.
While the path updates for Exchange V2 are correct, the code lacks error handling for missing or malformed events.
Consider wrapping the event processing in a try-except block:
- failed_order_hashes = json.loads(result["events"]["injective.exchange.v2.EventOrderFail.hashes"][0]) - failed_order_codes = json.loads(result["events"]["injective.exchange.v2.EventOrderFail.flags"][0]) + try: + failed_order_hashes = json.loads(result["events"]["injective.exchange.v2.EventOrderFail.hashes"][0]) + failed_order_codes = json.loads(result["events"]["injective.exchange.v2.EventOrderFail.flags"][0]) + except (KeyError, IndexError, json.JSONDecodeError) as e: + print(f"Error processing event: {e}") + continue📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try: failed_order_hashes = json.loads(result["events"]["injective.exchange.v2.EventOrderFail.hashes"][0]) failed_order_codes = json.loads(result["events"]["injective.exchange.v2.EventOrderFail.flags"][0]) except (KeyError, IndexError, json.JSONDecodeError) as e: print(f"Error processing event: {e}") continue
examples/chain_client/ibc/transfer/1_MsgTransfer.py (1)
39-42: 🛠️ Refactor suggestion
Add validation and improve clarity of token amount calculation.
While the use of Decimal for precise calculations is good, consider adding basic validation:
token_decimals = 18 +# Validate transfer amount is positive transfer_amount = Decimal("0.1") * Decimal(f"1e{token_decimals}") +if transfer_amount <= 0: + raise ValueError("Transfer amount must be positive") inj_chain_denom = "inj" token_amount = composer.coin(amount=int(transfer_amount), denom=inj_chain_denom)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.token_decimals = 18 # Validate transfer amount is positive transfer_amount = Decimal("0.1") * Decimal(f"1e{token_decimals}") if transfer_amount <= 0: raise ValueError("Transfer amount must be positive") inj_chain_denom = "inj" token_amount = composer.coin(amount=int(transfer_amount), denom=inj_chain_denom)
examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py (1)
41-41: 💡 Codebase verification
🛠️ Refactor suggestion
Based on the gathered information, I can now generate the final response.
Add documentation for the factory quote denom format
The factory quote denom format (
factory/<creator_address>/<subdenom>
) is used consistently across spot, perpetual, and futures market launches, but lacks documentation. Add the following comment to explain the format:message = composer.msg_instant_perpetual_market_launch_v2( sender=address.to_acc_bech32(), ticker="INJ/USDC PERP", + # Quote denom format: factory/<creator_address>/<subdenom> + # creator_address: The Injective address that created the token + # subdenom: The token's subdenom (e.g., 'usdc') quote_denom="factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/usdc",Evidence:
- The format is used in multiple market launch examples but lacks explanation
- Token factory module tests confirm this is the expected format (e.g.,
"factory/inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0/ninja"
)- The format is part of the token factory module's core functionality for creating and managing custom tokens
🔗 Analysis chain
Document the factory quote denom format.
The quote denom now uses a factory address format (
factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/usdc
). This is a breaking change that requires documentation.Add a comment explaining the factory quote denom format:
message = composer.msg_instant_perpetual_market_launch_v2( sender=address.to_acc_bech32(), ticker="INJ/USDC PERP", + # Quote denom format: factory/<creator_address>/<subdenom> quote_denom="factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/usdc",
Let's verify the factory address format consistency:
Let me search for any existing documentation about the factory quote denom format.
Let me check for any existing comments or documentation in the example files.
Let me check if there are any related test files or documentation that might explain the factory denom format.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify quote denom factory address format usage # Expected: Should find consistent usage of factory address format # Check for factory address format usage echo "Checking factory address format usage..." rg "factory/inj\w+/usdc" --type py -B 2 -A 2Length of output: 1797
Script:
#!/bin/bash # Look for documentation about factory quote denom format echo "Searching for documentation in Python files..." rg -i "factory.*denom" --type py -B 2 -A 2 echo -e "\nSearching for documentation in markdown files..." rg -i "factory.*denom|quote.*denom" --type md -B 2 -A 2 echo -e "\nChecking docstrings in relevant files..." rg "\"\"\".*factory.*denom|'''.*factory.*denom" --multiline --type pyLength of output: 34918
Script:
#!/bin/bash # Look for comments or documentation in example files echo "Checking example files for documentation..." rg -B 2 -A 2 "quote_denom.*factory" examples/ rg -B 2 -A 2 "# .*factory.*denom" examples/ rg -B 2 -A 2 "\"\"\".*factory.*denom" examples/Length of output: 1897
Script:
#!/bin/bash # Look for test files and documentation related to factory denom echo "Checking test files..." fd -t f "test.*token_factory" -x cat {} echo -e "\nChecking for token factory documentation..." fd -t f "README|CHANGELOG|docs" -x rg -i "factory.*denom|token.*factory" {}Length of output: 5781
examples/chain_client/exchange/1_MsgDeposit.py (1)
34-34: 🛠️ Refactor suggestion
Add documentation for V2 API changes and migration.
This example demonstrates the new V2 deposit message, but lacks documentation about important API changes:
- The amount parameter is now an integer instead of float
- The denom format has changed to lowercase
- V1 deposit method is being deprecated
Add a docstring explaining the changes:
+# Example of depositing funds using Exchange V2 API +# Note: This example uses msg_deposit_v2 which expects: +# - amount as integer (e.g., 1 instead of 0.000001) +# - denom in lowercase format (e.g., "inj" instead of "INJ") +# The older msg_deposit (V1) is deprecated and will be removed in future versions. msg = composer.msg_deposit_v2(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="inj")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.# Example of depositing funds using Exchange V2 API # Note: This example uses msg_deposit_v2 which expects: # - amount as integer (e.g., 1 instead of 0.000001) # - denom in lowercase format (e.g., "inj" instead of "INJ") # The older msg_deposit (V1) is deprecated and will be removed in future versions. msg = composer.msg_deposit_v2(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="inj")
examples/chain_client/insurance/1_MsgCreateInsuranceFund.py (1)
35-39: 🛠️ Refactor suggestion
Add parameter validation and documentation.
Several critical parameters have been updated:
- The ticker format includes a timestamp (5202d32a9-1701406800-SF)
- quote_denom now uses a specific Peggy contract address
- oracle_type is now a string enum ("Band")
Consider adding:
- Input validation for the ticker format
- Documentation for valid oracle_type values
- Verification of the Peggy contract address
msg = composer.msg_create_insurance_fund( + # Ticker format: <id>-<timestamp>-SF sender=address.to_acc_bech32(), ticker="5202d32a9-1701406800-SF", + # Peggy contract address for USDT quote_denom="peggy0xdAC17F958D2ee523a2206206994597C13D831ec7", oracle_base="Frontrunner", oracle_quote="Frontrunner", + # Supported values: "Band", "Pyth", "Provider" oracle_type="Band", expiry=-2, initial_deposit=1000, )📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.msg = composer.msg_create_insurance_fund( # Ticker format: <id>-<timestamp>-SF sender=address.to_acc_bech32(), ticker="5202d32a9-1701406800-SF", # Peggy contract address for USDT quote_denom="peggy0xdAC17F958D2ee523a2206206994597C13D831ec7", oracle_base="Frontrunner", oracle_quote="Frontrunner", # Supported values: "Band", "Pyth", "Provider" oracle_type="Band", expiry=-2, initial_deposit=1000, )
examples/chain_client/insurance/2_MsgUnderwrite.py (1)
34-36: 🛠️ Refactor suggestion
Consider making token_decimals configurable.
The hardcoded value of 6 for
token_decimals
might not work for all tokens. Different tokens can have different decimal places (e.g., USDT typically has 6, while others might have 18).Consider fetching the decimals from a configuration or token metadata:
-token_decimals = 6 +# Fetch from token metadata or config +token_decimals = get_token_decimals(quote_denom) amount = 100 chain_amount = Decimal(str(amount)) * Decimal(f"1e{token_decimals}")Committable suggestion skipped: line range outside the PR's diff.
examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py (1)
38-45: 🛠️ Refactor suggestion
Document the new V2 parameters and improve example usability.
While the code correctly demonstrates the new V2 message structure, it could be more helpful for users migrating from V1 to V2.
Consider these improvements:
- msg = composer.msg_cancel_derivative_order_v2( - sender=address.to_acc_bech32(), - market_id=market_id, - subaccount_id=subaccount_id, - order_hash=order_hash, - is_buy=True, - is_market_order=False, - is_conditional=False, - ) + # New in V2: Additional parameters required for canceling orders + # is_buy: True for buy orders, False for sell orders + # is_market_order: True for market orders, False for limit orders + # is_conditional: True for conditional orders (e.g., stop-loss), False otherwise + + # Fetch the original order details to ensure correct cancellation parameters + # In a real scenario, you would typically: + # 1. Fetch the order details using the order_hash + # 2. Extract is_buy, is_market_order, and is_conditional from the order + + msg = composer.msg_cancel_derivative_order_v2( + sender=address.to_acc_bech32(), + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + # These values should match the original order's properties + is_buy=True, # Example: True for buy orders + is_market_order=False, # Example: False for limit orders + is_conditional=False, # Example: False for regular orders + )Additionally, consider adding parameter validation:
def validate_order_params(is_buy: bool, is_market_order: bool, is_conditional: bool) -> None: """Validate the order parameters match the original order to prevent cancellation failures.""" if not isinstance(is_buy, bool) or not isinstance(is_market_order, bool) or not isinstance(is_conditional, bool): raise ValueError("Order parameters must be boolean values")examples/chain_client/peggy/1_MsgSendToEth.py (1)
40-41: 🛠️ Refactor suggestion
Consider making token decimals configurable.
The hardcoded
token_decimals = 6
might not work for all tokens. Consider making this configurable or fetching it dynamically based on the token being bridged.-token_decimals = 6 +# Fetch from token registry or pass as parameter +token_decimals = get_token_decimals("inj") # or pass as parameterCommittable suggestion skipped: line range outside the PR's diff.
examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py (1)
38-45: 🛠️ Refactor suggestion
Add documentation for new V2 parameters
The example uses hardcoded values for the new V2 parameters (
is_buy=True, is_market_order=False, is_conditional=False
) without explaining their significance. This could be confusing for users migrating from V1 to V2.Consider adding comments to explain:
- The purpose of each new parameter
- How these parameters affect order cancellation
- When to use different combinations of these parameters
# prepare tx msg +# V2 Parameters explanation: +# is_buy: True for buy orders, False for sell orders +# is_market_order: True for market orders, False for limit orders +# is_conditional: True for conditional orders, False for regular orders msg = composer.msg_cancel_binary_options_order_v2( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash, is_buy=True, # Canceling a buy order is_market_order=False, # Canceling a limit order is_conditional=False, # Canceling a regular (non-conditional) order )📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.# prepare tx msg # V2 Parameters explanation: # is_buy: True for buy orders, False for sell orders # is_market_order: True for market orders, False for limit orders # is_conditional: True for conditional orders, False for regular orders msg = composer.msg_cancel_binary_options_order_v2( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash, is_buy=True, # Canceling a buy order is_market_order=False, # Canceling a limit order is_conditional=False, # Canceling a regular (non-conditional) order )
pyinjective/orderhash.py (1)
99-101:
⚠️ Potential issueAdd input validation to prevent potential conversion errors.
The function assumes the input string is a valid decimal number. Consider adding input validation to handle malformed inputs gracefully.
Here's a suggested improvement:
def param_to_backend_go(param: str) -> str: + try: + decimal_param = Decimal(param) + if decimal_param < 0: + raise ValueError("Negative values are not allowed") + except (ValueError, TypeError, InvalidOperation) as e: + raise ValueError(f"Invalid parameter value: {param}. Error: {str(e)}") go_param = Token.convert_value_from_extended_decimal_format(value=Decimal(param)) return f"{go_param.normalize():.18f}"Committable suggestion skipped: line range outside the PR's diff.
examples/chain_client/1_LocalOrderHash.py (2)
92-96: 🛠️ Refactor suggestion
Consider refactoring duplicate transaction code.
The transaction building and broadcasting code is duplicated multiple times in this file. Consider extracting the common transaction building logic into a helper function.
Here's a suggested refactor:
async def build_and_broadcast_tx( client, composer, messages, address, network, priv_key, pub_key ): tx = ( Transaction() .with_messages(*messages) .with_sequence(client.get_sequence()) .with_account_num(client.get_number()) .with_chain_id(network.chain_id) ) gas_price = GAS_PRICE base_gas = 85000 gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT 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) res = await client.broadcast_tx_sync_mode(tx_raw_bytes) gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") return res, gas_limit, gas_feeThen use it like:
res, gas_limit, gas_fee = await build_and_broadcast_tx( client=client, composer=composer, messages=[spot_msg, deriv_msg], address=address, network=network, priv_key=priv_key, pub_key=pub_key )
221-225:
⚠️ Potential issueFix version compatibility issue.
This code attempts to create V2 batch messages (
msg_batch_create_spot_limit_orders_v2
) using orders created with V1 methods. This mixing of V1 and V2 methods could lead to compatibility issues.Ensure that both order creation and message creation use the same version (V2) consistently throughout the example.
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (1)
74-361:
⚠️ Potential issueHandle potential deque underflow in response methods
In the methods from
QueryExchangeParams
toL3SpotOrderBook
, you're callingpop()
on the response deques without checking if they are empty. If a deque is empty, callingpop()
will raise anIndexError
. To ensure robustness, consider checking if the deque is not empty before popping, and handle the empty case appropriately.Here is how you can modify the methods:
async def QueryExchangeParams( self, request: exchange_query_pb.QueryExchangeParamsRequest, context=None, metadata=None ): - return self.exchange_params.pop() + if self.exchange_params: + return self.exchange_params.pop() + else: + # Handle empty deque case, e.g., return a default response or raise an appropriate exception + raise ValueError("No responses available in exchange_params deque")Apply similar changes to all methods where you're popping from a deque to prevent unhandled exceptions.
Committable suggestion skipped: line range outside the PR's diff.
pyinjective/proto/injective/exchange/v2/market_pb2.py (1)
15-16: 🛠️ Refactor suggestion
Remove unused imports to clean up the code
The imports
gogoproto_dot_gogo__pb2
andinjective_dot_oracle_dot_v1beta1_dot_oracle__pb2
are not used in this module. Removing them will reduce unnecessary dependencies and improve code readability.Apply this diff to remove the unused imports:
-from pyinjective.proto.gogoproto import gogo_pb2 as gogoproto_dot_gogo__pb2 -from pyinjective.proto.injective.oracle.v1beta1 import oracle_pb2 as injective_dot_oracle_dot_v1beta1_dot_oracle__pb2📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
🧰 Tools
🪛 Ruff
15-15:
pyinjective.proto.gogoproto.gogo_pb2
imported but unusedRemove unused import:
pyinjective.proto.gogoproto.gogo_pb2
(F401)
16-16:
pyinjective.proto.injective.oracle.v1beta1.oracle_pb2
imported but unusedRemove unused import:
pyinjective.proto.injective.oracle.v1beta1.oracle_pb2
(F401)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (2)
625-626: 🛠️ Refactor suggestion
⚠️ Potential issueEnsure proper exception handling in
_execute_call
The
_execute_call
method is crucial for executing all gRPC calls within this class. It is important to ensure that this method handles exceptions appropriately to prevent unhandled exceptions from propagating and to provide meaningful error messages.Consider reviewing the implementation of
self._assistant.execute_call()
to confirm that:
- Exceptions are caught and handled or logged as needed.
- Retry logic is implemented for transient errors.
- Appropriate error messages are returned to the caller.
555-566:
⚠️ Potential issueAdd input validation in
fetch_trader_derivative_conditional_orders
The method accepts optional
subaccount_id
andmarket_id
. If both areNone
, the request may be invalid or return unintended results. Adding input validation to ensure that at least one parameter is provided would enhance reliability.Apply this diff to include input validation:
async def fetch_trader_derivative_conditional_orders( self, subaccount_id: Optional[str] = None, market_id: Optional[str] = None, ) -> Dict[str, Any]: + if subaccount_id is None and market_id is None: + raise ValueError("At least one of 'subaccount_id' or 'market_id' must be provided.") request = exchange_query_pb.QueryTraderDerivativeConditionalOrdersRequest( subaccount_id=subaccount_id, market_id=market_id,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.self, subaccount_id: Optional[str] = None, market_id: Optional[str] = None, ) -> Dict[str, Any]: if subaccount_id is None and market_id is None: raise ValueError("At least one of 'subaccount_id' or 'market_id' must be provided.") request = exchange_query_pb.QueryTraderDerivativeConditionalOrdersRequest( subaccount_id=subaccount_id, market_id=market_id, ) response = await self._execute_call(call=self._stub.TraderDerivativeConditionalOrders, request=request) return response
pyinjective/proto/injective/exchange/v2/exchange_pb2.py (1)
15-20: 🛠️ Refactor suggestion
Remove unused imports from the generated file.
Static analysis tools have detected that the following imports are unused:
-from pyinjective.proto.gogoproto import gogo_pb2 as gogoproto_dot_gogo__pb2 -from pyinjective.proto.amino import amino_pb2 as amino_dot_amino__pb2 -from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2 -from pyinjective.proto.injective.oracle.v1beta1 import oracle_pb2 as injective_dot_oracle_dot_v1beta1_dot_oracle__pb2 -from pyinjective.proto.injective.exchange.v2 import market_pb2 as injective_dot_exchange_dot_v2_dot_market__pb2 -from pyinjective.proto.injective.exchange.v2 import order_pb2 as injective_dot_exchange_dot_v2_dot_order__pb2Removing these unused imports will clean up the code and eliminate unnecessary dependencies.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
🧰 Tools
🪛 Ruff
15-15:
pyinjective.proto.gogoproto.gogo_pb2
imported but unusedRemove unused import:
pyinjective.proto.gogoproto.gogo_pb2
(F401)
16-16:
pyinjective.proto.amino.amino_pb2
imported but unusedRemove unused import:
pyinjective.proto.amino.amino_pb2
(F401)
17-17:
pyinjective.proto.cosmos.base.v1beta1.coin_pb2
imported but unusedRemove unused import:
pyinjective.proto.cosmos.base.v1beta1.coin_pb2
(F401)
18-18:
pyinjective.proto.injective.oracle.v1beta1.oracle_pb2
imported but unusedRemove unused import:
pyinjective.proto.injective.oracle.v1beta1.oracle_pb2
(F401)
19-19:
pyinjective.proto.injective.exchange.v2.market_pb2
imported but unusedRemove unused import:
pyinjective.proto.injective.exchange.v2.market_pb2
(F401)
20-20:
pyinjective.proto.injective.exchange.v2.order_pb2
imported but unusedRemove unused import:
pyinjective.proto.injective.exchange.v2.order_pb2
(F401)
pyinjective/proto/injective/exchange/v2/proposal_pb2.py (1)
15-23: 🛠️ Refactor suggestion
Remove unused imports to clean up the code
The imports on lines 15-23 are not used in this module and can be safely removed to improve code cleanliness and reduce warnings from static analysis tools. Since this file is auto-generated, please consider adjusting the code generation process or the
.proto
definitions to prevent unused imports.- from pyinjective.proto.cosmos_proto import cosmos_pb2 as cosmos__proto_dot_cosmos__pb2 - from pyinjective.proto.gogoproto import gogo_pb2 as gogoproto_dot_gogo__pb2 - from pyinjective.proto.amino import amino_pb2 as amino_dot_amino__pb2 - from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2 - from pyinjective.proto.cosmos.msg.v1 import msg_pb2 as cosmos_dot_msg_dot_v1_dot_msg__pb2 - from pyinjective.proto.cosmos.distribution.v1beta1 import distribution_pb2 as cosmos_dot_distribution_dot_v1beta1_dot_distribution__pb2 - from pyinjective.proto.injective.exchange.v2 import exchange_pb2 as injective_dot_exchange_dot_v2_dot_exchange__pb2 - from pyinjective.proto.injective.exchange.v2 import market_pb2 as injective_dot_exchange_dot_v2_dot_market__pb2 - from pyinjective.proto.injective.oracle.v1beta1 import oracle_pb2 as injective_dot_oracle_dot_v1beta1_dot_oracle__pb2Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Ruff
15-15:
pyinjective.proto.cosmos_proto.cosmos_pb2
imported but unusedRemove unused import:
pyinjective.proto.cosmos_proto.cosmos_pb2
(F401)
16-16:
pyinjective.proto.gogoproto.gogo_pb2
imported but unusedRemove unused import:
pyinjective.proto.gogoproto.gogo_pb2
(F401)
17-17:
pyinjective.proto.amino.amino_pb2
imported but unusedRemove unused import:
pyinjective.proto.amino.amino_pb2
(F401)
18-18:
pyinjective.proto.cosmos.base.v1beta1.coin_pb2
imported but unusedRemove unused import:
pyinjective.proto.cosmos.base.v1beta1.coin_pb2
(F401)
19-19:
pyinjective.proto.cosmos.msg.v1.msg_pb2
imported but unusedRemove unused import:
pyinjective.proto.cosmos.msg.v1.msg_pb2
(F401)
20-20:
pyinjective.proto.cosmos.distribution.v1beta1.distribution_pb2
imported but unusedRemove unused import:
pyinjective.proto.cosmos.distribution.v1beta1.distribution_pb2
(F401)
21-21:
pyinjective.proto.injective.exchange.v2.exchange_pb2
imported but unusedRemove unused import:
pyinjective.proto.injective.exchange.v2.exchange_pb2
(F401)
22-22:
pyinjective.proto.injective.exchange.v2.market_pb2
imported but unusedRemove unused import:
pyinjective.proto.injective.exchange.v2.market_pb2
(F401)
23-23:
pyinjective.proto.injective.oracle.v1beta1.oracle_pb2
imported but unusedRemove unused import:
pyinjective.proto.injective.oracle.v1beta1.oracle_pb2
(F401)
pyinjective/proto/injective/exchange/v2/tx_pb2_grpc.py (3)
644-644:
⚠️ Potential issueInvalid use of
add_registered_method_handlers
on the server object.At line 644, the method
server.add_registered_method_handlers
is called:server.add_registered_method_handlers('injective.exchange.v2.Msg', rpc_method_handlers)This method is not part of the standard gRPC server API in Python and will result in an
AttributeError
. The correct approach is to useadd_generic_rpc_handlers
, which has already been called on the previous line (line 643). Therefore, this line should be removed.Apply the following change:
server.add_generic_rpc_handlers((generic_handler,)) -server.add_registered_method_handlers('injective.exchange.v2.Msg', rpc_method_handlers)
653-1595:
⚠️ Potential issueRemove
_registered_method=True
fromMsg
class method definitions.The static methods in the
Msg
class (lines 653-1595) include_registered_method=True
in the call togrpc.experimental.unary_unary
. Thegrpc.experimental.unary_unary
function does not accept this parameter. Including it will cause runtime errors.Apply the following change to each method:
return grpc.experimental.unary_unary( request, target, '/injective.exchange.v2.Msg/Deposit', injective_dot_exchange_dot_v2_dot_tx__pb2.MsgDeposit.SerializeToString, injective_dot_exchange_dot_v2_dot_tx__pb2.MsgDepositResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata, - _registered_method=True) + )Repeat this change for all static methods in the
Msg
class to ensure they function correctly.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.def Deposit(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary( request, target, '/injective.exchange.v2.Msg/Deposit', injective_dot_exchange_dot_v2_dot_tx__pb2.MsgDeposit.SerializeToString, injective_dot_exchange_dot_v2_dot_tx__pb2.MsgDepositResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def Withdraw(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary( request, target, '/injective.exchange.v2.Msg/Withdraw', injective_dot_exchange_dot_v2_dot_tx__pb2.MsgWithdraw.SerializeToString, injective_dot_exchange_dot_v2_dot_tx__pb2.MsgWithdrawResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
18-193:
⚠️ Potential issueRemove
_registered_method=True
from gRPC method definitions inMsgStub
class.In the
MsgStub
class (lines 18-193), each method includes the parameter_registered_method=True
in the call tochannel.unary_unary
. Theunary_unary
method of the gRPCChannel
does not accept a_registered_method
parameter. Including it will cause runtime errors.Apply the following change to each method:
self.Deposit = channel.unary_unary( '/injective.exchange.v2.Msg/Deposit', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgDeposit.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgDepositResponse.FromString, - _registered_method=True) + )Repeat this change for all methods in the
MsgStub
class to ensure compatibility with the gRPC Python library.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.self.Deposit = channel.unary_unary( '/injective.exchange.v2.Msg/Deposit', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgDeposit.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgDepositResponse.FromString) self.Withdraw = channel.unary_unary( '/injective.exchange.v2.Msg/Withdraw', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgWithdraw.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgWithdrawResponse.FromString) self.InstantSpotMarketLaunch = channel.unary_unary( '/injective.exchange.v2.Msg/InstantSpotMarketLaunch', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgInstantSpotMarketLaunch.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgInstantSpotMarketLaunchResponse.FromString) self.InstantPerpetualMarketLaunch = channel.unary_unary( '/injective.exchange.v2.Msg/InstantPerpetualMarketLaunch', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgInstantPerpetualMarketLaunch.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgInstantPerpetualMarketLaunchResponse.FromString) self.InstantExpiryFuturesMarketLaunch = channel.unary_unary( '/injective.exchange.v2.Msg/InstantExpiryFuturesMarketLaunch', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgInstantExpiryFuturesMarketLaunch.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgInstantExpiryFuturesMarketLaunchResponse.FromString) self.CreateSpotLimitOrder = channel.unary_unary( '/injective.exchange.v2.Msg/CreateSpotLimitOrder', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateSpotLimitOrder.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateSpotLimitOrderResponse.FromString) self.BatchCreateSpotLimitOrders = channel.unary_unary( '/injective.exchange.v2.Msg/BatchCreateSpotLimitOrders', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchCreateSpotLimitOrders.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchCreateSpotLimitOrdersResponse.FromString) self.CreateSpotMarketOrder = channel.unary_unary( '/injective.exchange.v2.Msg/CreateSpotMarketOrder', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateSpotMarketOrder.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateSpotMarketOrderResponse.FromString) self.CancelSpotOrder = channel.unary_unary( '/injective.exchange.v2.Msg/CancelSpotOrder', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCancelSpotOrder.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCancelSpotOrderResponse.FromString) self.BatchCancelSpotOrders = channel.unary_unary( '/injective.exchange.v2.Msg/BatchCancelSpotOrders', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchCancelSpotOrders.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchCancelSpotOrdersResponse.FromString) self.BatchUpdateOrders = channel.unary_unary( '/injective.exchange.v2.Msg/BatchUpdateOrders', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchUpdateOrders.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchUpdateOrdersResponse.FromString) self.PrivilegedExecuteContract = channel.unary_unary( '/injective.exchange.v2.Msg/PrivilegedExecuteContract', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgPrivilegedExecuteContract.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgPrivilegedExecuteContractResponse.FromString) self.CreateDerivativeLimitOrder = channel.unary_unary( '/injective.exchange.v2.Msg/CreateDerivativeLimitOrder', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateDerivativeLimitOrder.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateDerivativeLimitOrderResponse.FromString) self.BatchCreateDerivativeLimitOrders = channel.unary_unary( '/injective.exchange.v2.Msg/BatchCreateDerivativeLimitOrders', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchCreateDerivativeLimitOrders.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchCreateDerivativeLimitOrdersResponse.FromString) self.CreateDerivativeMarketOrder = channel.unary_unary( '/injective.exchange.v2.Msg/CreateDerivativeMarketOrder', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateDerivativeMarketOrder.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateDerivativeMarketOrderResponse.FromString) self.CancelDerivativeOrder = channel.unary_unary( '/injective.exchange.v2.Msg/CancelDerivativeOrder', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCancelDerivativeOrder.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCancelDerivativeOrderResponse.FromString) self.BatchCancelDerivativeOrders = channel.unary_unary( '/injective.exchange.v2.Msg/BatchCancelDerivativeOrders', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchCancelDerivativeOrders.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchCancelDerivativeOrdersResponse.FromString) self.InstantBinaryOptionsMarketLaunch = channel.unary_unary( '/injective.exchange.v2.Msg/InstantBinaryOptionsMarketLaunch', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgInstantBinaryOptionsMarketLaunch.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgInstantBinaryOptionsMarketLaunchResponse.FromString) self.CreateBinaryOptionsLimitOrder = channel.unary_unary( '/injective.exchange.v2.Msg/CreateBinaryOptionsLimitOrder', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateBinaryOptionsLimitOrder.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateBinaryOptionsLimitOrderResponse.FromString) self.CreateBinaryOptionsMarketOrder = channel.unary_unary( '/injective.exchange.v2.Msg/CreateBinaryOptionsMarketOrder', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateBinaryOptionsMarketOrder.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCreateBinaryOptionsMarketOrderResponse.FromString) self.CancelBinaryOptionsOrder = channel.unary_unary( '/injective.exchange.v2.Msg/CancelBinaryOptionsOrder', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCancelBinaryOptionsOrder.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgCancelBinaryOptionsOrderResponse.FromString) self.BatchCancelBinaryOptionsOrders = channel.unary_unary( '/injective.exchange.v2.Msg/BatchCancelBinaryOptionsOrders', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchCancelBinaryOptionsOrders.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgBatchCancelBinaryOptionsOrdersResponse.FromString) self.SubaccountTransfer = channel.unary_unary( '/injective.exchange.v2.Msg/SubaccountTransfer', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgSubaccountTransfer.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgSubaccountTransferResponse.FromString) self.ExternalTransfer = channel.unary_unary( '/injective.exchange.v2.Msg/ExternalTransfer', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgExternalTransfer.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgExternalTransferResponse.FromString) self.LiquidatePosition = channel.unary_unary( '/injective.exchange.v2.Msg/LiquidatePosition', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgLiquidatePosition.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgLiquidatePositionResponse.FromString) self.EmergencySettleMarket = channel.unary_unary( '/injective.exchange.v2.Msg/EmergencySettleMarket', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgEmergencySettleMarket.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgEmergencySettleMarketResponse.FromString) self.IncreasePositionMargin = channel.unary_unary( '/injective.exchange.v2.Msg/IncreasePositionMargin', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgIncreasePositionMargin.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgIncreasePositionMarginResponse.FromString) self.DecreasePositionMargin = channel.unary_unary( '/injective.exchange.v2.Msg/DecreasePositionMargin', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgDecreasePositionMargin.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgDecreasePositionMarginResponse.FromString) self.RewardsOptOut = channel.unary_unary( '/injective.exchange.v2.Msg/RewardsOptOut', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgRewardsOptOut.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgRewardsOptOutResponse.FromString) self.AdminUpdateBinaryOptionsMarket = channel.unary_unary( '/injective.exchange.v2.Msg/AdminUpdateBinaryOptionsMarket', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgAdminUpdateBinaryOptionsMarket.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgAdminUpdateBinaryOptionsMarketResponse.FromString) self.UpdateParams = channel.unary_unary( '/injective.exchange.v2.Msg/UpdateParams', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgUpdateParams.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgUpdateParamsResponse.FromString) self.UpdateSpotMarket = channel.unary_unary( '/injective.exchange.v2.Msg/UpdateSpotMarket', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgUpdateSpotMarket.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgUpdateSpotMarketResponse.FromString) self.UpdateDerivativeMarket = channel.unary_unary( '/injective.exchange.v2.Msg/UpdateDerivativeMarket', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgUpdateDerivativeMarket.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgUpdateDerivativeMarketResponse.FromString) self.AuthorizeStakeGrants = channel.unary_unary( '/injective.exchange.v2.Msg/AuthorizeStakeGrants', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgAuthorizeStakeGrants.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgAuthorizeStakeGrantsResponse.FromString) self.ActivateStakeGrant = channel.unary_unary( '/injective.exchange.v2.Msg/ActivateStakeGrant', request_serializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgActivateStakeGrant.SerializeToString, response_deserializer=injective_dot_exchange_dot_v2_dot_tx__pb2.MsgActivateStakeGrantResponse.FromString)
pyinjective/proto/injective/exchange/v1beta1/query_pb2.py (1)
22-22:
⚠️ Potential issueAuto-generated code: Modifications should be made in the
.proto
filesThis file is generated by the protocol buffer compiler as indicated by the header comments. Any changes should be made in the corresponding
.proto
files and then regenerated to reflect here.
@@ -58,7 +47,6 @@ async def main() -> None: | |||
margin=Decimal("0.5"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why in some places we leave Decimal
and in some not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry @PavelInjective. What do you mean with "we leave Decimal"?
Or maybe you can mention an example of those places you mean we don't leave Decimal
@@ -37,7 +37,7 @@ async def main() -> None: | |||
fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" | |||
cid = str(uuid.uuid4()) | |||
|
|||
order = composer.derivative_order( | |||
order = composer.create_v2_derivative_order( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why in some places we have v2
in the middle and in some as a suffix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is just according to what sounds better in the method name
base_denom="INJ", | ||
quote_denom="USDC", | ||
base_denom="inj", | ||
quote_denom="factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/usdc", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is it updated like that? Because it's the "1st level" msg constructor, that's why we use "precise" (in the case of a factory token - with factory
prefix, in the case of the ibc
token - with ibc prefix) token name rather than generic name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no longer internal translation from token symbol to token denom. In V2 the user is expected to provide the token denom
@@ -44,33 +44,33 @@ async def main() -> None: | |||
spot_market_id_cancel_2 = "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0" | |||
|
|||
derivative_orders_to_cancel = [ | |||
composer.order_data( | |||
composer.create_v2_order_data_without_mask( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again - suffix in the middle
|
||
return response | ||
|
||
async def fetch_l3_derivative_orderbook( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the l3 derivative orderbook?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a new endpoint in the chain exchange module
"MsgCancelBinaryOptionsOrder": injective_exchange_tx_pb.MsgCancelBinaryOptionsOrderResponse, | ||
"MsgAdminUpdateBinaryOptionsMarket": injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarketResponse, | ||
"MsgInstantBinaryOptionsMarketLaunch": injective_exchange_tx_pb.MsgInstantBinaryOptionsMarketLaunchResponse, | ||
"MsgCreateSpotLimitOrder": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if we use a workaround like that instead of full hardcoding:
def get_response_type(request_name):
response_type_name = f"{request_name}Response"
return getattr(injective_exchange_tx_v2_pb, response_type_name, None)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens with requests that have "Request" as the last word in the name but the response name is not "RequestResponse"?
} | ||
|
||
GRPC_MESSAGE_TYPE_TO_CLASS_MAP = { | ||
"/injective.exchange.v1beta1.MsgCreateSpotLimitOrder": injective_exchange_tx_pb.MsgCreateSpotLimitOrder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same refactoring suggestion as for the map above. replace hardcoding with pattern matching
pyinjective/ofac.json
Outdated
@@ -1,48 +1,158 @@ | |||
[ | |||
"0x01e2919679362dfbc9ee1644ba9c6da6d6245bb1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we remove ini
files in favor of lists repo, but leave this ofac.json
file in the sdk repo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The INI files are not a local copy of the lists repo. They are old files with different information that have been marked as deprecated for months now, and I am removing in this version
…o feat/add_support_exchange_v2
…o feat/add_support_exchange_v2
…d the extra digits in the amounts
IMPORTANT: Do not merge this PR until the Exchange V2 protos are officially part of a chain releas and the
buf.gen.yaml
file can be changed to point to an official tag instead of a non-release branch.Solves CHAIN-220
Summary by CodeRabbit
New Features
ChainGrpcExchangeApi
with new functionalities related to trading operations and market data retrieval.Bug Fixes
Documentation
Refactor