langchain-verdix 0.1.0__tar.gz
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.
- langchain_verdix-0.1.0/.gitignore +7 -0
- langchain_verdix-0.1.0/LICENSE +21 -0
- langchain_verdix-0.1.0/PKG-INFO +178 -0
- langchain_verdix-0.1.0/README.md +146 -0
- langchain_verdix-0.1.0/examples/check_before_send.py +33 -0
- langchain_verdix-0.1.0/langchain_verdix/__init__.py +35 -0
- langchain_verdix-0.1.0/langchain_verdix/_constants.py +24 -0
- langchain_verdix-0.1.0/langchain_verdix/_version.py +1 -0
- langchain_verdix-0.1.0/langchain_verdix/client.py +442 -0
- langchain_verdix-0.1.0/langchain_verdix/errors.py +7 -0
- langchain_verdix-0.1.0/langchain_verdix/py.typed +0 -0
- langchain_verdix-0.1.0/langchain_verdix/tools.py +228 -0
- langchain_verdix-0.1.0/pyproject.toml +83 -0
- langchain_verdix-0.1.0/tests/__init__.py +0 -0
- langchain_verdix-0.1.0/tests/mock_api.py +142 -0
- langchain_verdix-0.1.0/tests/test_client.py +312 -0
- langchain_verdix-0.1.0/tests/test_standard.py +34 -0
- langchain_verdix-0.1.0/tests/test_tools.py +191 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Verdix
|
|
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.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: langchain-verdix
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: LangChain tool: check an EVM address on Base before sending it funds (safe/caution/danger). Pays per call via x402 in USDC from your agent's wallet, within caps you set.
|
|
5
|
+
Project-URL: Homepage, https://api.verdixapi.com
|
|
6
|
+
Project-URL: Repository, https://github.com/verdixapi/langchain-verdix
|
|
7
|
+
Project-URL: Issues, https://github.com/verdixapi/langchain-verdix/issues
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: address,address-poisoning,agents,base,langchain,langgraph,risk,scam,security,tool,usdc,wallet,x402
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Security
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: eth-account>=0.13
|
|
22
|
+
Requires-Dist: httpx<1,>=0.28.1
|
|
23
|
+
Requires-Dist: langchain-core<2,>=1.0
|
|
24
|
+
Requires-Dist: pydantic<3,>=2.7
|
|
25
|
+
Requires-Dist: x402[evm]<3,>=2.22
|
|
26
|
+
Provides-Extra: test
|
|
27
|
+
Requires-Dist: langchain-tests<2,>=1.0; extra == 'test'
|
|
28
|
+
Requires-Dist: langchain<2,>=1.0; extra == 'test'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'test'
|
|
30
|
+
Requires-Dist: pytest>=8; extra == 'test'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# langchain-verdix
|
|
34
|
+
|
|
35
|
+
A [LangChain](https://python.langchain.com) tool that screens an EVM address on Base **before your agent sends it funds**, and answers `safe`, `caution` or `danger` with reasons.
|
|
36
|
+
|
|
37
|
+
It checks OFAC sanctions, scam, phishing and exploit lists, live **address-poisoning lookalikes**, burn addresses, contract and deployer signals, and on-chain behaviour. You don't need an API key or an account. Each check is paid per call via [x402](https://x402.org), in USDC on Base, from your agent's own wallet, under caps you set.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install -U langchain-verdix
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Payments are real USDC on Base mainnet; there is no testnet mode.
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import os
|
|
51
|
+
|
|
52
|
+
from eth_account import Account
|
|
53
|
+
from langchain.agents import create_agent
|
|
54
|
+
from langchain_verdix import VerdixAddressRiskTool
|
|
55
|
+
|
|
56
|
+
check_address_risk = VerdixAddressRiskTool(
|
|
57
|
+
account=Account.from_key(os.environ["AGENT_PRIVATE_KEY"]),
|
|
58
|
+
max_price_per_call_usd=0.10, # never pay more than $0.10 for one check
|
|
59
|
+
max_total_spend_usd=1.00, # and at most $1 in total
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
agent = create_agent("openai:gpt-5-mini", tools=[check_address_risk])
|
|
63
|
+
result = agent.invoke(
|
|
64
|
+
{
|
|
65
|
+
"messages": [
|
|
66
|
+
{
|
|
67
|
+
"role": "user",
|
|
68
|
+
"content": "Send 250 USDC on Base to 0x000000000000000000000000000000000000dEaD.",
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
print(result["messages"][-1].content)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Any chat model that supports tool calling works, as does LangGraph (`ToolNode`) or calling the tool directly:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
check_address_risk.invoke(
|
|
80
|
+
{"address": "0x000000000000000000000000000000000000dEaD", "tier": "quick"}
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The model gets one tool, `check_address_risk(address, tier?)`, and sees this result as JSON:
|
|
85
|
+
|
|
86
|
+
```jsonc
|
|
87
|
+
{
|
|
88
|
+
"verdict": "danger", // "safe" | "caution" | "danger"
|
|
89
|
+
"risk_score": 90,
|
|
90
|
+
"reasons": ["burn_address"],
|
|
91
|
+
"checked": ["ofac", "scam_lists", "poisoning_watch", "burn_list", "..."],
|
|
92
|
+
"advice": "Do not send funds to this address. Show the reasons to the user.",
|
|
93
|
+
"tier": "standard",
|
|
94
|
+
"price_usd": 0.1,
|
|
95
|
+
"complete": true,
|
|
96
|
+
"charged": true,
|
|
97
|
+
"payment": { "transaction": "0x...", "network": "eip155:8453", "payer": "0x..." },
|
|
98
|
+
"retry_after_seconds": null,
|
|
99
|
+
"address": "0x000000000000000000000000000000000000dEaD",
|
|
100
|
+
"chain": "base",
|
|
101
|
+
"as_of": "2026-10-02T12:00:00+00:00"
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The same dict is the `artifact` of the `ToolMessage`, so your code can read the payment's transaction hash without parsing the content.
|
|
106
|
+
|
|
107
|
+
### What the verdicts mean
|
|
108
|
+
|
|
109
|
+
| Verdict | Meaning | What the agent should do |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| `safe` | None of the checks in `checked` found a risk signal. **Not a guarantee.** | Still confirm the full address and amount with the user. |
|
|
112
|
+
| `caution` | Risk signals were found, or a data source could not be reached (`complete: false`). | Show the reasons and send only if the user explicitly confirms. |
|
|
113
|
+
| `danger` | Strong risk signals: sanctioned, known scam, poisoning lookalike, burn address... | Do not send. |
|
|
114
|
+
|
|
115
|
+
The tool description tells the model the same thing, and every result carries an `advice` string.
|
|
116
|
+
|
|
117
|
+
### Tiers
|
|
118
|
+
|
|
119
|
+
The model picks a tier by what is at stake. It can only pick the tiers that fit under `max_price_per_call_usd`: the others are left out of the tool's description and input schema.
|
|
120
|
+
|
|
121
|
+
| Tier | List price | When |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `quick` | $0.02 | Small, routine transfers (under ~$100) to an address used before. Sanctions, scam lists, poisoning lookalikes, burn addresses, contract/deployer signals and a fast address-age read. |
|
|
124
|
+
| `standard` (default) | $0.10 | ~$100-$1,000, or any address that came from a message, a transaction history or a copy-paste. Adds deeper on-chain behaviour analysis. |
|
|
125
|
+
| `deep` | $0.50 | Over ~$1,000, first-time counterparties, contract interactions. Currently the same checks as `standard`; new counterparty checks land here first. |
|
|
126
|
+
|
|
127
|
+
Each tier has its own URL (`https://api.verdixapi.com/risk/address/{tier}`) with a single price, so the tier the model asks for is exactly the tier that is paid.
|
|
128
|
+
|
|
129
|
+
## Options
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
VerdixAddressRiskTool(
|
|
133
|
+
account=..., # required: an eth_account account (or any x402 ClientEvmSigner)
|
|
134
|
+
max_price_per_call_usd=0.10, # required: refuse any check costing more, before signing
|
|
135
|
+
max_total_spend_usd=1.00, # optional: total budget for this tool instance
|
|
136
|
+
allowed_tiers=["quick", "standard"], # optional (default: all tiers within the cap)
|
|
137
|
+
default_tier="standard", # optional: used when the model gives none
|
|
138
|
+
api_url=None, # optional: default https://api.verdixapi.com
|
|
139
|
+
)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Payments and safety
|
|
143
|
+
|
|
144
|
+
- The wallet needs a little **USDC on Base mainnet**. It needs no ETH: x402 payments are gasless signatures that the facilitator settles.
|
|
145
|
+
- The private key only signs the payment locally. It is never sent anywhere.
|
|
146
|
+
- A payment is signed only for **USDC on Base**, only for the tier requested, and only at or under `max_price_per_call_usd`. Anything else is refused before signing.
|
|
147
|
+
- Before each payment is signed, its price is reserved against `max_total_spend_usd`, so parallel tool calls (threads or asyncio) cannot overspend. The reservation is released when the API reports no charge.
|
|
148
|
+
- **You are not charged when a data source fails.** The API then answers `caution` with `complete: false` (and `retry_after_seconds`), and never `safe`.
|
|
149
|
+
- The model cannot change the caps: they are fixed when the tool is created.
|
|
150
|
+
- A refusal (price over the cap, budget used up, malformed address) goes back to the model as the tool's error message instead of ending the run.
|
|
151
|
+
|
|
152
|
+
## Without a model
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from langchain_verdix import VerdixClient
|
|
156
|
+
|
|
157
|
+
verdix = VerdixClient(account=account, max_price_per_call_usd=0.10)
|
|
158
|
+
|
|
159
|
+
pricing = verdix.get_pricing() # free: reads the unpaid 402 quotes
|
|
160
|
+
result = verdix.check_address("0x...", tier="quick") # or: await verdix.acheck_address(...)
|
|
161
|
+
if result.verdict != "safe":
|
|
162
|
+
... # stop, or ask the user
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The errors to expect are `VerdixError`s: a malformed address, a price over your cap, an exhausted budget or an unexpected API answer.
|
|
166
|
+
|
|
167
|
+
## Development
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
pip install -e ".[test]"
|
|
171
|
+
pytest # offline: mocked API, throwaway key, sockets disabled, no payment
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`examples/check_before_send.py` makes one real paid check.
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
MIT
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# langchain-verdix
|
|
2
|
+
|
|
3
|
+
A [LangChain](https://python.langchain.com) tool that screens an EVM address on Base **before your agent sends it funds**, and answers `safe`, `caution` or `danger` with reasons.
|
|
4
|
+
|
|
5
|
+
It checks OFAC sanctions, scam, phishing and exploit lists, live **address-poisoning lookalikes**, burn addresses, contract and deployer signals, and on-chain behaviour. You don't need an API key or an account. Each check is paid per call via [x402](https://x402.org), in USDC on Base, from your agent's own wallet, under caps you set.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install -U langchain-verdix
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Payments are real USDC on Base mainnet; there is no testnet mode.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
import os
|
|
19
|
+
|
|
20
|
+
from eth_account import Account
|
|
21
|
+
from langchain.agents import create_agent
|
|
22
|
+
from langchain_verdix import VerdixAddressRiskTool
|
|
23
|
+
|
|
24
|
+
check_address_risk = VerdixAddressRiskTool(
|
|
25
|
+
account=Account.from_key(os.environ["AGENT_PRIVATE_KEY"]),
|
|
26
|
+
max_price_per_call_usd=0.10, # never pay more than $0.10 for one check
|
|
27
|
+
max_total_spend_usd=1.00, # and at most $1 in total
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
agent = create_agent("openai:gpt-5-mini", tools=[check_address_risk])
|
|
31
|
+
result = agent.invoke(
|
|
32
|
+
{
|
|
33
|
+
"messages": [
|
|
34
|
+
{
|
|
35
|
+
"role": "user",
|
|
36
|
+
"content": "Send 250 USDC on Base to 0x000000000000000000000000000000000000dEaD.",
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
print(result["messages"][-1].content)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Any chat model that supports tool calling works, as does LangGraph (`ToolNode`) or calling the tool directly:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
check_address_risk.invoke(
|
|
48
|
+
{"address": "0x000000000000000000000000000000000000dEaD", "tier": "quick"}
|
|
49
|
+
)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The model gets one tool, `check_address_risk(address, tier?)`, and sees this result as JSON:
|
|
53
|
+
|
|
54
|
+
```jsonc
|
|
55
|
+
{
|
|
56
|
+
"verdict": "danger", // "safe" | "caution" | "danger"
|
|
57
|
+
"risk_score": 90,
|
|
58
|
+
"reasons": ["burn_address"],
|
|
59
|
+
"checked": ["ofac", "scam_lists", "poisoning_watch", "burn_list", "..."],
|
|
60
|
+
"advice": "Do not send funds to this address. Show the reasons to the user.",
|
|
61
|
+
"tier": "standard",
|
|
62
|
+
"price_usd": 0.1,
|
|
63
|
+
"complete": true,
|
|
64
|
+
"charged": true,
|
|
65
|
+
"payment": { "transaction": "0x...", "network": "eip155:8453", "payer": "0x..." },
|
|
66
|
+
"retry_after_seconds": null,
|
|
67
|
+
"address": "0x000000000000000000000000000000000000dEaD",
|
|
68
|
+
"chain": "base",
|
|
69
|
+
"as_of": "2026-10-02T12:00:00+00:00"
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The same dict is the `artifact` of the `ToolMessage`, so your code can read the payment's transaction hash without parsing the content.
|
|
74
|
+
|
|
75
|
+
### What the verdicts mean
|
|
76
|
+
|
|
77
|
+
| Verdict | Meaning | What the agent should do |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| `safe` | None of the checks in `checked` found a risk signal. **Not a guarantee.** | Still confirm the full address and amount with the user. |
|
|
80
|
+
| `caution` | Risk signals were found, or a data source could not be reached (`complete: false`). | Show the reasons and send only if the user explicitly confirms. |
|
|
81
|
+
| `danger` | Strong risk signals: sanctioned, known scam, poisoning lookalike, burn address... | Do not send. |
|
|
82
|
+
|
|
83
|
+
The tool description tells the model the same thing, and every result carries an `advice` string.
|
|
84
|
+
|
|
85
|
+
### Tiers
|
|
86
|
+
|
|
87
|
+
The model picks a tier by what is at stake. It can only pick the tiers that fit under `max_price_per_call_usd`: the others are left out of the tool's description and input schema.
|
|
88
|
+
|
|
89
|
+
| Tier | List price | When |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| `quick` | $0.02 | Small, routine transfers (under ~$100) to an address used before. Sanctions, scam lists, poisoning lookalikes, burn addresses, contract/deployer signals and a fast address-age read. |
|
|
92
|
+
| `standard` (default) | $0.10 | ~$100-$1,000, or any address that came from a message, a transaction history or a copy-paste. Adds deeper on-chain behaviour analysis. |
|
|
93
|
+
| `deep` | $0.50 | Over ~$1,000, first-time counterparties, contract interactions. Currently the same checks as `standard`; new counterparty checks land here first. |
|
|
94
|
+
|
|
95
|
+
Each tier has its own URL (`https://api.verdixapi.com/risk/address/{tier}`) with a single price, so the tier the model asks for is exactly the tier that is paid.
|
|
96
|
+
|
|
97
|
+
## Options
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
VerdixAddressRiskTool(
|
|
101
|
+
account=..., # required: an eth_account account (or any x402 ClientEvmSigner)
|
|
102
|
+
max_price_per_call_usd=0.10, # required: refuse any check costing more, before signing
|
|
103
|
+
max_total_spend_usd=1.00, # optional: total budget for this tool instance
|
|
104
|
+
allowed_tiers=["quick", "standard"], # optional (default: all tiers within the cap)
|
|
105
|
+
default_tier="standard", # optional: used when the model gives none
|
|
106
|
+
api_url=None, # optional: default https://api.verdixapi.com
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Payments and safety
|
|
111
|
+
|
|
112
|
+
- The wallet needs a little **USDC on Base mainnet**. It needs no ETH: x402 payments are gasless signatures that the facilitator settles.
|
|
113
|
+
- The private key only signs the payment locally. It is never sent anywhere.
|
|
114
|
+
- A payment is signed only for **USDC on Base**, only for the tier requested, and only at or under `max_price_per_call_usd`. Anything else is refused before signing.
|
|
115
|
+
- Before each payment is signed, its price is reserved against `max_total_spend_usd`, so parallel tool calls (threads or asyncio) cannot overspend. The reservation is released when the API reports no charge.
|
|
116
|
+
- **You are not charged when a data source fails.** The API then answers `caution` with `complete: false` (and `retry_after_seconds`), and never `safe`.
|
|
117
|
+
- The model cannot change the caps: they are fixed when the tool is created.
|
|
118
|
+
- A refusal (price over the cap, budget used up, malformed address) goes back to the model as the tool's error message instead of ending the run.
|
|
119
|
+
|
|
120
|
+
## Without a model
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from langchain_verdix import VerdixClient
|
|
124
|
+
|
|
125
|
+
verdix = VerdixClient(account=account, max_price_per_call_usd=0.10)
|
|
126
|
+
|
|
127
|
+
pricing = verdix.get_pricing() # free: reads the unpaid 402 quotes
|
|
128
|
+
result = verdix.check_address("0x...", tier="quick") # or: await verdix.acheck_address(...)
|
|
129
|
+
if result.verdict != "safe":
|
|
130
|
+
... # stop, or ask the user
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The errors to expect are `VerdixError`s: a malformed address, a price over your cap, an exhausted budget or an unexpected API answer.
|
|
134
|
+
|
|
135
|
+
## Development
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
pip install -e ".[test]"
|
|
139
|
+
pytest # offline: mocked API, throwaway key, sockets disabled, no payment
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`examples/check_before_send.py` makes one real paid check.
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""One real, paid Verdix check through the LangChain tool (no model needed).
|
|
2
|
+
|
|
3
|
+
Pays REAL USDC on Base mainnet ($0.02, quick tier) from AGENT_PRIVATE_KEY.
|
|
4
|
+
|
|
5
|
+
AGENT_PRIVATE_KEY=0x... python examples/check_before_send.py [address]
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
from eth_account import Account
|
|
13
|
+
|
|
14
|
+
from langchain_verdix import VerdixAddressRiskTool
|
|
15
|
+
|
|
16
|
+
address = sys.argv[1] if len(sys.argv) > 1 else "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
|
|
17
|
+
|
|
18
|
+
tool = VerdixAddressRiskTool(
|
|
19
|
+
account=Account.from_key(os.environ["AGENT_PRIVATE_KEY"]),
|
|
20
|
+
max_price_per_call_usd=0.02, # quick tier only
|
|
21
|
+
max_total_spend_usd=0.02, # one check
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
message = tool.invoke(
|
|
25
|
+
{
|
|
26
|
+
"type": "tool_call",
|
|
27
|
+
"id": "example",
|
|
28
|
+
"name": tool.name,
|
|
29
|
+
"args": {"address": address, "tier": "quick"},
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
# A refusal or API error comes back as the message content, with no artifact.
|
|
33
|
+
print(json.dumps(message.artifact, indent=2) if message.artifact else message.content)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""LangChain tool: check an EVM address on Base before sending it funds."""
|
|
2
|
+
|
|
3
|
+
from langchain_verdix._constants import (
|
|
4
|
+
DEFAULT_API_URL,
|
|
5
|
+
TIER_LIST_PRICES_USD,
|
|
6
|
+
VERDIX_TIERS,
|
|
7
|
+
VerdixTier,
|
|
8
|
+
)
|
|
9
|
+
from langchain_verdix._version import __version__
|
|
10
|
+
from langchain_verdix.client import (
|
|
11
|
+
VerdixCheckResult,
|
|
12
|
+
VerdixClient,
|
|
13
|
+
VerdixPayment,
|
|
14
|
+
VerdixTierQuote,
|
|
15
|
+
VerdixVerdict,
|
|
16
|
+
tiers_within_cap,
|
|
17
|
+
)
|
|
18
|
+
from langchain_verdix.errors import VerdixError
|
|
19
|
+
from langchain_verdix.tools import VerdixAddressRiskTool
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"DEFAULT_API_URL",
|
|
23
|
+
"TIER_LIST_PRICES_USD",
|
|
24
|
+
"VERDIX_TIERS",
|
|
25
|
+
"VerdixAddressRiskTool",
|
|
26
|
+
"VerdixCheckResult",
|
|
27
|
+
"VerdixClient",
|
|
28
|
+
"VerdixError",
|
|
29
|
+
"VerdixPayment",
|
|
30
|
+
"VerdixTier",
|
|
31
|
+
"VerdixTierQuote",
|
|
32
|
+
"VerdixVerdict",
|
|
33
|
+
"__version__",
|
|
34
|
+
"tiers_within_cap",
|
|
35
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
DEFAULT_API_URL = "https://api.verdixapi.com"
|
|
4
|
+
|
|
5
|
+
# CAIP-2 id of Base mainnet, the only network Verdix accepts payment on.
|
|
6
|
+
BASE_MAINNET = "eip155:8453"
|
|
7
|
+
|
|
8
|
+
# Native USDC on Base (lowercase), the only asset Verdix accepts.
|
|
9
|
+
USDC_BASE = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"
|
|
10
|
+
|
|
11
|
+
USDC_DECIMALS = 6
|
|
12
|
+
|
|
13
|
+
VerdixTier = Literal["quick", "standard", "deep"]
|
|
14
|
+
|
|
15
|
+
VERDIX_TIERS: tuple[VerdixTier, ...] = ("quick", "standard", "deep")
|
|
16
|
+
|
|
17
|
+
# List prices in USD, used to pick which tiers fit under your cap and to
|
|
18
|
+
# describe them to the model. The API's own 402 quote is authoritative: a
|
|
19
|
+
# tier is never paid for if its live price is above max_price_per_call_usd.
|
|
20
|
+
TIER_LIST_PRICES_USD: dict[VerdixTier, float] = {
|
|
21
|
+
"quick": 0.02,
|
|
22
|
+
"standard": 0.10,
|
|
23
|
+
"deep": 0.50,
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|