warrant-client 0.1.0 → 0.1.2
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.
- package/README.md +223 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,90 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
1
3
|
# warrant-client
|
|
2
4
|
|
|
3
|
-
Buy
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
**Buy what an agent needs, one call at a time, in USDC on Hedera.**
|
|
6
|
+
|
|
7
|
+
A permanent name. An email inbox it owns and receives replies at. Sealed
|
|
8
|
+
agent-to-agent mail. A real phone number and SMS. Language model inference.
|
|
9
|
+
Memory written to a file nobody can edit. No API key, no signup, no human in
|
|
10
|
+
the loop: the account that pays is the identity.
|
|
11
|
+
|
|
12
|
+
[](https://www.npmjs.com/package/warrant-client)
|
|
13
|
+
[](https://hashscan.io/testnet/contract/0xF33E2E0ecc982416f788759083129de6A147a1FE)
|
|
14
|
+
[](https://github.com/coinbase/x402)
|
|
15
|
+
[](https://nodejs.org)
|
|
16
|
+
[](https://github.com/martinvibes/warrant/blob/master/LICENSE)
|
|
17
|
+
|
|
18
|
+
[Console](https://warrant-aufgabe.vercel.app) ·
|
|
19
|
+
[Docs](https://warrant-aufgabe.vercel.app/docs) ·
|
|
20
|
+
[Ledger](https://warrant-aufgabe.vercel.app/ledger) ·
|
|
21
|
+
[Catalogue](https://warrant-api-production-e111.up.railway.app/v1/catalogue) ·
|
|
22
|
+
[Spec](https://warrant-api-production-e111.up.railway.app/openapi.json) ·
|
|
23
|
+
[Skill file](https://warrant-api-production-e111.up.railway.app/skill.md) ·
|
|
24
|
+
[MCP](https://qmt6sdhe5ffmva3zl2iagc6hkm.bazgateway.com/mcp) ·
|
|
25
|
+
[Source](https://github.com/martinvibes/warrant)
|
|
26
|
+
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
> An agent that has to ask a human before it can send an email is not autonomous.
|
|
32
|
+
> This is the other half: it pays for what it uses, and a contract on Hedera
|
|
33
|
+
> decides whether it may.
|
|
6
34
|
|
|
7
35
|
```bash
|
|
8
36
|
npm i warrant-client
|
|
9
37
|
```
|
|
10
38
|
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
The fastest path from zero to an agent with an on-chain name, a real inbox, and
|
|
42
|
+
a memory that outlives the process. Every paid step is a real settlement on
|
|
43
|
+
Hedera, and every resource is owned by the account that paid for it.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# 0. Install the CLI, and set the account that pays. It needs testnet USDC and
|
|
47
|
+
# nothing else —
|
|
48
|
+
# the facilitator sponsors the network fee, so no HBAR is required.
|
|
49
|
+
npm i -g warrant-client
|
|
50
|
+
|
|
51
|
+
export WARRANT_ACCOUNT_ID=0.0.10514332
|
|
52
|
+
export WARRANT_PRIVATE_KEY=302e… # DER or hex
|
|
53
|
+
export WARRANT_AGENT_ADDRESS=0x7d14…33cC # only identity.mint needs this
|
|
54
|
+
|
|
55
|
+
# 1. See what is for sale, and what it costs. Free, and needs no key.
|
|
56
|
+
warrant catalogue
|
|
57
|
+
|
|
58
|
+
# 2. Mint the agent's identity — soulbound ERC-721 on Hedera ($0.10)
|
|
59
|
+
warrant buy identity.mint
|
|
60
|
+
|
|
61
|
+
# 3. Claim an inbox it owns and receives replies at ($1.00)
|
|
62
|
+
warrant buy email.inbox --name scout
|
|
63
|
+
|
|
64
|
+
# 4. Send a real email from it ($0.20)
|
|
65
|
+
warrant buy email.send --from scout@0gent.xyz --to you@example.com \
|
|
66
|
+
--subject "Hello" --body "from the agent, paid for by the agent"
|
|
67
|
+
|
|
68
|
+
# 5. Ask a model, paid per call ($0.02)
|
|
69
|
+
warrant buy inference --prompt "What is Hedera in one sentence?"
|
|
70
|
+
|
|
71
|
+
# 6. Write something it will still know tomorrow ($0.05)
|
|
72
|
+
warrant buy memory.write --content "the peer at 0x7510 answers on scout@0gent.xyz"
|
|
73
|
+
|
|
74
|
+
# 7. Search real phone inventory (free — an agent that cannot see the price
|
|
75
|
+
# before it commits is not choosing)
|
|
76
|
+
warrant read '/v1/phone/search?country=US&area=415'
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Without installing, put the package name in front, because the command is
|
|
80
|
+
`warrant` and the package is `warrant-client`:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx --package warrant-client warrant catalogue
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## In code
|
|
87
|
+
|
|
11
88
|
```ts
|
|
12
89
|
import { Warrant } from "warrant-client";
|
|
13
90
|
|
|
@@ -16,46 +93,167 @@ const warrant = new Warrant({
|
|
|
16
93
|
privateKey: process.env.WARRANT_PRIVATE_KEY!,
|
|
17
94
|
});
|
|
18
95
|
|
|
19
|
-
const { result, settlement } = await warrant.buy("inference", {
|
|
96
|
+
const { result, settlement } = await warrant.buy("inference", {
|
|
97
|
+
prompt: "summarise x402 in one line",
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
console.log(result); // the resource
|
|
101
|
+
console.log(settlement); // the Hedera transaction it was paid for in
|
|
20
102
|
```
|
|
21
103
|
|
|
22
|
-
|
|
23
|
-
|
|
104
|
+
One call replaces three: the request that comes back `402`, the signed payment,
|
|
105
|
+
and the retry. Endpoints and prices are read from the service's own catalogue,
|
|
106
|
+
so a service that adds a resource does not need this package republished.
|
|
107
|
+
|
|
108
|
+
## Command reference
|
|
24
109
|
|
|
25
|
-
|
|
110
|
+
Prices are quoted in USDC and settled at request time over
|
|
111
|
+
[x402](https://github.com/coinbase/x402) — one payment per call, no
|
|
112
|
+
subscriptions, no minimum. Flags become the JSON body: `--prompt hello` is
|
|
113
|
+
`{"prompt":"hello"}`.
|
|
114
|
+
|
|
115
|
+
### Free — no key, no account, no payment
|
|
116
|
+
|
|
117
|
+
| Command | Cost | Notes |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| `warrant catalogue` | free | What is for sale and the live price. The same table the server charges against. |
|
|
120
|
+
| `warrant read /v1/receipts` | free | Every settled purchase, signed. Add `?limit=3`. |
|
|
121
|
+
| `warrant read /v1/purchases` | free | The public ledger, including what was refused. |
|
|
122
|
+
| `warrant read /v1/contracts` | free | Addresses of the three contracts, and the receipt issuer. |
|
|
123
|
+
| `warrant read /v1/stats` | free | Totals: purchases, agents, spend. |
|
|
124
|
+
| `warrant read /v1/agents/0.0.10514332` | free | What one agent owns and what it has left. |
|
|
125
|
+
| `warrant read '/v1/phone/search?country=US&area=415'` | free | Real inventory, before you commit to buying one. |
|
|
126
|
+
| `warrant read /v1/memory/<fileId>` | free | Read back a memory file from Hedera. |
|
|
127
|
+
| `warrant read /v1/email/inbox/<address>` | free | Read what arrived in an inbox the account owns. |
|
|
128
|
+
|
|
129
|
+
### Paid — settled in USDC, one payment per call
|
|
130
|
+
|
|
131
|
+
| Command | Cost | Status | Notes |
|
|
132
|
+
|---|---|---|---|
|
|
133
|
+
| `warrant buy identity.mint` | $0.10 | ✅ Live | Soulbound ERC-721 on Hedera's EVM, one per address, plus the public key other agents seal mail to. Optional `--metadataURI`, `--encryptionKey`. Needs `WARRANT_AGENT_ADDRESS`. |
|
|
134
|
+
| `warrant buy inference --prompt "…"` | $0.02 | ✅ Live | One language model call, returned in OpenAI shape. Optional `--model`, `--maxTokens`. |
|
|
135
|
+
| `warrant buy email.inbox --name scout` | $1.00 | ✅ Live | Provisions `scout@0gent.xyz`, owned by the paying account, and **receives replies** — not just outbound. |
|
|
136
|
+
| `warrant buy email.send --from … --to … --subject … --body …` | $0.20 | ✅ Live | A real email from an address the agent owns, via Resend. |
|
|
137
|
+
| `warrant buy email.sealed --from … --to … --toAgent 0x… --subject … --body …` | $0.25 | ✅ Live | Encrypted to the recipient's on-chain key. This service relays it and cannot read it. |
|
|
138
|
+
| `warrant buy memory.write --content "…"` | $0.05 | ✅ Live | A permanent Hedera file, up to 4096 bytes, that nobody — this service included — can edit. |
|
|
139
|
+
| `warrant buy phone.provision --country US` | $0.50 | ✅ Live | A real number in 170+ countries, SMS capable, via Telnyx. Or `--phoneNumber +1…` from a search. |
|
|
140
|
+
| `warrant buy sms.send --from +1… --to +1… --text "…"` | $0.01 | ✅ Live | One text from a number the agent owns. |
|
|
141
|
+
|
|
142
|
+
Nothing is listed as coming soon. An offer whose provider is not configured is
|
|
143
|
+
not shown and not sold, so the catalogue never advertises a price that will not
|
|
144
|
+
be honoured.
|
|
145
|
+
|
|
146
|
+
## How payment works
|
|
147
|
+
|
|
148
|
+
1. Call a paid endpoint with no payment. It answers **`402 Payment Required`**
|
|
149
|
+
with the amount, the asset and where to pay.
|
|
150
|
+
2. Sign an x402 payment for exactly that amount and retry the same request with
|
|
151
|
+
a `payment-signature` header.
|
|
152
|
+
3. The resource runs, and its owner is the account that paid. The settlement id
|
|
153
|
+
comes back in the `payment-response` header.
|
|
154
|
+
|
|
155
|
+
This package does all three. Settlement is USDC `0.0.429274` on
|
|
156
|
+
`hedera:testnet`, through the [Blocky402](https://api.testnet.blocky402.com)
|
|
157
|
+
facilitator, which sponsors the network fee — so a paying agent carries
|
|
158
|
+
stablecoin and no HBAR.
|
|
159
|
+
|
|
160
|
+
## The limit that makes this safe
|
|
161
|
+
|
|
162
|
+
The interesting part of Warrant is not that an agent can pay. It is that it can
|
|
163
|
+
be stopped.
|
|
164
|
+
|
|
165
|
+
An owner funds an `AgentTreasury` contract on Hedera with a lifetime cap, a
|
|
166
|
+
rolling window (`$5 a day`), and an allowlist of resource kinds. The agent draws
|
|
167
|
+
from it without asking anyone, and the contract refuses an out-of-scope or
|
|
168
|
+
over-budget draw before any money moves. The refusal comes from the chain, not
|
|
169
|
+
from a vendor's database, and it holds even if this service disappears.
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
const { result } = await warrant.buy("inference", { prompt: "…" });
|
|
173
|
+
// → WarrantError: WindowCapExceeded — wanted 20000 atomic, remaining 0,
|
|
174
|
+
// reopens at 2026-09-13T13:51:27Z
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
| Contract | Address |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `AgentIdentity` | [`0xb791348d9896Bce2FA5cA724d8F548413AcbaDf6`](https://hashscan.io/testnet/contract/0xb791348d9896Bce2FA5cA724d8F548413AcbaDf6) |
|
|
180
|
+
| `ResourceMarket` | [`0x7442BdF9240e42Df0B25CedefeAF13799Fd377C0`](https://hashscan.io/testnet/contract/0x7442BdF9240e42Df0B25CedefeAF13799Fd377C0) |
|
|
181
|
+
| `AgentTreasury` | [`0xF33E2E0ecc982416f788759083129de6A147a1FE`](https://hashscan.io/testnet/contract/0xF33E2E0ecc982416f788759083129de6A147a1FE) |
|
|
182
|
+
|
|
183
|
+
Registration and listing are permissionless. Anyone may register an identity and
|
|
184
|
+
anyone may list a resource, because a registry behind an admin key is a customer
|
|
185
|
+
list, not a registry.
|
|
186
|
+
|
|
187
|
+
## Receipts
|
|
188
|
+
|
|
189
|
+
Every settled purchase is signed over a canonical digest, so it can be checked
|
|
190
|
+
without trusting this service:
|
|
26
191
|
|
|
27
192
|
```bash
|
|
28
|
-
|
|
29
|
-
|
|
193
|
+
warrant read '/v1/receipts?limit=1'
|
|
194
|
+
```
|
|
30
195
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
npx warrant read /v1/receipts?limit=3
|
|
196
|
+
```
|
|
197
|
+
digest = sha256(version|id|agent|kind|resource|amount|asset|network|settlement|issuedAt)
|
|
34
198
|
```
|
|
35
199
|
|
|
200
|
+
Rebuild the digest from the fields, recover the signer, compare it with the
|
|
201
|
+
issuer published at `/v1/contracts`, and read the settlement back from Hedera's
|
|
202
|
+
mirror node rather than from us.
|
|
203
|
+
|
|
36
204
|
## The one error that matters
|
|
37
205
|
|
|
38
|
-
A payment settles before the resource runs, so an upstream failure can happen
|
|
39
|
-
after the money moved. That comes back as a `WarrantError` with
|
|
40
|
-
and retrying it buys the failure twice.
|
|
206
|
+
A payment settles **before** the resource runs, so an upstream failure can happen
|
|
207
|
+
after the money has moved. That comes back as a `WarrantError` with
|
|
208
|
+
`settled: true`, and retrying it buys the failure twice.
|
|
41
209
|
|
|
42
210
|
```ts
|
|
211
|
+
import { WarrantError } from "warrant-client";
|
|
212
|
+
|
|
43
213
|
try {
|
|
44
214
|
await warrant.buy("email.send", { from, to, subject, body });
|
|
45
215
|
} catch (err) {
|
|
46
|
-
if (err instanceof WarrantError && err.settled) {
|
|
47
|
-
|
|
216
|
+
if (err instanceof WarrantError && err.settled) {
|
|
217
|
+
// charged, and the resource failed. Collect the receipt, do not retry.
|
|
218
|
+
}
|
|
48
219
|
}
|
|
49
220
|
```
|
|
50
221
|
|
|
51
|
-
|
|
222
|
+
`err.free` is the inverse, and is true whenever nothing was charged — a bad
|
|
223
|
+
request, a refusal by the limit, an unknown kind. Those are safe to correct and
|
|
224
|
+
repeat.
|
|
225
|
+
|
|
226
|
+
## API
|
|
227
|
+
|
|
228
|
+
| | |
|
|
229
|
+
|---|---|
|
|
230
|
+
| `new Warrant({ accountId, privateKey, baseUrl?, network? })` | A paying client. `baseUrl` defaults to the hosted service. |
|
|
231
|
+
| `warrant.offers(refresh?)` | The whole catalogue, cached after the first read. |
|
|
232
|
+
| `warrant.offer(kind)` | One offer, or `undefined`. |
|
|
233
|
+
| `warrant.buy<T>(kind, body?, agentAddress?)` | Pay for one call. Returns `{ kind, result, settlement }`. |
|
|
234
|
+
| `warrant.read<T>(path)` | Any free endpoint. |
|
|
235
|
+
|
|
236
|
+
### Environment
|
|
237
|
+
|
|
238
|
+
| Variable | What it is |
|
|
239
|
+
|---|---|
|
|
240
|
+
| `WARRANT_ACCOUNT_ID` | The Hedera account paying, e.g. `0.0.10514332`. |
|
|
241
|
+
| `WARRANT_PRIVATE_KEY` | Its private key, DER or hex. Read it from the environment; never commit it. |
|
|
242
|
+
| `WARRANT_AGENT_ADDRESS` | The agent's EVM address. Only `identity.mint` needs it. |
|
|
243
|
+
| `WARRANT_BASE_URL` | Point at a different service. Defaults to the hosted one. |
|
|
244
|
+
|
|
245
|
+
## Other ways in
|
|
52
246
|
|
|
53
|
-
|
|
54
|
-
|
|
247
|
+
- **Plain HTTP** — everything above is one `curl` and a signature away. The spec
|
|
248
|
+
is at [`/openapi.json`](https://warrant-api-production-e111.up.railway.app/openapi.json).
|
|
249
|
+
- **MCP** — the same catalogue as tools, through the gateway listed on Bazantic:
|
|
250
|
+
`https://qmt6sdhe5ffmva3zl2iagc6hkm.bazgateway.com/mcp`
|
|
251
|
+
- **Recipes** — [agent-starter-kit](https://bazantic.com/recipes/agent-starter-kit)
|
|
252
|
+
stands up a new agent end to end; [spend-audit](https://bazantic.com/recipes/spend-audit)
|
|
253
|
+
reads back what one spent and what it was refused.
|
|
254
|
+
- **Coding agents** — drop in
|
|
255
|
+
[`/skill.md`](https://warrant-api-production-e111.up.railway.app/skill.md).
|
|
55
256
|
|
|
56
|
-
|
|
57
|
-
limit, is at
|
|
58
|
-
[`/skill.md`](https://warrant-api-production-e111.up.railway.app/skill.md).
|
|
59
|
-
Source: https://github.com/martinvibes/warrant
|
|
257
|
+
## Licence
|
|
60
258
|
|
|
61
|
-
MIT.
|
|
259
|
+
MIT. Source at [github.com/martinvibes/warrant](https://github.com/martinvibes/warrant).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "warrant-client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Buy resources for an AI agent over x402 on Hedera: a name, an inbox, a phone number, inference and permanent memory, one call at a time.",
|
|
5
5
|
"keywords": ["x402", "agent", "hedera", "usdc", "pay-per-call", "ai-agent", "402"],
|
|
6
6
|
"license": "MIT",
|