@stellar-agent-services/provider-kit 0.0.0-stage → 0.1.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.
Files changed (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +506 -2
  3. package/dist/approve/assets/index-BazIJAI2.css +1 -0
  4. package/dist/approve/assets/index-CL28cSJy.js +420 -0
  5. package/dist/approve/favicon.svg +1 -0
  6. package/dist/approve/index.html +18 -0
  7. package/dist/cli/approval-view.d.ts +80 -0
  8. package/dist/cli/approval-view.d.ts.map +1 -0
  9. package/dist/cli/approval-view.js +5 -0
  10. package/dist/cli/approval-view.js.map +1 -0
  11. package/dist/cli/approval.d.ts +132 -0
  12. package/dist/cli/approval.d.ts.map +1 -0
  13. package/dist/cli/approval.js +542 -0
  14. package/dist/cli/approval.js.map +1 -0
  15. package/dist/cli/check.d.ts +3 -0
  16. package/dist/cli/check.d.ts.map +1 -0
  17. package/dist/cli/check.js +137 -0
  18. package/dist/cli/check.js.map +1 -0
  19. package/dist/cli/dev-account.d.ts +28 -0
  20. package/dist/cli/dev-account.d.ts.map +1 -0
  21. package/dist/cli/dev-account.js +62 -0
  22. package/dist/cli/dev-account.js.map +1 -0
  23. package/dist/cli/dev.d.ts +27 -0
  24. package/dist/cli/dev.d.ts.map +1 -0
  25. package/dist/cli/dev.js +226 -0
  26. package/dist/cli/dev.js.map +1 -0
  27. package/dist/cli/discovery.d.ts +20 -0
  28. package/dist/cli/discovery.d.ts.map +1 -0
  29. package/dist/cli/discovery.js +202 -0
  30. package/dist/cli/discovery.js.map +1 -0
  31. package/dist/cli/env-file.d.ts +16 -0
  32. package/dist/cli/env-file.d.ts.map +1 -0
  33. package/dist/cli/env-file.js +77 -0
  34. package/dist/cli/env-file.js.map +1 -0
  35. package/dist/cli/fly.d.ts +28 -0
  36. package/dist/cli/fly.d.ts.map +1 -0
  37. package/dist/cli/fly.js +92 -0
  38. package/dist/cli/fly.js.map +1 -0
  39. package/dist/cli/index.d.ts +3 -0
  40. package/dist/cli/index.d.ts.map +1 -0
  41. package/dist/cli/index.js +11 -0
  42. package/dist/cli/index.js.map +1 -0
  43. package/dist/cli/init.d.ts +3 -0
  44. package/dist/cli/init.d.ts.map +1 -0
  45. package/dist/cli/init.js +170 -0
  46. package/dist/cli/init.js.map +1 -0
  47. package/dist/cli/launch.d.ts +21 -0
  48. package/dist/cli/launch.d.ts.map +1 -0
  49. package/dist/cli/launch.js +627 -0
  50. package/dist/cli/launch.js.map +1 -0
  51. package/dist/cli/main.d.ts +2 -0
  52. package/dist/cli/main.d.ts.map +1 -0
  53. package/dist/cli/main.js +158 -0
  54. package/dist/cli/main.js.map +1 -0
  55. package/dist/cli/owner-chain.d.ts +88 -0
  56. package/dist/cli/owner-chain.d.ts.map +1 -0
  57. package/dist/cli/owner-chain.js +284 -0
  58. package/dist/cli/owner-chain.js.map +1 -0
  59. package/dist/cli/owner-steps.d.ts +33 -0
  60. package/dist/cli/owner-steps.d.ts.map +1 -0
  61. package/dist/cli/owner-steps.js +121 -0
  62. package/dist/cli/owner-steps.js.map +1 -0
  63. package/dist/cli/processes.d.ts +47 -0
  64. package/dist/cli/processes.d.ts.map +1 -0
  65. package/dist/cli/processes.js +129 -0
  66. package/dist/cli/processes.js.map +1 -0
  67. package/dist/cli/reconcile.d.ts +3 -0
  68. package/dist/cli/reconcile.d.ts.map +1 -0
  69. package/dist/cli/reconcile.js +76 -0
  70. package/dist/cli/reconcile.js.map +1 -0
  71. package/dist/cli/register.d.ts +9 -0
  72. package/dist/cli/register.d.ts.map +1 -0
  73. package/dist/cli/register.js +209 -0
  74. package/dist/cli/register.js.map +1 -0
  75. package/dist/cli/request-validation.d.ts +5 -0
  76. package/dist/cli/request-validation.d.ts.map +1 -0
  77. package/dist/cli/request-validation.js +144 -0
  78. package/dist/cli/request-validation.js.map +1 -0
  79. package/dist/cli/serve.d.ts +25 -0
  80. package/dist/cli/serve.d.ts.map +1 -0
  81. package/dist/cli/serve.js +73 -0
  82. package/dist/cli/serve.js.map +1 -0
  83. package/dist/cli/shared.d.ts +142 -0
  84. package/dist/cli/shared.d.ts.map +1 -0
  85. package/dist/cli/shared.js +110 -0
  86. package/dist/cli/shared.js.map +1 -0
  87. package/dist/cli/status.d.ts +32 -0
  88. package/dist/cli/status.d.ts.map +1 -0
  89. package/dist/cli/status.js +248 -0
  90. package/dist/cli/status.js.map +1 -0
  91. package/dist/cli/target.d.ts +14 -0
  92. package/dist/cli/target.d.ts.map +1 -0
  93. package/dist/cli/target.js +43 -0
  94. package/dist/cli/target.js.map +1 -0
  95. package/dist/cli/trustline.d.ts +3 -0
  96. package/dist/cli/trustline.d.ts.map +1 -0
  97. package/dist/cli/trustline.js +114 -0
  98. package/dist/cli/trustline.js.map +1 -0
  99. package/dist/cli/try.d.ts +54 -0
  100. package/dist/cli/try.d.ts.map +1 -0
  101. package/dist/cli/try.js +448 -0
  102. package/dist/cli/try.js.map +1 -0
  103. package/dist/cli/tunnel.d.ts +13 -0
  104. package/dist/cli/tunnel.d.ts.map +1 -0
  105. package/dist/cli/tunnel.js +43 -0
  106. package/dist/cli/tunnel.js.map +1 -0
  107. package/dist/cli/validators.d.ts +6 -0
  108. package/dist/cli/validators.d.ts.map +1 -0
  109. package/dist/cli/validators.js +14 -0
  110. package/dist/cli/validators.js.map +1 -0
  111. package/dist/define-service.d.ts +71 -0
  112. package/dist/define-service.d.ts.map +1 -0
  113. package/dist/define-service.js +86 -0
  114. package/dist/define-service.js.map +1 -0
  115. package/dist/gateway/config.d.ts +88 -0
  116. package/dist/gateway/config.d.ts.map +1 -0
  117. package/dist/gateway/config.js +201 -0
  118. package/dist/gateway/config.js.map +1 -0
  119. package/dist/gateway/openapi.d.ts +69 -0
  120. package/dist/gateway/openapi.d.ts.map +1 -0
  121. package/dist/gateway/openapi.js +677 -0
  122. package/dist/gateway/openapi.js.map +1 -0
  123. package/dist/gateway/upstream.d.ts +15 -0
  124. package/dist/gateway/upstream.d.ts.map +1 -0
  125. package/dist/gateway/upstream.js +95 -0
  126. package/dist/gateway/upstream.js.map +1 -0
  127. package/dist/http/bounded.d.ts +3 -0
  128. package/dist/http/bounded.d.ts.map +1 -0
  129. package/dist/http/bounded.js +23 -0
  130. package/dist/http/bounded.js.map +1 -0
  131. package/dist/http/node-server.d.ts +15 -0
  132. package/dist/http/node-server.d.ts.map +1 -0
  133. package/dist/http/node-server.js +120 -0
  134. package/dist/http/node-server.js.map +1 -0
  135. package/dist/http/rate-limit.d.ts +11 -0
  136. package/dist/http/rate-limit.d.ts.map +1 -0
  137. package/dist/http/rate-limit.js +35 -0
  138. package/dist/http/rate-limit.js.map +1 -0
  139. package/dist/http/router.d.ts +29 -0
  140. package/dist/http/router.d.ts.map +1 -0
  141. package/dist/http/router.js +329 -0
  142. package/dist/http/router.js.map +1 -0
  143. package/dist/index.d.ts +20 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +31 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/jobs/memory-store.d.ts +3 -0
  148. package/dist/jobs/memory-store.d.ts.map +1 -0
  149. package/dist/jobs/memory-store.js +121 -0
  150. package/dist/jobs/memory-store.js.map +1 -0
  151. package/dist/jobs/reconcile.d.ts +22 -0
  152. package/dist/jobs/reconcile.d.ts.map +1 -0
  153. package/dist/jobs/reconcile.js +82 -0
  154. package/dist/jobs/reconcile.js.map +1 -0
  155. package/dist/jobs/recovery.d.ts +19 -0
  156. package/dist/jobs/recovery.d.ts.map +1 -0
  157. package/dist/jobs/recovery.js +65 -0
  158. package/dist/jobs/recovery.js.map +1 -0
  159. package/dist/jobs/runner.d.ts +38 -0
  160. package/dist/jobs/runner.d.ts.map +1 -0
  161. package/dist/jobs/runner.js +194 -0
  162. package/dist/jobs/runner.js.map +1 -0
  163. package/dist/jobs/scheduler.d.ts +66 -0
  164. package/dist/jobs/scheduler.d.ts.map +1 -0
  165. package/dist/jobs/scheduler.js +197 -0
  166. package/dist/jobs/scheduler.js.map +1 -0
  167. package/dist/jobs/sqlite-store.d.ts +8 -0
  168. package/dist/jobs/sqlite-store.d.ts.map +1 -0
  169. package/dist/jobs/sqlite-store.js +231 -0
  170. package/dist/jobs/sqlite-store.js.map +1 -0
  171. package/dist/jobs/store.d.ts +118 -0
  172. package/dist/jobs/store.d.ts.map +1 -0
  173. package/dist/jobs/store.js +36 -0
  174. package/dist/jobs/store.js.map +1 -0
  175. package/dist/manifest.d.ts +11 -0
  176. package/dist/manifest.d.ts.map +1 -0
  177. package/dist/manifest.js +99 -0
  178. package/dist/manifest.js.map +1 -0
  179. package/dist/payments/chain.d.ts +23 -0
  180. package/dist/payments/chain.d.ts.map +1 -0
  181. package/dist/payments/chain.js +108 -0
  182. package/dist/payments/chain.js.map +1 -0
  183. package/dist/payments/facilitator.d.ts +44 -0
  184. package/dist/payments/facilitator.d.ts.map +1 -0
  185. package/dist/payments/facilitator.js +125 -0
  186. package/dist/payments/facilitator.js.map +1 -0
  187. package/dist/payments/onchain.d.ts +36 -0
  188. package/dist/payments/onchain.d.ts.map +1 -0
  189. package/dist/payments/onchain.js +191 -0
  190. package/dist/payments/onchain.js.map +1 -0
  191. package/dist/payments/payload-checks.d.ts +22 -0
  192. package/dist/payments/payload-checks.d.ts.map +1 -0
  193. package/dist/payments/payload-checks.js +113 -0
  194. package/dist/payments/payload-checks.js.map +1 -0
  195. package/dist/payments/settlement.d.ts +22 -0
  196. package/dist/payments/settlement.d.ts.map +1 -0
  197. package/dist/payments/settlement.js +65 -0
  198. package/dist/payments/settlement.js.map +1 -0
  199. package/dist/payments/x402-server.d.ts +8 -0
  200. package/dist/payments/x402-server.d.ts.map +1 -0
  201. package/dist/payments/x402-server.js +74 -0
  202. package/dist/payments/x402-server.js.map +1 -0
  203. package/dist/provider.d.ts +63 -0
  204. package/dist/provider.d.ts.map +1 -0
  205. package/dist/provider.js +177 -0
  206. package/dist/provider.js.map +1 -0
  207. package/dist/registration.d.ts +86 -0
  208. package/dist/registration.d.ts.map +1 -0
  209. package/dist/registration.js +162 -0
  210. package/dist/registration.js.map +1 -0
  211. package/dist/testing.d.ts +13 -0
  212. package/dist/testing.d.ts.map +1 -0
  213. package/dist/testing.js +48 -0
  214. package/dist/testing.js.map +1 -0
  215. package/dist/validation-request.d.ts +36 -0
  216. package/dist/validation-request.d.ts.map +1 -0
  217. package/dist/validation-request.js +101 -0
  218. package/dist/validation-request.js.map +1 -0
  219. package/package.json +55 -4
  220. package/schemas/gateway-config.schema.json +140 -0
@@ -0,0 +1,177 @@
1
+ // createProvider(): wires services, payments, the job store, the queue and the HTTP routes into one
2
+ // Fetch-API handler.
3
+ //
4
+ // Returns { fetch(request) } for Hono, Node, Workers, Deno or Bun. The provider holds no Stellar
5
+ // secret key: it knows its payTo address, and the facilitator verifies and settles.
6
+ //
7
+ // Startup, in order:
8
+ // 1. createProvider() checks the config and the manifest it builds, and throws on any problem a client
9
+ // or verifier would reject (§2.4), so a broken provider never takes a payment.
10
+ // 2. ready() checks that the facilitator settles this network with sponsored fees, runs the recovery
11
+ // sweep for jobs a restart left behind, and starts the queue's workers. create-job awaits it, and
12
+ // answers 503 (nothing charged) until it has succeeded; it is retried after a failure.
13
+ // Each service gets a lane with its capacity (jobs/scheduler.ts), and create-job can have a per-caller
14
+ // rate limit (http/rate-limit.ts): docs/provider-standard.md §5.8.
15
+ //
16
+ // With a Soroban RPC (`rpc`, the public one by default on testnet), the provider reads the chain: it
17
+ // decides payment_uncertain jobs after every sweep (jobs/reconcile.ts) [J13], and times on-success jobs
18
+ // by their payment's expiration ledger (payments/chain.ts). Neither holds up startup or a request when
19
+ // the RPC is slow or down.
20
+ import { hostname } from "node:os";
21
+ import { randomUUID } from "node:crypto";
22
+ import { DEFAULT_MANIFEST_PATH, DEFAULT_RETENTION_SECONDS, stellarAddressKind } from "@stellar-agent-services/protocol";
23
+ import { rateLimiter } from "./http/rate-limit.js";
24
+ import { MAX_HOLD_SECONDS, route } from "./http/router.js";
25
+ import { memoryStore } from "./jobs/memory-store.js";
26
+ import { reconcile } from "./jobs/reconcile.js";
27
+ import { strandedJobs, sweep } from "./jobs/recovery.js";
28
+ import { runLeased } from "./jobs/runner.js";
29
+ import { laneFor, scheduler } from "./jobs/scheduler.js";
30
+ import { buildManifest, checkManifest, DEFAULT_MAX_TIMEOUT_SECONDS } from "./manifest.js";
31
+ import { ledgerClock, rpcChain } from "./payments/chain.js";
32
+ import { checkFacilitator, httpFacilitator, settleTimeoutSeconds } from "./payments/facilitator.js";
33
+ const QUEUE_POLL_MS = 1000;
34
+ const SWEEP_INTERVAL_MS = 30_000;
35
+ const READY_RETRY_MS = 10_000;
36
+ export function createProvider(config) {
37
+ const baseUrl = new URL(config.baseUrl);
38
+ const local = baseUrl.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(baseUrl.hostname);
39
+ if (baseUrl.protocol !== "https:" && !(config.dev && local)) {
40
+ throw new TypeError("baseUrl must be https:// (http://localhost is allowed with dev: true)");
41
+ }
42
+ if (stellarAddressKind(config.payTo) === undefined)
43
+ throw new TypeError("payTo must be a valid G... or C... address");
44
+ const holdSeconds = config.holdSeconds ?? MAX_HOLD_SECONDS;
45
+ if (holdSeconds < 0 || holdSeconds > MAX_HOLD_SECONDS)
46
+ throw new RangeError(`holdSeconds must be 0–${MAX_HOLD_SECONDS}`);
47
+ const leaseSeconds = config.leaseSeconds ?? 30;
48
+ if (!Number.isInteger(leaseSeconds) || leaseSeconds < 3)
49
+ throw new RangeError("leaseSeconds must be a whole number of at least 3");
50
+ const maxTimeoutSeconds = config.maxTimeoutSeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS;
51
+ const settleSeconds = config.settleTimeoutSeconds ?? settleTimeoutSeconds(maxTimeoutSeconds);
52
+ if (!Number.isInteger(settleSeconds) || settleSeconds < 1)
53
+ throw new RangeError("settleTimeoutSeconds must be a whole number of at least 1");
54
+ const names = new Set();
55
+ for (const service of config.services) {
56
+ if (names.has(service.name))
57
+ throw new TypeError(`two services are named "${service.name}" [M7]`);
58
+ names.add(service.name);
59
+ // The signed payment expires about maxTimeoutSeconds after signing, so on-success work must
60
+ // finish well inside it [S2].
61
+ if (service.charge === "on-success" && service.expectedDurationSeconds > maxTimeoutSeconds / 2) {
62
+ throw new RangeError(`service "${service.name}": on-success work must take at most half of maxTimeoutSeconds [S2]; use charge "upfront"`);
63
+ }
64
+ }
65
+ const manifest = buildManifest(config, config.services);
66
+ const manifestPath = config.manifestPath ?? DEFAULT_MANIFEST_PATH;
67
+ const manifestUrl = new URL(manifestPath, baseUrl.origin).toString();
68
+ const violations = checkManifest(manifest, manifestUrl, config.dev);
69
+ if (violations.length > 0) {
70
+ const list = violations.map((violation) => ` [${violation.rule}] ${violation.pointer || "/"}: ${violation.message}`).join("\n");
71
+ throw new TypeError(`the manifest would not pass Provider Standard v1 checks:\n${list}`);
72
+ }
73
+ const facilitator = typeof config.facilitator === "string"
74
+ ? httpFacilitator(config.facilitator, { dev: config.dev ?? false, settleTimeoutSeconds: settleSeconds })
75
+ : config.facilitator;
76
+ const store = config.store ?? memoryStore();
77
+ const chain = config.rpc === false ? undefined : typeof config.rpc === "object" ? config.rpc : rpcChain(config.network, config.rpc, { dev: config.dev ?? false });
78
+ const clock = chain === undefined ? undefined : ledgerClock(chain);
79
+ const services = new Map(config.services.map((service) => [service.name, service]));
80
+ const owner = `${hostname()}:${process.pid}:${randomUUID().slice(0, 8)}`;
81
+ const queue = scheduler({
82
+ store,
83
+ lanes: config.services.map((service) => laneFor(service, maxTimeoutSeconds)),
84
+ owner,
85
+ leaseSeconds,
86
+ pollMs: QUEUE_POLL_MS,
87
+ ...(config.runQueuedJobs === false ? {} : { work: (job) => runLeased(job, { store, services, scheduler: queue, owner, leaseSeconds }) }),
88
+ });
89
+ const sweepOptions = {
90
+ maxTimeoutSeconds,
91
+ settleTimeoutSeconds: settleSeconds,
92
+ retentionSeconds: config.retentionSeconds ?? DEFAULT_RETENTION_SECONDS,
93
+ clock,
94
+ };
95
+ let starting;
96
+ let sweeps;
97
+ let closed = false;
98
+ // One reconciliation at a time: a slow RPC must not stack them up.
99
+ let reconciling;
100
+ const reconcileJobs = () => {
101
+ if (chain === undefined || closed)
102
+ return;
103
+ reconciling ??= (async () => {
104
+ const results = await reconcile(store, { chain, network: config.network, asset: manifest.payment.accepts[0].asset });
105
+ for (const result of results) {
106
+ // Undecided jobs were logged when they became uncertain, and are looked at again next time.
107
+ if (result.outcome === "settled")
108
+ console.error(`[provider-kit] job ${result.jobId}: reconciled, settled in ${result.transaction}; now ${result.status}`);
109
+ if (result.outcome === "not_settled")
110
+ console.error(`[provider-kit] job ${result.jobId}: reconciled, not settled (${result.reason}); now ${result.status}, nothing charged`);
111
+ }
112
+ // Paid and queued again: start them now rather than at the next poll.
113
+ for (const result of results)
114
+ if (result.status === "queued" && services.has(result.service))
115
+ queue.wake(result.service);
116
+ })()
117
+ .catch((error) => console.error("[provider-kit] reconciliation failed:", error))
118
+ .finally(() => (reconciling = undefined));
119
+ };
120
+ const ready = () => {
121
+ if (closed)
122
+ return Promise.reject(new Error("the provider is closed"));
123
+ starting ??= (async () => {
124
+ await checkFacilitator(facilitator, config.network);
125
+ if (chain === undefined && config.rpc !== false) {
126
+ console.warn(`[provider-kit] no Soroban RPC for ${config.network}: set rpc to decide payment_uncertain jobs automatically; until then, run provider-kit reconcile`);
127
+ }
128
+ await sweep(store, sweepOptions);
129
+ const stranded = await strandedJobs(store, services);
130
+ if (stranded.size > 0) {
131
+ const list = [...stranded].map(([service, count]) => `${count} of "${service}"`).join(", ");
132
+ console.warn(`[provider-kit] paid jobs of services this provider no longer offers wait until they are offered again: ${list}`);
133
+ }
134
+ queue.start();
135
+ reconcileJobs();
136
+ sweeps = setInterval(() => {
137
+ sweep(store, sweepOptions).then(reconcileJobs, (error) => console.error("[provider-kit] the recovery sweep failed:", error));
138
+ }, SWEEP_INTERVAL_MS);
139
+ sweeps.unref();
140
+ })().catch((error) => {
141
+ // Try again on a later request, not on every one.
142
+ setTimeout(() => (starting = undefined), READY_RETRY_MS).unref();
143
+ throw error;
144
+ });
145
+ return starting;
146
+ };
147
+ const context = {
148
+ manifest,
149
+ manifestPath,
150
+ services,
151
+ store,
152
+ facilitator,
153
+ scheduler: queue,
154
+ ready,
155
+ rateLimit: config.rateLimit === undefined ? undefined : rateLimiter(config.rateLimit),
156
+ holdSeconds,
157
+ settleTimeoutMs: settleSeconds * 1000,
158
+ clock,
159
+ retentionSeconds: sweepOptions.retentionSeconds,
160
+ loseCreateJobResponse: config.loseCreateJobResponse ?? false,
161
+ };
162
+ return {
163
+ manifest,
164
+ manifestUrl,
165
+ fetch: (request) => route(request, context),
166
+ ready,
167
+ async close() {
168
+ closed = true;
169
+ queue.stop();
170
+ clearInterval(sweeps);
171
+ // Its writes are compare-and-set, but the store must stay open until they finish.
172
+ await reconciling;
173
+ await store.close?.();
174
+ },
175
+ };
176
+ }
177
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import type { ProviderManifest, StellarNetwork } from "@stellar-agent-services/protocol";
2
+ import { type StellarConfig } from "@trionlabs/stellar8004";
3
+ /** The registration's service entry that points to the manifest [I1]. */
4
+ export declare const REGISTRATION_SERVICE_NAME = "stellar-agent-services";
5
+ export interface RegistrationOptions {
6
+ /** An image URL for explorers. */
7
+ image?: string;
8
+ /** ERC-8004 trust models, such as "reputation". */
9
+ supportedTrust?: string[];
10
+ }
11
+ /** The 8004 registration file for a provider whose manifest is served at `manifestUrl` [I1]. */
12
+ export declare function registrationFile(manifest: ProviderManifest, manifestUrl: string, options?: RegistrationOptions): Record<string, unknown>;
13
+ /** The file as a data: URI, which the registry stores on chain. Throws above 8 KiB: host the file and register its URL instead. */
14
+ export declare function registrationDataUri(file: Record<string, unknown>): string;
15
+ /** The 8004 contracts and RPC for a network. */
16
+ export declare function registryConfig(network: StellarNetwork): StellarConfig;
17
+ /** A validation request as the Validation Registry keeps it. `response` and `responseHash` are set once answered. */
18
+ export interface ValidationRecord {
19
+ validator: string;
20
+ agentId: number;
21
+ hasResponse: boolean;
22
+ /** 0–100, higher is better. */
23
+ response: number;
24
+ /** Lowercase hex. */
25
+ responseHash: string;
26
+ tag: string;
27
+ /** The ledger of the last change. */
28
+ lastUpdate: number;
29
+ }
30
+ /** The registry reads the kit makes, each a simulation: no key, no transaction. rpcRegistry() is the real one; tests pass a fake. */
31
+ export interface RegistryReader {
32
+ readonly network: StellarNetwork;
33
+ /** The contract ids, for the invocations the CLI hands to the Stellar CLI. */
34
+ readonly contracts: {
35
+ identity: string;
36
+ validation: string;
37
+ };
38
+ /** The agent's registration URI, or undefined when the agent doesn't exist. */
39
+ agentUri(agentId: number): Promise<string | undefined>;
40
+ /** The agent's wallet, or undefined when none is set. */
41
+ agentWallet(agentId: number): Promise<string | undefined>;
42
+ /** The agent's owner, or undefined when the agent doesn't exist. */
43
+ agentOwner(agentId: number): Promise<string | undefined>;
44
+ /** The one address the owner approved for the agent, if any. */
45
+ agentApproved(agentId: number): Promise<string | undefined>;
46
+ /** Whether the owner made `operator` an operator of all its agents. */
47
+ isOperator(owner: string, operator: string): Promise<boolean>;
48
+ /** The validation request with this hash (64 hex characters), or undefined when there is none. */
49
+ validation(requestHash: string): Promise<ValidationRecord | undefined>;
50
+ /** The agent's validation requests, newest last: each one's hash and record, at most AGENT_VALIDATIONS_READ. */
51
+ agentValidations(agentId: number): Promise<(ValidationRecord & {
52
+ requestHash: string;
53
+ })[]>;
54
+ }
55
+ /** The most validation requests agentValidations() reads for one agent. */
56
+ export declare const AGENT_VALIDATIONS_READ = 100;
57
+ export declare function rpcRegistry(network: StellarNetwork, rpcUrl?: string): RegistryReader;
58
+ /**
59
+ * The registries' rule for who may act for an agent, by changing its registration (set_agent_uri) or asking
60
+ * for its validation (validation_request): its owner, the address approved for it, or an operator of the owner's.
61
+ */
62
+ export declare function mayActFor(registry: RegistryReader, agentId: number, owner: string, address: string): Promise<boolean>;
63
+ export interface RegistrationFinding {
64
+ rule: "I1" | "I2" | "I3";
65
+ ok: boolean;
66
+ message: string;
67
+ }
68
+ /**
69
+ * Checks the provider's 8004 registration against its manifest (I1–I3), reading the identity registry
70
+ * over RPC. Without provider.agentId there is nothing on chain to check, which is an I2 finding.
71
+ */
72
+ export declare function checkRegistration(manifest: ProviderManifest, manifestUrl: string, options?: {
73
+ rpcUrl?: string;
74
+ fetch?: typeof fetch;
75
+ registry?: RegistryReader;
76
+ }): Promise<RegistrationFinding[]>;
77
+ /** checkRegistration(), and the registration file it read: undefined when there is none, or it can't be read. */
78
+ export declare function inspectRegistration(manifest: ProviderManifest, manifestUrl: string, options?: {
79
+ rpcUrl?: string;
80
+ fetch?: typeof fetch;
81
+ registry?: RegistryReader;
82
+ }): Promise<{
83
+ findings: RegistrationFinding[];
84
+ file?: Record<string, unknown>;
85
+ }>;
86
+ //# sourceMappingURL=registration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registration.d.ts","sourceRoot":"","sources":["../src/registration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,162 @@
1
+ // Stellar 8004 identity for the provider (docs/provider-standard.md §7).
2
+ //
3
+ // - registrationFile(): the ERC-8004 registration file that names the manifest [I1], built with the
4
+ // @trionlabs/stellar8004 helpers. `provider-kit register` puts it on chain.
5
+ // - checkRegistration(): reads the registry (no key needed) and checks I1–I3: the registration names
6
+ // this manifest, the manifest names the agent, and the agent's wallet is the manifest's payTo.
7
+ // inspectRegistration() also returns the registration file it read, which is what search shows.
8
+ // - rpcRegistry(): the identity and validation registry reads, which tests replace with a fake.
9
+ // - mayActFor(): who may change an agent's registration or ask for its validation.
10
+ // Nothing here signs. Registering is an owner action: the CLI has the owner's wallet sign it on a local
11
+ // approval page, or hands it to the Stellar CLI keychain (--source).
12
+ import { buildMetadataJson, IdentityClient, MAINNET_CONFIG, TESTNET_CONFIG, toDataUri, ValidationClient } from "@trionlabs/stellar8004";
13
+ /** The registration's service entry that points to the manifest [I1]. */
14
+ export const REGISTRATION_SERVICE_NAME = "stellar-agent-services";
15
+ /** The 8004 registration file for a provider whose manifest is served at `manifestUrl` [I1]. */
16
+ export function registrationFile(manifest, manifestUrl, options = {}) {
17
+ return buildMetadataJson({
18
+ name: manifest.provider.name,
19
+ description: manifest.provider.description ?? "",
20
+ imageUrl: options.image ?? "",
21
+ services: [
22
+ { name: REGISTRATION_SERVICE_NAME, endpoint: manifestUrl, version: "1" },
23
+ { name: "web", endpoint: manifest.baseUrl },
24
+ ],
25
+ supportedTrust: options.supportedTrust ?? [],
26
+ x402Enabled: true,
27
+ });
28
+ }
29
+ /** The file as a data: URI, which the registry stores on chain. Throws above 8 KiB: host the file and register its URL instead. */
30
+ export function registrationDataUri(file) {
31
+ return toDataUri(file);
32
+ }
33
+ /** The 8004 contracts and RPC for a network. */
34
+ export function registryConfig(network) {
35
+ return network === "stellar:pubnet" ? MAINNET_CONFIG : TESTNET_CONFIG;
36
+ }
37
+ /** The most validation requests agentValidations() reads for one agent. */
38
+ export const AGENT_VALIDATIONS_READ = 100;
39
+ export function rpcRegistry(network, rpcUrl) {
40
+ const config = registryConfig(network);
41
+ const options = { networkPassphrase: config.networkPassphrase, rpcUrl: rpcUrl ?? config.rpcUrl };
42
+ const identity = new IdentityClient({ ...options, contractId: config.contracts.identity });
43
+ const validation = new ValidationClient({ ...options, contractId: config.contracts.validation });
44
+ return {
45
+ network,
46
+ contracts: { identity: config.contracts.identity, validation: config.contracts.validation },
47
+ async agentUri(agentId) {
48
+ const result = (await identity.agent_uri({ agent_id: agentId })).result;
49
+ return result.isOk() ? result.unwrap() : undefined;
50
+ },
51
+ async agentWallet(agentId) {
52
+ return (await identity.get_agent_wallet({ agent_id: agentId })).result ?? undefined;
53
+ },
54
+ async agentOwner(agentId) {
55
+ return (await identity.find_owner({ agent_id: agentId })).result ?? undefined;
56
+ },
57
+ async agentApproved(agentId) {
58
+ return (await identity.get_approved({ token_id: agentId })).result ?? undefined;
59
+ },
60
+ async isOperator(owner, operator) {
61
+ return (await identity.is_approved_for_all({ owner, operator })).result;
62
+ },
63
+ validation: readValidation,
64
+ async agentValidations(agentId) {
65
+ const hashes = [];
66
+ const page = 25;
67
+ while (hashes.length < AGENT_VALIDATIONS_READ) {
68
+ const found = (await validation.get_agent_validations_paginated({ agent_id: agentId, start: hashes.length, limit: page })).result;
69
+ hashes.push(...found.map((hash) => Buffer.from(hash).toString("hex")));
70
+ if (found.length < page)
71
+ break;
72
+ }
73
+ const records = await Promise.all(hashes.slice(0, AGENT_VALIDATIONS_READ).map(async (requestHash) => ({ requestHash, record: await readValidation(requestHash) })));
74
+ return records.flatMap(({ requestHash, record }) => (record === undefined ? [] : [{ ...record, requestHash }]));
75
+ },
76
+ };
77
+ async function readValidation(requestHash) {
78
+ const result = (await validation.get_validation_status({ request_hash: Buffer.from(requestHash, "hex") })).result;
79
+ if (!result.isOk())
80
+ return undefined;
81
+ const status = result.unwrap();
82
+ return {
83
+ validator: status.validator_address,
84
+ agentId: status.agent_id,
85
+ hasResponse: status.has_response,
86
+ response: status.response,
87
+ responseHash: Buffer.from(status.response_hash).toString("hex"),
88
+ tag: status.tag,
89
+ lastUpdate: Number(status.last_update),
90
+ };
91
+ }
92
+ }
93
+ /**
94
+ * The registries' rule for who may act for an agent, by changing its registration (set_agent_uri) or asking
95
+ * for its validation (validation_request): its owner, the address approved for it, or an operator of the owner's.
96
+ */
97
+ export async function mayActFor(registry, agentId, owner, address) {
98
+ if (address === owner)
99
+ return true;
100
+ if ((await registry.agentApproved(agentId)) === address)
101
+ return true;
102
+ return registry.isOperator(owner, address);
103
+ }
104
+ /**
105
+ * Checks the provider's 8004 registration against its manifest (I1–I3), reading the identity registry
106
+ * over RPC. Without provider.agentId there is nothing on chain to check, which is an I2 finding.
107
+ */
108
+ export async function checkRegistration(manifest, manifestUrl, options = {}) {
109
+ return (await inspectRegistration(manifest, manifestUrl, options)).findings;
110
+ }
111
+ /** checkRegistration(), and the registration file it read: undefined when there is none, or it can't be read. */
112
+ export async function inspectRegistration(manifest, manifestUrl, options = {}) {
113
+ const agentId = manifest.provider.agentId;
114
+ if (agentId === undefined) {
115
+ return { findings: [{ rule: "I2", ok: false, message: "provider.agentId is not set: `provider-kit launch` registers the provider and saves its agent id" }] };
116
+ }
117
+ const network = manifest.payment.accepts[0].network;
118
+ const registry = options.registry ?? rpcRegistry(network, options.rpcUrl);
119
+ const uri = await registry.agentUri(agentId);
120
+ if (uri === undefined)
121
+ return { findings: [{ rule: "I2", ok: false, message: `agent ${agentId} does not exist in the ${network} identity registry` }] };
122
+ const findings = [{ rule: "I2", ok: true, message: `agent ${agentId} is registered on ${network}` }];
123
+ const file = await readRegistration(uri, options.fetch ?? fetch);
124
+ const services = Array.isArray(file?.["services"]) ? file["services"] : [];
125
+ const listed = services.some((service) => service.name === REGISTRATION_SERVICE_NAME && service.endpoint === manifestUrl);
126
+ findings.push(file === undefined
127
+ ? { rule: "I1", ok: false, message: "the registration file can't be read from the agent URI" }
128
+ : listed
129
+ ? { rule: "I1", ok: true, message: "the registration file lists this manifest" }
130
+ : { rule: "I1", ok: false, message: `the registration file does not list { name: "${REGISTRATION_SERVICE_NAME}", endpoint: "${manifestUrl}" }` });
131
+ const wallet = await registry.agentWallet(agentId);
132
+ const payTo = manifest.payment.accepts[0].payTo;
133
+ findings.push(wallet === payTo
134
+ ? { rule: "I3", ok: true, message: "the agent wallet is the manifest's payTo" }
135
+ : { rule: "I3", ok: false, message: `the agent wallet is ${wallet ?? "not set"}, but payTo is ${payTo}` });
136
+ return file === undefined ? { findings } : { findings, file };
137
+ }
138
+ /** A registration file from a data: or https: agent URI. Undefined if it can't be read. */
139
+ async function readRegistration(uri, fetcher) {
140
+ try {
141
+ let text;
142
+ const data = /^data:application\/json(;base64)?,(.*)$/s.exec(uri);
143
+ if (data !== null) {
144
+ text = data[1] === undefined ? decodeURIComponent(data[2]) : Buffer.from(data[2], "base64").toString("utf8");
145
+ }
146
+ else if (uri.startsWith("https://")) {
147
+ const response = await fetcher(uri, { redirect: "error", signal: AbortSignal.timeout(15_000) });
148
+ if (!response.ok)
149
+ return undefined;
150
+ text = await response.text();
151
+ }
152
+ else {
153
+ return undefined;
154
+ }
155
+ const parsed = JSON.parse(text);
156
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : undefined;
157
+ }
158
+ catch {
159
+ return undefined;
160
+ }
161
+ }
162
+ //# sourceMappingURL=registration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registration.js","sourceRoot":"","sources":["../src/registration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { Keypair } from "@stellar/stellar-sdk";
2
+ import type { PaymentPayload, PaymentRequirements } from "@x402/core/types";
3
+ export interface TestPaymentOptions {
4
+ /** The auth-entry nonce. Default: random. Two payments with the same payer and nonce are one payment. */
5
+ nonce?: bigint;
6
+ /** The last ledger the signature is valid for. Default 1,000,000 (fixtures use fixed values). */
7
+ expirationLedger?: number;
8
+ /** Pay this instead of what the requirements ask, to test refusals. */
9
+ override?: Partial<Pick<PaymentRequirements, "amount" | "payTo" | "asset">>;
10
+ }
11
+ /** A signed x402 v2 `exact` payment for the requirements, from `payer`. */
12
+ export declare function signTestPayment(requirements: PaymentRequirements, payer: Keypair, options?: TestPaymentOptions): Promise<PaymentPayload>;
13
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAUA,OAAO,EAAoC,OAAO,EAAgF,MAAM,sBAAsB,CAAC;AAC/J,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAK5E,MAAM,WAAW,kBAAkB;IACjC,yGAAyG;IACzG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;CAC7E;AAED,2EAA2E;AAC3E,wBAAsB,eAAe,CACnC,YAAY,EAAE,mBAAmB,EACjC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,cAAc,CAAC,CAiCzB"}
@@ -0,0 +1,48 @@
1
+ // Test helpers for providers and clients: real x402 `exact` payments, signed offline.
2
+ //
3
+ // import { signTestPayment } from "@stellar-agent-services/provider-kit/testing";
4
+ //
5
+ // The payment is the same transaction the x402 client builds (one SAC transfer authorized by the
6
+ // payer's signed auth entry), without the RPC round trips, so the provider's local payment checks run
7
+ // on it unchanged. Nothing here touches the network; pair it with a fake facilitator.
8
+ import { randomBytes } from "node:crypto";
9
+ import { Account, Address, authorizeEntry, Keypair, nativeToScVal, Networks, Operation, TimeoutInfinite, TransactionBuilder, xdr } from "@stellar/stellar-sdk";
10
+ /** The all-zero account the x402 client uses as transaction source; the facilitator rebuilds the transaction. */
11
+ const NULL_ACCOUNT = "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF";
12
+ /** A signed x402 v2 `exact` payment for the requirements, from `payer`. */
13
+ export async function signTestPayment(requirements, payer, options = {}) {
14
+ const passphrase = requirements.network === "stellar:pubnet" ? Networks.PUBLIC : Networks.TESTNET;
15
+ const paid = { ...requirements, ...options.override };
16
+ const call = new xdr.InvokeContractArgs({
17
+ contractAddress: Address.fromString(paid.asset).toScAddress(),
18
+ functionName: "transfer",
19
+ args: [
20
+ nativeToScVal(payer.publicKey(), { type: "address" }),
21
+ nativeToScVal(paid.payTo, { type: "address" }),
22
+ nativeToScVal(BigInt(paid.amount), { type: "i128" }),
23
+ ],
24
+ });
25
+ const unsigned = new xdr.SorobanAuthorizationEntry({
26
+ credentials: xdr.SorobanCredentials.sorobanCredentialsAddress(new xdr.SorobanAddressCredentials({
27
+ address: Address.fromString(payer.publicKey()).toScAddress(),
28
+ nonce: xdr.Int64.fromString((options.nonce ?? randomNonce()).toString()),
29
+ signatureExpirationLedger: 0,
30
+ signature: xdr.ScVal.scvVoid(),
31
+ })),
32
+ rootInvocation: new xdr.SorobanAuthorizedInvocation({
33
+ function: xdr.SorobanAuthorizedFunction.sorobanAuthorizedFunctionTypeContractFn(call),
34
+ subInvocations: [],
35
+ }),
36
+ });
37
+ const signed = await authorizeEntry(unsigned, payer, options.expirationLedger ?? 1_000_000, passphrase);
38
+ const transaction = new TransactionBuilder(new Account(NULL_ACCOUNT, "0"), { fee: "100", networkPassphrase: passphrase })
39
+ .addOperation(Operation.invokeHostFunction({ func: xdr.HostFunction.hostFunctionTypeInvokeContract(call), auth: [signed] }))
40
+ // No wall-clock timebounds, so fixtures never expire.
41
+ .setTimeout(TimeoutInfinite)
42
+ .build();
43
+ return { x402Version: 2, accepted: requirements, payload: { transaction: transaction.toXDR() } };
44
+ }
45
+ function randomNonce() {
46
+ return randomBytes(8).readBigInt64BE() & 0x7fffffffffffffffn;
47
+ }
48
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { type ProviderManifest, type ValidationRequest } from "@stellar-agent-services/protocol";
2
+ import { type RegistryReader } from "./registration.js";
3
+ /** One validation_request, checked and ready to sign. */
4
+ export interface PreparedValidationRequest {
5
+ request: ValidationRequest;
6
+ /** sha256 of the request's canonical bytes, 64 hex characters: the on-chain request_hash. */
7
+ requestHash: string;
8
+ /** A data: URI holding exactly those bytes. */
9
+ requestUri: string;
10
+ /** The Validation Registry contract. */
11
+ contractId: string;
12
+ }
13
+ export declare class ValidationRequestError extends Error {
14
+ readonly problems: string[];
15
+ name: string;
16
+ constructor(problems: string[]);
17
+ }
18
+ export interface ValidationRequestOptions {
19
+ /** The verifier's G... account: the only one that may answer. */
20
+ validator: string;
21
+ /** The account that will sign, when it is known. Without it, who may ask is left to the registry. */
22
+ signer?: string;
23
+ registry: RegistryReader;
24
+ /** For a registration file at an https: agent URI. */
25
+ fetch?: typeof fetch;
26
+ now?: () => Date;
27
+ }
28
+ /** Checks everything a validation_request depends on, then builds it. Throws a ValidationRequestError listing every problem. */
29
+ export declare function prepareValidationRequest(manifest: ProviderManifest, manifestUrl: string, options: ValidationRequestOptions): Promise<PreparedValidationRequest>;
30
+ /** The arguments of `stellar` that send the request: a contract invocation of validation_request. `caller` is the --source key's address. */
31
+ export declare function validationRequestArguments(prepared: PreparedValidationRequest, options: {
32
+ source: string;
33
+ network: string;
34
+ caller: string;
35
+ }): string[];
36
+ //# sourceMappingURL=validation-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-request.d.ts","sourceRoot":"","sources":["../src/validation-request.ts"],"names":[],"mappings":"AAeA,OAAO,EAML,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAgC,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEtF,yDAAyD;AACzD,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,6FAA6F;IAC7F,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,sBAAuB,SAAQ,KAAK;IAEnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE;IAD9B,IAAI,SAA4B;gBACpB,QAAQ,EAAE,MAAM,EAAE;CAGxC;AAED,MAAM,WAAW,wBAAwB;IACvC,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,qGAAqG;IACrG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,cAAc,CAAC;IACzB,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,gIAAgI;AAChI,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,gBAAgB,EAC1B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,yBAAyB,CAAC,CA0CpC;AAED,6IAA6I;AAC7I,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,yBAAyB,EAAE,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,EAAE,CAuBtJ"}