Skip to content
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ pip install web3-wallet-connect
```python
import streamlit as st

from python_web3_wallet import my_component
from python_web3_wallet import wallet_component

c = my_component(recipient="0x...", amount_in_ether="0.01") # Displays RainbowKit wallet
c = wallet_component(recipient="0x...", amount_in_ether="0.01") # Displays RainbowKit wallet
# Optionally data (as a Hex-formatted string) can be passed to populate the data field when sending a transaction.
# c = my_component(recipient="0x...", amount_in_ether="0.01", data="0x78da2b492d2e0100045d01c1")
# c = wallet_component(recipient="0x...", amount_in_ether="0.01", data="0x78da2b492d2e0100045d01c1")
```
2 changes: 1 addition & 1 deletion python_web3_wallet/README
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ python setup.py sdist bdist_wheel
# publish on testpy
python -m twine upload --repository testpypi dist/* --verbose
# upload to pypi
python -m twine upload dist/* --verbose
python -m twine upload dist/* --verbose
```
2 changes: 1 addition & 1 deletion python_web3_wallet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
# `declare_component` and call it done. The wrapper allows us to customize
# our component's API: we can pre-process its input args, post-process its
# output value, and add a docstring for users.
def my_component(recipient: str, amount_in_ether: str, data: str, key=None):
def wallet_component(recipient: str, amount_in_ether: str, data: str | None = None, key=None):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding to our discussion on Slack on having multiple components in the same package -> see https://discuss.streamlit.io/t/creating-multiple-custom-components-in-the-same-python-package/10906/7

tl;dr some work would be needed to maintain multiple components in parallel. Since this is still in the testing phase and we are validating this ideas internally, I decided to keep just one custom component for simplicity.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But in that case, this repo and pypi package shouldn't be called python-web3-wallet-streamlit.

More something in terms of agent-communication-streamlit.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or you could duplicate this repository with the new name, and merge this PR there. That way we have 2 repositories:

  1. One that already works for sending classic xDai transactions.
  2. Second that is meant for sending messages to agent.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal of this repository is to simply house a Streamlit wallet component allowing users to send messages to agents.
Previously, sending messages involved sending classic xDai transactions.. This logic changed after our internal discussion with Martin and now involves executing a transaction on a smart contract. Hence, I refactored the logic and now pressing the button triggers the aforementioned transaction. Per the above, I don't think it's necessary to create a new repo/create a new component, since the old logic has been deprecated in favor of the new one.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought you got my reasoning over Slack -- on the one hand, we talk about how awesome it would be to have some tools/frameworks to drive people to Gnosis (AI), on the other, when we have a handy functional component that could be interesting for machine learning people who mostly work in Python and Streamlit, it's going to be deleted because keeping it involves a few boring clicks around Github and PyPi.

However, in the end, it's all your code in this repository, so if you want to get rid of it, I won't block it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on the one hand, we talk about how awesome it would be to have some tools/frameworks to drive people to Gnosis (AI)

This requires a bit more planning - it's not "build it and they will come", this involves DevRel, talking to the community to see what they want to build, we prepare something, give talks, etc etc - simply having 1...N components is not going to move the needle.
Happy to brainstorm on this better, but closing this as per above.

"""Create a new instance of "my_component".
Parameters
Expand Down
2 changes: 1 addition & 1 deletion python_web3_wallet/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@

import streamlit as st
st.title('My title')
c = component(recipient="0x07354C0aD12741E8F222eB439cFf4c01716cA627", amountInEther="0.01", data=None)
c = component(recipient="0x07354C0aD12741E8F222eB439cFf4c01716cA627", amountInEther="0.00001", data='0x48656c6c6f20776f726c64')
56 changes: 44 additions & 12 deletions python_web3_wallet/frontend/src/PythonWeb3Wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@ import {
ComponentProps,
} from "streamlit-component-lib";
import { type Hex, getAddress, parseEther } from 'viem';
import React, { useCallback, useEffect, useMemo, useState, ReactElement } from "react"
import React, { useEffect, useMemo, useState, ReactElement } from "react"
import { ConnectButton } from "@rainbow-me/rainbowkit"
import '@rainbow-me/rainbowkit/styles.css';
import { useAccount, useSendTransaction } from "wagmi";

import { useAccount, useSendTransaction, useWriteContract, useChainId, useWaitForTransactionReceipt, BaseError } from "wagmi";
import { abi } from './abi';
import { AGENT_COMMUNICATION_CONTRACT } from "./constants";
/**
* This is a React-based component template. The passed props are coming from the
* Streamlit library. Your custom args can be accessed via the `args` props.
*/
function PythonWeb3Wallet({ args, disabled, theme }: ComponentProps): ReactElement {
const { recipient, amountInEther, data } = args;

const {
data: hash,
error,
writeContractAsync
} = useWriteContract();

const { sendTransaction } = useSendTransaction();
const account = useAccount();

const [isFocused, setIsFocused] = useState(false)
Expand All @@ -38,28 +43,55 @@ function PythonWeb3Wallet({ args, disabled, theme }: ComponentProps): ReactEleme
}, [style, theme]);


const sendMessage = async () => {
console.log(`sending message with content ${data as Hex} to ${recipient}`);

try {
const txHash = await writeContractAsync({
abi,
address: AGENT_COMMUNICATION_CONTRACT,
functionName: 'sendMessage',
args: [
getAddress(recipient),
data as Hex,
],
value: parseEther(amountInEther),
}, {
onError: (err) => console.log(err),
});
console.log(`txHash ${txHash}`);
} catch {
// We simply pass here since errors already logged.
}


};



return (
<>
<button
style={{
backgroundColor: !account.isConnected ? 'gray' : 'blue',
color: 'white',
padding: '15px 30px',
marginBottom: '15px',
fontSize: '18px',
border: 'none',
borderRadius: '10px',
}}
onClick={() =>
sendTransaction({
to: getAddress(recipient),
value: parseEther(amountInEther),
data: data as Hex
})
}
onClick={(sendMessage)}
disabled={!account.isConnected}
>
Send transaction
Send message to agent
</button>

{error && (
<div>Error: {(error as BaseError).shortMessage || error.message}</div>
)}


<div
style={{
paddingBottom: '500px'
Expand Down
21 changes: 21 additions & 0 deletions python_web3_wallet/frontend/src/abi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Abi from AgentCommunicationContract - see https://gnosisscan.io/address/0xd422e0059ed819e8d792af936da206878188e34f#code
export const abi = [
{
"type": "function",
"name": "sendMessage",
"inputs": [
{
"name": "agentAddress",
"type": "address",
"internalType": "address"
},
{
"name": "message",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [],
"stateMutability": "payable"
},
] as const
1 change: 1 addition & 0 deletions python_web3_wallet/frontend/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const AGENT_COMMUNICATION_CONTRACT = '0xd422e0059ed819e8d792af936da206878188e34f';
13 changes: 12 additions & 1 deletion python_web3_wallet/frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,27 @@ import ReactDOM from "react-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { getDefaultConfig, RainbowKitProvider } from "@rainbow-me/rainbowkit";
import { WagmiProvider } from "wagmi";
import { gnosis } from "wagmi/chains";
import { Chain, gnosis, localhost } from "wagmi/chains";
import PythonWeb3Wallet from "./PythonWeb3Wallet";

const queryClient = new QueryClient();

// for using with forked-Gnosis chain
// const gnosisFoundryLocalhost = {
// id: 99,
// name: 'Gnosis-Fork',
// nativeCurrency: { name: 'Ether', symbol: 'xDAI', decimals: 18 },
// rpcUrls: {
// default: { http: ['http://127.0.0.1:8545'] },
// },
// } as const satisfies Chain;

const config = getDefaultConfig({
appName: 'app',
projectId: process.env.REACT_APP_RAINBOW_WALLET_PROJECT_ID!,
chains: [
gnosis,
//gnosisFoundryLocalhost
],
});

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

setuptools.setup(
name="python_web3_wallet",
version="0.0.3",
version="0.0.4",
author="Gnosis AI",
author_email="ai@gnosis.io",
description="Streamlit component that allows users to connect a wallet and send transactions with dynamic recipients and amounts",
Expand Down