From d8710f9de7bc287c4652360ac540a26ba9d58a55 Mon Sep 17 00:00:00 2001 From: enigmarikki Date: Mon, 2 Dec 2024 13:50:41 -0500 Subject: [PATCH 1/8] "wip : integrate wasm" --- agent_server.py | 3 +- injective_functions/exchange/exchange.py | 2 +- injective_functions/utils/helpers.py | 1 - injective_functions/utils/utils_schema.json | 20 ----- injective_functions/wasm/mito_contracts.py | 99 +++++++++++++++++++++ injective_functions/wasm/wasm_schema.json | 0 6 files changed, 101 insertions(+), 24 deletions(-) delete mode 100644 injective_functions/utils/utils_schema.json create mode 100644 injective_functions/wasm/mito_contracts.py create mode 100644 injective_functions/wasm/wasm_schema.json diff --git a/agent_server.py b/agent_server.py index 8364a5f..8caa90b 100644 --- a/agent_server.py +++ b/agent_server.py @@ -46,7 +46,7 @@ def __init__(self): "./injective_functions/exchange/exchange_schema.json", "./injective_functions/staking/staking_schema.json", "./injective_functions/token_factory/token_factory_schema.json", - "./injective_functions/utils/utils_schema.json", + "./injective_functions/wasm/wasm_schema.json" ] self.function_schemas = FunctionSchemaLoader.load_schemas(schema_paths) @@ -146,7 +146,6 @@ async def get_response( ) response_message = response.choices[0].message - print(response_message) # Handle function calling if ( hasattr(response_message, "function_call") diff --git a/injective_functions/exchange/exchange.py b/injective_functions/exchange/exchange.py index 5fe56a7..38e174b 100644 --- a/injective_functions/exchange/exchange.py +++ b/injective_functions/exchange/exchange.py @@ -206,7 +206,7 @@ async def trader_derivative_orders_by_hash( ) return {"success": True, "result": orders} except Exception as e: - return {"success": False, "result": detailed_exception_info(e)} + return {"success": False, "error": detailed_exception_info(e)} async def trader_spot_orders_by_hash( self, market_id: str, subaccount_idx: int, order_hashes: List[str] diff --git a/injective_functions/utils/helpers.py b/injective_functions/utils/helpers.py index cd7e935..ca8b493 100644 --- a/injective_functions/utils/helpers.py +++ b/injective_functions/utils/helpers.py @@ -5,7 +5,6 @@ import requests from injective_functions.utils.indexer_requests import get_market_id - def base64convert(s): try: int(s.replace("0x", ""), 16) diff --git a/injective_functions/utils/utils_schema.json b/injective_functions/utils/utils_schema.json deleted file mode 100644 index 4b53bf2..0000000 --- a/injective_functions/utils/utils_schema.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "functions": [ - { - "name": "set_network", - "description": "This will get the current network to use", - "parameters": { - "type": "object", - "properties": { - "network_type": { - "type": "string", - "enum": ["testnet", "mainnet"], - "default": "mainnet", - "description": "Network to query (testnet or mainnet)" - } - } - }, - "required": ["network_type"] - } - ] - } \ No newline at end of file diff --git a/injective_functions/wasm/mito_contracts.py b/injective_functions/wasm/mito_contracts.py new file mode 100644 index 0000000..7504ba2 --- /dev/null +++ b/injective_functions/wasm/mito_contracts.py @@ -0,0 +1,99 @@ +from decimal import Decimal +from injective_functions.base import InjectiveBase +from injective_functions.utils.helpers import VaultContractType, SpotRedemptionType +from typing import List, Dict +import json + +#class SpotRedemptionType: +# BaseQnly = "BaseOnly" +# QuoteOnly = "QuoteOnly" +# BaseAndQuote = "BaseAndQuote" +# FixedBaseAndQuote = "FixedBaseAndQuote" +# VariableBaseAndQuote = "VariableBaseAndQuote" + +class MitoContracts(InjectiveBase): + def __init__(self, chain_client): + super().__init__(chain_client) + self.contract_type = { + "ManagedVault" : "crates.io:managed-vault", + "CPMM" : "crates.io:vault-cpmm-spot", + "ASMMSpot" : "crates.io:vault-cpmm-asmm-spot", + "ASMMPerp" : "crates.io:vault-cpmm-asmm-perp" + } + + # TODO: add fetch functions to get mito launchpads + # currently there is no python-sdk endpoints + def _order_funds_by_denom(self, amounts: List[Tuple[float, str]]) -> str: + """Sort and format funds by denom""" + sorted_amounts = sorted(amounts, key=lambda x: x[1]) + return ",".join(f"{amount}{denom}" for amount, denom in sorted_amounts) + # This section deals with all the transactions related to mito + # Subscribe to Launchpad + async def subscribe_to_launchpad( + self, contract_address: str, quote_denom: str, amount: float + ) -> Dict: + json_data = json.dumps({"msg": {}, "action": "subscribe"}) + funds = f"{amount}{quote_denom}" + msg = self.chain_client.composer.msg_execute_contract_compat( + sender=self.chain_client.address.to_acc_bech32(), + contract=contract_address, + msg=json_data, + funds=funds, + ) + return await self.chain_client.build_and_broadcast_tx(msg) + + # Claim Launchpad Subscription + async def claim_launchpad_subscription(self, contract_address: str) -> Dict: + json_data = json.dumps({"msg": {}, "action": "Claim"}) + msg = self.chain_client.composer.msg_execute_contract_compat( + sender=self.chain_client.address.to_acc_bech32(), + contract=contract_address, + msg=json_data, + ) + return await self.chain_client.build_and_broadcast_tx(msg) + # Subcribe to spot + # TODO: Improve parameterization + async def subscription_mito_spot( + self, + base_amount: float, + base_denom: str, + quote_amount: float, + quote_denom: str, + vault_subaccount_id: str, + max_penalty: float, + vault_master_address: str, + vault_contract_type: str, + spot_redemption_type: str, + trader_subaccount_idx: float = 0, + ) -> Dict: + """ + Subscribe to Mito spot trading vault + """ + subscription_args = ( + {"slippage": {"max_penalty": str(max_penalty)}} + if vault_contract_type == "CPMM" + else {} + ) + + data = { + "vault_subaccount_id": vault_subaccount_id, + "trader_subaccount_id": self.chain_client.address.get_subaccount_id(trader_subaccount_idx), + "msg": {"subscribe": subscription_args}, + } + + funds_list = [] + if spot_redemption_type != "QuoteOnly" and base_amount > 0: + funds_list.append((base_amount, base_denom)) + if spot_redemption_type != "BaseOnly" and quote_amount > 0: + funds_list.append((quote_amount, quote_denom)) + + funds = self._order_funds_by_denom(funds_list) + + msg = self.chain_client.composer.msg_privileged_execute_contract( + sender=self.chain_client.address.to_acc_bech32(), + contract=vault_master_address, + msg=json.dumps(data), + funds=funds, + ) + + return await self.chain_client.build_and_broadcast_tx(msg) diff --git a/injective_functions/wasm/wasm_schema.json b/injective_functions/wasm/wasm_schema.json new file mode 100644 index 0000000..e69de29 From deb64dfa9a6dce16494f0bb36185728263c202f0 Mon Sep 17 00:00:00 2001 From: enigmarikki Date: Thu, 5 Dec 2024 10:05:15 -0500 Subject: [PATCH 2/8] "chore: changed response of detailed exceptions" --- agent_server.py | 3 ++- injective_functions/utils/helpers.py | 5 ++--- injective_functions/wasm/mito_contracts.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/agent_server.py b/agent_server.py index 8caa90b..9519184 100644 --- a/agent_server.py +++ b/agent_server.py @@ -46,7 +46,7 @@ def __init__(self): "./injective_functions/exchange/exchange_schema.json", "./injective_functions/staking/staking_schema.json", "./injective_functions/token_factory/token_factory_schema.json", - "./injective_functions/wasm/wasm_schema.json" + "./injective_functions/wasm/wasm_schema.json", ] self.function_schemas = FunctionSchemaLoader.load_schemas(schema_paths) @@ -146,6 +146,7 @@ async def get_response( ) response_message = response.choices[0].message + print(response_message) # Handle function calling if ( hasattr(response_message, "function_call") diff --git a/injective_functions/utils/helpers.py b/injective_functions/utils/helpers.py index ca8b493..455b30e 100644 --- a/injective_functions/utils/helpers.py +++ b/injective_functions/utils/helpers.py @@ -76,8 +76,7 @@ async def impute_market_id(market_id): def detailed_exception_info(e) -> Dict: return { - "success": False, - "error": { + "message": str(e), "type": type(e).__name__, "module": e.__class__.__module__, @@ -88,4 +87,4 @@ def detailed_exception_info(e) -> Dict: "context": str(e.__context__) if e.__context__ else None, }, }, - } + diff --git a/injective_functions/wasm/mito_contracts.py b/injective_functions/wasm/mito_contracts.py index 7504ba2..a55fe06 100644 --- a/injective_functions/wasm/mito_contracts.py +++ b/injective_functions/wasm/mito_contracts.py @@ -52,7 +52,7 @@ async def claim_launchpad_subscription(self, contract_address: str) -> Dict: ) return await self.chain_client.build_and_broadcast_tx(msg) # Subcribe to spot - # TODO: Improve parameterization + #TODO: Add support to derivative vaults async def subscription_mito_spot( self, base_amount: float, From 049ee6fb224421a8c2239f1ac4af33dda866b580 Mon Sep 17 00:00:00 2001 From: enigmarikki Date: Thu, 5 Dec 2024 13:31:04 -0500 Subject: [PATCH 3/8] "wip: skeleton structure of mito contracts" --- injective_functions/exchange/exchange.py | 3 +- injective_functions/utils/helpers.py | 7 +- injective_functions/wasm/mito_contracts.py | 111 ++++++++++++++++++--- 3 files changed, 105 insertions(+), 16 deletions(-) diff --git a/injective_functions/exchange/exchange.py b/injective_functions/exchange/exchange.py index a1ab8c8..77a2ea4 100644 --- a/injective_functions/exchange/exchange.py +++ b/injective_functions/exchange/exchange.py @@ -10,11 +10,12 @@ from typing import Dict, List + class InjectiveExchange(InjectiveBase): def __init__(self, chain_client) -> None: # Initializes the network and the composer super().__init__(chain_client) - + async def get_subaccount_deposits( self, subaccount_idx: int, denoms: List[str] = None ) -> Dict: diff --git a/injective_functions/utils/helpers.py b/injective_functions/utils/helpers.py index 455b30e..97545c3 100644 --- a/injective_functions/utils/helpers.py +++ b/injective_functions/utils/helpers.py @@ -5,6 +5,7 @@ import requests from injective_functions.utils.indexer_requests import get_market_id + def base64convert(s): try: int(s.replace("0x", ""), 16) @@ -75,8 +76,8 @@ async def impute_market_id(market_id): def detailed_exception_info(e) -> Dict: - return { - + return ( + { "message": str(e), "type": type(e).__name__, "module": e.__class__.__module__, @@ -87,4 +88,4 @@ def detailed_exception_info(e) -> Dict: "context": str(e.__context__) if e.__context__ else None, }, }, - + ) diff --git a/injective_functions/wasm/mito_contracts.py b/injective_functions/wasm/mito_contracts.py index a55fe06..86048c7 100644 --- a/injective_functions/wasm/mito_contracts.py +++ b/injective_functions/wasm/mito_contracts.py @@ -4,21 +4,16 @@ from typing import List, Dict import json -#class SpotRedemptionType: -# BaseQnly = "BaseOnly" -# QuoteOnly = "QuoteOnly" -# BaseAndQuote = "BaseAndQuote" -# FixedBaseAndQuote = "FixedBaseAndQuote" -# VariableBaseAndQuote = "VariableBaseAndQuote" +#TODO: Fetch vault details and abstract away the vault data through gpt class MitoContracts(InjectiveBase): def __init__(self, chain_client): super().__init__(chain_client) self.contract_type = { - "ManagedVault" : "crates.io:managed-vault", - "CPMM" : "crates.io:vault-cpmm-spot", - "ASMMSpot" : "crates.io:vault-cpmm-asmm-spot", - "ASMMPerp" : "crates.io:vault-cpmm-asmm-perp" + "ManagedVault": "crates.io:managed-vault", + "CPMM": "crates.io:vault-cpmm-spot", + "ASMMSpot": "crates.io:vault-cpmm-asmm-spot", + "ASMMPerp": "crates.io:vault-cpmm-asmm-perp", } # TODO: add fetch functions to get mito launchpads @@ -27,6 +22,7 @@ def _order_funds_by_denom(self, amounts: List[Tuple[float, str]]) -> str: """Sort and format funds by denom""" sorted_amounts = sorted(amounts, key=lambda x: x[1]) return ",".join(f"{amount}{denom}" for amount, denom in sorted_amounts) + # This section deals with all the transactions related to mito # Subscribe to Launchpad async def subscribe_to_launchpad( @@ -51,8 +47,9 @@ async def claim_launchpad_subscription(self, contract_address: str) -> Dict: msg=json_data, ) return await self.chain_client.build_and_broadcast_tx(msg) + # Subcribe to spot - #TODO: Add support to derivative vaults + # TODO: Add support to derivative vaults async def subscription_mito_spot( self, base_amount: float, @@ -77,7 +74,9 @@ async def subscription_mito_spot( data = { "vault_subaccount_id": vault_subaccount_id, - "trader_subaccount_id": self.chain_client.address.get_subaccount_id(trader_subaccount_idx), + "trader_subaccount_id": self.chain_client.address.get_subaccount_id( + trader_subaccount_idx + ), "msg": {"subscribe": subscription_args}, } @@ -97,3 +96,91 @@ async def subscription_mito_spot( ) return await self.chain_client.build_and_broadcast_tx(msg) + + async def redeem_mito_vault( + self, + redeem_amount: float, + lp_denom: str, + vault_subaccount_id: str, + max_penalty: float, + vault_master_address: str, + market_type: str, + redemption_type: str, + trader_subaccount_idx: float = 0, + ) -> Dict: + """ + Redeem from Mito vault + """ + subscription_args = ( + {"slippage": {"max_penalty": str(max_penalty)}} + if market_type == "Derivative" + else {} + ) + subscription_args["redemption_type"] = redemption_type + + data = { + "vault_subaccount_id": vault_subaccount_id, + "trader_subaccount_id": self.chain_client.address.get_subaccount_id( + trader_subaccount_idx + ), + "msg": {"redeem": subscription_args}, + } + + funds = f"{redeem_amount} {lp_denom}" + + msg = self.chain_client.composer.msg_privileged_execute_contract( + sender=self.chain_client.address.to_acc_bech32(), + contract=vault_master_address, + msg=json.dumps(data), + funds=funds, + ) + + return await self.chain_client.build_and_broadcast_tx(msg) + + async def stake_mito_vault( + self, + amount: float, + vault_lp_denom: str, + vault_token_decimals: int, + staking_contract_address: str, + ) -> Dict: + """ + Stake LP tokens in Mito vault + """ + amount_in_chain = int(amount * (10**vault_token_decimals)) + funds = f"{amount_in_chain}{vault_lp_denom}" + + msg = self.chain_client.composer.msg_execute_contract_compat( + sender=self.chain_client.address.to_acc_bech32(), + contract=staking_contract_address, + msg=json.dumps({"action": "stake", "msg": {}}), + funds=funds, + ) + + return await self.chain_client.build_and_broadcast_tx(msg) + + async def unstake_mito( + self, + amount: float, + vault_lp_denom: str, + vault_token_decimals: int, + staking_contract_address: str, + ) -> Dict: + """Unstake LP tokens from Mito vault""" + amount_in_chain = int(amount * (10 ** vault_token_decimals)) + + msg = self.chain_client.composer.msg_execute_contract_compat( + sender=self.chain_client.address.to_acc_bech32(), + contract=staking_contract_address, + msg=json.dumps({ + "action": "unstake", + "msg": { + "coin": { + "denom": vault_lp_denom, + "amount": str(amount_in_chain) + } + } + }), + ) + + return await self.chain_client.build_and_broadcast_tx(msg) From 233989d380450020a1dd6cb8d346fac234e8ada7 Mon Sep 17 00:00:00 2001 From: enigmarikki Date: Thu, 5 Dec 2024 14:23:00 -0500 Subject: [PATCH 4/8] "wip : tx mito contracts done" --- injective_functions/wasm/mito_contracts.py | 117 ++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/injective_functions/wasm/mito_contracts.py b/injective_functions/wasm/mito_contracts.py index 86048c7..9d76853 100644 --- a/injective_functions/wasm/mito_contracts.py +++ b/injective_functions/wasm/mito_contracts.py @@ -1,7 +1,7 @@ from decimal import Decimal from injective_functions.base import InjectiveBase from injective_functions.utils.helpers import VaultContractType, SpotRedemptionType -from typing import List, Dict +from typing import List, Dict, Tuple import json @@ -184,3 +184,118 @@ async def unstake_mito( ) return await self.chain_client.build_and_broadcast_tx(msg) + + async def claim_stake_mito_vault( + self, + vault_lp_denom: str, + staking_contract_address: str, + ) -> Dict: + """ + Claim staking rewards from Mito vault + """ + msg = self.chain_client.composer.msg_execute_contract_compat( + sender=self.chain_client.address.to_acc_bech32(), + contract=staking_contract_address, + msg=json.dumps({ + "action": "claim_stake", + "msg": { + "lp_token": vault_lp_denom + } + }), + funds="", + ) + + return await self.chain_client.build_and_broadcast_tx(msg) + async def claim_rewards_mito( + self, + vault_lp_denom: str, + staking_contract_address: str, + ) -> Dict: + """ + Claim rewards from Mito vault + """ + msg = self.chain_client.composer.msg_execute_contract_compat( + sender=self.chain_client.address.to_acc_bech32(), + contract=staking_contract_address, + msg=json.dumps({ + "action": "claim_rewards", + "msg": { + "lp_token": vault_lp_denom + } + }), + funds="", + ) + + return await self.chain_client.build_and_broadcast_tx(msg) + + #TODO: Need to test in testnet + async def instantiate_cpmm_vault( + self, + inj_amount: float, + base_token_amount: float, + base_token_denom: str, + quote_token_amount: float, + quote_token_denom: str, + market_id: str, + fee_bps: int, + base_decimals: int, + quote_decimals: int, + owner_address: str = None, + ) -> Dict: + """ + Instantiate a CPMM vault with specified parameters + """ + if owner_address is None: + owner_address = self.chain_client.address.to_acc_bech32() + + # Set contract configuration based on network + CPMM_CONTRACT_CODE = 540 + MITO_MASTER_CONTRACT_ADDRESS = "inj1vcqkkvqs7prqu70dpddfj7kqeqfdz5gg662qs3" + + funds = [ + f"{int(quote_token_amount)}{quote_token_denom}", + f"{int(base_token_amount)}{base_token_denom}" + ] + funds_str = ",".join(funds) + #TODO: improve the parameterization + data = { + "action": "register_vault", + "msg": { + "is_subscribing_with_funds": True, + "registration_mode": { + "permissionless": { + "whitelisted_vault_code_id": CPMM_CONTRACT_CODE + } + }, + "instantiate_vault_msg": { + "Amm": { + "owner": owner_address, + "master_address": MITO_MASTER_CONTRACT_ADDRESS, + "notional_value_cap": "1000000000000000000000000", + "market_id": market_id, + "pricing_strategy": { + "SmoothingPricingWithRelativePriceRange": { + "bid_range": "0.8", + "ask_range": "0.8" + } + }, + "max_invariant_sensitivity_bps": "5", + "max_price_sensitivity_bps": "5", + "fee_bps": fee_bps, + "order_type": "Vanilla", + "config_owner": owner_address, + "base_decimals": base_decimals, + "quote_decimals": quote_decimals + } + } + } + } + + msg = self.chain_client.composer.msg_execute_contract_compat( + sender=owner_address, + contract=MITO_MASTER_CONTRACT_ADDRESS, + msg=json.dumps(data), + funds=funds_str, + ) + + return await self.chain_client.build_and_broadcast_tx(msg) \ No newline at end of file From e2ca6d199d6afae663fb7a0c8223b8928689a693 Mon Sep 17 00:00:00 2001 From: enigmarikki Date: Thu, 5 Dec 2024 18:26:09 -0500 Subject: [PATCH 5/8] "feat: added mito fetch apis" --- .../utils/mito_get_requests_schema.json | 550 ++++++++++++++++++ injective_functions/utils/mito_requests.py | 353 +++++++++++ 2 files changed, 903 insertions(+) create mode 100644 injective_functions/utils/mito_get_requests_schema.json create mode 100644 injective_functions/utils/mito_requests.py diff --git a/injective_functions/utils/mito_get_requests_schema.json b/injective_functions/utils/mito_get_requests_schema.json new file mode 100644 index 0000000..5f74bb6 --- /dev/null +++ b/injective_functions/utils/mito_get_requests_schema.json @@ -0,0 +1,550 @@ +{ + "functions": [ + { + "name": "get_vaults", + "description": "Retrieve a list of vaults.", + "parameters": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "description": "Maximum number of vaults to retrieve" + }, + "pageIndex": { + "type": "integer", + "description": "Page index for pagination" + }, + "codeID": { + "type": "string", + "description": "Optional code ID filter" + } + }, + "required": [] + } + }, + { + "name": "get_vault", + "description": "Retrieve a specific vault by slug or contract address.", + "parameters": { + "type": "object", + "properties": { + "slug": { + "type": "string", + "description": "Slug of the vault" + }, + "contractAddress": { + "type": "string", + "description": "Contract address of the vault" + } + }, + "required": [] + } + }, + { + "name": "get_lp_token_price_chart", + "description": "Retrieve LP token price chart for a given vault.", + "parameters": { + "type": "object", + "properties": { + "vaultAddress": { + "type": "string", + "description": "Vault address (required path param)" + }, + "fromTime": { + "type": "string", + "description": "Start time for the chart data" + }, + "toTime": { + "type": "string", + "description": "End time for the chart data" + } + }, + "required": ["vaultAddress"] + } + }, + { + "name": "get_tvl_chart", + "description": "Retrieve TVL chart data for a given vault.", + "parameters": { + "type": "object", + "properties": { + "vaultAddress": { + "type": "string", + "description": "Vault address (required path param)" + }, + "fromTime": { + "type": "string", + "description": "Start time for the chart data" + }, + "toTime": { + "type": "string", + "description": "End time for the chart data" + } + }, + "required": ["vaultAddress"] + } + }, + { + "name": "get_vaults_by_holder_address", + "description": "Retrieve vaults subscribed by a particular holder.", + "parameters": { + "type": "object", + "properties": { + "holderAddress": { + "type": "string", + "description": "Holder address (required path param)" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + }, + "pageIndex": { + "type": "integer", + "description": "Page index for pagination" + }, + "vaultAddress": { + "type": "string", + "description": "Filter by specific vault address" + }, + "skip": { + "type": "integer", + "description": "Number of records to skip" + } + }, + "required": ["holderAddress"] + } + }, + { + "name": "get_lp_holders", + "description": "Retrieve LP token holders for a given vault.", + "parameters": { + "type": "object", + "properties": { + "vaultAddress": { + "type": "string", + "description": "Vault address (required path param)" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + }, + "pageIndex": { + "type": "integer", + "description": "Page index for pagination" + }, + "stakingContractAddress": { + "type": "string", + "description": "Filter by staking contract address" + }, + "skip": { + "type": "integer", + "description": "Number of records to skip" + } + }, + "required": ["vaultAddress"] + } + }, + { + "name": "get_portfolio", + "description": "Retrieve portfolio summary for a holder.", + "parameters": { + "type": "object", + "properties": { + "holderAddress": { + "type": "string", + "description": "Holder address (required path param)" + }, + "stakingContractAddress": { + "type": "string", + "description": "Optional staking contract filter" + } + }, + "required": ["holderAddress"] + } + }, + { + "name": "get_leaderboard", + "description": "Retrieve the leaderboard.", + "parameters": { + "type": "object", + "properties": {}, + "required": [] + } + }, + { + "name": "get_leaderboard_epochs", + "description": "Retrieve leaderboard epochs.", + "parameters": { + "type": "object", + "properties": { + "fromEpochId": { + "type": "integer", + "description": "Starting epoch ID" + }, + "toEpochId": { + "type": "integer", + "description": "Ending epoch ID" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + } + }, + "required": [] + } + }, + { + "name": "get_transfers_history", + "description": "Retrieve historical transfers.", + "parameters": { + "type": "object", + "properties": { + "vault": { + "type": "string", + "description": "Vault address filter" + }, + "account": { + "type": "string", + "description": "Account address filter" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + }, + "fromNumber": { + "type": "integer", + "description": "From block/record number" + }, + "toNumber": { + "type": "integer", + "description": "To block/record number" + } + }, + "required": [] + } + }, + { + "name": "get_staking_pools", + "description": "Retrieve staking pools.", + "parameters": { + "type": "object", + "properties": { + "staker": { + "type": "string", + "description": "Staker address filter" + }, + "stakingContractAddress": { + "type": "string", + "description": "Staking contract address filter" + } + }, + "required": [] + } + }, + { + "name": "get_staking_reward_by_account", + "description": "Retrieve staking rewards for a given staker.", + "parameters": { + "type": "object", + "properties": { + "staker": { + "type": "string", + "description": "Staker address (required path param)" + }, + "stakingContractAddress": { + "type": "string", + "description": "Staking contract address filter" + } + }, + "required": ["staker"] + } + }, + { + "name": "get_staking_history", + "description": "Retrieve historical staking activities.", + "parameters": { + "type": "object", + "properties": { + "fromNumber": { + "type": "integer", + "description": "From block/record number" + }, + "toNumber": { + "type": "integer", + "description": "To block/record number" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + }, + "staker": { + "type": "string", + "description": "Staker address filter" + } + }, + "required": [] + } + }, + { + "name": "get_staking_amount_at_height", + "description": "Retrieve staking amounts at a given height.", + "parameters": { + "type": "object", + "properties": { + "stakingContractAddress": { + "type": "string", + "description": "Staking contract address (required path param)" + }, + "denom": { + "type": "string", + "description": "Denomination filter" + }, + "height": { + "type": "string", + "description": "Block height" + }, + "staker": { + "type": "string", + "description": "Staker address filter" + }, + "skip": { + "type": "integer", + "description": "Records to skip" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + } + }, + "required": ["stakingContractAddress"] + } + }, + { + "name": "get_health", + "description": "Check health of the API.", + "parameters": { + "type": "object", + "properties": {}, + "required": [] + } + }, + { + "name": "get_execution", + "description": "Retrieve execution logs for a contract.", + "parameters": { + "type": "object", + "properties": { + "contractAddress": { + "type": "string", + "description": "Contract address (required path param)" + } + }, + "required": ["contractAddress"] + } + }, + { + "name": "get_missions", + "description": "Retrieve mission status of an account.", + "parameters": { + "type": "object", + "properties": { + "account_address": { + "type": "string", + "description": "Account address (required path param)" + } + }, + "required": ["account_address"] + } + }, + { + "name": "get_mission_leaderboard", + "description": "Retrieve mission leaderboard.", + "parameters": { + "type": "object", + "properties": { + "userAddress": { + "type": "string", + "description": "User address filter" + } + }, + "required": [] + } + }, + { + "name": "list_idos", + "description": "Retrieve IDOs based on provided filters.", + "parameters": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "IDO status filter" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + }, + "toNumber": { + "type": "integer", + "description": "Ending record number" + }, + "accountAddress": { + "type": "string", + "description": "Filter by account address" + }, + "ownerAddress": { + "type": "string", + "description": "Filter by owner address" + } + }, + "required": [] + } + }, + { + "name": "get_ido", + "description": "Retrieve a single IDO by contract address.", + "parameters": { + "type": "object", + "properties": { + "contractAddress": { + "type": "string", + "description": "IDO contract address (required path param)" + }, + "accountAddress": { + "type": "string", + "description": "Filter by account address" + } + }, + "required": ["contractAddress"] + } + }, + { + "name": "get_ido_subscribers", + "description": "Retrieve subscribers of a given IDO.", + "parameters": { + "type": "object", + "properties": { + "contractAddress": { + "type": "string", + "description": "IDO contract address (required path param)" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + }, + "skip": { + "type": "integer", + "description": "Number of records to skip" + }, + "sortBy": { + "type": "string", + "description": "Sort by 'subscribedTime' or 'subscribedAmount'" + } + }, + "required": ["contractAddress"] + } + }, + { + "name": "get_ido_subscription", + "description": "Retrieve subscription details in a given IDO for a specific account.", + "parameters": { + "type": "object", + "properties": { + "contractAddress": { + "type": "string", + "description": "IDO contract address (required path param)" + }, + "accountAddress": { + "type": "string", + "description": "Account address (required path param)" + } + }, + "required": ["contractAddress", "accountAddress"] + } + }, + { + "name": "get_ido_activities", + "description": "Retrieve subscription activities for an IDO.", + "parameters": { + "type": "object", + "properties": { + "contractAddress": { + "type": "string", + "description": "IDO contract address filter" + }, + "accountAddress": { + "type": "string", + "description": "Account address filter" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + }, + "toNumber": { + "type": "integer", + "description": "Ending record number" + } + }, + "required": [] + } + }, + { + "name": "get_whitelist", + "description": "Retrieve the whitelist of accounts for a given IDO.", + "parameters": { + "type": "object", + "properties": { + "idoAddress": { + "type": "string", + "description": "IDO address (required path param)" + }, + "skip": { + "type": "integer", + "description": "Number of records to skip" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + } + }, + "required": ["idoAddress"] + } + }, + { + "name": "get_token_metadata", + "description": "Retrieve token metadata being processed by the backend.", + "parameters": { + "type": "object", + "properties": {}, + "required": [] + } + }, + { + "name": "get_claim_references", + "description": "Retrieve claim references for a given IDO and account.", + "parameters": { + "type": "object", + "properties": { + "accountAddress": { + "type": "string", + "description": "Account address" + }, + "idoAddress": { + "type": "string", + "description": "IDO address" + }, + "skip": { + "type": "integer", + "description": "Number of records to skip" + }, + "limit": { + "type": "integer", + "description": "Max number of results" + } + }, + "required": ["accountAddress", "idoAddress"] + } + } + ] + } + \ No newline at end of file diff --git a/injective_functions/utils/mito_requests.py b/injective_functions/utils/mito_requests.py new file mode 100644 index 0000000..27eb593 --- /dev/null +++ b/injective_functions/utils/mito_requests.py @@ -0,0 +1,353 @@ +import aiohttp + + +class MitoAPIClient: + def __init__(self, base_url: str): + self.base_url = base_url.rstrip("/") + + async def _request(self, method: str, path: str, **query_params): + # Remove any query_params that are None + query_params = {k: v for k, v in query_params.items() if v is not None} + + url = f"{self.base_url}{path}" + + async with aiohttp.ClientSession() as session: + async with session.request(method, url, params=query_params) as response: + response.raise_for_status() + return await response.json() + + # Endpoint: GetVaults + # Path: /vaults + # Query params: limit, pageIndex, codeID + async def get_vaults( + self, limit: int = None, pageIndex: int = None, codeID: str = None + ): + return await self._request( + "GET", "/vaults", limit=limit, pageIndex=pageIndex, codeID=codeID + ) + + # Endpoint: GetVault + # Path: /vault + # Query params: slug, contractAddress + async def get_vault(self, slug: str = None, contractAddress: str = None): + return await self._request( + "GET", "/vault", slug=slug, contractAddress=contractAddress + ) + + # Endpoint: LPTokenPriceChart + # Path: /vaults/{vaultAddress}/lpTokenPriceChart + # Path param: vaultAddress + # Query params: fromTime, toTime + async def get_lp_token_price_chart( + self, vaultAddress: str, fromTime: str = None, toTime: str = None + ): + path = f"/vaults/{vaultAddress}/lpTokenPriceChart" + return await self._request("GET", path, fromTime=fromTime, toTime=toTime) + + # Endpoint: TVLChart + # Path: /vaults/{vaultAddress}/tvlChart + # Path param: vaultAddress + # Query params: fromTime, toTime + async def get_tvl_chart( + self, vaultAddress: str, fromTime: str = None, toTime: str = None + ): + path = f"/vaults/{vaultAddress}/tvlChart" + return await self._request("GET", path, fromTime=fromTime, toTime=toTime) + + # Endpoint: VaultsByHolderAddress + # Path: /holders/{holderAddress}/vaults + # Path param: holderAddress + # Query params: limit, pageIndex, vaultAddress, skip + async def get_vaults_by_holder_address( + self, + holderAddress: str, + limit: int = None, + pageIndex: int = None, + vaultAddress: str = None, + skip: int = None, + ): + path = f"/holders/{holderAddress}/vaults" + return await self._request( + "GET", + path, + limit=limit, + pageIndex=pageIndex, + vaultAddress=vaultAddress, + skip=skip, + ) + + # Endpoint: LPHolders + # Path: /vaults/{vaultAddress}/holders + # Path param: vaultAddress + # Query params: limit, pageIndex, stakingContractAddress, skip + async def get_lp_holders( + self, + vaultAddress: str, + limit: int = None, + pageIndex: int = None, + stakingContractAddress: str = None, + skip: int = None, + ): + path = f"/vaults/{vaultAddress}/holders" + return await self._request( + "GET", + path, + limit=limit, + pageIndex=pageIndex, + stakingContractAddress=stakingContractAddress, + skip=skip, + ) + + # Endpoint: Portfolio + # Path: /holders/{holderAddress}/portfolio + # Path param: holderAddress + # Query params: stakingContractAddress + async def get_portfolio( + self, holderAddress: str, stakingContractAddress: str = None + ): + path = f"/holders/{holderAddress}/portfolio" + return await self._request( + "GET", path, stakingContractAddress=stakingContractAddress + ) + + # Endpoint: Leaderboard + # Path: /leaderboard + async def get_leaderboard(self): + return await self._request("GET", "/leaderboard") + + # Endpoint: LeaderboardEpochs + # Path: /leaderboards + # Query params: fromEpochId, toEpochId, limit + async def get_leaderboard_epochs( + self, fromEpochId: int = None, toEpochId: int = None, limit: int = None + ): + return await self._request( + "GET", + "/leaderboards", + fromEpochId=fromEpochId, + toEpochId=toEpochId, + limit=limit, + ) + + # Endpoint: TransfersHistory + # Path: /transfersHistory + # Query params: vault, account, limit, fromNumber, toNumber + async def get_transfers_history( + self, + vault: str = None, + account: str = None, + limit: int = None, + fromNumber: int = None, + toNumber: int = None, + ): + return await self._request( + "GET", + "/transfersHistory", + vault=vault, + account=account, + limit=limit, + fromNumber=fromNumber, + toNumber=toNumber, + ) + + # Endpoint: GetStakingPools + # Path: /stakingPools + # Query params: staker, stakingContractAddress + async def get_staking_pools( + self, staker: str = None, stakingContractAddress: str = None + ): + return await self._request( + "GET", + "/stakingPools", + staker=staker, + stakingContractAddress=stakingContractAddress, + ) + + # Endpoint: StakingRewardByAccount + # Path: /holders/{staker}/stakingRewards + # Path param: staker + # Query params: stakingContractAddress + async def get_staking_reward_by_account( + self, staker: str, stakingContractAddress: str = None + ): + path = f"/holders/{staker}/stakingRewards" + return await self._request( + "GET", path, stakingContractAddress=stakingContractAddress + ) + + # Endpoint: StakingHistory + # Path: /stakingHistory + # Query params: fromNumber, toNumber, limit, staker + async def get_staking_history( + self, + fromNumber: int = None, + toNumber: int = None, + limit: int = None, + staker: str = None, + ): + return await self._request( + "GET", + "/stakingHistory", + fromNumber=fromNumber, + toNumber=toNumber, + limit=limit, + staker=staker, + ) + + # Endpoint: StakingAmountAtHeight + # Path: /stakingHistory/{stakingContractAddress}/amounts + # Path param: stakingContractAddress + # Query params: denom, height, staker, skip, limit + async def get_staking_amount_at_height( + self, + stakingContractAddress: str, + denom: str = None, + height: str = None, + staker: str = None, + skip: int = None, + limit: int = None, + ): + path = f"/stakingHistory/{stakingContractAddress}/amounts" + return await self._request( + "GET", + path, + denom=denom, + height=height, + staker=staker, + skip=skip, + limit=limit, + ) + + # Endpoint: Health + # Path: /health + async def get_health(self): + return await self._request("GET", "/health") + + # Endpoint: Execution + # Path: /execution/{contractAddress} + # Path param: contractAddress + async def get_execution(self, contractAddress: str): + path = f"/execution/{contractAddress}" + return await self._request("GET", path) + + # Endpoint: Missions + # Path: /missions/{account_address} + # Path param: account_address + async def get_missions(self, account_address: str): + path = f"/missions/{account_address}" + return await self._request("GET", path) + + # Endpoint: MissionLeaderboard + # Path: /missionsLeaderboard + # Query params: userAddress + async def get_mission_leaderboard(self, userAddress: str = None): + return await self._request( + "GET", "/missionsLeaderboard", userAddress=userAddress + ) + + # Endpoint: ListIDOs + # Path: /launchpad/idos + # Query params: status, limit, toNumber, accountAddress, ownerAddress + async def list_idos( + self, + status: str = None, + limit: int = None, + toNumber: int = None, + accountAddress: str = None, + ownerAddress: str = None, + ): + return await self._request( + "GET", + "/launchpad/idos", + status=status, + limit=limit, + toNumber=toNumber, + accountAddress=accountAddress, + ownerAddress=ownerAddress, + ) + + # Endpoint: GetIDO + # Path: /launchpad/idos/{contractAddress} + # Path param: contractAddress + # Query params: accountAddress + async def get_ido(self, contractAddress: str, accountAddress: str = None): + path = f"/launchpad/idos/{contractAddress}" + return await self._request("GET", path, accountAddress=accountAddress) + + # Endpoint: GetIDOSubscribers + # Path: /launchpad/idos/{contractAddress}/subscribers + # Path param: contractAddress + # Query params: limit, skip, sortBy + async def get_ido_subscribers( + self, + contractAddress: str, + limit: int = None, + skip: int = None, + sortBy: str = None, + ): + path = f"/launchpad/idos/{contractAddress}/subscribers" + return await self._request("GET", path, limit=limit, skip=skip, sortBy=sortBy) + + # Endpoint: GetIDOSubscription + # Path: /launchpad/idos/{contractAddress}/subscription/{accountAddress} + # Path params: contractAddress, accountAddress + async def get_ido_subscription(self, contractAddress: str, accountAddress: str): + path = f"/launchpad/idos/{contractAddress}/subscription/{accountAddress}" + return await self._request("GET", path) + + # Endpoint: GetIDOActivities + # Path: /launchpad/activities + # Query params: contractAddress, accountAddress, limit, toNumber + async def get_ido_activities( + self, + contractAddress: str = None, + accountAddress: str = None, + limit: int = None, + toNumber: int = None, + ): + return await self._request( + "GET", + "/launchpad/activities", + contractAddress=contractAddress, + accountAddress=accountAddress, + limit=limit, + toNumber=toNumber, + ) + + # Endpoint: GetWhitelist + # Path: /launchpad/idos/{idoAddress}/whitelist + # Path param: idoAddress + # Query params: skip, limit + async def get_whitelist(self, idoAddress: str, skip: int = None, limit: int = None): + path = f"/launchpad/idos/{idoAddress}/whitelist" + return await self._request("GET", path, skip=skip, limit=limit) + + # Endpoint: TokenMetadata + # Path: /tokenMetadata + async def get_token_metadata(self): + return await self._request("GET", "/tokenMetadata") + + # Endpoint: GetClaimReferences + # Path: /launchpad/claimReferences/ + # Query params: accountAddress, idoAddress, skip, limit + async def get_claim_references( + self, accountAddress: str, idoAddress: str, skip: int = None, limit: int = None + ): + return await self._request( + "GET", + "/launchpad/claimReferences/", + accountAddress=accountAddress, + idoAddress=idoAddress, + skip=skip, + limit=limit, + ) + + +# import asyncio +# +# async def main(): +# client = MitoAPIClient("https://k8s.mainnet.mito.grpc-web.injective.network/api/v1") +# vaults = await client.get_vaults(limit=5) +# print(vaults) +# +# asyncio.run(main()) From 67a536bf2929a17bfb5c7d9e1a144c2327b998dd Mon Sep 17 00:00:00 2001 From: enigmarikki Date: Thu, 5 Dec 2024 18:51:03 -0500 Subject: [PATCH 6/8] "wip: finished integrating mito api with gpt calls" --- agent_server.py | 1 + injective_functions/factory.py | 4 ++- injective_functions/utils/function_helper.py | 36 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/agent_server.py b/agent_server.py index 9519184..c4ee461 100644 --- a/agent_server.py +++ b/agent_server.py @@ -47,6 +47,7 @@ def __init__(self): "./injective_functions/staking/staking_schema.json", "./injective_functions/token_factory/token_factory_schema.json", "./injective_functions/wasm/wasm_schema.json", + "./injective_functions/utils/mito_get_requests_schema.json" ] self.function_schemas = FunctionSchemaLoader.load_schemas(schema_paths) diff --git a/injective_functions/factory.py b/injective_functions/factory.py index 003e7d1..c997b99 100644 --- a/injective_functions/factory.py +++ b/injective_functions/factory.py @@ -8,8 +8,9 @@ from injective_functions.exchange.trader import InjectiveTrading from injective_functions.staking import InjectiveStaking from injective_functions.token_factory import InjectiveTokenFactory +from injective_functions.utils.mito_requests import MitoAPIClient - +MITO_BASE_URI = "https://k8s.mainnet.mito.grpc-web.injective.network/api/v1" class InjectiveClientFactory: """Factory for creating Injective client instances.""" @@ -41,6 +42,7 @@ async def create_all(private_key: str, network_type: str = "mainnet") -> Dict: "trader": InjectiveTrading(chain_client), "staking": InjectiveStaking(chain_client), "token_factory": InjectiveTokenFactory(chain_client), + "mito_fetch_data": MitoAPIClient(MITO_BASE_URI) } print(clients) return clients diff --git a/injective_functions/utils/function_helper.py b/injective_functions/utils/function_helper.py index 4843213..9350ebb 100644 --- a/injective_functions/utils/function_helper.py +++ b/injective_functions/utils/function_helper.py @@ -59,6 +59,42 @@ class InjectiveFunctionMapper: "mint": ("token_factory", "mint"), "burn": ("token_factory", "burn"), "set_denom_metadata": ("token_factory", "set_denom_metadata"), + # Mito fetch functions + "get_vaults": ("mito_fetch_data", "get_vaults"), + "get_vault": ("mito_fetch_data", "get_vault"), + "get_lp_token_price_chart": ("mito_fetch_data", "get_lp_token_price_chart"), + "get_tvl_chart": ("mito_fetch_data", "get_tvl_chart"), + "get_vaults_by_holder_address": ( + "mito_fetch_data", + "get_vaults_by_holder_address", + ), + "get_lp_holders": ("mito_fetch_data", "get_lp_holders"), + "get_portfolio": ("mito_fetch_data", "get_portfolio"), + "get_leaderboard": ("mito_fetch_data", "get_leaderboard"), + "get_leaderboard_epochs": ("mito_fetch_data", "get_leaderboard_epochs"), + "get_transfers_history": ("mito_fetch_data", "get_transfers_history"), + "get_staking_pools": ("mito_fetch_data", "get_staking_pools"), + "get_staking_reward_by_account": ( + "mito_fetch_data", + "get_staking_reward_by_account", + ), + "get_staking_history": ("mito_fetch_data", "get_staking_history"), + "get_staking_amount_at_height": ( + "mito_fetch_data", + "get_staking_amount_at_height", + ), + "get_health": ("mito_fetch_data", "get_health"), + "get_execution": ("mito_fetch_data", "get_execution"), + "get_missions": ("mito_fetch_data", "get_missions"), + "get_mission_leaderboard": ("mito,fetch_data", "get_mission_leaderboard"), + "list_idos": ("mito_fetch_data", "list_idos"), + "get_ido": ("mito_fetch_data", "get_ido"), + "get_ido_subscribers": ("mito_fetch_data", "get_ido_subscribers"), + "get_ido_subscription": ("mito_fetch_data", "get_ido_subscription"), + "get_ido_activities": ("mito_fetch_data", "get_ido_activities"), + "get_whitelist": ("mito_fetch_data", "get_whitelist"), + "get_token_metadata": ("mito_fetch_data", "get_token_metadata"), + "get_claim_references": ("mito_fetch_data", "get_claim_references"), } @classmethod From f1d09495bf43854bd306f996543061d63dd9e231 Mon Sep 17 00:00:00 2001 From: enigmarikki Date: Thu, 5 Dec 2024 19:15:22 -0500 Subject: [PATCH 7/8] "wip: finished adding function schema for mito transactions" --- injective_functions/wasm/mito_contracts.py | 82 +++--- injective_functions/wasm/wasm_schema.json | 302 +++++++++++++++++++++ 2 files changed, 342 insertions(+), 42 deletions(-) diff --git a/injective_functions/wasm/mito_contracts.py b/injective_functions/wasm/mito_contracts.py index 9d76853..4f570a2 100644 --- a/injective_functions/wasm/mito_contracts.py +++ b/injective_functions/wasm/mito_contracts.py @@ -4,9 +4,13 @@ from typing import List, Dict, Tuple import json +# Set contract configuration based on network +CPMM_CONTRACT_CODE = 540 +MITO_MASTER_CONTRACT_ADDRESS = "inj1vcqkkvqs7prqu70dpddfj7kqeqfdz5gg662qs3" + #TODO: Fetch vault details and abstract away the vault data through gpt -class MitoContracts(InjectiveBase): +class InjectiveMitoContracts(InjectiveBase): def __init__(self, chain_client): super().__init__(chain_client) self.contract_type = { @@ -72,13 +76,13 @@ async def subscription_mito_spot( else {} ) - data = { + data = json.dumps({ "vault_subaccount_id": vault_subaccount_id, "trader_subaccount_id": self.chain_client.address.get_subaccount_id( trader_subaccount_idx ), "msg": {"subscribe": subscription_args}, - } + }) funds_list = [] if spot_redemption_type != "QuoteOnly" and base_amount > 0: @@ -91,7 +95,7 @@ async def subscription_mito_spot( msg = self.chain_client.composer.msg_privileged_execute_contract( sender=self.chain_client.address.to_acc_bech32(), contract=vault_master_address, - msg=json.dumps(data), + msg=data, funds=funds, ) @@ -118,20 +122,20 @@ async def redeem_mito_vault( ) subscription_args["redemption_type"] = redemption_type - data = { + data = json.dumps({ "vault_subaccount_id": vault_subaccount_id, "trader_subaccount_id": self.chain_client.address.get_subaccount_id( trader_subaccount_idx ), "msg": {"redeem": subscription_args}, - } + }) - funds = f"{redeem_amount} {lp_denom}" + funds = f"{redeem_amount}{lp_denom}" msg = self.chain_client.composer.msg_privileged_execute_contract( sender=self.chain_client.address.to_acc_bech32(), contract=vault_master_address, - msg=json.dumps(data), + msg=data, funds=funds, ) @@ -141,19 +145,18 @@ async def stake_mito_vault( self, amount: float, vault_lp_denom: str, - vault_token_decimals: int, staking_contract_address: str, ) -> Dict: """ Stake LP tokens in Mito vault """ - amount_in_chain = int(amount * (10**vault_token_decimals)) - funds = f"{amount_in_chain}{vault_lp_denom}" - + #TODO: verify if this has to be chain denom or not + funds = f"{amount}{vault_lp_denom}" + data = json.dumps({"action": "stake", "msg": {}}) msg = self.chain_client.composer.msg_execute_contract_compat( sender=self.chain_client.address.to_acc_bech32(), contract=staking_contract_address, - msg=json.dumps({"action": "stake", "msg": {}}), + msg=data, funds=funds, ) @@ -168,11 +171,7 @@ async def unstake_mito( ) -> Dict: """Unstake LP tokens from Mito vault""" amount_in_chain = int(amount * (10 ** vault_token_decimals)) - - msg = self.chain_client.composer.msg_execute_contract_compat( - sender=self.chain_client.address.to_acc_bech32(), - contract=staking_contract_address, - msg=json.dumps({ + data = json.dumps({ "action": "unstake", "msg": { "coin": { @@ -180,7 +179,11 @@ async def unstake_mito( "amount": str(amount_in_chain) } } - }), + }) + msg = self.chain_client.composer.msg_execute_contract_compat( + sender=self.chain_client.address.to_acc_bech32(), + contract=staking_contract_address, + msg=data ) return await self.chain_client.build_and_broadcast_tx(msg) @@ -193,16 +196,16 @@ async def claim_stake_mito_vault( """ Claim staking rewards from Mito vault """ - msg = self.chain_client.composer.msg_execute_contract_compat( - sender=self.chain_client.address.to_acc_bech32(), - contract=staking_contract_address, - msg=json.dumps({ + data = json.dumps({ "action": "claim_stake", "msg": { "lp_token": vault_lp_denom } - }), - funds="", + }) + msg = self.chain_client.composer.msg_execute_contract_compat( + sender=self.chain_client.address.to_acc_bech32(), + contract=staking_contract_address, + msg= data ) return await self.chain_client.build_and_broadcast_tx(msg) @@ -214,24 +217,24 @@ async def claim_rewards_mito( """ Claim rewards from Mito vault """ - msg = self.chain_client.composer.msg_execute_contract_compat( - sender=self.chain_client.address.to_acc_bech32(), - contract=staking_contract_address, - msg=json.dumps({ + data = json.dumps({ "action": "claim_rewards", "msg": { "lp_token": vault_lp_denom } - }), - funds="", + }) + msg = self.chain_client.composer.msg_execute_contract_compat( + sender=self.chain_client.address.to_acc_bech32(), + contract=staking_contract_address, + msg=data ) return await self.chain_client.build_and_broadcast_tx(msg) - #TODO: Need to test in testnet + #TODO: Need to test in testnet and improve parameterization of the default cpmm + #This is the permissionless cpmm vault async def instantiate_cpmm_vault( self, - inj_amount: float, base_token_amount: float, base_token_denom: str, quote_token_amount: float, @@ -248,16 +251,11 @@ async def instantiate_cpmm_vault( if owner_address is None: owner_address = self.chain_client.address.to_acc_bech32() - # Set contract configuration based on network - CPMM_CONTRACT_CODE = 540 - MITO_MASTER_CONTRACT_ADDRESS = "inj1vcqkkvqs7prqu70dpddfj7kqeqfdz5gg662qs3" - funds = [ - f"{int(quote_token_amount)}{quote_token_denom}", - f"{int(base_token_amount)}{base_token_denom}" + (quote_token_amount, quote_token_denom), + (base_token_amount ,base_token_denom) ] - funds_str = ",".join(funds) - #TODO: improve the parameterization + funds = self._order_funds_by_denom(funds) data = { "action": "register_vault", "msg": { @@ -295,7 +293,7 @@ async def instantiate_cpmm_vault( sender=owner_address, contract=MITO_MASTER_CONTRACT_ADDRESS, msg=json.dumps(data), - funds=funds_str, + funds=funds, ) return await self.chain_client.build_and_broadcast_tx(msg) \ No newline at end of file diff --git a/injective_functions/wasm/wasm_schema.json b/injective_functions/wasm/wasm_schema.json index e69de29..1dc8bf5 100644 --- a/injective_functions/wasm/wasm_schema.json +++ b/injective_functions/wasm/wasm_schema.json @@ -0,0 +1,302 @@ +{ + "functions": [ + { + "name": "subscribe_to_launchpad", + "description": "Subscribe to a launchpad using specified contract address and funds.", + "parameters": { + "type": "object", + "properties": { + "contract_address": { + "type": "string", + "description": "The contract address for the launchpad." + }, + "quote_denom": { + "type": "string", + "description": "Denomination of the quote token." + }, + "amount": { + "type": "number", + "description": "Amount of funds to subscribe with." + } + }, + "required": ["contract_address", "quote_denom", "amount"] + } + }, + { + "name": "claim_launchpad_subscription", + "description": "Claim subscription for a launchpad.", + "parameters": { + "type": "object", + "properties": { + "contract_address": { + "type": "string", + "description": "The contract address for the launchpad." + } + }, + "required": ["contract_address"] + } + }, + { + "name": "subscription_mito_spot", + "description": "Subscribe to a Mito spot trading vault.", + "parameters": { + "type": "object", + "properties": { + "base_amount": { + "type": "number", + "description": "Amount of base token." + }, + "base_denom": { + "type": "string", + "description": "Denomination of base token." + }, + "quote_amount": { + "type": "number", + "description": "Amount of quote token." + }, + "quote_denom": { + "type": "string", + "description": "Denomination of quote token." + }, + "vault_subaccount_id": { + "type": "string", + "description": "Vault subaccount ID." + }, + "max_penalty": { + "type": "number", + "description": "Maximum penalty for slippage." + }, + "vault_master_address": { + "type": "string", + "description": "Vault master contract address." + }, + "vault_contract_type": { + "type": "string", + "description": "Type of the vault contract." + }, + "spot_redemption_type": { + "type": "string", + "description": "Type of spot redemption." + }, + "trader_subaccount_idx": { + "type": "number", + "description": "Trader's subaccount index.", + "default": 0 + } + }, + "required": [ + "base_amount", + "base_denom", + "quote_amount", + "quote_denom", + "vault_subaccount_id", + "max_penalty", + "vault_master_address", + "vault_contract_type", + "spot_redemption_type" + ] + } + }, + { + "name": "redeem_mito_vault", + "description": "Redeem funds from a Mito vault.", + "parameters": { + "type": "object", + "properties": { + "redeem_amount": { + "type": "number", + "description": "Amount to redeem." + }, + "lp_denom": { + "type": "string", + "description": "LP token denomination." + }, + "vault_subaccount_id": { + "type": "string", + "description": "Vault subaccount ID." + }, + "max_penalty": { + "type": "number", + "description": "Maximum penalty for slippage." + }, + "vault_master_address": { + "type": "string", + "description": "Vault master contract address." + }, + "market_type": { + "type": "string", + "description": "Market type (e.g., 'Derivative')." + }, + "redemption_type": { + "type": "string", + "description": "Type of redemption." + }, + "trader_subaccount_idx": { + "type": "number", + "description": "Trader's subaccount index.", + "default": 0 + } + }, + "required": [ + "redeem_amount", + "lp_denom", + "vault_subaccount_id", + "max_penalty", + "vault_master_address", + "market_type", + "redemption_type" + ] + } + }, + { + "name": "stake_mito_vault", + "description": "Stake LP tokens in a Mito vault.", + "parameters": { + "type": "object", + "properties": { + "amount": { + "type": "number", + "description": "Amount to stake." + }, + "vault_lp_denom": { + "type": "string", + "description": "LP token denomination." + }, + "staking_contract_address": { + "type": "string", + "description": "Staking contract address." + } + }, + "required": [ + "amount", + "vault_lp_denom", + "staking_contract_address" + ] + } + }, + { + "name": "unstake_mito", + "description": "Unstake LP tokens from a Mito vault.", + "parameters": { + "type": "object", + "properties": { + "amount": { + "type": "number", + "description": "Amount to unstake." + }, + "vault_lp_denom": { + "type": "string", + "description": "LP token denomination." + }, + "vault_token_decimals": { + "type": "integer", + "description": "Decimals of the token." + }, + "staking_contract_address": { + "type": "string", + "description": "Staking contract address." + } + }, + "required": [ + "amount", + "vault_lp_denom", + "vault_token_decimals", + "staking_contract_address" + ] + } + }, + { + "name": "claim_stake_mito_vault", + "description": "Claim staking rewards from a Mito vault.", + "parameters": { + "type": "object", + "properties": { + "vault_lp_denom": { + "type": "string", + "description": "LP token denomination." + }, + "staking_contract_address": { + "type": "string", + "description": "Staking contract address." + } + }, + "required": ["vault_lp_denom", "staking_contract_address"] + } + }, + { + "name": "claim_rewards_mito", + "description": "Claim rewards from a Mito vault.", + "parameters": { + "type": "object", + "properties": { + "vault_lp_denom": { + "type": "string", + "description": "LP token denomination." + }, + "staking_contract_address": { + "type": "string", + "description": "Staking contract address." + } + }, + "required": ["vault_lp_denom", "staking_contract_address"] + } + }, + { + "name": "instantiate_cpmm_vault", + "description": "Instantiate a CPMM vault with specified parameters.", + "parameters": { + "type": "object", + "properties": { + "base_token_amount": { + "type": "number", + "description": "Amount of base token." + }, + "base_token_denom": { + "type": "string", + "description": "Base token denomination." + }, + "quote_token_amount": { + "type": "number", + "description": "Amount of quote token." + }, + "quote_token_denom": { + "type": "string", + "description": "Quote token denomination." + }, + "market_id": { + "type": "string", + "description": "Market ID for the vault." + }, + "fee_bps": { + "type": "integer", + "description": "Fee basis points." + }, + "base_decimals": { + "type": "integer", + "description": "Decimals of base token." + }, + "quote_decimals": { + "type": "integer", + "description": "Decimals of quote token." + }, + "owner_address": { + "type": "string", + "description": "Owner's address for the vault.", + "default": null + } + }, + "required": [ + "base_token_amount", + "base_token_denom", + "quote_token_amount", + "quote_token_denom", + "market_id", + "fee_bps", + "base_decimals", + "quote_decimals" + ] + } + } + ] + } + \ No newline at end of file From 706a4ac4a6f7eed174c57f589de9ca28ec973123 Mon Sep 17 00:00:00 2001 From: enigmarikki Date: Thu, 5 Dec 2024 19:21:01 -0500 Subject: [PATCH 8/8] "feat: finished integrating both mito fetch + txs api with function calling" --- injective_functions/factory.py | 4 +++- injective_functions/utils/function_helper.py | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/injective_functions/factory.py b/injective_functions/factory.py index c997b99..69e95f3 100644 --- a/injective_functions/factory.py +++ b/injective_functions/factory.py @@ -9,6 +9,7 @@ from injective_functions.staking import InjectiveStaking from injective_functions.token_factory import InjectiveTokenFactory from injective_functions.utils.mito_requests import MitoAPIClient +from injective_functions.wasm.mito_contracts import InjectiveMitoContracts MITO_BASE_URI = "https://k8s.mainnet.mito.grpc-web.injective.network/api/v1" class InjectiveClientFactory: @@ -42,7 +43,8 @@ async def create_all(private_key: str, network_type: str = "mainnet") -> Dict: "trader": InjectiveTrading(chain_client), "staking": InjectiveStaking(chain_client), "token_factory": InjectiveTokenFactory(chain_client), - "mito_fetch_data": MitoAPIClient(MITO_BASE_URI) + "mito_fetch_data": MitoAPIClient(MITO_BASE_URI), + "mito_transactions": InjectiveMitoContracts(chain_client) } print(clients) return clients diff --git a/injective_functions/utils/function_helper.py b/injective_functions/utils/function_helper.py index 9350ebb..2f2150a 100644 --- a/injective_functions/utils/function_helper.py +++ b/injective_functions/utils/function_helper.py @@ -95,6 +95,19 @@ class InjectiveFunctionMapper: "get_whitelist": ("mito_fetch_data", "get_whitelist"), "get_token_metadata": ("mito_fetch_data", "get_token_metadata"), "get_claim_references": ("mito_fetch_data", "get_claim_references"), + # Mito txs + "subscribe_to_launchpad": ("mito_transactions", "subscribe_to_launchpad"), + "claim_launchpad_subscription": ( + "mito_transactions", + "claim_launchpad_subscription", + ), + "subscription_mito_spot": ("mito_transactions", "subscription_mito_spot"), + "redeem_mito_vault": ("mito_transactions", "redeem_mito_vault"), + "stake_mito_vault": ("mito_transactions", "stake_mito_vault"), + "unstake_mito": ("mito_transactions", "unstake_mito"), + "claim_stake_mito_vault": ("mito_transactions", "claim_stake_mito_vault"), + "claim_rewards_mito": ("mito_transactions", "claim_rewards_mito"), + "instantiate_cpmm_vault": ("mito_transactions", "instantiate_cpmm_vault"), } @classmethod