-
Notifications
You must be signed in to change notification settings - Fork 163
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add Python Solana wallet implementation (#233)
* feat: add Python Solana wallet implementation Co-Authored-By: [email protected] <[email protected]> * feat: add README, pyproject.toml, poetry.toml, and __init__.py for Solana wallet Co-Authored-By: [email protected] <[email protected]> * Rename wallet-building function * Fix transaction construction in wallet * Add Solana example to validate Solana wallet * Better .env.template and PubKey derivation fix * Rename solana wallet build function * Langchain Solana example --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: [email protected] <[email protected]> Co-authored-by: Andrea V <[email protected]>
- Loading branch information
1 parent
a6970f8
commit 4040ead
Showing
17 changed files
with
4,240 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
OPENAI_API_KEY= | ||
SOLANA_RPC_ENDPOINT=https://api.devnet.solana.com | ||
SOLANA_WALLET_SEED=2JpXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Langchain web3 Example | ||
|
||
## Setup | ||
|
||
Copy the `.env.template` and populate with your values. | ||
|
||
``` | ||
cp .env.template .env | ||
``` | ||
|
||
Install dependencies | ||
|
||
``` | ||
poetry install --no-root | ||
``` | ||
|
||
## Usage | ||
|
||
``` | ||
poetry run example.py | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import os | ||
from dotenv import load_dotenv | ||
|
||
# Load environment variables | ||
load_dotenv() | ||
|
||
from langchain_openai import ChatOpenAI | ||
from langchain.agents import AgentExecutor, create_tool_calling_agent | ||
from langchain_core.prompts import ChatPromptTemplate | ||
from solana.rpc.api import Client as SolanaClient | ||
from solders.keypair import Keypair | ||
|
||
from goat_adapters.langchain import get_on_chain_tools | ||
from goat_wallets.solana import solana | ||
|
||
# Initialize Solana client and wallet | ||
client = SolanaClient(os.getenv("SOLANA_RPC_ENDPOINT")) | ||
keypair = Keypair.from_base58_string(os.getenv("SOLANA_WALLET_SEED") or "") | ||
wallet = solana(client, keypair) | ||
|
||
# Initialize LLM | ||
llm = ChatOpenAI(model="gpt-4o-mini") | ||
|
||
|
||
def main(): | ||
# Get the prompt template | ||
prompt = ChatPromptTemplate.from_messages( | ||
[ | ||
("system", "You are a helpful assistant"), | ||
("placeholder", "{chat_history}"), | ||
("human", "{input}"), | ||
("placeholder", "{agent_scratchpad}"), | ||
] | ||
) | ||
|
||
# Initialize tools with Solana wallet | ||
tools = get_on_chain_tools( | ||
wallet=wallet, | ||
plugins=[], # Add Solana specific plugins here when needed | ||
) | ||
|
||
agent = create_tool_calling_agent(llm, tools, prompt) | ||
agent_executor = AgentExecutor( | ||
agent=agent, tools=tools, handle_parsing_errors=True, verbose=True | ||
) | ||
|
||
while True: | ||
user_input = input("\nYou: ").strip() | ||
|
||
if user_input.lower() == "quit": | ||
print("Goodbye!") | ||
break | ||
|
||
try: | ||
response = agent_executor.invoke( | ||
{ | ||
"input": user_input, | ||
} | ||
) | ||
|
||
print("\nAssistant:", response["output"]) | ||
except Exception as e: | ||
print("\nError:", str(e)) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[virtualenvs] | ||
in-project = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
[tool.poetry] | ||
name = "goat-sdk-example-langchain-solana" | ||
version = "0.1.0" | ||
description = "Goat example for Langchain with Solana" | ||
authors = ["Andrea Villa <[email protected]>"] | ||
readme = "README.md" | ||
keywords = ["goat", "sdk", "solana", "agents", "ai"] | ||
homepage = "https://ohmygoat.dev/" | ||
repository = "https://github.com/goat-sdk/goat" | ||
packages = [ | ||
{ include = "example.py" }, | ||
] | ||
|
||
[tool.poetry.dependencies] | ||
python = "^3.12" | ||
langchain = "^0.3.2" | ||
langchain-openai = "^0.2.14" | ||
python-dotenv = "^1.0.1" | ||
solana = "^0.30.2" | ||
solders = "^0.18.0" | ||
goat-sdk = "^0.1.0" | ||
goat-sdk-wallet-solana = "^0.1.0" | ||
goat-sdk-adapter-langchain = "^0.1.0" | ||
|
||
[tool.poetry.group.test.dependencies] | ||
pytest = "^8.3.4" | ||
pytest-asyncio = "^0.25.0" | ||
|
||
[tool.poetry.urls] | ||
"Bug Tracker" = "https://github.com/goat-sdk/goat/issues" | ||
|
||
[tool.pytest.ini_options] | ||
addopts = [ | ||
"--import-mode=importlib", | ||
] | ||
pythonpath = "src" | ||
asyncio_default_fixture_loop_scope = "function" | ||
|
||
[build-system] | ||
requires = ["poetry-core"] | ||
build-backend = "poetry.core.masonry.api" | ||
|
||
[tool.poetry.group.dev.dependencies] | ||
ruff = "^0.8.6" | ||
goat-sdk = { path = "../../../src/goat-sdk", develop = true } | ||
goat-sdk-wallet-solana = { path = "../../../src/wallets/solana", develop = true } | ||
goat-sdk-adapter-langchain = { path = "../../../src/adapters/langchain", develop = true } | ||
|
||
[tool.ruff] | ||
line-length = 120 | ||
target-version = "py312" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
SOLANA_RPC_ENDPOINT=https://api.devnet.solana.com | ||
SOLANA_WALLET_SEED=2JpXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import os | ||
from dotenv import load_dotenv | ||
from solana.rpc.api import Client as SolanaClient | ||
from solders.keypair import Keypair | ||
from solders.instruction import Instruction | ||
from typing import List, Optional | ||
from goat_wallets.solana import solana, SolanaTransaction | ||
|
||
# Load environment variables | ||
load_dotenv() | ||
|
||
# Initialize Solana client and keypair | ||
client = SolanaClient(os.getenv("SOLANA_RPC_ENDPOINT")) | ||
keypair = Keypair.from_base58_string(os.getenv("SOLANA_WALLET_SEED") or "") | ||
|
||
# Create wallet instance | ||
wallet = solana(client, keypair) | ||
|
||
# Get wallet address | ||
address = wallet.get_address() | ||
|
||
# Check balance | ||
balance = wallet.balance_of(address) | ||
|
||
# Sign message | ||
signature = wallet.sign_message("Hello, Solana!") | ||
|
||
# Send transaction | ||
transaction: SolanaTransaction = { | ||
"instructions": [], # Add your Instruction objects here | ||
"address_lookup_table_addresses": None, # Optional List[str] | ||
"accounts_to_sign": None, # Optional List[Keypair] | ||
} | ||
result = wallet.send_transaction(transaction) |
Oops, something went wrong.