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
Binary file modified .coverage
Binary file not shown.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ config = {
"app_secret": "your-privy-app-secret", # Required - your Privy application secret
"signing_key": "wallet-auth:your-signing-key", # Required - your Privy wallet authorization signing key
"jupiter_api_key": "my-jupiter-api-key", # Required - get free key at portal.jup.ag
"rpc_url": "https://mainnet.helius-rpc.com/?api-key=YOUR_KEY", # Recommended - Helius RPC for reliable tx sending
"referral_account": "my-referral-account", # Optional - for collecting fees
"referral_fee": 50, # Optional - fee in basis points (50-255 bps)
"payer_private_key": "payer-private-key", # Optional - for gasless transactions
Expand All @@ -335,6 +336,9 @@ config = {
}
```

**RPC URL (Recommended):**
If configured, transactions are sent directly via RPC instead of Jupiter's execute endpoint, which can timeout. Helius RPC is recommended for reliable transaction landing.

**Actions:** Same as Jupiter Trigger (create, cancel, cancel_all, list)

### Privy Recurring
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "sakit"
version = "14.1.7"
version = "14.1.8"
description = "Solana Agent Kit"
authors = ["Bevan Hunt <bevan@bevanhunt.com>"]
license = "MIT"
Expand Down
32 changes: 25 additions & 7 deletions sakit/privy_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from solders.message import to_bytes_versioned # type: ignore

from sakit.utils.trigger import JupiterTrigger
from sakit.utils.wallet import send_raw_transaction_with_priority

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -192,6 +193,7 @@ def __init__(self, registry: Optional[ToolRegistry] = None):
self._referral_account: Optional[str] = None
self._referral_fee: Optional[int] = None
self._payer_private_key: Optional[str] = None
self._rpc_url: Optional[str] = None

def get_schema(self) -> Dict[str, Any]:
return {
Expand Down Expand Up @@ -265,6 +267,7 @@ def configure(self, config: Dict[str, Any]) -> None:
self._referral_account = tool_cfg.get("referral_account")
self._referral_fee = tool_cfg.get("referral_fee")
self._payer_private_key = tool_cfg.get("payer_private_key")
self._rpc_url = tool_cfg.get("rpc_url")

async def execute(
self,
Expand Down Expand Up @@ -372,13 +375,28 @@ async def _sign_and_execute( # pragma: no cover
"message": "Failed to sign transaction via Privy.",
}

# Execute
exec_result = await trigger.execute(signed_tx, request_id)

if not exec_result.success:
return {"status": "error", "message": exec_result.error}

return {"status": "success", "signature": exec_result.signature}
# Send via RPC or fallback to Jupiter execute
if self._rpc_url:
# Use configured RPC (Helius recommended) instead of Jupiter's execute endpoint
tx_bytes = base64.b64decode(signed_tx)
send_result = await send_raw_transaction_with_priority(
rpc_url=self._rpc_url,
tx_bytes=tx_bytes,
)
if not send_result.get("success"):
return {
"status": "error",
"message": send_result.get(
"error", "Failed to send transaction"
),
}
return {"status": "success", "signature": send_result.get("signature")}
else:
# Fallback to Jupiter execute if no RPC configured
exec_result = await trigger.execute(signed_tx, request_id)
if not exec_result.success:
return {"status": "error", "message": exec_result.error}
return {"status": "success", "signature": exec_result.signature}

except Exception as e:
logger.exception(f"Failed to sign and execute: {str(e)}")
Expand Down
18 changes: 18 additions & 0 deletions tests/test_privy_trigger_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,24 @@ def test_configure_stores_optional_config(self, privy_trigger_tool_with_payer):
assert privy_trigger_tool_with_payer._referral_account == "RefAcct123"
assert privy_trigger_tool_with_payer._referral_fee == 50

def test_configure_stores_rpc_url(self):
"""Should store RPC URL from config for direct transaction sending."""
tool = PrivyTriggerTool()
tool.configure(
{
"tools": {
"privy_trigger": {
"app_id": "test-app-id",
"app_secret": "test-app-secret",
"signing_key": f"wallet-auth:{TEST_EC_KEY_SEC1}",
"jupiter_api_key": "test-api-key",
"rpc_url": "https://mainnet.helius-rpc.com/?api-key=test",
}
}
}
)
assert tool._rpc_url == "https://mainnet.helius-rpc.com/?api-key=test"

def test_configure_with_empty_config(self):
"""Should handle empty config gracefully."""
tool = PrivyTriggerTool()
Expand Down