diff --git a/.coverage b/.coverage index 69493b2..e1a528b 100644 Binary files a/.coverage and b/.coverage differ diff --git a/README.md b/README.md index df8cb86..5eff862 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Solana Agent Kit provides a growing library of plugins that enhance your Solana * Solana Transfer - Transfer Solana tokens between the agent's wallet and the destination wallet * Solana Ultra - Swap Solana tokens using Jupiter Ultra API with automatic slippage, priority fees, and transaction landing -* Solana DFlow Swap - Fast token swaps using DFlow API with platform fees +* Solana DFlow Swap - Fast token swaps using DFlow API * Jupiter Trigger - Create, cancel, and manage limit orders using Jupiter Trigger API * Jupiter Recurring - Create, cancel, and manage DCA orders using Jupiter Recurring API * Jupiter Holdings - Get token holdings with USD values for any wallet @@ -26,7 +26,7 @@ Solana Agent Kit provides a growing library of plugins that enhance your Solana * Privy Ultra - Swap tokens using Jupiter Ultra with Privy delegated wallets * Privy Trigger - Create and manage limit orders with Privy delegated wallets * Privy Recurring - Create and manage DCA orders with Privy delegated wallets -* Privy DFlow Swap - Fast token swaps using DFlow API with Privy delegated wallets and platform fees +* Privy DFlow Swap - Fast token swaps using DFlow API with Privy delegated wallets * Privy Wallet Address - Get the wallet address of a Privy delegated wallet * Privy Create User - Create a new Privy user with a linked Telegram account (for bot-first flows) * Privy Create Wallet - Create a Solana wallet for a Privy user with optional bot delegation @@ -102,15 +102,15 @@ By default, Jupiter Ultra provides gasless swaps when the user has < 0.01 SOL an ### Solana DFlow Swap -This plugin enables Solana Agent to swap tokens using DFlow's Swap API with a Solana keypair. DFlow offers faster swaps compared to Jupiter Ultra with competitive rates and supports platform fees for monetization. +This plugin enables Solana Agent to swap tokens using DFlow's Swap API with a Solana keypair. DFlow offers faster swaps compared to Jupiter Ultra with competitive rates. + +**Note:** Platform fees are not supported with DFlow. Use Solana Ultra (Jupiter) if you need to collect fees on swaps. ```python config = { "tools": { "solana_dflow_swap": { "private_key": "my-private-key", # Required - base58 string - "platform_fee_bps": 50, # Optional - platform fee in basis points (e.g., 50 = 0.5%) - "fee_account": "your-fee-token-account", # Optional - token account to receive platform fees "payer_private_key": "payer-private-key", # Optional - for gasless/sponsored transactions "rpc_url": "https://api.mainnet-beta.solana.com", # Optional - RPC URL (defaults to mainnet) }, @@ -120,12 +120,8 @@ config = { **Features:** - **Fast Swaps**: DFlow typically executes faster than Jupiter Ultra -- **Platform Fees**: Collect fees on swaps (in basis points) paid to your fee account - **Gasless Transactions**: Optionally sponsor gas fees for users via `payer_private_key` -**Platform Fee Setup:** -To collect platform fees, you need to create a token account for the output token and provide it as `fee_account`. The `platform_fee_bps` specifies the fee amount (e.g., 50 = 0.5%). - ### Jupiter Trigger This plugin enables Solana Agent to create, cancel, and manage limit orders using Jupiter's Trigger API. It's a smart tool that handles the full lifecycle of limit orders with a single action parameter. @@ -363,7 +359,9 @@ config = { ### Privy DFlow Swap -This plugin enables Solana Agent to swap tokens using DFlow's Swap API with Privy delegated wallets. DFlow offers faster swaps compared to Jupiter Ultra with competitive rates and supports platform fees for monetization. +This plugin enables Solana Agent to swap tokens using DFlow's Swap API with Privy delegated wallets. DFlow offers faster swaps compared to Jupiter Ultra with competitive rates. + +**Note:** Platform fees are not supported with DFlow. Use Privy Ultra (Jupiter) if you need to collect fees on swaps. Transactions are signed via Privy and sent via your configured RPC (Helius recommended) for reliable blockhash handling and priority fees. @@ -375,8 +373,6 @@ 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 "rpc_url": "https://mainnet.helius-rpc.com/?api-key=YOUR_KEY", # Required - Helius recommended for priority fees - "platform_fee_bps": 50, # Optional - platform fee in basis points (e.g., 50 = 0.5%) - "fee_account": "your-fee-token-account", # Optional - token account to receive platform fees "payer_private_key": "payer-private-key", # Optional - for gasless/sponsored transactions }, }, @@ -385,7 +381,6 @@ config = { **Features:** - **Fast Swaps**: DFlow typically executes faster than Jupiter Ultra -- **Platform Fees**: Collect fees on swaps (in basis points) paid to your fee account - **Privy Delegated Wallets**: Seamless user experience with embedded wallets - **Helius Priority Fees**: Uses Helius priority fee estimation for reliable transaction landing - **Gasless Transactions**: Optionally sponsor gas fees for users via `payer_private_key` @@ -393,9 +388,6 @@ config = { **RPC URL (Required):** Helius RPC is strongly recommended (`https://mainnet.helius-rpc.com/?api-key=YOUR_KEY`). Helius provides priority fee estimation and better blockhash handling, which significantly improves transaction success rates. Get a free API key at [helius.dev](https://helius.dev). -**Platform Fee Setup:** -To collect platform fees, you need to create a token account for the output token and provide it as `fee_account`. The `platform_fee_bps` specifies the fee amount (e.g., 50 = 0.5%). - ### Privy Wallet Address This plugin enables Solana Agent to get the wallet address of a Privy delegated wallet. diff --git a/pyproject.toml b/pyproject.toml index 34a68f2..584e9f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "sakit" -version = "14.1.3" +version = "14.1.4" description = "Solana Agent Kit" authors = ["Bevan Hunt "] license = "MIT" diff --git a/sakit/privy_dflow_swap.py b/sakit/privy_dflow_swap.py index 81be3b5..7dcc144 100644 --- a/sakit/privy_dflow_swap.py +++ b/sakit/privy_dflow_swap.py @@ -1,14 +1,15 @@ -""" -DFlow Swap tool for Privy embedded wallets. +"""DFlow Swap tool for Privy embedded wallets. Enables fast token swaps using DFlow's Swap API via Privy delegated wallets. Uses the official Privy Python SDK for wallet operations. -DFlow offers faster swaps compared to Jupiter Ultra with similar liquidity -and supports platform fees for monetization. +DFlow offers faster swaps compared to Jupiter Ultra with similar liquidity. Transactions are signed via Privy's signTransaction and sent via Helius RPC for priority fees and reliable blockhash handling. + +Note: Platform fees are not supported. Use Jupiter Ultra (privy_ultra) if you +need to collect fees on swaps. """ import base64 @@ -207,9 +208,6 @@ def __init__(self, registry: Optional[ToolRegistry] = None): self._app_id: Optional[str] = None self._app_secret: Optional[str] = None self._signing_key: Optional[str] = None - self._platform_fee_bps: Optional[int] = None - self._fee_account: Optional[str] = None - self._referral_account: Optional[str] = None self._payer_private_key: Optional[str] = None self._rpc_url: Optional[str] = None @@ -249,9 +247,6 @@ def configure(self, config: Dict[str, Any]) -> None: self._app_id = tool_cfg.get("app_id") self._app_secret = tool_cfg.get("app_secret") self._signing_key = tool_cfg.get("signing_key") - self._platform_fee_bps = tool_cfg.get("platform_fee_bps") - self._fee_account = tool_cfg.get("fee_account") - self._referral_account = tool_cfg.get("referral_account") self._payer_private_key = tool_cfg.get("payer_private_key") # RPC URL for sending transactions (Helius recommended for priority fees) self._rpc_url = tool_cfg.get("rpc_url") @@ -306,10 +301,6 @@ async def execute( # pragma: no cover amount=int(amount), user_public_key=public_key, slippage_bps=slippage_bps if slippage_bps > 0 else None, - platform_fee_bps=self._platform_fee_bps, - platform_fee_mode="outputMint", - fee_account=self._fee_account, - referral_account=self._referral_account, sponsor=sponsor, ) @@ -386,7 +377,6 @@ async def execute( # pragma: no cover "input_mint": order_result.input_mint, "output_mint": order_result.output_mint, "price_impact": order_result.price_impact_pct, - "platform_fee": order_result.platform_fee, "execution_mode": order_result.execution_mode, "message": f"Swap successful! Signature: {signature}", } diff --git a/sakit/solana_dflow_swap.py b/sakit/solana_dflow_swap.py index 0802f5d..7d71d34 100644 --- a/sakit/solana_dflow_swap.py +++ b/sakit/solana_dflow_swap.py @@ -1,9 +1,10 @@ -""" -DFlow Swap tool for Solana wallets. +"""DFlow Swap tool for Solana wallets. Enables fast token swaps using DFlow's Swap API with a Solana keypair. -DFlow offers faster swaps compared to Jupiter Ultra with similar liquidity -and supports platform fees for monetization. +DFlow offers faster swaps compared to Jupiter Ultra with similar liquidity. + +Note: Platform fees are not supported. Use Jupiter Ultra (solana_ultra) if you +need to collect fees on swaps. """ import base64 @@ -77,9 +78,6 @@ def __init__(self, registry: Optional[ToolRegistry] = None): registry=registry, ) self._private_key: Optional[str] = None - self._platform_fee_bps: Optional[int] = None - self._fee_account: Optional[str] = None - self._referral_account: Optional[str] = None self._payer_private_key: Optional[str] = None self._rpc_url: Optional[str] = None @@ -113,9 +111,6 @@ def configure(self, config: Dict[str, Any]) -> None: super().configure(config) tool_cfg = config.get("tools", {}).get("solana_dflow_swap", {}) self._private_key = tool_cfg.get("private_key") - self._platform_fee_bps = tool_cfg.get("platform_fee_bps") - self._fee_account = tool_cfg.get("fee_account") - self._referral_account = tool_cfg.get("referral_account") self._payer_private_key = tool_cfg.get("payer_private_key") self._rpc_url = tool_cfg.get("rpc_url") or DEFAULT_RPC_URL @@ -150,10 +145,6 @@ async def execute( amount=amount, user_public_key=user_pubkey, slippage_bps=slippage_bps if slippage_bps > 0 else None, - platform_fee_bps=self._platform_fee_bps, - platform_fee_mode="outputMint", - fee_account=self._fee_account, - referral_account=self._referral_account, sponsor=sponsor, ) @@ -191,7 +182,6 @@ async def execute( "input_mint": order_result.input_mint, "output_mint": order_result.output_mint, "price_impact": order_result.price_impact_pct, - "platform_fee": order_result.platform_fee, "execution_mode": order_result.execution_mode, "message": f"Swap successful! Signature: {signature}", } diff --git a/tests/test_privy_dflow_swap_tool.py b/tests/test_privy_dflow_swap_tool.py index e26a19b..7c8df95 100644 --- a/tests/test_privy_dflow_swap_tool.py +++ b/tests/test_privy_dflow_swap_tool.py @@ -65,8 +65,8 @@ def test_configure_sets_credentials(self): "app_id": "test_app_id", "app_secret": "test_app_secret", "signing_key": "test_signing_key", - "platform_fee_bps": 50, - "fee_account": "FeeAccount123", + "payer_private_key": "payer_key", + "rpc_url": "https://custom-rpc.com", } } } @@ -76,8 +76,8 @@ def test_configure_sets_credentials(self): assert tool._app_id == "test_app_id" assert tool._app_secret == "test_app_secret" assert tool._signing_key == "test_signing_key" - assert tool._platform_fee_bps == 50 - assert tool._fee_account == "FeeAccount123" + assert tool._payer_private_key == "payer_key" + assert tool._rpc_url == "https://custom-rpc.com" class TestPrivyDFlowSwapToolExecute: @@ -96,8 +96,7 @@ def configured_tool(self): "signing_key": "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg" + "A" * 43 + "=", - "platform_fee_bps": 50, - "fee_account": "FeeAccount123", + "rpc_url": "https://api.mainnet-beta.solana.com", } } } diff --git a/tests/test_solana_dflow_swap_tool.py b/tests/test_solana_dflow_swap_tool.py index 9795504..f6715dd 100644 --- a/tests/test_solana_dflow_swap_tool.py +++ b/tests/test_solana_dflow_swap_tool.py @@ -69,9 +69,6 @@ def test_configure_sets_credentials(self): "tools": { "solana_dflow_swap": { "private_key": "test_private_key", - "platform_fee_bps": 50, - "fee_account": "FeeAccount123", - "referral_account": "RefAccount123", "payer_private_key": "payer_key", "rpc_url": "https://custom-rpc.com", } @@ -81,9 +78,6 @@ def test_configure_sets_credentials(self): tool.configure(config) assert tool._private_key == "test_private_key" - assert tool._platform_fee_bps == 50 - assert tool._fee_account == "FeeAccount123" - assert tool._referral_account == "RefAccount123" assert tool._payer_private_key == "payer_key" assert tool._rpc_url == "https://custom-rpc.com" @@ -214,7 +208,7 @@ def test_plugin_configure(self): "tools": { "solana_dflow_swap": { "private_key": "test_private_key", - "platform_fee_bps": 100, + "payer_private_key": "payer_key", } } } @@ -222,7 +216,7 @@ def test_plugin_configure(self): tool = plugin.get_tools()[0] assert tool._private_key == "test_private_key" - assert tool._platform_fee_bps == 100 + assert tool._payer_private_key == "payer_key" class TestSignDFlowTransaction: @@ -469,55 +463,6 @@ async def test_execute_with_slippage_bps(self): call_kwargs = mock_dflow_instance.get_order.call_args.kwargs assert call_kwargs.get("slippage_bps") == 100 - @pytest.mark.asyncio - async def test_execute_with_platform_fees(self): - """Should pass platform fee configuration.""" - tool = SolanaDFlowSwapTool() - tool._private_key = "5MaiiCavjCmn9Hs1o3eznqDEhRwxo7pXiAYez7keQUviUkauRiTMD8DrESdrNjN8zd9mTmVhRvBJeg5vhyvgrAhG" - tool._rpc_url = "https://api.mainnet-beta.solana.com" - tool._platform_fee_bps = 50 - tool._fee_account = "FeeAccount123" - tool._referral_account = "RefAccount123" - - with ( - patch("sakit.solana_dflow_swap.DFlowSwap") as MockDFlow, - patch("sakit.solana_dflow_swap._sign_dflow_transaction") as mock_sign, - patch.object( - tool, "_send_transaction", new_callable=AsyncMock - ) as mock_send, - ): - mock_dflow_instance = MagicMock() - mock_order_result = MagicMock( - success=True, - transaction="dHJhbnNhY3Rpb24=", - in_amount="1000000000", - out_amount="50000000", - min_out_amount="49500000", - input_mint="So11111111111111111111111111111111111111112", - output_mint="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - price_impact_pct="0.1", - platform_fee="100", - execution_mode="direct", - error=None, - ) - mock_dflow_instance.get_order = AsyncMock(return_value=mock_order_result) - MockDFlow.return_value = mock_dflow_instance - - mock_sign.return_value = "c2lnbmVkX3R4" - mock_send.return_value = "5abc123def456" - - await tool.execute( - input_mint="So11111111111111111111111111111111111111112", - output_mint="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - amount=1000000000, - ) - - # Verify fee config was passed - call_kwargs = mock_dflow_instance.get_order.call_args.kwargs - assert call_kwargs.get("platform_fee_bps") == 50 - assert call_kwargs.get("fee_account") == "FeeAccount123" - assert call_kwargs.get("referral_account") == "RefAccount123" - @pytest.mark.asyncio async def test_execute_exception_handling(self): """Should handle exceptions gracefully."""