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 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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
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[] | never[];
732
+ verifications: never[] | import("./types.js").VerificationRecord[];
733
733
  }, NoInfer<import("@ai-sdk/provider-utils").Context>>;
734
734
  });
735
735
  };
@@ -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;