proofgate-agentkit 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,30 @@
1
+ """ProofGate Action Provider for Coinbase AgentKit.
2
+
3
+ Blockchain guardrails for AI agents - validate transactions before execution.
4
+ """
5
+
6
+ from .action_provider import (
7
+ ProofGateActionProvider,
8
+ proofgate_action_provider,
9
+ )
10
+ from .config import ProofGateConfig
11
+ from .exceptions import ProofGateValidationError
12
+ from .wrapper import (
13
+ ProofGateWrapper,
14
+ wrap_with_proofgate,
15
+ )
16
+
17
+ __version__ = "0.1.0"
18
+
19
+ __all__ = [
20
+ # Action Provider
21
+ "ProofGateActionProvider",
22
+ "proofgate_action_provider",
23
+ # Config
24
+ "ProofGateConfig",
25
+ # Wrapper
26
+ "ProofGateWrapper",
27
+ "wrap_with_proofgate",
28
+ # Exceptions
29
+ "ProofGateValidationError",
30
+ ]
@@ -0,0 +1,311 @@
1
+ """ProofGate Action Provider for Coinbase AgentKit.
2
+
3
+ This module provides the ProofGateActionProvider class that validates
4
+ transactions through ProofGate before they are executed.
5
+ """
6
+
7
+ import logging
8
+ from typing import Any, Optional
9
+
10
+ from coinbase_agentkit.action_providers import ActionProvider, create_action
11
+ from coinbase_agentkit.network import Network
12
+ from coinbase_agentkit.wallet_providers import EvmWalletProvider
13
+ from proofgate import ProofGate, ProofGateError
14
+ from pydantic import BaseModel, Field
15
+
16
+ from .config import ProofGateConfig
17
+ from .exceptions import ProofGateValidationError
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class ValidateTransactionSchema(BaseModel):
23
+ """Schema for validating a transaction through ProofGate."""
24
+
25
+ to: str = Field(..., description="The destination address of the transaction")
26
+ data: str = Field(default="0x", description="The transaction calldata (hex)")
27
+ value: str = Field(default="0", description="The value to send in wei")
28
+ guardrail_id: Optional[str] = Field(None, description="Override guardrail ID")
29
+
30
+
31
+ class CheckAgentSchema(BaseModel):
32
+ """Schema for checking an agent's trust score."""
33
+
34
+ wallet_address: str = Field(..., description="The wallet address to check")
35
+
36
+
37
+ class ProofGateActionProvider(ActionProvider[EvmWalletProvider]):
38
+ """Action provider that validates transactions through ProofGate.
39
+
40
+ ProofGate acts as a security layer that validates blockchain transactions
41
+ before execution, protecting AI agents from:
42
+ - Wallet drains from prompt injection attacks
43
+ - Infinite token approvals to malicious contracts
44
+ - Excessive spending beyond limits
45
+ - High slippage swaps
46
+
47
+ Example:
48
+ ```python
49
+ from proofgate_agentkit import ProofGateActionProvider, ProofGateConfig
50
+
51
+ config = ProofGateConfig(
52
+ api_key="pg_your_api_key",
53
+ guardrail_id="your_guardrail_id",
54
+ )
55
+ provider = ProofGateActionProvider(config)
56
+ ```
57
+ """
58
+
59
+ def __init__(
60
+ self,
61
+ config: ProofGateConfig,
62
+ action_providers: Optional[list[ActionProvider]] = None,
63
+ ) -> None:
64
+ """Initialize the ProofGate action provider.
65
+
66
+ Args:
67
+ config: ProofGate configuration with API credentials.
68
+ action_providers: Optional list of sub-providers.
69
+ """
70
+ super().__init__("proofgate", action_providers or [])
71
+ self.config = config
72
+
73
+ # Initialize ProofGate client
74
+ self._client = ProofGate(
75
+ api_key=config.api_key,
76
+ chain_id=config.chain_id,
77
+ guardrail_id=config.guardrail_id,
78
+ base_url=config.base_url,
79
+ timeout=config.timeout,
80
+ )
81
+
82
+ @property
83
+ def client(self) -> ProofGate:
84
+ """Get the ProofGate client."""
85
+ return self._client
86
+
87
+ def validate_transaction(
88
+ self,
89
+ from_address: str,
90
+ to: str,
91
+ data: str = "0x",
92
+ value: str = "0",
93
+ chain_id: Optional[int] = None,
94
+ guardrail_id: Optional[str] = None,
95
+ ) -> str:
96
+ """Validate a transaction through ProofGate.
97
+
98
+ Args:
99
+ from_address: The sender address.
100
+ to: The destination address.
101
+ data: Transaction calldata (hex).
102
+ value: Value in wei.
103
+ chain_id: Override chain ID.
104
+ guardrail_id: Override guardrail ID.
105
+
106
+ Returns:
107
+ The validation/proof ID if transaction is safe.
108
+
109
+ Raises:
110
+ ProofGateValidationError: If transaction is blocked.
111
+ """
112
+ try:
113
+ result = self._client.validate(
114
+ from_address=from_address,
115
+ to=to,
116
+ data=data,
117
+ value=value,
118
+ chain_id=chain_id,
119
+ guardrail_id=guardrail_id,
120
+ )
121
+
122
+ if self.config.log_validations:
123
+ logger.info(
124
+ f"ProofGate validation: {result.result} | "
125
+ f"ID: {result.validation_id} | "
126
+ f"To: {to}"
127
+ )
128
+
129
+ if not result.safe:
130
+ raise ProofGateValidationError(
131
+ message=f"Transaction blocked by ProofGate: {result.reason}",
132
+ validation_id=result.validation_id,
133
+ reason=result.reason,
134
+ checks=[check.model_dump() for check in result.checks] if result.checks else [],
135
+ evidence_uri=result.evidence_uri,
136
+ )
137
+
138
+ return result.validation_id
139
+
140
+ except ProofGateError as e:
141
+ if self.config.fail_open:
142
+ logger.warning(f"ProofGate API error (fail_open=True): {e}")
143
+ return "fail_open_bypass"
144
+ raise ProofGateValidationError(
145
+ message=f"ProofGate API error: {e}",
146
+ reason=str(e),
147
+ ) from e
148
+
149
+ @create_action(
150
+ name="validate_transaction",
151
+ description="""
152
+ Validate a blockchain transaction through ProofGate before execution.
153
+
154
+ This tool checks if a transaction is safe to execute by validating it
155
+ against ProofGate's security guardrails. Use this before any transaction
156
+ that sends funds or interacts with contracts.
157
+
158
+ Inputs:
159
+ - to: The destination address of the transaction
160
+ - data: The transaction calldata in hex format (default: "0x")
161
+ - value: The value to send in wei (default: "0")
162
+ - guardrail_id: Optional override for the guardrail ID
163
+
164
+ Returns the validation result with proof ID if safe, or blocks with reason.
165
+ """,
166
+ schema=ValidateTransactionSchema,
167
+ )
168
+ def validate_transaction_action(
169
+ self, wallet_provider: EvmWalletProvider, args: dict[str, Any]
170
+ ) -> str:
171
+ """Validate a transaction through ProofGate.
172
+
173
+ Args:
174
+ wallet_provider: The wallet provider instance.
175
+ args: Input arguments for the action.
176
+
177
+ Returns:
178
+ A message with validation result.
179
+ """
180
+ try:
181
+ validated_args = ValidateTransactionSchema(**args)
182
+ from_address = wallet_provider.get_address()
183
+ network = wallet_provider.get_network()
184
+ chain_id = int(network.chain_id) if network.chain_id else self.config.chain_id
185
+
186
+ proof_id = self.validate_transaction(
187
+ from_address=from_address,
188
+ to=validated_args.to,
189
+ data=validated_args.data,
190
+ value=validated_args.value,
191
+ chain_id=chain_id,
192
+ guardrail_id=validated_args.guardrail_id,
193
+ )
194
+
195
+ return (
196
+ f"✅ Transaction validated by ProofGate\n"
197
+ f"Proof ID: {proof_id}\n"
198
+ f"From: {from_address}\n"
199
+ f"To: {validated_args.to}\n"
200
+ f"Value: {validated_args.value} wei\n"
201
+ f"The transaction is safe to execute."
202
+ )
203
+
204
+ except ProofGateValidationError as e:
205
+ return (
206
+ f"🚫 Transaction BLOCKED by ProofGate\n"
207
+ f"Reason: {e.reason}\n"
208
+ f"Validation ID: {e.validation_id}\n"
209
+ f"Evidence: {e.evidence_uri or 'N/A'}\n"
210
+ f"DO NOT execute this transaction."
211
+ )
212
+
213
+ except Exception as e:
214
+ return f"Error validating transaction: {e}"
215
+
216
+ @create_action(
217
+ name="check_agent_trust",
218
+ description="""
219
+ Check an agent wallet's trust score on ProofGate.
220
+
221
+ This tool retrieves the trust score and verification status of an
222
+ agent wallet address. Higher trust scores may have higher spending limits.
223
+
224
+ Inputs:
225
+ - wallet_address: The wallet address to check
226
+
227
+ Returns the agent's trust score, tier, and verification status.
228
+ """,
229
+ schema=CheckAgentSchema,
230
+ )
231
+ def check_agent_trust(
232
+ self, wallet_provider: EvmWalletProvider, args: dict[str, Any]
233
+ ) -> str:
234
+ """Check an agent's trust score.
235
+
236
+ Args:
237
+ wallet_provider: The wallet provider instance.
238
+ args: Input arguments for the action.
239
+
240
+ Returns:
241
+ A message with the agent's trust information.
242
+ """
243
+ try:
244
+ validated_args = CheckAgentSchema(**args)
245
+ agent = self._client.check_agent(validated_args.wallet_address)
246
+
247
+ return (
248
+ f"Agent Trust Score for {validated_args.wallet_address}:\n"
249
+ f"- Trust Score: {agent.trust_score}\n"
250
+ f"- Tier: {agent.tier}\n"
251
+ f"- Verification Status: {agent.verification_status}"
252
+ )
253
+
254
+ except ProofGateError as e:
255
+ return f"Error checking agent trust: {e}"
256
+
257
+ except Exception as e:
258
+ return f"Error: {e}"
259
+
260
+ def supports_network(self, network: Network) -> bool:
261
+ """Check if the network is supported.
262
+
263
+ ProofGate supports EVM networks.
264
+
265
+ Args:
266
+ network: The network to check.
267
+
268
+ Returns:
269
+ True if the network is EVM-based.
270
+ """
271
+ return network.protocol_family == "evm"
272
+
273
+
274
+ def proofgate_action_provider(
275
+ api_key: str,
276
+ guardrail_id: Optional[str] = None,
277
+ chain_id: Optional[int] = None,
278
+ fail_open: bool = False,
279
+ **kwargs: Any,
280
+ ) -> ProofGateActionProvider:
281
+ """Create a new ProofGateActionProvider instance.
282
+
283
+ This is a convenience factory function for creating the provider.
284
+
285
+ Args:
286
+ api_key: ProofGate API key.
287
+ guardrail_id: Default guardrail ID.
288
+ chain_id: Default chain ID.
289
+ fail_open: Whether to allow transactions on API failure.
290
+ **kwargs: Additional config options.
291
+
292
+ Returns:
293
+ A configured ProofGateActionProvider.
294
+
295
+ Example:
296
+ ```python
297
+ provider = proofgate_action_provider(
298
+ api_key="pg_your_api_key",
299
+ guardrail_id="your_guardrail_id",
300
+ chain_id=8453, # Base
301
+ )
302
+ ```
303
+ """
304
+ config = ProofGateConfig(
305
+ api_key=api_key,
306
+ guardrail_id=guardrail_id,
307
+ chain_id=chain_id,
308
+ fail_open=fail_open,
309
+ **kwargs,
310
+ )
311
+ return ProofGateActionProvider(config)
@@ -0,0 +1,33 @@
1
+ """Configuration for ProofGate Action Provider."""
2
+
3
+ from typing import Optional
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ class ProofGateConfig(BaseModel):
9
+ """Configuration for ProofGate validation.
10
+
11
+ Attributes:
12
+ api_key: ProofGate API key (required). Get from proofgate.xyz/dashboard.
13
+ guardrail_id: Default guardrail ID to use for validation.
14
+ chain_id: Default chain ID (e.g., 1 for Ethereum, 8453 for Base).
15
+ base_url: Custom API base URL. Defaults to ProofGate's production API.
16
+ timeout: Request timeout in seconds.
17
+ fail_open: If True, allow transactions when ProofGate API is unreachable.
18
+ Default False (fail closed for security).
19
+ log_validations: If True, log validation results. Default True.
20
+ """
21
+
22
+ api_key: str = Field(..., description="ProofGate API key")
23
+ guardrail_id: Optional[str] = Field(None, description="Default guardrail ID")
24
+ chain_id: Optional[int] = Field(None, description="Default chain ID")
25
+ base_url: Optional[str] = Field(None, description="Custom API base URL")
26
+ timeout: float = Field(30.0, description="Request timeout in seconds")
27
+ fail_open: bool = Field(False, description="Allow tx on API failure")
28
+ log_validations: bool = Field(True, description="Log validation results")
29
+
30
+ class Config:
31
+ """Pydantic config."""
32
+
33
+ extra = "forbid"
@@ -0,0 +1,48 @@
1
+ """Exceptions for ProofGate Action Provider."""
2
+
3
+ from typing import Any, Optional
4
+
5
+
6
+ class ProofGateValidationError(Exception):
7
+ """Raised when ProofGate blocks a transaction.
8
+
9
+ Attributes:
10
+ validation_id: The ProofGate validation ID.
11
+ reason: The reason the transaction was blocked.
12
+ checks: List of validation checks that were performed.
13
+ evidence_uri: URI to the evidence for this validation.
14
+ """
15
+
16
+ def __init__(
17
+ self,
18
+ message: str,
19
+ validation_id: Optional[str] = None,
20
+ reason: Optional[str] = None,
21
+ checks: Optional[list[dict[str, Any]]] = None,
22
+ evidence_uri: Optional[str] = None,
23
+ ) -> None:
24
+ """Initialize the exception.
25
+
26
+ Args:
27
+ message: Human-readable error message.
28
+ validation_id: The ProofGate validation ID.
29
+ reason: The reason the transaction was blocked.
30
+ checks: List of validation checks performed.
31
+ evidence_uri: URI to validation evidence.
32
+ """
33
+ super().__init__(message)
34
+ self.validation_id = validation_id
35
+ self.reason = reason
36
+ self.checks = checks or []
37
+ self.evidence_uri = evidence_uri
38
+
39
+ def __str__(self) -> str:
40
+ """Return string representation."""
41
+ parts = [str(self.args[0])]
42
+ if self.reason:
43
+ parts.append(f"Reason: {self.reason}")
44
+ if self.validation_id:
45
+ parts.append(f"Validation ID: {self.validation_id}")
46
+ if self.evidence_uri:
47
+ parts.append(f"Evidence: {self.evidence_uri}")
48
+ return " | ".join(parts)
File without changes
@@ -0,0 +1,290 @@
1
+ """Transaction wrapper that adds ProofGate validation to any action provider.
2
+
3
+ This module provides utilities to wrap existing action providers with
4
+ ProofGate validation, intercepting transactions before execution.
5
+ """
6
+
7
+ import functools
8
+ import logging
9
+ from typing import Any, Callable, Optional, TypeVar
10
+
11
+ from coinbase_agentkit.action_providers import Action, ActionProvider
12
+ from coinbase_agentkit.wallet_providers import EvmWalletProvider
13
+
14
+ from .action_provider import ProofGateActionProvider
15
+ from .config import ProofGateConfig
16
+ from .exceptions import ProofGateValidationError
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ T = TypeVar("T")
21
+
22
+
23
+ class ProofGateWrapper:
24
+ """Wraps wallet provider methods to add ProofGate validation.
25
+
26
+ This class intercepts transaction methods (send_transaction, native_transfer)
27
+ and validates them through ProofGate before execution.
28
+
29
+ Example:
30
+ ```python
31
+ from proofgate_agentkit import ProofGateWrapper, ProofGateConfig
32
+
33
+ config = ProofGateConfig(api_key="pg_xxx", guardrail_id="xxx")
34
+ wrapper = ProofGateWrapper(config)
35
+
36
+ # Wrap the wallet provider
37
+ wrapped_wallet = wrapper.wrap(wallet_provider)
38
+
39
+ # Now all transactions will be validated
40
+ wrapped_wallet.send_transaction({...}) # Validated first!
41
+ ```
42
+ """
43
+
44
+ def __init__(self, config: ProofGateConfig) -> None:
45
+ """Initialize the wrapper.
46
+
47
+ Args:
48
+ config: ProofGate configuration.
49
+ """
50
+ self.config = config
51
+ self._provider = ProofGateActionProvider(config)
52
+
53
+ def wrap(self, wallet_provider: EvmWalletProvider) -> EvmWalletProvider:
54
+ """Wrap a wallet provider with ProofGate validation.
55
+
56
+ This patches the wallet provider's send_transaction method to
57
+ validate transactions before execution.
58
+
59
+ Args:
60
+ wallet_provider: The wallet provider to wrap.
61
+
62
+ Returns:
63
+ The same wallet provider with patched methods.
64
+ """
65
+ original_send = wallet_provider.send_transaction
66
+
67
+ @functools.wraps(original_send)
68
+ def validated_send(tx: dict[str, Any]) -> str:
69
+ """Send transaction after ProofGate validation."""
70
+ from_address = wallet_provider.get_address()
71
+ network = wallet_provider.get_network()
72
+ chain_id = int(network.chain_id) if network.chain_id else self.config.chain_id
73
+
74
+ to = tx.get("to", "")
75
+ data = tx.get("data", "0x")
76
+ value = str(tx.get("value", 0))
77
+
78
+ # Validate through ProofGate
79
+ proof_id = self._provider.validate_transaction(
80
+ from_address=from_address,
81
+ to=to,
82
+ data=data,
83
+ value=value,
84
+ chain_id=chain_id,
85
+ )
86
+
87
+ logger.info(f"ProofGate approved transaction | Proof ID: {proof_id}")
88
+
89
+ # Execute the original transaction
90
+ return original_send(tx)
91
+
92
+ # Patch the method
93
+ wallet_provider.send_transaction = validated_send # type: ignore
94
+
95
+ return wallet_provider
96
+
97
+
98
+ def wrap_with_proofgate(
99
+ action_provider: ActionProvider[EvmWalletProvider],
100
+ config: ProofGateConfig,
101
+ ) -> ActionProvider[EvmWalletProvider]:
102
+ """Wrap an action provider's transaction actions with ProofGate validation.
103
+
104
+ This creates a wrapper that intercepts actions that result in transactions
105
+ and validates them through ProofGate first.
106
+
107
+ Args:
108
+ action_provider: The action provider to wrap.
109
+ config: ProofGate configuration.
110
+
111
+ Returns:
112
+ A wrapped action provider.
113
+
114
+ Example:
115
+ ```python
116
+ from coinbase_agentkit.action_providers import erc20_action_provider
117
+ from proofgate_agentkit import wrap_with_proofgate, ProofGateConfig
118
+
119
+ config = ProofGateConfig(api_key="pg_xxx")
120
+ erc20 = erc20_action_provider()
121
+ safe_erc20 = wrap_with_proofgate(erc20, config)
122
+ ```
123
+ """
124
+ pg_provider = ProofGateActionProvider(config)
125
+
126
+ class WrappedActionProvider(ActionProvider[EvmWalletProvider]):
127
+ """Wrapper that validates transactions through ProofGate."""
128
+
129
+ def __init__(self) -> None:
130
+ super().__init__(
131
+ f"proofgate_wrapped_{action_provider.name}",
132
+ [action_provider],
133
+ )
134
+ self._inner = action_provider
135
+ self._pg = pg_provider
136
+
137
+ def get_actions(self, wallet_provider: EvmWalletProvider) -> list[Action]:
138
+ """Get wrapped actions that validate through ProofGate."""
139
+ original_actions = self._inner.get_actions(wallet_provider)
140
+ wrapped_actions = []
141
+
142
+ # Actions that modify state (need validation)
143
+ tx_action_names = {
144
+ "transfer",
145
+ "approve",
146
+ "native_transfer",
147
+ "swap",
148
+ "supply",
149
+ "withdraw",
150
+ "borrow",
151
+ "repay",
152
+ "wrap",
153
+ "unwrap",
154
+ "mint",
155
+ "burn",
156
+ }
157
+
158
+ for action in original_actions:
159
+ # Check if this is a transaction action
160
+ action_name_lower = action.name.lower()
161
+ needs_validation = any(
162
+ tx_name in action_name_lower for tx_name in tx_action_names
163
+ )
164
+
165
+ if needs_validation:
166
+ wrapped_actions.append(
167
+ self._wrap_action(action, wallet_provider)
168
+ )
169
+ else:
170
+ wrapped_actions.append(action)
171
+
172
+ return wrapped_actions
173
+
174
+ def _wrap_action(
175
+ self, action: Action, wallet_provider: EvmWalletProvider
176
+ ) -> Action:
177
+ """Wrap an action with ProofGate validation."""
178
+ original_invoke = action.invoke
179
+
180
+ def wrapped_invoke(args: dict[str, Any]) -> str:
181
+ """Invoke with ProofGate validation."""
182
+ # Extract transaction details from args
183
+ to = args.get("to") or args.get("contract_address") or args.get("destination_address", "")
184
+ value = str(args.get("value", 0))
185
+
186
+ if to:
187
+ try:
188
+ from_address = wallet_provider.get_address()
189
+ network = wallet_provider.get_network()
190
+ chain_id = int(network.chain_id) if network.chain_id else config.chain_id
191
+
192
+ proof_id = self._pg.validate_transaction(
193
+ from_address=from_address,
194
+ to=to,
195
+ data="0x", # Simplified - could extract real data
196
+ value=value,
197
+ chain_id=chain_id,
198
+ )
199
+
200
+ logger.info(
201
+ f"ProofGate approved {action.name} | "
202
+ f"Proof ID: {proof_id}"
203
+ )
204
+
205
+ except ProofGateValidationError as e:
206
+ return (
207
+ f"🚫 Action BLOCKED by ProofGate\n"
208
+ f"Action: {action.name}\n"
209
+ f"Reason: {e.reason}\n"
210
+ f"Validation ID: {e.validation_id}\n"
211
+ f"This action was not executed."
212
+ )
213
+
214
+ return original_invoke(args)
215
+
216
+ return Action(
217
+ name=action.name,
218
+ description=f"[ProofGate Protected] {action.description}",
219
+ args_schema=action.args_schema,
220
+ invoke=wrapped_invoke,
221
+ )
222
+
223
+ def supports_network(self, network: Any) -> bool:
224
+ """Check network support."""
225
+ return self._inner.supports_network(network)
226
+
227
+ return WrappedActionProvider()
228
+
229
+
230
+ def create_validated_action(
231
+ config: ProofGateConfig,
232
+ extract_tx_params: Optional[Callable[[dict[str, Any]], dict[str, Any]]] = None,
233
+ ) -> Callable[[Callable[..., T]], Callable[..., T]]:
234
+ """Decorator to add ProofGate validation to an action function.
235
+
236
+ Args:
237
+ config: ProofGate configuration.
238
+ extract_tx_params: Function to extract tx params (to, data, value) from args.
239
+
240
+ Returns:
241
+ A decorator that adds validation.
242
+
243
+ Example:
244
+ ```python
245
+ @create_validated_action(config)
246
+ def my_transfer_action(wallet_provider, args):
247
+ # This will be validated first
248
+ ...
249
+ ```
250
+ """
251
+ pg_provider = ProofGateActionProvider(config)
252
+
253
+ def decorator(func: Callable[..., T]) -> Callable[..., T]:
254
+ @functools.wraps(func)
255
+ def wrapper(
256
+ self: Any,
257
+ wallet_provider: EvmWalletProvider,
258
+ args: dict[str, Any],
259
+ ) -> T:
260
+ # Extract transaction parameters
261
+ if extract_tx_params:
262
+ tx_params = extract_tx_params(args)
263
+ else:
264
+ tx_params = {
265
+ "to": args.get("to") or args.get("contract_address", ""),
266
+ "data": args.get("data", "0x"),
267
+ "value": str(args.get("value", 0)),
268
+ }
269
+
270
+ if tx_params.get("to"):
271
+ from_address = wallet_provider.get_address()
272
+ network = wallet_provider.get_network()
273
+ chain_id = int(network.chain_id) if network.chain_id else config.chain_id
274
+
275
+ # This will raise ProofGateValidationError if blocked
276
+ proof_id = pg_provider.validate_transaction(
277
+ from_address=from_address,
278
+ to=tx_params["to"],
279
+ data=tx_params.get("data", "0x"),
280
+ value=tx_params.get("value", "0"),
281
+ chain_id=chain_id,
282
+ )
283
+
284
+ logger.info(f"ProofGate validated | Proof ID: {proof_id}")
285
+
286
+ return func(self, wallet_provider, args)
287
+
288
+ return wrapper
289
+
290
+ return decorator
@@ -0,0 +1,343 @@
1
+ Metadata-Version: 2.4
2
+ Name: proofgate-agentkit
3
+ Version: 0.1.0
4
+ Summary: ProofGate Action Provider for Coinbase AgentKit - Blockchain guardrails for AI agents
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Keywords: proofgate,agentkit,coinbase,blockchain,security,ai-agent,guardrails
8
+ Author: bytes0xcr6
9
+ Author-email: 102038261+bytes0xcr6@users.noreply.github.com
10
+ Requires-Python: >=3.10,<4.0
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Security
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Dist: coinbase-agentkit (>=0.1.0,<0.2.0)
24
+ Requires-Dist: proofgate (>=0.1.0,<0.2.0)
25
+ Requires-Dist: pydantic (>=2.0.0,<3.0.0)
26
+ Project-URL: Documentation, https://docs.proofgate.xyz
27
+ Project-URL: Homepage, https://github.com/proofgate/proofgate-agentkit
28
+ Project-URL: Repository, https://github.com/proofgate/proofgate-agentkit
29
+ Description-Content-Type: text/markdown
30
+
31
+ # proofgate-agentkit
32
+
33
+ > ProofGate Action Provider for Coinbase AgentKit - Blockchain guardrails for AI agents
34
+
35
+ [![PyPI version](https://badge.fury.io/py/proofgate-agentkit.svg)](https://pypi.org/project/proofgate-agentkit/)
36
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
38
+
39
+ ## What is this?
40
+
41
+ `proofgate-agentkit` integrates [ProofGate](https://proofgate.xyz) with [Coinbase AgentKit](https://github.com/coinbase/agentkit), providing security guardrails for AI agent blockchain transactions.
42
+
43
+ **ProofGate validates transactions before your AI agent executes them**, preventing:
44
+
45
+ - 🚫 **Wallet drains** from prompt injection attacks
46
+ - 🚫 **Infinite approvals** to malicious contracts
47
+ - 🚫 **Excessive spending** beyond daily limits
48
+ - 🚫 **High slippage** swaps that lose money
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ pip install proofgate-agentkit
54
+ ```
55
+
56
+ Or with Poetry:
57
+
58
+ ```bash
59
+ poetry add proofgate-agentkit
60
+ ```
61
+
62
+ ## Quick Start
63
+
64
+ ### 1. As an Action Provider
65
+
66
+ Add ProofGate as an action provider to validate transactions explicitly:
67
+
68
+ ```python
69
+ from coinbase_agentkit import AgentKit, AgentKitConfig
70
+ from proofgate_agentkit import proofgate_action_provider
71
+
72
+ # Create the ProofGate action provider
73
+ proofgate = proofgate_action_provider(
74
+ api_key="pg_your_api_key", # Get from proofgate.xyz/dashboard
75
+ guardrail_id="your_guardrail", # Create at proofgate.xyz/guardrails
76
+ chain_id=8453, # Base mainnet
77
+ )
78
+
79
+ # Add to your AgentKit configuration
80
+ agent = AgentKit(
81
+ config=AgentKitConfig(
82
+ # ... your config
83
+ ),
84
+ action_providers=[
85
+ proofgate,
86
+ # ... other providers
87
+ ],
88
+ )
89
+ ```
90
+
91
+ Now your agent has access to these actions:
92
+ - `validate_transaction` - Validate a transaction before execution
93
+ - `check_agent_trust` - Check a wallet's trust score
94
+
95
+ ### 2. Wrap Existing Providers
96
+
97
+ Automatically validate all transactions from any action provider:
98
+
99
+ ```python
100
+ from coinbase_agentkit.action_providers import erc20_action_provider, wallet_action_provider
101
+ from proofgate_agentkit import wrap_with_proofgate, ProofGateConfig
102
+
103
+ config = ProofGateConfig(
104
+ api_key="pg_your_api_key",
105
+ guardrail_id="your_guardrail",
106
+ )
107
+
108
+ # Wrap providers - all their transaction actions will be validated
109
+ safe_erc20 = wrap_with_proofgate(erc20_action_provider(), config)
110
+ safe_wallet = wrap_with_proofgate(wallet_action_provider(), config)
111
+
112
+ agent = AgentKit(
113
+ config=AgentKitConfig(...),
114
+ action_providers=[safe_erc20, safe_wallet],
115
+ )
116
+ ```
117
+
118
+ ### 3. Wrap the Wallet Provider
119
+
120
+ Validate ALL transactions at the wallet level:
121
+
122
+ ```python
123
+ from coinbase_agentkit.wallet_providers import CdpWalletProvider
124
+ from proofgate_agentkit import ProofGateWrapper, ProofGateConfig
125
+
126
+ # Create wallet provider
127
+ wallet = CdpWalletProvider(...)
128
+
129
+ # Wrap with ProofGate
130
+ config = ProofGateConfig(
131
+ api_key="pg_your_api_key",
132
+ guardrail_id="your_guardrail",
133
+ )
134
+ wrapper = ProofGateWrapper(config)
135
+ safe_wallet = wrapper.wrap(wallet)
136
+
137
+ # Now every send_transaction() call is validated first
138
+ agent = AgentKit(
139
+ config=AgentKitConfig(...),
140
+ wallet_provider=safe_wallet,
141
+ )
142
+ ```
143
+
144
+ ## Configuration
145
+
146
+ ```python
147
+ from proofgate_agentkit import ProofGateConfig
148
+
149
+ config = ProofGateConfig(
150
+ # Required
151
+ api_key="pg_xxx", # Your ProofGate API key
152
+
153
+ # Optional
154
+ guardrail_id="xxx", # Default guardrail to use
155
+ chain_id=8453, # Default chain (8453 = Base)
156
+ base_url="https://...", # Custom API URL
157
+ timeout=30.0, # Request timeout (seconds)
158
+ fail_open=False, # Allow tx on API failure (default: False)
159
+ log_validations=True, # Log validation results (default: True)
160
+ )
161
+ ```
162
+
163
+ ### Fail Open vs Fail Closed
164
+
165
+ By default, `fail_open=False` means:
166
+ - If ProofGate API is unreachable, transactions are **blocked**
167
+ - This is the secure default
168
+
169
+ Set `fail_open=True` for:
170
+ - Allow transactions when ProofGate is unavailable
171
+ - Useful for testing or when availability > security
172
+
173
+ ## Usage Examples
174
+
175
+ ### Explicit Validation
176
+
177
+ ```python
178
+ from proofgate_agentkit import ProofGateActionProvider, ProofGateConfig, ProofGateValidationError
179
+
180
+ config = ProofGateConfig(api_key="pg_xxx", guardrail_id="xxx")
181
+ provider = ProofGateActionProvider(config)
182
+
183
+ try:
184
+ proof_id = provider.validate_transaction(
185
+ from_address="0xYourAgent...",
186
+ to="0xContract...",
187
+ data="0xa9059cbb...",
188
+ value="0",
189
+ )
190
+ print(f"✅ Safe! Proof ID: {proof_id}")
191
+ # Execute transaction...
192
+
193
+ except ProofGateValidationError as e:
194
+ print(f"🚫 Blocked: {e.reason}")
195
+ print(f"Evidence: {e.evidence_uri}")
196
+ ```
197
+
198
+ ### With LangChain
199
+
200
+ ```python
201
+ from langchain_openai import ChatOpenAI
202
+ from coinbase_agentkit import AgentKit
203
+ from coinbase_agentkit_langchain import get_langchain_tools
204
+ from proofgate_agentkit import proofgate_action_provider
205
+
206
+ # Setup AgentKit with ProofGate
207
+ agent_kit = AgentKit(
208
+ config=config,
209
+ action_providers=[
210
+ proofgate_action_provider(
211
+ api_key="pg_xxx",
212
+ guardrail_id="xxx",
213
+ ),
214
+ # ... other providers
215
+ ],
216
+ )
217
+
218
+ # Get tools for LangChain
219
+ tools = get_langchain_tools(agent_kit)
220
+
221
+ # Create agent
222
+ llm = ChatOpenAI(model="gpt-4")
223
+ agent = create_react_agent(llm, tools)
224
+ ```
225
+
226
+ ### Programmatic Validation in Custom Actions
227
+
228
+ ```python
229
+ from coinbase_agentkit.action_providers import ActionProvider, create_action
230
+ from proofgate_agentkit import ProofGateActionProvider, ProofGateConfig
231
+
232
+ class MyCustomProvider(ActionProvider):
233
+ def __init__(self):
234
+ super().__init__("my_custom", [])
235
+
236
+ # Initialize ProofGate for validation
237
+ config = ProofGateConfig(api_key="pg_xxx")
238
+ self._proofgate = ProofGateActionProvider(config)
239
+
240
+ @create_action(name="dangerous_action", description="...", schema=MySchema)
241
+ def dangerous_action(self, wallet_provider, args):
242
+ # Validate first!
243
+ self._proofgate.validate_transaction(
244
+ from_address=wallet_provider.get_address(),
245
+ to=args["to"],
246
+ data=args["data"],
247
+ value=args["value"],
248
+ )
249
+
250
+ # If we get here, it's safe
251
+ return wallet_provider.send_transaction({...})
252
+ ```
253
+
254
+ ## Guardrails
255
+
256
+ Guardrails define what your agent can do. Create them at [proofgate.xyz/guardrails](https://www.proofgate.xyz/guardrails).
257
+
258
+ Example rules:
259
+ - ✅ **Whitelist contracts**: Only Uniswap, Aave, Compound
260
+ - ✅ **Max approval**: 1,000 USDC per approval
261
+ - ✅ **Max slippage**: 1% on swaps
262
+ - ✅ **Daily limit**: $10,000 total spending
263
+ - ✅ **Blocked methods**: No `setApprovalForAll`
264
+
265
+ ## Error Handling
266
+
267
+ ```python
268
+ from proofgate_agentkit import ProofGateValidationError
269
+
270
+ try:
271
+ provider.validate_transaction(...)
272
+ except ProofGateValidationError as e:
273
+ print(f"Blocked: {e.reason}")
274
+ print(f"Validation ID: {e.validation_id}")
275
+ print(f"Evidence URI: {e.evidence_uri}")
276
+
277
+ # Access individual check results
278
+ for check in e.checks:
279
+ print(f" - {check['name']}: {check['result']}")
280
+ ```
281
+
282
+ ## API Reference
283
+
284
+ ### ProofGateActionProvider
285
+
286
+ The main action provider class.
287
+
288
+ **Methods:**
289
+ - `validate_transaction(from_address, to, data, value, chain_id, guardrail_id)` → `str`
290
+ - Returns proof_id if safe, raises `ProofGateValidationError` if blocked
291
+
292
+ **Actions (for LLM agents):**
293
+ - `validate_transaction` - Validate a transaction
294
+ - `check_agent_trust` - Check wallet trust score
295
+
296
+ ### ProofGateWrapper
297
+
298
+ Wraps wallet providers for automatic validation.
299
+
300
+ **Methods:**
301
+ - `wrap(wallet_provider)` → `EvmWalletProvider`
302
+ - Returns the same provider with patched `send_transaction`
303
+
304
+ ### wrap_with_proofgate
305
+
306
+ Factory function to wrap action providers.
307
+
308
+ ```python
309
+ wrapped = wrap_with_proofgate(provider, config)
310
+ ```
311
+
312
+ ## Development
313
+
314
+ ```bash
315
+ # Clone
316
+ git clone https://github.com/proofgate/proofgate-agentkit
317
+ cd proofgate-agentkit/python
318
+
319
+ # Install dependencies
320
+ poetry install
321
+
322
+ # Run tests
323
+ poetry run pytest
324
+
325
+ # Format
326
+ poetry run black .
327
+ poetry run ruff check --fix .
328
+
329
+ # Type check
330
+ poetry run mypy proofgate_agentkit
331
+ ```
332
+
333
+ ## License
334
+
335
+ MIT License - see [LICENSE](LICENSE) for details.
336
+
337
+ ## Links
338
+
339
+ - 🌐 [ProofGate Website](https://proofgate.xyz)
340
+ - 📚 [Documentation](https://docs.proofgate.xyz)
341
+ - 🔧 [Coinbase AgentKit](https://github.com/coinbase/agentkit)
342
+ - 🐍 [proofgate Python SDK](https://pypi.org/project/proofgate/)
343
+
@@ -0,0 +1,10 @@
1
+ proofgate_agentkit/__init__.py,sha256=Lsqm3LN4D2OP6reOqw1QXu3JUNVFoW5VpLSn9RDQ7iU,660
2
+ proofgate_agentkit/action_provider.py,sha256=X_H5Cq9JK9fXUOa2jt4ssVXwIP61B4zGccqqb5YgOrs,10253
3
+ proofgate_agentkit/config.py,sha256=o1OZGSscpt4CiC7yhRgLuToNNIWXB6IbpzEkOZ27VvY,1387
4
+ proofgate_agentkit/exceptions.py,sha256=hHu9nwEdRUqL0mDoj7UUPDeKpDw-_Mkh2t4AI8_UwWo,1617
5
+ proofgate_agentkit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ proofgate_agentkit/wrapper.py,sha256=x7jvvdbpqeuKcX0ZXB6jkuQiLhG8uzWENKWUMgiM2IQ,10066
7
+ proofgate_agentkit-0.1.0.dist-info/METADATA,sha256=zS1JXuwIqWoYNWOKSBvo25_tO7QSVvGHtC-cmyYZUTM,9826
8
+ proofgate_agentkit-0.1.0.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
9
+ proofgate_agentkit-0.1.0.dist-info/licenses/LICENSE,sha256=P65zjuntxfANEktkG--DbihXXh8IiwF__0Zehegy_2U,1066
10
+ proofgate_agentkit-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.3.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ProofGate
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.