Skip to content

Commit d03177a

Browse files
add privy wallet address
1 parent b8c35c3 commit d03177a

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "sakit"
3-
version = "12.1.0"
3+
version = "12.2.0"
44
description = "Solana Agent Kit"
55
authors = ["Bevan Hunt <bevan@bevanhunt.com>"]
66
license = "MIT"
@@ -44,3 +44,4 @@ rugcheck = "sakit.rugcheck:get_plugin"
4444
privy_swap = "sakit.privy_swap:get_plugin"
4545
privy_transfer = "sakit.privy_transfer:get_plugin"
4646
privy_balance = "sakit.privy_balance:get_plugin"
47+
privy_wallet_address = "sakit.privy_wallet_address:get_plugin"

sakit/privy_wallet_address.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from typing import Dict, Any, List, Optional
2+
from solana_agent import AutoTool, ToolRegistry
3+
import httpx
4+
5+
6+
async def get_privy_embedded_wallet_address(
7+
user_id: str, app_id: str, app_secret: str
8+
) -> Optional[str]:
9+
url = f"https://auth.privy.io/api/v1/users/{user_id}"
10+
headers = {"privy-app-id": app_id}
11+
auth = (app_id, app_secret)
12+
async with httpx.AsyncClient() as client:
13+
resp = await client.get(url, headers=headers, auth=auth, timeout=10)
14+
resp.raise_for_status()
15+
data = resp.json()
16+
for acct in data.get("linked_accounts", []):
17+
if acct.get("connector_type") == "embedded" and acct.get("delegated"):
18+
return acct["public_key"]
19+
return None
20+
21+
22+
class PrivyWalletAddressCheckerTool(AutoTool):
23+
def __init__(self, registry: Optional[ToolRegistry] = None):
24+
super().__init__(
25+
name="privy_wallet_address",
26+
description="Get the wallet address of a Privy delegated embedded wallet.",
27+
registry=registry,
28+
)
29+
self.api_key = None
30+
self.app_id = None
31+
self.app_secret = None
32+
33+
def get_schema(self) -> Dict[str, Any]:
34+
return {
35+
"type": "object",
36+
"properties": {
37+
"user_id": {
38+
"type": "string",
39+
"description": "Privy user id (did) to check delegated embedded wallet balance.",
40+
}
41+
},
42+
"required": ["user_id"],
43+
"additionalProperties": False,
44+
}
45+
46+
def configure(self, config: Dict[str, Any]) -> None:
47+
tool_cfg = config.get("tools", {}).get("privy_balance", {})
48+
self.app_id = tool_cfg.get("app_id")
49+
self.app_secret = tool_cfg.get("app_secret")
50+
51+
async def execute(self, user_id: str) -> Dict[str, Any]:
52+
if not all([self.app_id, self.app_secret]):
53+
return {"status": "error", "message": "Privy config missing."}
54+
wallet_address = await get_privy_embedded_wallet_address(
55+
user_id, self.app_id, self.app_secret
56+
)
57+
if not wallet_address:
58+
return {
59+
"status": "error",
60+
"message": "No delegated embedded wallet found for user.",
61+
}
62+
return {
63+
"status": "success",
64+
"result": wallet_address,
65+
}
66+
67+
68+
class PrivyWalletAddressCheckerPlugin:
69+
def __init__(self):
70+
self.name = "privy_wallet_address"
71+
self.config = None
72+
self.tool_registry = None
73+
self._tool = None
74+
75+
@property
76+
def description(self):
77+
return "Plugin for checking the wallet address of a Privy delegated embedded wallet."
78+
79+
def initialize(self, tool_registry: ToolRegistry) -> None:
80+
self.tool_registry = tool_registry
81+
self._tool = PrivyWalletAddressCheckerTool(registry=tool_registry)
82+
83+
def configure(self, config: Dict[str, Any]) -> None:
84+
self.config = config
85+
if self._tool:
86+
self._tool.configure(self.config)
87+
88+
def get_tools(self) -> List[AutoTool]:
89+
return [self._tool] if self._tool else []
90+
91+
92+
def get_plugin():
93+
return PrivyWalletAddressCheckerPlugin()

0 commit comments

Comments
 (0)