@x1id/resolve 0.3.0 → 0.6.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/dist/x402.d.ts ADDED
@@ -0,0 +1,107 @@
1
+ /**
2
+ * x402 ("HTTP 402 Payment Required") payment requirements — the pure,
3
+ * dependency-free half of x1id's x402 support. Types and the
4
+ * `PaymentRequirements` builder live here; actual transaction construction
5
+ * and verification need real Solana transaction parsing (`@solana/web3.js`)
6
+ * and live in `mcp/src/x402/` instead, matching this SDK's established
7
+ * boundary (zero dependencies, no crypto/serialization — see delegate.ts's
8
+ * module docs for the same reasoning applied elsewhere).
9
+ *
10
+ * Field names and the `"exact"` scheme's wire shape are taken verbatim from
11
+ * the x402 Foundation's own SVM scheme spec
12
+ * (x402-foundation/x402, specs/schemes/exact/scheme_exact_svm.md, and the
13
+ * Go reference implementation under go/mechanisms/svm/exact/), verified
14
+ * 2026-09-22 — NOT invented. See `docs/x402.md` for the full design,
15
+ * including what's explicitly OUT of scope here (a facilitator).
16
+ *
17
+ * # The one x1id-specific choice: the network identifier
18
+ *
19
+ * x402's Solana networks use `"solana:<genesis-hash>"` (CAIP-2-shaped). X1
20
+ * is SVM-compatible but its OWN chain — not Solana — so it gets its own
21
+ * namespace under the identical convention: `"x1:<genesis-hash>"`. This is
22
+ * NOT an x402-foundation-registered network; it's a principled extension of
23
+ * their own pattern to a new SVM-compatible chain, not a claim of official
24
+ * support. {@link X1_TESTNET_NETWORK} is the live testnet genesis hash,
25
+ * verified against `getGenesisHash` 2026-09-22.
26
+ */
27
+ /** X1 testnet's x402 network identifier (`"x1:<genesis-hash>"`, verified
28
+ * live 2026-09-22 via `getGenesisHash`). */
29
+ export declare const X1_TESTNET_NETWORK = "x1:C7ucgdDEhxLTpXHhWSZxavSVmaNTUJWwT5iTdeaviDho";
30
+ /** The x402 scheme x1id implements — "exact": pay a fixed amount of a named
31
+ * asset to a named recipient. (x402 also defines "upto" for usage-based
32
+ * pricing; not implemented here.) */
33
+ export declare const X402_SCHEME_EXACT = "exact";
34
+ export declare const X402_VERSION = 2;
35
+ /** One entry of a 402 response's `accepts[]` — the SVM `"exact"` scheme's
36
+ * `PaymentRequirements`, field names verbatim from the spec. */
37
+ export interface X402PaymentRequirements {
38
+ readonly scheme: "exact";
39
+ /** `"x1:<genesis-hash>"` — see the module docs. */
40
+ readonly network: string;
41
+ /** Smallest-unit amount, as a DECIMAL STRING (e.g. lamports, or an SPL
42
+ * token's atomic units) — never a number (precision). */
43
+ readonly amount: string;
44
+ /** The SPL/Token-2022 mint's base58 address. */
45
+ readonly asset: string;
46
+ /** The recipient's base58 address (a wallet, not the token account —
47
+ * the payer derives the destination ATA from this + `asset`). */
48
+ readonly payTo: string;
49
+ readonly maxTimeoutSeconds: number;
50
+ readonly extra: {
51
+ /** The sponsor that will co-sign as fee payer, base58. REQUIRED by the
52
+ * spec for the client to build a transaction at all — x1id's v1 has
53
+ * no sponsor (see docs/x402.md): this SDK always sets it to the
54
+ * BUYER's own address (self-sponsored, no facilitator, no custody). */
55
+ readonly feePayer: string;
56
+ /** UTF-8, <=256 bytes. Lets a seller correlate the on-chain payment to
57
+ * an invoice without a unique deposit address per sale. */
58
+ readonly memo?: string;
59
+ readonly recentBlockhash?: string;
60
+ readonly lastValidBlockHeight?: string;
61
+ };
62
+ }
63
+ /** The 402 response body's `accepts[]` wrapper — what a resource server
64
+ * actually returns. */
65
+ export interface X402PaymentRequiredResponse {
66
+ readonly x402Version: typeof X402_VERSION;
67
+ readonly accepts: readonly X402PaymentRequirements[];
68
+ }
69
+ /** What the client sends back (as the `payload.transaction` field, once
70
+ * base64-encoded — see `mcp/src/x402/transaction.ts` for actually
71
+ * building and encoding one; this type documents the wire shape only). */
72
+ export interface X402PaymentPayload {
73
+ readonly x402Version: typeof X402_VERSION;
74
+ readonly accepted: X402PaymentRequirements;
75
+ readonly payload: {
76
+ /** Base64-encoded, serialized, partially-signed versioned transaction. */
77
+ readonly transaction: string;
78
+ };
79
+ }
80
+ export interface BuildX402RequirementsParams {
81
+ /** The recipient's base58 address. */
82
+ readonly payTo: string;
83
+ /** The SPL/Token-2022 mint's base58 address. */
84
+ readonly asset: string;
85
+ /** Smallest-unit amount as a decimal string. */
86
+ readonly amount: string;
87
+ /** X1id v1 has no sponsoring facilitator (see the module docs):
88
+ * the buyer pays their own transaction fee, so `extra.feePayer` is
89
+ * always set to this same buyer address. Pass the address the caller
90
+ * expects to pay from. */
91
+ readonly buyer: string;
92
+ readonly network?: string;
93
+ readonly maxTimeoutSeconds?: number;
94
+ readonly memo?: string;
95
+ readonly recentBlockhash?: string;
96
+ readonly lastValidBlockHeight?: string;
97
+ }
98
+ /**
99
+ * Build one `accepts[]` entry — the resource-server side of a 402 response.
100
+ * Pure data; does not touch chain, does not fetch a blockhash (pass
101
+ * `recentBlockhash`/`lastValidBlockHeight` if you have one fresh, or omit
102
+ * and let the buyer fetch their own — the spec allows either).
103
+ */
104
+ export declare function buildX402Requirements(p: BuildX402RequirementsParams): X402PaymentRequirements;
105
+ /** Parse a 402 response body, returning null if it doesn't look like one
106
+ * (missing/wrong `x402Version`, `accepts` not an array). Never throws. */
107
+ export declare function parseX402Response(body: unknown): X402PaymentRequiredResponse | null;
package/dist/x402.js ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * x402 ("HTTP 402 Payment Required") payment requirements — the pure,
3
+ * dependency-free half of x1id's x402 support. Types and the
4
+ * `PaymentRequirements` builder live here; actual transaction construction
5
+ * and verification need real Solana transaction parsing (`@solana/web3.js`)
6
+ * and live in `mcp/src/x402/` instead, matching this SDK's established
7
+ * boundary (zero dependencies, no crypto/serialization — see delegate.ts's
8
+ * module docs for the same reasoning applied elsewhere).
9
+ *
10
+ * Field names and the `"exact"` scheme's wire shape are taken verbatim from
11
+ * the x402 Foundation's own SVM scheme spec
12
+ * (x402-foundation/x402, specs/schemes/exact/scheme_exact_svm.md, and the
13
+ * Go reference implementation under go/mechanisms/svm/exact/), verified
14
+ * 2026-09-22 — NOT invented. See `docs/x402.md` for the full design,
15
+ * including what's explicitly OUT of scope here (a facilitator).
16
+ *
17
+ * # The one x1id-specific choice: the network identifier
18
+ *
19
+ * x402's Solana networks use `"solana:<genesis-hash>"` (CAIP-2-shaped). X1
20
+ * is SVM-compatible but its OWN chain — not Solana — so it gets its own
21
+ * namespace under the identical convention: `"x1:<genesis-hash>"`. This is
22
+ * NOT an x402-foundation-registered network; it's a principled extension of
23
+ * their own pattern to a new SVM-compatible chain, not a claim of official
24
+ * support. {@link X1_TESTNET_NETWORK} is the live testnet genesis hash,
25
+ * verified against `getGenesisHash` 2026-09-22.
26
+ */
27
+ /** X1 testnet's x402 network identifier (`"x1:<genesis-hash>"`, verified
28
+ * live 2026-09-22 via `getGenesisHash`). */
29
+ export const X1_TESTNET_NETWORK = "x1:C7ucgdDEhxLTpXHhWSZxavSVmaNTUJWwT5iTdeaviDho";
30
+ /** The x402 scheme x1id implements — "exact": pay a fixed amount of a named
31
+ * asset to a named recipient. (x402 also defines "upto" for usage-based
32
+ * pricing; not implemented here.) */
33
+ export const X402_SCHEME_EXACT = "exact";
34
+ export const X402_VERSION = 2;
35
+ /**
36
+ * Build one `accepts[]` entry — the resource-server side of a 402 response.
37
+ * Pure data; does not touch chain, does not fetch a blockhash (pass
38
+ * `recentBlockhash`/`lastValidBlockHeight` if you have one fresh, or omit
39
+ * and let the buyer fetch their own — the spec allows either).
40
+ */
41
+ export function buildX402Requirements(p) {
42
+ if (!/^\d+$/.test(p.amount)) {
43
+ throw new Error("amount must be a decimal string of smallest units (e.g. \"1000000\")");
44
+ }
45
+ if (p.memo !== undefined && new TextEncoder().encode(p.memo).length > 256) {
46
+ throw new Error("memo must be <=256 UTF-8 bytes");
47
+ }
48
+ const extra = { feePayer: p.buyer };
49
+ if (p.memo !== undefined)
50
+ extra.memo = p.memo;
51
+ if (p.recentBlockhash !== undefined) {
52
+ extra.recentBlockhash = p.recentBlockhash;
53
+ }
54
+ if (p.lastValidBlockHeight !== undefined) {
55
+ extra.lastValidBlockHeight = p.lastValidBlockHeight;
56
+ }
57
+ return {
58
+ scheme: X402_SCHEME_EXACT,
59
+ network: p.network ?? X1_TESTNET_NETWORK,
60
+ amount: p.amount,
61
+ asset: p.asset,
62
+ payTo: p.payTo,
63
+ maxTimeoutSeconds: p.maxTimeoutSeconds ?? 60,
64
+ extra,
65
+ };
66
+ }
67
+ /** Parse a 402 response body, returning null if it doesn't look like one
68
+ * (missing/wrong `x402Version`, `accepts` not an array). Never throws. */
69
+ export function parseX402Response(body) {
70
+ if (typeof body !== "object" || body === null)
71
+ return null;
72
+ const b = body;
73
+ if (b.x402Version !== X402_VERSION || !Array.isArray(b.accepts))
74
+ return null;
75
+ return { x402Version: X402_VERSION, accepts: b.accepts };
76
+ }
package/package.json CHANGED
@@ -1,34 +1,70 @@
1
1
  {
2
2
  "name": "@x1id/resolve",
3
- "version": "0.3.0",
3
+ "version": "0.6.0",
4
4
  "description": "Resolve @handles and X1NS names on X1. Never silently picks between namespaces.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": {
9
- ".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
10
13
  "./wasm/x1_resolve_wasm.wasm": "./wasm/x1_resolve_wasm.wasm",
11
14
  "./wasm/*": "./wasm/*",
12
15
  "./package.json": "./package.json"
13
16
  },
14
- "files": ["dist", "wasm", "README.md"],
17
+ "files": [
18
+ "dist",
19
+ "wasm",
20
+ "schema",
21
+ "README.md"
22
+ ],
15
23
  "scripts": {
16
24
  "build:wasm": "cargo build --release -p x1-resolve-wasm --target wasm32-unknown-unknown && cp target/wasm32-unknown-unknown/release/x1_resolve_wasm.wasm wasm/",
17
25
  "build": "tsc -p tsconfig.json",
18
26
  "test": "node --test test/*.test.js",
19
27
  "lint:package": "publint",
20
- "prepublishOnly": "cargo build --release -p x1-resolve-wasm --target wasm32-unknown-unknown --manifest-path ../Cargo.toml && node ../web/verify-wasm.mjs wasm/x1_resolve_wasm.wasm ../target/wasm32-unknown-unknown/release/x1_resolve_wasm.wasm && npm run build"
28
+ "prepublishOnly": "npm run build"
21
29
  },
22
- "keywords": ["x1", "x1id", "solana", "svm", "naming", "x1ns", "handles", "wallet", "resolver", "web3"],
30
+ "keywords": [
31
+ "x1",
32
+ "x1id",
33
+ "solana",
34
+ "svm",
35
+ "naming",
36
+ "x1ns",
37
+ "handles",
38
+ "wallet",
39
+ "resolver",
40
+ "web3"
41
+ ],
23
42
  "homepage": "https://x1id.io",
24
43
  "license": "MIT",
25
- "publishConfig": { "access": "public" },
26
- "engines": { "node": ">=18" },
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "engines": {
48
+ "node": ">=18"
49
+ },
27
50
  "devDependencies": {
28
51
  "typescript": "^5.6.0",
29
52
  "@types/node": "^22.0.0",
30
53
  "publint": "^0.2.0"
31
54
  },
32
- "peerDependencies": { "@solana/web3.js": "^1.95.0" },
33
- "peerDependenciesMeta": { "@solana/web3.js": { "optional": true } }
55
+ "peerDependencies": {
56
+ "@solana/web3.js": "^1.95.0"
57
+ },
58
+ "peerDependenciesMeta": {
59
+ "@solana/web3.js": {
60
+ "optional": true
61
+ }
62
+ },
63
+ "repository": {
64
+ "type": "git",
65
+ "url": "git+https://github.com/fortiblox/x1id-sdk.git"
66
+ },
67
+ "bugs": {
68
+ "url": "https://x1id.io"
69
+ }
34
70
  }
@@ -0,0 +1,91 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://x1id.io/schema/agent-manifest.json",
4
+ "title": "x1id agent manifest",
5
+ "description": "A machine-readable description of an @handle operating as an AI agent — what it does, how to reach it, and how to pay it. Nothing here is a payment fact: payment.addresses[] is a mirror of the on-chain address Record(s) and payment.x402 is a pre-flight hint; the chain and the live 402 response always win. See docs/agent-records.md.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["x1id"],
9
+ "properties": {
10
+ "x1id": {
11
+ "type": "object",
12
+ "additionalProperties": false,
13
+ "required": ["version", "name", "network", "handle"],
14
+ "properties": {
15
+ "version": { "const": 1 },
16
+ "name": { "type": "string", "minLength": 1, "maxLength": 260, "description": "The canonical @handle name, without the @." },
17
+ "network": { "type": "string", "enum": ["testnet", "mainnet"] },
18
+ "handle": { "type": "string", "pattern": "^[1-9A-HJ-NP-Za-km-z]{32,44}$", "description": "The Handle PDA account address, base58 — the uniqueness anchor. A manifest served for the wrong name/handle is discarded on read." }
19
+ }
20
+ },
21
+ "identity": {
22
+ "type": "object",
23
+ "additionalProperties": false,
24
+ "properties": {
25
+ "attestation": { "type": "string", "pattern": "^[1-9A-HJ-NP-Za-km-z]{32,44}$", "description": "Base58 address of a non-stale Attestation account on this handle (kind DNS or SOCIAL). See docs/agent-records.md §4 for what L1 does and does not prove." },
26
+ "description": { "type": "string", "maxLength": 2048 }
27
+ }
28
+ },
29
+ "endpoints": {
30
+ "type": "array",
31
+ "maxItems": 32,
32
+ "items": {
33
+ "type": "object",
34
+ "additionalProperties": false,
35
+ "required": ["type", "url"],
36
+ "properties": {
37
+ "type": { "type": "string", "enum": ["x402", "mcp", "a2a", "http"] },
38
+ "url": { "$ref": "#/$defs/HttpsUrl" }
39
+ }
40
+ }
41
+ },
42
+ "capabilities": {
43
+ "type": "object",
44
+ "additionalProperties": false,
45
+ "required": ["url"],
46
+ "properties": {
47
+ "schema": { "$ref": "#/$defs/HttpsUrl" },
48
+ "url": { "$ref": "#/$defs/HttpsUrl" }
49
+ }
50
+ },
51
+ "payment": {
52
+ "type": "object",
53
+ "additionalProperties": false,
54
+ "properties": {
55
+ "addresses": {
56
+ "type": "array",
57
+ "maxItems": 16,
58
+ "items": {
59
+ "type": "object",
60
+ "additionalProperties": false,
61
+ "required": ["coinType", "address"],
62
+ "properties": {
63
+ "coinType": { "type": "integer", "minimum": 0 },
64
+ "address": { "type": "string", "minLength": 1, "maxLength": 128 },
65
+ "verified": { "type": "boolean" }
66
+ }
67
+ }
68
+ },
69
+ "x402": {
70
+ "type": "object",
71
+ "additionalProperties": false,
72
+ "required": ["network"],
73
+ "properties": {
74
+ "network": { "type": "string", "minLength": 1, "description": "e.g. \"x1-testnet\" or \"x1-mainnet\" — an x1id-defined network tag, not a CAIP-2 EVM chain id." },
75
+ "asset": { "type": "string", "maxLength": 128 },
76
+ "scheme": { "type": "string", "minLength": 1, "maxLength": 32 },
77
+ "facilitator": { "$ref": "#/$defs/HttpsUrl" },
78
+ "extra": { "type": "object" }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ },
84
+ "$defs": {
85
+ "HttpsUrl": {
86
+ "type": "string",
87
+ "pattern": "^https://[^\\s@/]+(/[^\\s]*)?$",
88
+ "maxLength": 2048
89
+ }
90
+ }
91
+ }
Binary file