inamprotocol 0.19.0 → 0.21.0
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 +60 -0
- package/dist/aiSdk.d.ts +16 -16
- package/dist/check.d.ts +115 -0
- package/dist/check.js +391 -0
- package/dist/check.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +40 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +13 -2
- package/dist/client.js +31 -9
- package/dist/client.js.map +1 -1
- package/dist/core/schemas.d.ts +4 -4
- package/dist/http.d.ts +9 -0
- package/dist/http.js +4 -0
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/webBotAuth.d.ts +53 -0
- package/dist/webBotAuth.js +127 -0
- package/dist/webBotAuth.js.map +1 -0
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -10,6 +10,48 @@ This package is a standalone build of the same crypto/client code the [Node refe
|
|
|
10
10
|
npm install inamprotocol
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
## inam check before you pay
|
|
14
|
+
|
|
15
|
+
One command, no key, no INAM account, and useful even when nobody involved uses INAM:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
npx inamprotocol check https://x402.coinstats.app/markets # an x402 resource
|
|
19
|
+
npx inamprotocol check 0x89e9e1ab11dd1b138b1dce6d6a4a0926aafd5029 # a payTo wallet
|
|
20
|
+
npx inamprotocol check did:key:z6MkpSvw1Yuc3ReWhCmt5RwY5LVZqMRY9p8NvpA2TSQCPPyK # an INAM agent
|
|
21
|
+
npx inamprotocol check https://seller.example/api --method POST --json
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
inam check https://x402.coinstats.app/markets
|
|
26
|
+
|
|
27
|
+
verdict CAUTION nothing failed, but some signals are missing; read the [warn] lines before paying
|
|
28
|
+
|
|
29
|
+
payment requirements
|
|
30
|
+
resource https://x402.coinstats.app/markets
|
|
31
|
+
about CoinStats global cryptocurrency market data — total market cap, 24h volume, BTC dominance, % changes
|
|
32
|
+
payTo 0xa2AD8183209E5d2F7f0d8F995f5601a0bb5100c7 0.001 USD Coin on Base (eip155:8453)
|
|
33
|
+
|
|
34
|
+
checks
|
|
35
|
+
[ ok ] HTTPS, certificate accepted
|
|
36
|
+
[ ok ] 402 with 1 payment option (x402 v2)
|
|
37
|
+
[warn] No ERC-8004 identity owned by 0xa2AD81…00c7 (on-chain on Base: 0)
|
|
38
|
+
[warn] 0xa2AD81…00c7 is not linked to any INAM ID
|
|
39
|
+
[info] No Web Bot Auth key directory (HTTP 404)
|
|
40
|
+
[ ok ] coinstats.app registered 2018-05-08 (3076 days ago)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
What it checks:
|
|
44
|
+
|
|
45
|
+
| Target | Signals |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| x402 URL | Fetches it without paying and parses the 402 (v2 `PAYMENT-REQUIRED` header or v1 body): payTo, network, asset, amount, resource, description. Then, per EVM payTo, everything a wallet gets. Plus: the `inam` extension's ID must have proven that payTo (else FAIL), HTTPS, a Web Bot Auth key directory at `/.well-known/http-message-signatures-directory` (signature verified), and the domain's RDAP registration date (shared hosts like `*.workers.dev` are labelled as such). |
|
|
48
|
+
| `0x` wallet | ERC-8004: agents it owns (8004scan index, all chains) and `balanceOf` on the chain's Identity Registry; feedback from the Reputation Registry, with feedback tagged `inam-receipt` counted as tied to a delivered task (SPEC.md §11.1). INAM: whether an INAM ID proved control of the wallet, and that ID's receipts and evidence level. |
|
|
49
|
+
| `did:key` | INAM registration, revocation, evidence level and receipts (`checkTrust`'s allow / escrow / deny), and ERC-8004 for its proven wallet. |
|
|
50
|
+
|
|
51
|
+
The verdict is the worst line, not a score: `FAIL` (exit 1) when a key check fails, such as no 402, unreadable payment requirements, plain http, an unknown or revoked ID, or a borrowed INAM ID whose proven wallet is not the payTo. `CAUTION` (exit 0, exit 1 with `--strict`) when signals are missing. `PASS` otherwise. Exit 2 on bad usage.
|
|
52
|
+
|
|
53
|
+
Use it as a gate before paying or in CI: `npx inamprotocol check "$URL" --strict || exit 1`. Programmatic use: `checkTarget(target, opts)` returns the same report (`formatReport(report)` prints it). On-chain reads use keyless public RPCs (Ethereum, Base, Base Sepolia); set `INAM_RPC_<chainId>` to use your own. `npx inam check` also works once `inamprotocol` is installed in the project or globally; without it, `npx inam` would fetch an unrelated package of that name.
|
|
54
|
+
|
|
13
55
|
## Usage
|
|
14
56
|
|
|
15
57
|
```ts
|
|
@@ -118,6 +160,24 @@ await inam.settle(); // countersigns run in the background; wait before a server
|
|
|
118
160
|
|
|
119
161
|
The requester only countersigns when the receipt's hashes match the exact request it sent and response it received. That confirms delivery, not quality; pass `accept: (res, receipt) => ...` to `inamFetch` to run your own check first.
|
|
120
162
|
|
|
163
|
+
### Web Bot Auth (signed agent requests)
|
|
164
|
+
|
|
165
|
+
Origins behind Cloudflare can recognize your agent by signature instead of User-Agent or IP. Opt in on `inamFetch`, and every request is signed with the agent's own Ed25519 key (HTTP Message Signatures, RFC 9421, Web Bot Auth profile):
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
const inam = inamFetch(client, { webBotAuth: { signatureAgent: "https://agent.example" } });
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`signatureAgent` is the https origin that serves your key directory. Serve it from there:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
// GET https://agent.example/.well-known/http-message-signatures-directory
|
|
175
|
+
const { body, headers } = client.webBotAuthDirectory(new URL(req.url).host);
|
|
176
|
+
return new Response(body, { headers });
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Signatures expire after 60 seconds (`expiresIn` to change). `Signature-Agent` uses the structured-string form Cloudflare accepts. Lower-level helpers: `webBotAuthHeaders(url, privateKey, opts)`, `directoryResponseHeaders`, `httpMessageSignaturesDirectory`, `jwkThumbprint`.
|
|
180
|
+
|
|
121
181
|
## Vercel AI SDK tools
|
|
122
182
|
|
|
123
183
|
```ts
|
package/dist/aiSdk.d.ts
CHANGED
|
@@ -509,19 +509,19 @@ export declare function inamTools(options?: {
|
|
|
509
509
|
};
|
|
510
510
|
output: NoInfer<{
|
|
511
511
|
receipt: import("./types.js").ExecutionReceipt;
|
|
512
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
512
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
513
513
|
}>;
|
|
514
514
|
}) => import("@ai-sdk/provider-utils").ToolResultOutput | PromiseLike<import("@ai-sdk/provider-utils").ToolResultOutput>) | undefined;
|
|
515
515
|
} & {
|
|
516
516
|
outputSchema?: import("ai").FlexibleSchema<{
|
|
517
517
|
receipt: import("./types.js").ExecutionReceipt;
|
|
518
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
518
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
519
519
|
}> | undefined;
|
|
520
520
|
execute: import("ai").ToolExecuteFunction<{
|
|
521
521
|
receiptId: string;
|
|
522
522
|
}, {
|
|
523
523
|
receipt: import("./types.js").ExecutionReceipt;
|
|
524
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
524
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
525
525
|
}, NoInfer<import("@ai-sdk/provider-utils").Context>>;
|
|
526
526
|
} & {
|
|
527
527
|
description?: string | ((options: {
|
|
@@ -545,7 +545,7 @@ export declare function inamTools(options?: {
|
|
|
545
545
|
receiptId: string;
|
|
546
546
|
}, {
|
|
547
547
|
receipt: import("./types.js").ExecutionReceipt;
|
|
548
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
548
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
549
549
|
}, NoInfer<import("@ai-sdk/provider-utils").Context>>;
|
|
550
550
|
}) | ({
|
|
551
551
|
deferLoading?: boolean;
|
|
@@ -575,19 +575,19 @@ export declare function inamTools(options?: {
|
|
|
575
575
|
};
|
|
576
576
|
output: NoInfer<{
|
|
577
577
|
receipt: import("./types.js").ExecutionReceipt;
|
|
578
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
578
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
579
579
|
}>;
|
|
580
580
|
}) => import("@ai-sdk/provider-utils").ToolResultOutput | PromiseLike<import("@ai-sdk/provider-utils").ToolResultOutput>) | undefined;
|
|
581
581
|
} & {
|
|
582
582
|
outputSchema?: import("ai").FlexibleSchema<{
|
|
583
583
|
receipt: import("./types.js").ExecutionReceipt;
|
|
584
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
584
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
585
585
|
}> | undefined;
|
|
586
586
|
execute: import("ai").ToolExecuteFunction<{
|
|
587
587
|
receiptId: string;
|
|
588
588
|
}, {
|
|
589
589
|
receipt: import("./types.js").ExecutionReceipt;
|
|
590
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
590
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
591
591
|
}, NoInfer<import("@ai-sdk/provider-utils").Context>>;
|
|
592
592
|
} & {
|
|
593
593
|
description?: string | ((options: {
|
|
@@ -611,7 +611,7 @@ export declare function inamTools(options?: {
|
|
|
611
611
|
receiptId: string;
|
|
612
612
|
}, {
|
|
613
613
|
receipt: import("./types.js").ExecutionReceipt;
|
|
614
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
614
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
615
615
|
}, NoInfer<import("@ai-sdk/provider-utils").Context>>;
|
|
616
616
|
}) | ({
|
|
617
617
|
deferLoading?: boolean;
|
|
@@ -641,19 +641,19 @@ export declare function inamTools(options?: {
|
|
|
641
641
|
};
|
|
642
642
|
output: NoInfer<{
|
|
643
643
|
receipt: import("./types.js").ExecutionReceipt;
|
|
644
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
644
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
645
645
|
}>;
|
|
646
646
|
}) => import("@ai-sdk/provider-utils").ToolResultOutput | PromiseLike<import("@ai-sdk/provider-utils").ToolResultOutput>) | undefined;
|
|
647
647
|
} & {
|
|
648
648
|
outputSchema?: import("ai").FlexibleSchema<{
|
|
649
649
|
receipt: import("./types.js").ExecutionReceipt;
|
|
650
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
650
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
651
651
|
}> | undefined;
|
|
652
652
|
execute: import("ai").ToolExecuteFunction<{
|
|
653
653
|
receiptId: string;
|
|
654
654
|
}, {
|
|
655
655
|
receipt: import("./types.js").ExecutionReceipt;
|
|
656
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
656
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
657
657
|
}, NoInfer<import("@ai-sdk/provider-utils").Context>>;
|
|
658
658
|
} & {
|
|
659
659
|
type: "provider";
|
|
@@ -670,7 +670,7 @@ export declare function inamTools(options?: {
|
|
|
670
670
|
receiptId: string;
|
|
671
671
|
}, {
|
|
672
672
|
receipt: import("./types.js").ExecutionReceipt;
|
|
673
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
673
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
674
674
|
}, NoInfer<import("@ai-sdk/provider-utils").Context>>;
|
|
675
675
|
}) | ({
|
|
676
676
|
deferLoading?: boolean;
|
|
@@ -700,19 +700,19 @@ export declare function inamTools(options?: {
|
|
|
700
700
|
};
|
|
701
701
|
output: NoInfer<{
|
|
702
702
|
receipt: import("./types.js").ExecutionReceipt;
|
|
703
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
703
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
704
704
|
}>;
|
|
705
705
|
}) => import("@ai-sdk/provider-utils").ToolResultOutput | PromiseLike<import("@ai-sdk/provider-utils").ToolResultOutput>) | undefined;
|
|
706
706
|
} & {
|
|
707
707
|
outputSchema?: import("ai").FlexibleSchema<{
|
|
708
708
|
receipt: import("./types.js").ExecutionReceipt;
|
|
709
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
709
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
710
710
|
}> | undefined;
|
|
711
711
|
execute: import("ai").ToolExecuteFunction<{
|
|
712
712
|
receiptId: string;
|
|
713
713
|
}, {
|
|
714
714
|
receipt: import("./types.js").ExecutionReceipt;
|
|
715
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
715
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
716
716
|
}, NoInfer<import("@ai-sdk/provider-utils").Context>>;
|
|
717
717
|
} & {
|
|
718
718
|
type: "provider";
|
|
@@ -729,7 +729,7 @@ export declare function inamTools(options?: {
|
|
|
729
729
|
receiptId: string;
|
|
730
730
|
}, {
|
|
731
731
|
receipt: import("./types.js").ExecutionReceipt;
|
|
732
|
-
verifications: import("./types.js").VerificationRecord[]
|
|
732
|
+
verifications: never[] | import("./types.js").VerificationRecord[];
|
|
733
733
|
}, NoInfer<import("@ai-sdk/provider-utils").Context>>;
|
|
734
734
|
});
|
|
735
735
|
};
|
package/dist/check.d.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/** `inam check <url | 0x wallet | did:key>`: a pre-payment check built from public signals.
|
|
2
|
+
*
|
|
3
|
+
* Useful with no INAM data at all: it reads the x402 402 response, asks ERC-8004 (on-chain
|
|
4
|
+
* through a public RPC, plus the 8004scan indexer for the reverse lookup by owner), looks for a
|
|
5
|
+
* Web Bot Auth key directory and the domain's RDAP registration date, and adds INAM's wallet
|
|
6
|
+
* link and receipts when they exist. It reports what it found, not a score. */
|
|
7
|
+
export type CheckStatus = "pass" | "warn" | "fail" | "info";
|
|
8
|
+
export interface CheckItem {
|
|
9
|
+
id: string;
|
|
10
|
+
status: CheckStatus;
|
|
11
|
+
label: string;
|
|
12
|
+
detail?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface PaymentOption {
|
|
15
|
+
scheme?: string;
|
|
16
|
+
network: string;
|
|
17
|
+
chainId: number | null;
|
|
18
|
+
asset?: string;
|
|
19
|
+
amount?: string;
|
|
20
|
+
/** Human price when the asset is a known 6-decimal USD stablecoin. */
|
|
21
|
+
price?: string;
|
|
22
|
+
payTo: string;
|
|
23
|
+
testnet: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface CheckReport {
|
|
26
|
+
target: string;
|
|
27
|
+
kind: "url" | "wallet" | "did";
|
|
28
|
+
/** Worst status among the checks: any fail is "fail", any warn is "caution". */
|
|
29
|
+
verdict: "pass" | "caution" | "fail";
|
|
30
|
+
checkedAt: string;
|
|
31
|
+
payment?: {
|
|
32
|
+
x402Version?: number;
|
|
33
|
+
status: number;
|
|
34
|
+
resource?: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
accepts: PaymentOption[];
|
|
37
|
+
inamDid?: string;
|
|
38
|
+
};
|
|
39
|
+
checks: CheckItem[];
|
|
40
|
+
}
|
|
41
|
+
export interface CheckOptions {
|
|
42
|
+
registryUrl?: string;
|
|
43
|
+
/** ERC-8004 indexer used for the reverse lookup by owner (no on-chain index exists). */
|
|
44
|
+
indexerUrl?: string;
|
|
45
|
+
/** chainId -> JSON-RPC URL; merged over the public defaults. */
|
|
46
|
+
rpc?: Record<number, string>;
|
|
47
|
+
method?: string;
|
|
48
|
+
timeoutMs?: number;
|
|
49
|
+
/** wallet (lowercase) -> INAM ID, if the caller already listed linked agents (the bulk scan does). */
|
|
50
|
+
linkedWallets?: Map<string, string>;
|
|
51
|
+
/** Skip the RDAP domain-age lookup. */
|
|
52
|
+
noRdap?: boolean;
|
|
53
|
+
/** Retries after HTTP 429 from the indexer and RDAP (default 1). The bulk scan raises it. */
|
|
54
|
+
retries?: number;
|
|
55
|
+
}
|
|
56
|
+
export declare const ERC8004: {
|
|
57
|
+
identity: {
|
|
58
|
+
mainnet: string;
|
|
59
|
+
testnet: string;
|
|
60
|
+
};
|
|
61
|
+
reputation: {
|
|
62
|
+
mainnet: string;
|
|
63
|
+
testnet: string;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
/** Keyless public RPCs. Other chains are covered by the indexer only, or by `rpc` / INAM_RPC_<chainId>. */
|
|
67
|
+
export declare const DEFAULT_RPC: Record<number, string>;
|
|
68
|
+
export declare const SHARED_HOSTING: RegExp;
|
|
69
|
+
export declare const isEvmAddress: (a: string) => boolean;
|
|
70
|
+
export declare const chainIdOf: (network: string) => number | null;
|
|
71
|
+
/** Payment requirements from a 402: the v2 PAYMENT-REQUIRED header, or the v1 JSON body. */
|
|
72
|
+
export declare function parsePaymentRequired(headers: Headers, body: string): any | null;
|
|
73
|
+
export declare function paymentOptions(required: any): PaymentOption[];
|
|
74
|
+
export declare function erc8004Balance(rpc: string, chainId: number, wallet: string, timeoutMs?: number): Promise<number>;
|
|
75
|
+
/** Feedback on one agent from the Reputation Registry: all of it, and the part tagged as INAM-receipt-backed (SPEC.md §11.1). */
|
|
76
|
+
export declare function erc8004Feedback(rpc: string, chainId: number, agentId: number, timeoutMs?: number): Promise<{
|
|
77
|
+
total: number;
|
|
78
|
+
receiptBacked: number;
|
|
79
|
+
}>;
|
|
80
|
+
export interface Erc8004Agent {
|
|
81
|
+
chainId: number;
|
|
82
|
+
agentId: number;
|
|
83
|
+
name?: string;
|
|
84
|
+
feedbacks: number;
|
|
85
|
+
testnet: boolean;
|
|
86
|
+
}
|
|
87
|
+
/** Agents a wallet owns, from the indexer (on-chain ERC-721 has no enumeration by owner). */
|
|
88
|
+
export declare function erc8004AgentsByOwner(indexerUrl: string, wallet: string, timeoutMs?: number, retries?: number): Promise<Erc8004Agent[]>;
|
|
89
|
+
export interface WalletErc8004 {
|
|
90
|
+
agents: Erc8004Agent[] | null;
|
|
91
|
+
onchain: {
|
|
92
|
+
chainId: number;
|
|
93
|
+
balance: number;
|
|
94
|
+
} | null;
|
|
95
|
+
feedback: {
|
|
96
|
+
total: number;
|
|
97
|
+
receiptBacked: number;
|
|
98
|
+
source: "onchain" | "indexer";
|
|
99
|
+
} | null;
|
|
100
|
+
errors: string[];
|
|
101
|
+
}
|
|
102
|
+
export declare function walletErc8004(wallet: string, chainId: number | null, opts?: CheckOptions): Promise<WalletErc8004>;
|
|
103
|
+
/** Every INAM agent with a proven EVM wallet (`linked.erc8004_id`), keyed by lowercase wallet. The registry has no lookup by wallet. */
|
|
104
|
+
export declare function inamLinkedWallets(registryUrl?: string, timeoutMs?: number): Promise<Map<string, string>>;
|
|
105
|
+
export declare function directoryItem(origin: string, timeoutMs?: number): Promise<CheckItem>;
|
|
106
|
+
/** Last two labels, or three under a two-letter ccTLD's co/com/org/net/ac/gov/edu. */
|
|
107
|
+
export declare function registrableDomain(host: string): string;
|
|
108
|
+
export declare function domainItem(host: string, timeoutMs?: number, retries?: number): Promise<CheckItem>;
|
|
109
|
+
export declare function checkWallet(wallet: string, opts?: CheckOptions & {
|
|
110
|
+
chainId?: number | null;
|
|
111
|
+
}): Promise<CheckReport>;
|
|
112
|
+
export declare function checkDid(did: string, opts?: CheckOptions): Promise<CheckReport>;
|
|
113
|
+
export declare function checkUrl(url: string, opts?: CheckOptions): Promise<CheckReport>;
|
|
114
|
+
export declare function checkTarget(target: string, opts?: CheckOptions): Promise<CheckReport>;
|
|
115
|
+
export declare function formatReport(r: CheckReport): string;
|