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.
- proofgate_agentkit/__init__.py +30 -0
- proofgate_agentkit/action_provider.py +311 -0
- proofgate_agentkit/config.py +33 -0
- proofgate_agentkit/exceptions.py +48 -0
- proofgate_agentkit/py.typed +0 -0
- proofgate_agentkit/wrapper.py +290 -0
- proofgate_agentkit-0.1.0.dist-info/METADATA +343 -0
- proofgate_agentkit-0.1.0.dist-info/RECORD +10 -0
- proofgate_agentkit-0.1.0.dist-info/WHEEL +4 -0
- proofgate_agentkit-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -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
|
+
[](https://pypi.org/project/proofgate-agentkit/)
|
|
36
|
+
[](https://www.python.org/downloads/)
|
|
37
|
+
[](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,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.
|