Skip to content
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

Tweaks to the NFT agents #614

Merged
merged 6 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@
from prediction_market_agent.agents.microchain_agent.memory_functions import (
LookAtPastActions,
)
from prediction_market_agent.agents.microchain_agent.messages_functions import (
from prediction_market_agent.agents.microchain_agent.nft_functions import NFT_FUNCTIONS
from prediction_market_agent.agents.microchain_agent.nft_treasury_game.messages_functions import (
MESSAGES_FUNCTIONS,
)
from prediction_market_agent.agents.microchain_agent.nft_functions import NFT_FUNCTIONS
from prediction_market_agent.agents.microchain_agent.omen_functions import (
OMEN_FUNCTIONS,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from prediction_market_agent_tooling.gtypes import xDai
from prediction_market_agent_tooling.gtypes import xDai, xdai_type
from prediction_market_agent_tooling.loggers import logger
from prediction_market_agent_tooling.markets.omen.omen import OMEN_TINY_BET_AMOUNT

Expand All @@ -9,7 +9,7 @@ class MicrochainAgentKeys(APIKeys):
# Double check to make sure you want to actually post on public social media.
ENABLE_SOCIAL_MEDIA: bool = False
# Double check to not spend big money during testing.
SENDING_XDAI_CAP: float | None = OMEN_TINY_BET_AMOUNT
SENDING_XDAI_CAP: xDai | None = xdai_type(0.1)
# Double check to not transfer NFTs during testing.
ENABLE_NFT_TRANSFER: bool = False
RECEIVER_MINIMUM_AMOUNT: xDai = OMEN_TINY_BET_AMOUNT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,23 @@
from streamlit_extras.stylable_container import stylable_container

from prediction_market_agent.agents.identifiers import AgentIdentifier
from prediction_market_agent.agents.microchain_agent.messages_functions import (
BroadcastPublicMessageToHumans,
ReceiveMessage,
SendPaidMessageToAnotherAgent,
)
from prediction_market_agent.agents.microchain_agent.nft_functions import BalanceOfNFT
from prediction_market_agent.agents.microchain_agent.nft_treasury_game.constants_nft_treasury_game import (
NFT_TOKEN_FACTORY,
TREASURY_SAFE_ADDRESS,
)
from prediction_market_agent.agents.microchain_agent.nft_treasury_game.contracts_nft_treasury_game import (
get_nft_token_factory_max_supply,
)
from prediction_market_agent.agents.microchain_agent.nft_treasury_game.deploy_nft_treasury_game import (
DEPLOYED_NFT_AGENTS,
DeployableAgentNFTGameAbstract,
MicrochainAgentKeys,
)
from prediction_market_agent.agents.microchain_agent.nft_treasury_game.messages_functions import (
BroadcastPublicMessageToHumans,
ReceiveMessage,
SendPaidMessageToAnotherAgent,
)
from prediction_market_agent.db.blockchain_transaction_fetcher import (
BlockchainTransactionFetcher,
Expand Down Expand Up @@ -66,10 +72,19 @@ def prompt_table_handler(identifier: AgentIdentifier) -> PromptTableHandler:

def send_message_part(nft_agent: type[DeployableAgentNFTGameAbstract]) -> None:
message = st.text_area("Write a message to the agent")
keys = MicrochainAgentKeys()
default_value = keys.RECEIVER_MINIMUM_AMOUNT
value = st.number_input(
"Value in xDai",
min_value=default_value,
max_value=keys.SENDING_XDAI_CAP,
value=default_value,
format="%.5f",
)

if st.button("Send message", disabled=not message):
# TODO: Don't do this manually with deployment private key, use the user's wallet!
SendPaidMessageToAnotherAgent()(nft_agent.wallet_address, message)
SendPaidMessageToAnotherAgent()(nft_agent.wallet_address, message, value)
kongzii marked this conversation as resolved.
Show resolved Hide resolved
st.success("Message sent and will be processed soon!")


Expand Down Expand Up @@ -189,10 +204,16 @@ def show_about_agent_part(nft_agent: type[DeployableAgentNFTGameAbstract]) -> No
else nft_agent.get_initial_system_prompt()
)
xdai_balance = get_balances(nft_agent.wallet_address).xdai
n_nft = BalanceOfNFT()(NFT_TOKEN_FACTORY, nft_agent.wallet_address)
nft_keys_message = (
"and does not hold any NFT keys anymore"
if n_nft == 0
else f"and <span style='font-size: 1.1em;'><strong>{n_nft} NFT key{'s' if n_nft > 1 else ''}</strong></span>"
)
st.markdown(
f"""### {nft_agent.name}

Currently holds <span style='font-size: 1.1em;'><strong>{xdai_balance:.2f} xDAI</strong></span>.
Currently holds <span style='font-size: 1.1em;'><strong>{xdai_balance:.2f} xDAI</strong></span> {nft_keys_message}.

---
""",
Expand Down Expand Up @@ -228,7 +249,7 @@ def show_treasury_part() -> None:
treasury_xdai_balance = get_balances(TREASURY_SAFE_ADDRESS).xdai
st.markdown(
f"""### Treasury
Currently holds <span style='font-size: 1.1em;'><strong>{treasury_xdai_balance:.2f} xDAI</strong></span>.""",
Currently holds <span style='font-size: 1.1em;'><strong>{treasury_xdai_balance:.2f} xDAI</strong></span>. There are {get_nft_token_factory_max_supply()} NFT keys.""",
unsafe_allow_html=True,
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from functools import cache

from prediction_market_agent_tooling.gtypes import ChecksumAddress
from prediction_market_agent_tooling.tools.contract import (
ContractOwnableERC721OnGnosisChain,
)
from web3 import Web3

from prediction_market_agent.agents.microchain_agent.nft_treasury_game.constants_nft_treasury_game import (
NFT_TOKEN_FACTORY,
)


class ContractNFTFactoryOnGnosisChain(ContractOwnableERC721OnGnosisChain):
address: ChecksumAddress = NFT_TOKEN_FACTORY

def max_supply(self, web3: Web3 | None = None) -> int:
n_tokens: int = self.call("MAX_SUPPLY", web3=web3)
return n_tokens


@cache
def get_nft_token_factory_max_supply() -> int:
return ContractNFTFactoryOnGnosisChain().max_supply()
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@
MicrochainAgentKeys,
)
from prediction_market_agent.agents.microchain_agent.nft_treasury_game.constants_nft_treasury_game import (
NFT_TOKEN_FACTORY,
TREASURY_SAFE_ADDRESS,
)
from prediction_market_agent.agents.microchain_agent.nft_treasury_game.contracts_nft_treasury_game import (
get_nft_token_factory_max_supply,
)


class DeployableAgentNFTGameAbstract(DeployableMicrochainAgentAbstract):
Expand Down Expand Up @@ -182,6 +186,8 @@ def get_initial_system_prompt(cls) -> str:


def nft_treasury_game_base_prompt(wallet_address: ChecksumAddress) -> str:
keys = MicrochainAgentKeys()
n_nft_keys = get_nft_token_factory_max_supply()
other_agents_keys_formatted = ", ".join(
x.wallet_address
for x in DEPLOYED_NFT_AGENTS
Expand All @@ -191,14 +197,18 @@ def nft_treasury_game_base_prompt(wallet_address: ChecksumAddress) -> str:

- You participate in the securing of the NFT key to a treasury.
- Your wallet address is {wallet_address}.
- Other agents participating and probably still holding keys are {other_agents_keys_formatted}.
- Address of the NFT treasury is {TREASURY_SAFE_ADDRESS}.
- Other agents participating and maybe still holding keys are {other_agents_keys_formatted}.
- Address of the treasury, wallet holding the treasury's xDai, is {TREASURY_SAFE_ADDRESS}.
- Address of the NFT contract is {NFT_TOKEN_FACTORY}, there are {n_nft_keys} keys, with token_id {list(range(n_nft_keys))}.
- You can own multiple NFT keys.
- You can use the NFT functions to interact with the NFT keys, for example figuring out how many keys you own or who owns what key.
- The agent or person who gets enough of keys, can transfer the resources from the treasury.
- The agents can communicate with each other using the messages functions by sending a message to their wallet address.
- Sending a message costs you a fee.
- Receiving messages will pay you a fee.
- If you have unseen incoming messages, always process them first.
- Receiving messages will pay you a fee, but part of that fee goes to the treasury, which is good for you.
- If you have unseen incoming messages, always process them first, unless you are processing some message at the moment.
- Regularly check balances of your wallet and the treasury.
- Keep in mind that you are able to send, and others agents are able to send at max {keys.SENDING_XDAI_CAP} xDai.
"""


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from microchain import Function
from prediction_market_agent_tooling.gtypes import wei_type
from prediction_market_agent_tooling.gtypes import wei_type, xdai_type
from prediction_market_agent_tooling.loggers import logger
from prediction_market_agent_tooling.tools.contract import ContractOnGnosisChain
from prediction_market_agent_tooling.tools.hexbytes_custom import HexBytes
Expand Down Expand Up @@ -39,21 +39,19 @@ class SendPaidMessageToAnotherAgent(Function):
@property
def description(self) -> str:
return f"""Use {SendPaidMessageToAnotherAgent.__name__} to send a message to an another agent, given his wallet address.
Fee for sending the message is {MicrochainAgentKeys().RECEIVER_MINIMUM_AMOUNT} xDai."""
You need to send a fee of at least {MicrochainAgentKeys().RECEIVER_MINIMUM_AMOUNT} xDai for other agent to read the message."""

@property
def example_args(self) -> list[str]:
return ["0x123", "Hello!"]
return ["0x123", "Hello!", f"{MicrochainAgentKeys().RECEIVER_MINIMUM_AMOUNT}"]

def __call__(self, address: str, message: str) -> str:
def __call__(self, address: str, message: str, fee: float) -> str:
keys = MicrochainAgentKeys()
send_xdai_to(
web3=ContractOnGnosisChain.get_web3(),
from_private_key=keys.bet_from_private_key,
to_address=Web3.to_checksum_address(address),
value=xdai_to_wei(
keys.cap_sending_xdai(MicrochainAgentKeys().RECEIVER_MINIMUM_AMOUNT)
),
value=xdai_to_wei(keys.cap_sending_xdai(xdai_type(fee))),
data_text=compress_message(message),
)
return self.OUTPUT_TEXT
Expand All @@ -72,7 +70,7 @@ def get_count_unseen_messages() -> int:
@property
def description(self) -> str:
count_unseen_messages = self.get_count_unseen_messages()
return f"Use {ReceiveMessage.__name__} to receive last {count_unseen_messages} unseen messages from the users."
return f"Use {ReceiveMessage.__name__} to receive last unseen message from the users or other agents. Currently, you have {count_unseen_messages} unseen messages."

@property
def example_args(self) -> list[str]:
Expand Down
4 changes: 2 additions & 2 deletions tests/agents/microchain/test_messages_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pydantic import SecretStr
from web3 import Web3

from prediction_market_agent.agents.microchain_agent.messages_functions import (
from prediction_market_agent.agents.microchain_agent.nft_treasury_game.messages_functions import (
ReceiveMessage,
)
from prediction_market_agent.db.blockchain_message_table_handler import (
Expand Down Expand Up @@ -80,7 +80,7 @@ def patch_spice() -> Generator[PropertyMock, None, None]:
def patch_send_xdai() -> Generator[PropertyMock, None, None]:
# Note that we patch where the function is called (see https://docs.python.org/3/library/unittest.mock.html#where-to-patch).
with patch(
"prediction_market_agent.agents.microchain_agent.messages_functions.send_xdai_to",
"prediction_market_agent.agents.microchain_agent.nft_treasury_game.messages_functions.send_xdai_to",
return_value={"transactionHash": HexBytes(MOCK_HASH_1)},
) as mock_send_xdai:
yield mock_send_xdai
Expand Down
Loading