stellarium-ts 0.13.0 → 0.15.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.
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAE7C,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAS1D,wGAAwG;AACxG,wBAAsB,YAAY,CAAC,QAAQ,GAAE,MAA8B,GAAG,OAAO,CAAC,QAAQ,CAAC,CAI9F;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,QAAQ,iBAsI9C"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAE7C,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAW1D,wGAAwG;AACxG,wBAAsB,YAAY,CAAC,QAAQ,GAAE,MAA8B,GAAG,OAAO,CAAC,QAAQ,CAAC,CAI9F;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,QAAQ,iBA0I9C"}
package/dist/db/db.js CHANGED
@@ -5,8 +5,10 @@ export const DEFAULT_DATABASE_PATH = './requestscript.db';
5
5
  * Bumped whenever the schema changes in a way `CREATE TABLE IF NOT EXISTS` can't apply.
6
6
  * Version 1 dropped `UNIQUE (base_url)` from `resource` and added uniqueness to the function tables.
7
7
  * Version 2 added `resource_function.restricted`.
8
+ * Version 3 added `resource.website` and the `description` columns of the resource tables.
9
+ * Version 4 renamed `resource_function_payment_manifest.cost_lamports` to `cost_micro_usdc` (payments moved to USDC).
8
10
  */
9
- const SCHEMA_VERSION = 2;
11
+ const SCHEMA_VERSION = 4;
10
12
  /** Opens (or creates) the node database and brings its schema up to date. Pass ':memory:' for tests. */
11
13
  export async function openDatabase(filename = DEFAULT_DATABASE_PATH) {
12
14
  const db = await open({ filename, driver: sqlite3.Database });
@@ -45,6 +47,8 @@ export async function createTables(db) {
45
47
  path TEXT NOT NULL,
46
48
  name TEXT NOT NULL,
47
49
  base_url TEXT NOT NULL,
50
+ website TEXT,
51
+ description TEXT,
48
52
  created_at TEXT NOT NULL,
49
53
  updated_at TEXT NOT NULL,
50
54
 
@@ -58,6 +62,7 @@ export async function createTables(db) {
58
62
  resource_id INTEGER NOT NULL,
59
63
  name TEXT NOT NULL,
60
64
  return_type TEXT NOT NULL,
65
+ description TEXT,
61
66
  restricted INTEGER NOT NULL DEFAULT 0,
62
67
  created_at TEXT NOT NULL,
63
68
  updated_at TEXT NOT NULL,
@@ -72,6 +77,7 @@ export async function createTables(db) {
72
77
  resource_function_id INTEGER NOT NULL,
73
78
  name TEXT NOT NULL,
74
79
  parameter_type TEXT NOT NULL,
80
+ description TEXT,
75
81
  created_at TEXT NOT NULL,
76
82
  updated_at TEXT NOT NULL,
77
83
 
@@ -83,7 +89,7 @@ export async function createTables(db) {
83
89
  CREATE TABLE IF NOT EXISTS resource_function_payment_manifest (
84
90
  id INTEGER PRIMARY KEY AUTOINCREMENT,
85
91
  resource_function_id INTEGER NOT NULL,
86
- cost_lamports INTEGER NOT NULL,
92
+ cost_micro_usdc INTEGER NOT NULL,
87
93
  recipient_address TEXT NOT NULL,
88
94
  created_at TEXT NOT NULL,
89
95
  updated_at TEXT NOT NULL,
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { StellariumNode, resolveConfig, type StellariumNodeOptions } from './server.js';
2
2
  export type { NodeConfig } from './service.js';
3
- export type { StellariumResource, StellariumResourceFunction, StellariumResourceFunctionPaymentManifest } from './resource/repository.js';
3
+ export type { StellariumResource, StellariumResourceFunction, StellariumResourceFunctionParameter, StellariumResourceFunctionPaymentManifest } from './resource/repository.js';
4
4
  export { CombinationResourceInvoker, invocationHash, paymentVoucherPayload, type PaymentVoucher } from './resource/invoker.js';
5
5
  export { grantHash, grantPayload, grantRenewalPayload, grantRequestPayload, grantsHash, CLOCK_SKEW_TOLERANCE_MS, invocationAuthorizationPayload, MAX_AUTHORIZATION_LIFETIME_MS, MAX_GRANT_CHAIN_LENGTH, MAX_GRANT_LIFETIME_MS, type Capability, type Grant, type GrantRenewalRequest, type GrantRequest, type InvocationAuthorization, } from './grant/grant.js';
6
6
  export type { ApproveGrant, GrantApproval, GrantOptions } from './grant/service.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxF,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,yCAAyC,EAAE,MAAM,0BAA0B,CAAC;AAE1I,OAAO,EAAE,0BAA0B,EAAE,cAAc,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE/H,OAAO,EACH,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,6BAA6B,EAC7B,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,uBAAuB,GAC/B,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpF,YAAY,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxF,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,mCAAmC,EAAE,yCAAyC,EAAE,MAAM,0BAA0B,CAAC;AAE/K,OAAO,EAAE,0BAA0B,EAAE,cAAc,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE/H,OAAO,EACH,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,6BAA6B,EAC7B,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,uBAAuB,GAC/B,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpF,YAAY,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
@@ -36,12 +36,12 @@ export declare const EXTERNAL_INVOKE_BASE_DELAY_MS = 500;
36
36
  export declare const EXTERNAL_INVOKE_TIMEOUT_MS = 30000;
37
37
  export declare class CombinationResourceInvoker implements ResourceInvoker {
38
38
  private readonly resourceRepository;
39
- private readonly costLimitLamports;
39
+ private readonly costLimitMicroUsdc;
40
40
  private readonly publicKey;
41
41
  private readonly privateKey;
42
42
  private readonly grantService?;
43
43
  /** Without a `grantService`, calls to restricted remote functions fail. */
44
- constructor(resourceRepository: ResourceRepository, costLimitLamports: number, publicKey: string, privateKey: string, grantService?: GrantService | undefined);
44
+ constructor(resourceRepository: ResourceRepository, costLimitMicroUsdc: number, publicKey: string, privateKey: string, grantService?: GrantService | undefined);
45
45
  /**
46
46
  * Invoke a function on a resource.
47
47
  * If the resource has a baseUrl, it will be invoked as a remote function.
@@ -1 +1 @@
1
- {"version":3,"file":"invoker.d.ts","sourceRoot":"","sources":["../../src/resource/invoker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,6BAA6B,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEzF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC1B,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,6BAA6B,EAAE,GAC5C,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC;;;;;;;;EAG/E;AAED,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAC7C,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,wEAAwE;AACxE,eAAO,MAAM,0BAA0B,QAAS,CAAC;AA2BjD,qBAAa,0BAA2B,YAAW,eAAe;IAGlD,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAAsB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAAU,OAAO,CAAC,QAAQ,CAAC,SAAS;IAAU,OAAO,CAAC,QAAQ,CAAC,UAAU;IAAU,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IADxN,2EAA2E;IAC3E,YAA6B,kBAAkB,EAAE,kBAAkB,EAAmB,iBAAiB,EAAE,MAAM,EAAmB,SAAS,EAAE,MAAM,EAAmB,UAAU,EAAE,MAAM,EAAmB,YAAY,CAAC,EAAE,YAAY,YAAA,EAAI;IAC1O;;;;;;;;;;;OAWG;IACG,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,6BAA6B,EAAE,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAAC,CAAC,CAgE7J;IAED,oBAAoB,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,6BAA6B,EAAE,GAAG,cAAc,CAQ5L;CACJ"}
1
+ {"version":3,"file":"invoker.d.ts","sourceRoot":"","sources":["../../src/resource/invoker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,6BAA6B,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEzF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC1B,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,6BAA6B,EAAE,GAC5C,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC;;;;;;;;EAG/E;AAED,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAC7C,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,wEAAwE;AACxE,eAAO,MAAM,0BAA0B,QAAS,CAAC;AA2BjD,qBAAa,0BAA2B,YAAW,eAAe;IAGlD,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAAsB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAAU,OAAO,CAAC,QAAQ,CAAC,SAAS;IAAU,OAAO,CAAC,QAAQ,CAAC,UAAU;IAAU,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IADzN,2EAA2E;IAC3E,YAA6B,kBAAkB,EAAE,kBAAkB,EAAmB,kBAAkB,EAAE,MAAM,EAAmB,SAAS,EAAE,MAAM,EAAmB,UAAU,EAAE,MAAM,EAAmB,YAAY,CAAC,EAAE,YAAY,YAAA,EAAI;IAC3O;;;;;;;;;;;OAWG;IACG,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,6BAA6B,EAAE,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAAC,CAAC,CAgE7J;IAED,oBAAoB,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,6BAA6B,EAAE,GAAG,cAAc,CAQ5L;CACJ"}
@@ -46,14 +46,14 @@ async function fetchWithRetry(url, init) {
46
46
  }
47
47
  export class CombinationResourceInvoker {
48
48
  resourceRepository;
49
- costLimitLamports;
49
+ costLimitMicroUsdc;
50
50
  publicKey;
51
51
  privateKey;
52
52
  grantService;
53
53
  /** Without a `grantService`, calls to restricted remote functions fail. */
54
- constructor(resourceRepository, costLimitLamports, publicKey, privateKey, grantService) {
54
+ constructor(resourceRepository, costLimitMicroUsdc, publicKey, privateKey, grantService) {
55
55
  this.resourceRepository = resourceRepository;
56
- this.costLimitLamports = costLimitLamports;
56
+ this.costLimitMicroUsdc = costLimitMicroUsdc;
57
57
  this.publicKey = publicKey;
58
58
  this.privateKey = privateKey;
59
59
  this.grantService = grantService;
@@ -95,10 +95,10 @@ export class CombinationResourceInvoker {
95
95
  let paymentVoucher;
96
96
  if (resourceFunction.paymentManifest) {
97
97
  console.log(`Resource function ${resource.name}.${functionName} has a payment manifest, creating payment voucher...`);
98
- if (resourceFunction.paymentManifest.costLamports > this.costLimitLamports) {
99
- throw new Error(`Function ${functionName} cost ${resourceFunction.paymentManifest.costLamports} lamports, which exceeds the cost limit of ${this.costLimitLamports} lamports`);
98
+ if (resourceFunction.paymentManifest.costMicroUsdc > this.costLimitMicroUsdc) {
99
+ throw new Error(`Function ${functionName} cost ${resourceFunction.paymentManifest.costMicroUsdc} micro-USDC, which exceeds the cost limit of ${this.costLimitMicroUsdc} micro-USDC`);
100
100
  }
101
- paymentVoucher = this.createPaymentVoucher(resourceFunction.paymentManifest.recipientAddress, resourceFunction.paymentManifest.costLamports, resource.path, resource.name, functionName, parameters);
101
+ paymentVoucher = this.createPaymentVoucher(resourceFunction.paymentManifest.recipientAddress, resourceFunction.paymentManifest.costMicroUsdc, resource.path, resource.name, functionName, parameters);
102
102
  requestBody.paymentVoucher = paymentVoucher;
103
103
  }
104
104
  // The voucher is created once and reused on every attempt, so the operator's
@@ -3,11 +3,16 @@ import { Database } from "sqlite";
3
3
  import type { StoredPeer } from "../peer/repository.js";
4
4
  export interface StellariumResourceFunctionPaymentManifest {
5
5
  id?: number;
6
- costLamports: number;
6
+ costMicroUsdc: number;
7
7
  recipientAddress: string;
8
8
  }
9
+ export interface StellariumResourceFunctionParameter extends ResourceFunctionParameter {
10
+ description?: string;
11
+ }
9
12
  export interface StellariumResourceFunction extends ResourceFunction {
10
13
  id?: number;
14
+ description?: string;
15
+ parameters: StellariumResourceFunctionParameter[];
11
16
  paymentManifest?: StellariumResourceFunctionPaymentManifest;
12
17
  /** Callers need a grant from the hosting node. Announced to peers so callers can tell. */
13
18
  restricted?: boolean;
@@ -15,6 +20,9 @@ export interface StellariumResourceFunction extends ResourceFunction {
15
20
  export interface StellariumResource extends Resource {
16
21
  id: number;
17
22
  baseUrl: string;
23
+ /** A URL where callers can learn more about the resource. */
24
+ website?: string;
25
+ description?: string;
18
26
  functions: StellariumResourceFunction[];
19
27
  }
20
28
  /**
@@ -63,7 +71,7 @@ export declare class ResourceRepository {
63
71
  getExternalResources(offset?: number, limit?: number): Promise<StellariumResource[]>;
64
72
  getResourceFunction(resourcePath: string, resourceName: string, functionName: string): Promise<StellariumResourceFunction | undefined>;
65
73
  getResourceFunctions(resourceId: number): Promise<StellariumResourceFunction[]>;
66
- getResourceParameters(resourceFunctionId: number): Promise<ResourceFunctionParameter[]>;
74
+ getResourceParameters(resourceFunctionId: number): Promise<StellariumResourceFunctionParameter[]>;
67
75
  getResourceFunctionPaymentManifest(resourceFunctionId: number): Promise<StellariumResourceFunctionPaymentManifest | undefined>;
68
76
  /**
69
77
  * One page of every resource this node knows: the ones it hosts first, then learned ones.
@@ -1 +1 @@
1
- {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/resource/repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/resource/repository.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,18 @@ import { isFreshExpiry, safeVerifyData } from "../crypto/utils.js";
6
6
  export function resourceAnnouncementPayload(resources, expiry) {
7
7
  return { resources, expiry };
8
8
  }
9
+ /** Peers' resources aren't validated on receipt, so a description that isn't a string is stored as absent. */
10
+ function optionalText(value) {
11
+ return typeof value === 'string' ? value : null;
12
+ }
13
+ /** Only http(s) URLs are kept, since clients may render a resource's website as a link. */
14
+ function optionalWebsite(value) {
15
+ if (typeof value !== 'string' || !URL.canParse(value)) {
16
+ return null;
17
+ }
18
+ const { protocol } = new URL(value);
19
+ return protocol === 'http:' || protocol === 'https:' ? value : null;
20
+ }
9
21
  const resourceKey = (resource) => `${resource.path}.${resource.name}`;
10
22
  export class ResourceRepository {
11
23
  db;
@@ -85,7 +97,7 @@ export class ResourceRepository {
85
97
  continue;
86
98
  }
87
99
  await this.deleteFunctions(existing.id);
88
- await this.db.run('UPDATE resource SET base_url = ?, peer_id = ?, updated_at = ? WHERE id = ?', [resource.baseUrl, peer.id, new Date().toISOString(), existing.id]);
100
+ await this.db.run('UPDATE resource SET base_url = ?, website = ?, description = ?, peer_id = ?, updated_at = ? WHERE id = ?', [resource.baseUrl, optionalWebsite(resource.website), optionalText(resource.description), peer.id, new Date().toISOString(), existing.id]);
89
101
  await this.insertFunctions(existing.id, resource.functions);
90
102
  }
91
103
  });
@@ -93,7 +105,7 @@ export class ResourceRepository {
93
105
  }
94
106
  async insert(resource, peerId) {
95
107
  const createdAt = new Date().toISOString();
96
- const result = await this.db.run('INSERT INTO resource (path, name, base_url, peer_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)', [resource.path, resource.name, resource.baseUrl, peerId, createdAt, createdAt]);
108
+ const result = await this.db.run('INSERT INTO resource (path, name, base_url, website, description, peer_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [resource.path, resource.name, resource.baseUrl, optionalWebsite(resource.website), optionalText(resource.description), peerId, createdAt, createdAt]);
97
109
  if (!result.changes || result.lastID === undefined) {
98
110
  throw new Error('Failed to create resource');
99
111
  }
@@ -102,13 +114,13 @@ export class ResourceRepository {
102
114
  async insertFunctions(resourceId, functions) {
103
115
  const createdAt = new Date().toISOString();
104
116
  for (const fn of functions) {
105
- const functionResult = await this.db.run('INSERT INTO resource_function (resource_id, name, return_type, restricted, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)', [resourceId, fn.name, fn.returnType, fn.restricted === true ? 1 : 0, createdAt, createdAt]);
117
+ const functionResult = await this.db.run('INSERT INTO resource_function (resource_id, name, return_type, description, restricted, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)', [resourceId, fn.name, fn.returnType, optionalText(fn.description), fn.restricted === true ? 1 : 0, createdAt, createdAt]);
106
118
  const functionId = functionResult.lastID;
107
119
  for (const parameter of fn.parameters) {
108
- await this.db.run('INSERT INTO resource_function_parameter (resource_function_id, name, parameter_type, created_at, updated_at) VALUES (?, ?, ?, ?, ?)', [functionId, parameter.name, parameter.type, createdAt, createdAt]);
120
+ await this.db.run('INSERT INTO resource_function_parameter (resource_function_id, name, parameter_type, description, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)', [functionId, parameter.name, parameter.type, optionalText(parameter.description), createdAt, createdAt]);
109
121
  }
110
122
  if (fn.paymentManifest) {
111
- await this.db.run('INSERT INTO resource_function_payment_manifest (resource_function_id, cost_lamports, recipient_address, created_at, updated_at) VALUES (?, ?, ?, ?, ?)', [functionId, fn.paymentManifest.costLamports, fn.paymentManifest.recipientAddress, createdAt, createdAt]);
123
+ await this.db.run('INSERT INTO resource_function_payment_manifest (resource_function_id, cost_micro_usdc, recipient_address, created_at, updated_at) VALUES (?, ?, ?, ?, ?)', [functionId, fn.paymentManifest.costMicroUsdc, fn.paymentManifest.recipientAddress, createdAt, createdAt]);
112
124
  }
113
125
  }
114
126
  }
@@ -155,6 +167,8 @@ export class ResourceRepository {
155
167
  path: r.path,
156
168
  name: r.name,
157
169
  baseUrl: r.base_url,
170
+ website: r.website ?? undefined,
171
+ description: r.description ?? undefined,
158
172
  metadata: { baseUrl: r.base_url },
159
173
  functions: await this.getResourceFunctions(r.id),
160
174
  })));
@@ -172,6 +186,7 @@ export class ResourceRepository {
172
186
  id: fn.id,
173
187
  name: fn.name,
174
188
  returnType: fn.return_type,
189
+ description: fn.description ?? undefined,
175
190
  parameters: await this.getResourceParameters(fn.id),
176
191
  exec: async () => undefined,
177
192
  paymentManifest: await this.getResourceFunctionPaymentManifest(fn.id),
@@ -184,6 +199,7 @@ export class ResourceRepository {
184
199
  id: f.id,
185
200
  name: f.name,
186
201
  returnType: f.return_type,
202
+ description: f.description ?? undefined,
187
203
  parameters: await this.getResourceParameters(f.id),
188
204
  exec: async () => undefined,
189
205
  paymentManifest: await this.getResourceFunctionPaymentManifest(f.id),
@@ -194,6 +210,7 @@ export class ResourceRepository {
194
210
  return (await this.db.all('SELECT * FROM resource_function_parameter WHERE resource_function_id = ? ORDER BY id', [resourceFunctionId])).map(p => ({
195
211
  name: p.name,
196
212
  type: p.parameter_type,
213
+ description: p.description ?? undefined,
197
214
  }));
198
215
  }
199
216
  async getResourceFunctionPaymentManifest(resourceFunctionId) {
@@ -203,7 +220,7 @@ export class ResourceRepository {
203
220
  }
204
221
  return {
205
222
  id: result.id,
206
- costLamports: result.cost_lamports,
223
+ costMicroUsdc: result.cost_micro_usdc,
207
224
  recipientAddress: result.recipient_address,
208
225
  };
209
226
  }
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AAKhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,MAAM,WAAW,eAAe;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B;AAED,UAAU,YAAY;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC/B;AAiDD,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,aAAa,MAAM,CAAC;AAsHjC;;;;GAIG;AACH,QAAA,MAAM,MAAM,EAAE,kBAAkB,CAAC,YAAY,CA8R5C,CAAC;eAGa,MAAM"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AAKhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,MAAM,WAAW,eAAe;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B;AAED,UAAU,YAAY;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC/B;AAiDD,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,aAAa,MAAM,CAAC;AAsHjC;;;;GAIG;AACH,QAAA,MAAM,MAAM,EAAE,kBAAkB,CAAC,YAAY,CAqS5C,CAAC;eAGa,MAAM"}
package/dist/routes.js CHANGED
@@ -109,7 +109,7 @@ function isValidPaymentVoucher(voucher, manifest, request) {
109
109
  if (voucher.invocationHash !== expectedHash) {
110
110
  return false;
111
111
  }
112
- if (voucher.amount < manifest.costLamports) {
112
+ if (voucher.amount < manifest.costMicroUsdc) {
113
113
  return false;
114
114
  }
115
115
  if (voucher.recipientAddress !== manifest.recipientAddress) {
@@ -176,12 +176,19 @@ const routes = async (fastify, options) => {
176
176
  resources: resources.map((resource) => ({
177
177
  path: resource.path,
178
178
  name: resource.name,
179
+ website: resource.website,
180
+ description: resource.description,
179
181
  functions: resource.functions.map((fn) => ({
180
182
  name: fn.name,
181
183
  returnType: fn.returnType,
182
- parameters: fn.parameters,
184
+ description: fn.description,
185
+ parameters: fn.parameters.map(parameter => ({
186
+ name: parameter.name,
187
+ type: parameter.type,
188
+ description: parameter.description,
189
+ })),
183
190
  paymentManifest: fn.paymentManifest ? ({
184
- costLamports: fn.paymentManifest.costLamports,
191
+ costMicroUsdc: fn.paymentManifest.costMicroUsdc,
185
192
  recipientAddress: fn.paymentManifest.recipientAddress,
186
193
  }) : undefined,
187
194
  restricted: fn.restricted || undefined,
package/dist/server.d.ts CHANGED
@@ -6,7 +6,7 @@ import type { ApproveGrant, GrantOptions } from './grant/service.js';
6
6
  import { StellariumResource } from './resource/repository.js';
7
7
  import { RateLimitConfig } from './routes.js';
8
8
  import { type NodeConfig } from './service.js';
9
- export declare const DEFAULT_COST_LIMIT_LAMPORTS = 10000;
9
+ export declare const DEFAULT_COST_LIMIT_MICRO_USDC = 10000;
10
10
  export declare const DEFAULT_GRANT_REFRESH_INTERVAL_MS: number;
11
11
  export interface StellariumNodeOptions {
12
12
  port?: number;
@@ -24,8 +24,8 @@ export interface StellariumNodeOptions {
24
24
  apiKey?: string;
25
25
  /** Defaults to `OPERATOR_URL`. */
26
26
  operatorUrl?: string;
27
- /** Most this node pays for one remote call. Defaults to `COST_LIMIT_LAMPORTS`, then 10,000. */
28
- costLimitLamports?: number;
27
+ /** Most this node pays for one remote call. Defaults to `COST_LIMIT_MICRO_USDC`, then 10,000 ($0.01). */
28
+ costLimitMicroUsdc?: number;
29
29
  /** SQLite file. Defaults to `./requestscript.db`; use ':memory:' for tests. */
30
30
  databasePath?: string;
31
31
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAiB,KAAK,UAAU,EAAgB,MAAM,cAAc,CAAC;AAG5E,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,iCAAiC,QAAgB,CAAC;AAE/D,MAAM,WAAW,qBAAqB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;IACnB,yFAAyF;IACzF,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B;AAaD,wBAAgB,aAAa,CAAC,OAAO,EAAE,qBAAqB,EAAE,SAAS,GAAE,kBAAkB,EAAO,GAAG,UAAU,CAgB9G;AAED,qBAAa,cAAc;IACvB,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,OAAO,CAAC,CAAU;IAEpB,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1D;IAED;;;OAGG;IACG,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDnF;IAED,8FAA8F;IACxF,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAEtG;IAED;;;OAGG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAEvI;IAED,wFAAwF;IAClF,YAAY,CAAC,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAE3H;IAED,mDAAmD;IAC7C,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5C;IAED;;;OAGG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzD;IAED,4FAA4F;IACtF,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnE;IAED,yCAAyC;IACnC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEvD;IAED,OAAO,CAAC,OAAO;CAMlB"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -3,7 +3,7 @@ import { DEFAULT_DATABASE_PATH, openDatabase } from './db/db.js';
3
3
  import routes from './routes.js';
4
4
  import { createService } from './service.js';
5
5
  import { StartupService } from './startup.js';
6
- export const DEFAULT_COST_LIMIT_LAMPORTS = 10_000;
6
+ export const DEFAULT_COST_LIMIT_MICRO_USDC = 10_000;
7
7
  export const DEFAULT_GRANT_REFRESH_INTERVAL_MS = 1000 * 60 * 5;
8
8
  function required(name, value) {
9
9
  if (!value) {
@@ -15,9 +15,9 @@ function hostsPaidFunctions(resources) {
15
15
  return resources.some(resource => resource.functions.some(fn => fn.paymentManifest));
16
16
  }
17
17
  export function resolveConfig(options, resources = []) {
18
- const costLimit = options.costLimitLamports ?? (process.env.COST_LIMIT_LAMPORTS ? Number(process.env.COST_LIMIT_LAMPORTS) : DEFAULT_COST_LIMIT_LAMPORTS);
18
+ const costLimit = options.costLimitMicroUsdc ?? (process.env.COST_LIMIT_MICRO_USDC ? Number(process.env.COST_LIMIT_MICRO_USDC) : DEFAULT_COST_LIMIT_MICRO_USDC);
19
19
  if (!Number.isSafeInteger(costLimit) || costLimit < 0) {
20
- throw new Error('costLimitLamports must be a nonnegative integer');
20
+ throw new Error('costLimitMicroUsdc must be a nonnegative integer');
21
21
  }
22
22
  return {
23
23
  baseUrl: required('BASE_URL', options.baseUrl ?? process.env.BASE_URL),
@@ -28,7 +28,7 @@ export function resolveConfig(options, resources = []) {
28
28
  operatorUrl: hostsPaidFunctions(resources)
29
29
  ? required('OPERATOR_URL', options.operatorUrl ?? process.env.OPERATOR_URL)
30
30
  : options.operatorUrl ?? process.env.OPERATOR_URL,
31
- costLimitLamports: costLimit,
31
+ costLimitMicroUsdc: costLimit,
32
32
  };
33
33
  }
34
34
  export class StellariumNode {
package/dist/service.d.ts CHANGED
@@ -17,7 +17,7 @@ export interface NodeConfig {
17
17
  /** Operator base URL, including `/v1`. Required when the node hosts paid functions. */
18
18
  operatorUrl?: string;
19
19
  /** Most this node will pay for one remote call. */
20
- costLimitLamports: number;
20
+ costLimitMicroUsdc: number;
21
21
  }
22
22
  export interface Service {
23
23
  config: NodeConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEvF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,KAAK,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAErE,4GAA4G;AAC5G,MAAM,WAAW,UAAU;IACvB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,iBAAiB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,OAAO;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,eAAe,EAAE,eAAe,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,YAAY,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC3B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAoBtI"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEvF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,KAAK,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAErE,4GAA4G;AAC5G,MAAM,WAAW,UAAU;IACvB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,kBAAkB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,OAAO;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,eAAe,EAAE,eAAe,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,YAAY,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC3B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAoBtI"}
package/dist/service.js CHANGED
@@ -9,7 +9,7 @@ export function createService(db, resources, config, options = {}) {
9
9
  const resourceRepository = new ResourceRepository(db, resources, config.baseUrl);
10
10
  const resourceResolver = new CombinationResourceResolver(resourceRepository);
11
11
  const grantService = new GrantService(new GrantRepository(db), config, options.approveGrant);
12
- const resourceInvoker = new CombinationResourceInvoker(resourceRepository, config.costLimitLamports, config.publicKey, config.privateKey, grantService);
12
+ const resourceInvoker = new CombinationResourceInvoker(resourceRepository, config.costLimitMicroUsdc, config.publicKey, config.privateKey, grantService);
13
13
  const operatorClient = new OperatorClient(config.operatorUrl);
14
14
  return {
15
15
  config,
@@ -17,7 +17,7 @@ describe("openDatabase", () => {
17
17
  const filename = path.join(dir, "node.db");
18
18
  await (await openDatabase(filename)).close();
19
19
  const db = await openDatabase(filename);
20
- expect(await db.get("PRAGMA user_version")).toEqual({ user_version: 2 });
20
+ expect(await db.get("PRAGMA user_version")).toEqual({ user_version: 4 });
21
21
  await db.close();
22
22
  });
23
23
  test("rebuilds resource tables from the old schema and keeps peers", async () => {
@@ -17,7 +17,7 @@ export function testConfig(overrides = {}) {
17
17
  ...generateBase64KeyPair(),
18
18
  apiKey: "secret",
19
19
  operatorUrl: "http://operator.invalid/v1",
20
- costLimitLamports: 100_000,
20
+ costLimitMicroUsdc: 100_000,
21
21
  ...overrides,
22
22
  };
23
23
  }
@@ -35,7 +35,7 @@ export function weatherResource(baseUrl = "http://127.0.0.1:3002") {
35
35
  parameters: [{ name: "city", type: "string" }],
36
36
  returnType: "int32",
37
37
  exec: async (args) => (args.find((arg) => arg.name === "city")?.value === "Oslo" ? 12 : 20),
38
- paymentManifest: { costLamports: COST, recipientAddress: RECIPIENT },
38
+ paymentManifest: { costMicroUsdc: COST, recipientAddress: RECIPIENT },
39
39
  },
40
40
  {
41
41
  name: "humidity",
@@ -36,7 +36,8 @@ function freePort() {
36
36
  * A provider node hosting the paid weather resource, a caller node that bootstraps from it,
37
37
  * and a fake operator that records settlements. Everything runs in-process over real HTTP.
38
38
  */
39
- describe("two-node network", () => {
39
+ // Each test starts real HTTP nodes on SQLite files, which can take several seconds on a loaded CI runner.
40
+ describe("two-node network", { timeout: 15_000 }, () => {
40
41
  const servers = [];
41
42
  const settlements = [];
42
43
  const callerKeys = generateBase64KeyPair();
@@ -106,7 +107,7 @@ describe("two-node network", () => {
106
107
  expect(callerResources.resources).toContainEqual(expect.objectContaining({
107
108
  name: "Weather",
108
109
  baseUrl: providerUrl,
109
- functions: expect.arrayContaining([expect.objectContaining({ name: "temperature", paymentManifest: { costLamports: COST, recipientAddress: RECIPIENT } })]),
110
+ functions: expect.arrayContaining([expect.objectContaining({ name: "temperature", paymentManifest: { costMicroUsdc: COST, recipientAddress: RECIPIENT } })]),
110
111
  }));
111
112
  expect(await run(caller.url)).toEqual({ returnValue: { value: 12, error: null } });
112
113
  await vi.waitFor(() => expect(settlements).toHaveLength(1));
@@ -179,7 +180,7 @@ describe("two-node network", () => {
179
180
  });
180
181
  });
181
182
  test("the caller refuses a call that costs more than its limit", async () => {
182
- const caller = await startCaller({ costLimitLamports: COST - 1 });
183
+ const caller = await startCaller({ costLimitMicroUsdc: COST - 1 });
183
184
  const result = await run(caller.url);
184
185
  expect(result.returnValue.value).toBeNull();
185
186
  expect(result.returnValue.error.message).toContain("exceeds the cost limit");
@@ -93,7 +93,7 @@ describe("external invoke retries", () => {
93
93
  });
94
94
  test("reuses the same payment voucher on every attempt", async () => {
95
95
  fetchMock.mockResolvedValueOnce(status(503)).mockResolvedValueOnce(status(503)).mockResolvedValueOnce(ok());
96
- const invoker = createInvoker({ costLamports: 10000, recipientAddress: "4HkmXgXCJ8tw1ih5VFHetRt4kWdo1VLBVmV7B5p6ctK2" });
96
+ const invoker = createInvoker({ costMicroUsdc: 10000, recipientAddress: "4HkmXgXCJ8tw1ih5VFHetRt4kWdo1VLBVmV7B5p6ctK2" });
97
97
  const pending = invoker.invoke(resource, "forecast", parameters);
98
98
  await vi.runAllTimersAsync();
99
99
  await pending;
@@ -139,7 +139,7 @@ describe("restricted functions", () => {
139
139
  fetchMock.mockResolvedValueOnce(new Response(null, { status: 503 })).mockResolvedValueOnce(new Response(JSON.stringify({ value: 42, error: null }), { status: 200 }));
140
140
  let nonce = 0;
141
141
  const authorize = vi.fn(() => ({ nonce: `nonce-${nonce++}` }));
142
- const invoker = createInvoker({ chainFor: async () => chain, authorize }, { costLamports: 10000, recipientAddress: "4HkmXgXCJ8tw1ih5VFHetRt4kWdo1VLBVmV7B5p6ctK2" });
142
+ const invoker = createInvoker({ chainFor: async () => chain, authorize }, { costMicroUsdc: 10000, recipientAddress: "4HkmXgXCJ8tw1ih5VFHetRt4kWdo1VLBVmV7B5p6ctK2" });
143
143
  const pending = invoker.invoke(resource, "forecast", parameters);
144
144
  await vi.runAllTimersAsync();
145
145
  await expect(pending).resolves.toEqual({ value: 42, error: null });
@@ -33,6 +33,24 @@ describe("ResourceRepository", () => {
33
33
  expect(functions.map(fn => [fn.name, fn.restricted])).toEqual([["open", true], ["peek", undefined]]);
34
34
  expect((await repository.getResourceFunction("com.provider", "Vault", "open"))?.restricted).toBe(true);
35
35
  });
36
+ test("keeps the descriptions of resources, functions and parameters", async () => {
37
+ await repository.learn({
38
+ ...resource("Forecast", [
39
+ { name: "tomorrow", description: "Tomorrow's forecast", parameters: [{ name: "city", type: "string", description: "City name" }] },
40
+ { name: "today", parameters: [{ name: "city", type: "string" }] },
41
+ ]),
42
+ website: "https://forecast.example",
43
+ description: "Weather forecasts",
44
+ });
45
+ const [learned] = await repository.getExternalResources();
46
+ expect(learned.website).toBe("https://forecast.example");
47
+ expect(learned.description).toBe("Weather forecasts");
48
+ expect(learned.functions.map(fn => [fn.name, fn.description, fn.parameters[0].description])).toEqual([
49
+ ["today", undefined, undefined],
50
+ ["tomorrow", "Tomorrow's forecast", "City name"],
51
+ ]);
52
+ expect((await repository.getResourceFunction("com.provider", "Forecast", "tomorrow"))?.description).toBe("Tomorrow's forecast");
53
+ });
36
54
  test("is idempotent, so startup can run on every boot", async () => {
37
55
  const learned = resource("Forecast", [{ name: "tomorrow" }]);
38
56
  await repository.learn(learned);
@@ -70,12 +88,12 @@ describe("ResourceRepository", () => {
70
88
  test("returns each function's own payment manifest", async () => {
71
89
  await repository.learn(resource("Forecast", [
72
90
  { name: "free" },
73
- { name: "paid", paymentManifest: { costLamports: 250, recipientAddress: RECIPIENT } },
91
+ { name: "paid", paymentManifest: { costMicroUsdc: 250, recipientAddress: RECIPIENT } },
74
92
  ]));
75
93
  const found = await repository.getResource("com.provider.Forecast");
76
94
  expect(found.metadata).toEqual({ baseUrl: PROVIDER });
77
95
  expect(found.functions.find(f => f.name === "free")?.paymentManifest).toBeUndefined();
78
- expect(found.functions.find(f => f.name === "paid")?.paymentManifest).toMatchObject({ costLamports: 250, recipientAddress: RECIPIENT });
96
+ expect(found.functions.find(f => f.name === "paid")?.paymentManifest).toMatchObject({ costMicroUsdc: 250, recipientAddress: RECIPIENT });
79
97
  });
80
98
  test("prefers the internal resource", async () => {
81
99
  const found = await repository.getResource("com.example.Weather");
@@ -101,17 +119,30 @@ describe("ResourceRepository", () => {
101
119
  test("adds new functions, parameters and payment manifests to a known resource", async () => {
102
120
  await save([resource("Forecast", [{ name: "today" }])]);
103
121
  const result = await save([resource("Forecast", [
104
- { name: "today", parameters: [{ name: "city", type: "string" }], paymentManifest: { costLamports: 100, recipientAddress: RECIPIENT } },
122
+ { name: "today", parameters: [{ name: "city", type: "string" }], paymentManifest: { costMicroUsdc: 100, recipientAddress: RECIPIENT } },
105
123
  { name: "tomorrow" },
106
124
  ])]);
107
125
  expect(result).toEqual({ ok: true, rejected: [] });
108
126
  const today = await repository.getResourceFunction("com.provider", "Forecast", "today");
109
127
  expect(today?.parameters).toEqual([{ name: "city", type: "string" }]);
110
- expect(today?.paymentManifest).toMatchObject({ costLamports: 100 });
128
+ expect(today?.paymentManifest).toMatchObject({ costMicroUsdc: 100 });
111
129
  expect(await repository.getResourceFunction("com.provider", "Forecast", "tomorrow")).toBeDefined();
112
130
  });
131
+ test("drops descriptions that aren't strings and websites that aren't http(s) URLs", async () => {
132
+ const sent = {
133
+ ...resource("Forecast", [{ name: "today", description: 42, parameters: [{ name: "city", type: "string", description: { text: "City" } }] }]),
134
+ website: "javascript:alert(1)",
135
+ description: ["Weather forecasts"],
136
+ };
137
+ await save([sent, { ...resource("Radar", []), website: "https://radar.example", description: "Rain radar" }]);
138
+ const [forecast, radar] = await repository.getExternalResources();
139
+ expect([forecast.website, forecast.description]).toEqual([undefined, undefined]);
140
+ expect(forecast.functions[0].description).toBeUndefined();
141
+ expect(forecast.functions[0].parameters[0].description).toBeUndefined();
142
+ expect([radar.website, radar.description]).toEqual(["https://radar.example", "Rain radar"]);
143
+ });
113
144
  test("removes functions and payment manifests the peer no longer advertises", async () => {
114
- await save([resource("Forecast", [{ name: "today", paymentManifest: { costLamports: 100, recipientAddress: RECIPIENT } }, { name: "old" }])]);
145
+ await save([resource("Forecast", [{ name: "today", paymentManifest: { costMicroUsdc: 100, recipientAddress: RECIPIENT } }, { name: "old" }])]);
115
146
  await save([resource("Forecast", [{ name: "today" }])]);
116
147
  expect((await repository.getResourceFunction("com.provider", "Forecast", "today"))?.paymentManifest).toBeUndefined();
117
148
  expect(await repository.getResourceFunction("com.provider", "Forecast", "old")).toBeUndefined();
@@ -270,7 +270,7 @@ describe("routes", () => {
270
270
  parameters: [{ name: "city", type: "string" }],
271
271
  returnType: "string",
272
272
  exec: async () => "sunny",
273
- paymentManifest: { costLamports: 500, recipientAddress: RECIPIENT },
273
+ paymentManifest: { costMicroUsdc: 500, recipientAddress: RECIPIENT },
274
274
  }],
275
275
  });
276
276
  function broadcast(resources, privateKey = keys.privateKey, publicKey = keys.publicKey) {
@@ -294,7 +294,7 @@ describe("routes", () => {
294
294
  const resources = (await fastify.inject({ method: "GET", url: "/v1/resources" })).json().resources;
295
295
  expect(resources.find((r) => r.name === "Forecast")).toMatchObject({
296
296
  baseUrl: peer.baseUrl,
297
- functions: [{ name: "tomorrow", paymentManifest: { costLamports: 500, recipientAddress: RECIPIENT } }],
297
+ functions: [{ name: "tomorrow", paymentManifest: { costMicroUsdc: 500, recipientAddress: RECIPIENT } }],
298
298
  });
299
299
  });
300
300
  test("rejects a broadcast from an unknown peer", async () => {
@@ -366,7 +366,7 @@ describe("restricted functions", () => {
366
366
  name: "Vault",
367
367
  functions: [
368
368
  { name: "open", parameters: [{ name: "city", type: "string" }], returnType: "int32", exec: async () => 7, restricted: true },
369
- { name: "premium", parameters: [{ name: "city", type: "string" }], returnType: "int32", exec: async () => 9, restricted: true, paymentManifest: { costLamports: COST, recipientAddress: RECIPIENT } },
369
+ { name: "premium", parameters: [{ name: "city", type: "string" }], returnType: "int32", exec: async () => 9, restricted: true, paymentManifest: { costMicroUsdc: COST, recipientAddress: RECIPIENT } },
370
370
  ],
371
371
  };
372
372
  const call = (functionName) => ({ resourcePath: "com.example", resourceName: "Vault", functionName, parameters });
@@ -1,5 +1,5 @@
1
1
  import { afterEach, describe, expect, test, vi } from "vitest";
2
- import { DEFAULT_COST_LIMIT_LAMPORTS, resolveConfig } from "../server.js";
2
+ import { DEFAULT_COST_LIMIT_MICRO_USDC, resolveConfig } from "../server.js";
3
3
  import { weatherResource } from "./helpers.js";
4
4
  describe("resolveConfig", () => {
5
5
  const keys = { baseUrl: "http://node.example", publicKey: "public", privateKey: "private" };
@@ -15,15 +15,15 @@ describe("resolveConfig", () => {
15
15
  vi.stubEnv("BASE_URL", "http://env.example");
16
16
  vi.stubEnv("SIGNING_PUBLIC_KEY", "env-public");
17
17
  vi.stubEnv("SIGNING_PRIVATE_KEY", "env-private");
18
- vi.stubEnv("COST_LIMIT_LAMPORTS", "500");
19
- expect(resolveConfig({})).toMatchObject({ baseUrl: "http://env.example", publicKey: "env-public", privateKey: "env-private", costLimitLamports: 500 });
18
+ vi.stubEnv("COST_LIMIT_MICRO_USDC", "500");
19
+ expect(resolveConfig({})).toMatchObject({ baseUrl: "http://env.example", publicKey: "env-public", privateKey: "env-private", costLimitMicroUsdc: 500 });
20
20
  });
21
21
  test("defaults the cost limit", () => {
22
- vi.stubEnv("COST_LIMIT_LAMPORTS", undefined);
23
- expect(resolveConfig(keys).costLimitLamports).toBe(DEFAULT_COST_LIMIT_LAMPORTS);
22
+ vi.stubEnv("COST_LIMIT_MICRO_USDC", undefined);
23
+ expect(resolveConfig(keys).costLimitMicroUsdc).toBe(DEFAULT_COST_LIMIT_MICRO_USDC);
24
24
  });
25
- test.each([-1, 1.5, Number.NaN])("rejects a cost limit of %s", (costLimitLamports) => {
26
- expect(() => resolveConfig({ ...keys, costLimitLamports })).toThrow("costLimitLamports");
25
+ test.each([-1, 1.5, Number.NaN])("rejects a cost limit of %s", (costLimitMicroUsdc) => {
26
+ expect(() => resolveConfig({ ...keys, costLimitMicroUsdc })).toThrow("costLimitMicroUsdc");
27
27
  });
28
28
  test("requires the signing keys and base URL", () => {
29
29
  vi.stubEnv("SIGNING_PRIVATE_KEY", undefined);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stellarium-ts",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "A Stellarium Node in TypeScript.",
5
5
  "homepage": "https://github.com/qualletio/stellarium-ts#readme",
6
6
  "bugs": {