@piprail/sdk 2.0.2 → 2.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.
package/dist/index.js CHANGED
@@ -2019,14 +2019,114 @@ function normalizeNetwork(network) {
2019
2019
  async function searchOpenIndexes(opts = {}) {
2020
2020
  const sources = opts.sources ?? ["bazaar", "402index"];
2021
2021
  const limit = opts.limit ?? 20;
2022
+ const filters = {
2023
+ ...optionalRaw("category", opts.category),
2024
+ ...optionalRaw("asset", opts.asset),
2025
+ ...optionalRaw("maxPrice", opts.maxPrice),
2026
+ ...optionalRaw("verified", opts.verified),
2027
+ ...optionalRaw("paymentValid", opts.paymentValid),
2028
+ ...optionalRaw("sort", opts.sort),
2029
+ ...optionalRaw("order", opts.order)
2030
+ };
2022
2031
  const results = await Promise.all(
2023
2032
  sources.map((source) => {
2024
2033
  if (source === "bazaar") return safeSearch(() => searchBazaar(opts.query, limit, opts.signal));
2025
- if (source === "402index") return safeSearch(() => search402Index(opts.query, limit, opts.signal));
2034
+ if (source === "402index") return safeSearch(() => search402Index(opts.query, limit, filters, opts.signal));
2026
2035
  return Promise.resolve([]);
2027
2036
  })
2028
2037
  );
2029
- return dedupeByResource(results.flat());
2038
+ const merged = applyClientFilters(dedupeByResource(results.flat()), opts);
2039
+ const wantRelevance = opts.query !== void 0 && (opts.sort ?? "relevance") === "relevance";
2040
+ if (wantRelevance) return rankResources(merged, opts.query);
2041
+ if (opts.sort && opts.sort !== "relevance") return sortResources(merged, opts.sort, opts.order ?? "desc");
2042
+ return merged;
2043
+ }
2044
+ function optionalRaw(field, value) {
2045
+ return value !== void 0 ? { [field]: value } : {};
2046
+ }
2047
+ function applyClientFilters(items, opts) {
2048
+ let out = items;
2049
+ if (opts.category) {
2050
+ const want = opts.category.toLowerCase();
2051
+ out = out.filter((r) => r.category !== void 0 && r.category.toLowerCase().startsWith(want));
2052
+ }
2053
+ if (opts.maxPrice !== void 0) {
2054
+ const max = opts.maxPrice;
2055
+ out = out.filter((r) => r.priceUsd === void 0 || r.priceUsd <= max);
2056
+ }
2057
+ if (opts.asset) {
2058
+ const want = opts.asset.toLowerCase();
2059
+ out = out.filter((r) => {
2060
+ const known = r.rails.map((x) => x.symbol ?? x.asset).filter((a) => !!a);
2061
+ return known.length === 0 || known.some((a) => a.toLowerCase() === want);
2062
+ });
2063
+ }
2064
+ if (opts.minReliability !== void 0) {
2065
+ const min = opts.minReliability;
2066
+ out = out.filter((r) => r.reliabilityScore === void 0 || r.reliabilityScore >= min);
2067
+ }
2068
+ return out;
2069
+ }
2070
+ function tokenize(s) {
2071
+ return (s ?? "").toLowerCase().match(/[a-z0-9]+/g) ?? [];
2072
+ }
2073
+ var FIELD_WEIGHTS = { name: 6, category: 4, tags: 4, path: 3, description: 2 };
2074
+ function fieldTokens(r) {
2075
+ let pathText = r.resource;
2076
+ try {
2077
+ const u = new URL(r.resource);
2078
+ pathText = `${u.hostname} ${u.pathname}`;
2079
+ } catch {
2080
+ }
2081
+ return [
2082
+ [tokenize(r.name), FIELD_WEIGHTS.name],
2083
+ [tokenize(r.category), FIELD_WEIGHTS.category],
2084
+ [tokenize((r.tags ?? []).join(" ")), FIELD_WEIGHTS.tags],
2085
+ [tokenize(pathText), FIELD_WEIGHTS.path],
2086
+ [tokenize(r.description), FIELD_WEIGHTS.description]
2087
+ ];
2088
+ }
2089
+ function scoreResource(r, queryTokens) {
2090
+ if (queryTokens.length === 0) return 0;
2091
+ const fields = fieldTokens(r);
2092
+ let score = 0;
2093
+ let matched = 0;
2094
+ for (const qt of queryTokens) {
2095
+ let hit = false;
2096
+ for (const [toks, w] of fields) {
2097
+ if (toks.includes(qt)) {
2098
+ score += w;
2099
+ hit = true;
2100
+ } else if (qt.length >= 4 && toks.some((t) => t.startsWith(qt) || t.length >= 4 && qt.startsWith(t))) {
2101
+ score += w * 0.4;
2102
+ hit = true;
2103
+ }
2104
+ }
2105
+ if (hit) matched++;
2106
+ }
2107
+ if (matched === 0) return 0;
2108
+ if (matched === queryTokens.length) score += 8;
2109
+ if (r.reliabilityScore !== void 0) score += r.reliabilityScore / 1e3;
2110
+ return score;
2111
+ }
2112
+ function rankResources(items, query) {
2113
+ const qTokens = tokenize(query);
2114
+ if (qTokens.length === 0) return items;
2115
+ return items.map((r, i) => ({ r, i, s: scoreResource(r, qTokens) })).filter((x) => x.s > 0).sort((a, b) => b.s - a.s || a.i - b.i).map((x) => ({ ...x.r, score: x.s }));
2116
+ }
2117
+ function sortResources(items, sort, order) {
2118
+ const dir = order === "asc" ? 1 : -1;
2119
+ const key = (r) => sort === "reliability" || sort === "uptime" ? r.reliabilityScore : sort === "price" ? r.priceUsd : sort === "name" ? (r.name ?? r.resource).toLowerCase() : void 0;
2120
+ return items.map((r, i) => ({ r, i })).sort((a, b) => {
2121
+ const ka = key(a.r);
2122
+ const kb = key(b.r);
2123
+ if (ka === void 0 && kb === void 0) return a.i - b.i;
2124
+ if (ka === void 0) return 1;
2125
+ if (kb === void 0) return -1;
2126
+ if (ka < kb) return -1 * dir;
2127
+ if (ka > kb) return 1 * dir;
2128
+ return a.i - b.i;
2129
+ }).map((x) => x.r);
2030
2130
  }
2031
2131
  async function safeSearch(run) {
2032
2132
  try {
@@ -2072,9 +2172,24 @@ function mapBazaarItem(raw) {
2072
2172
  ...optionalString("category", pickString(meta, "category"))
2073
2173
  };
2074
2174
  }
2075
- async function search402Index(query, limit, signal) {
2175
+ async function search402Index(query, limit, filters, signal) {
2176
+ const tokens = tokenize(query);
2177
+ const queries = query && tokens.length > 1 ? [.../* @__PURE__ */ new Set([query, ...tokens])].slice(0, 5) : [query];
2178
+ const pages = await Promise.all(queries.map((q) => safeSearch(() => fetch402Page(q, limit, filters, signal))));
2179
+ return dedupeByResource(pages.flat());
2180
+ }
2181
+ async function fetch402Page(query, limit, filters, signal) {
2076
2182
  const qs = new URLSearchParams({ limit: String(limit) });
2077
2183
  if (query) qs.set("q", query);
2184
+ if (filters.category) qs.set("category", filters.category);
2185
+ if (filters.asset) qs.set("payment_asset", filters.asset);
2186
+ if (filters.maxPrice !== void 0) qs.set("max_price_usd", String(filters.maxPrice));
2187
+ if (filters.verified) qs.set("verified", "true");
2188
+ if (filters.paymentValid) qs.set("payment_valid", "true");
2189
+ if (filters.sort && filters.sort !== "relevance") {
2190
+ qs.set("sort", filters.sort);
2191
+ qs.set("order", filters.order ?? "desc");
2192
+ }
2078
2193
  const res = await fetch(`${INDEX402_SEARCH}?${qs.toString()}`, {
2079
2194
  headers: clientHeaders({ accept: "application/json" }),
2080
2195
  ...signal ? { signal } : {}
@@ -2093,16 +2208,26 @@ function map402IndexItem(raw) {
2093
2208
  if (protocol !== "x402") return null;
2094
2209
  const rails = Array.isArray(o.accepts) ? mapRails(o.accepts) : railFrom402IndexFields(o);
2095
2210
  const priceUsd = pickNumber(o, "price_usd", "priceUsd", "price");
2211
+ const reliabilityScore = pickNumber(o, "reliability_score", "reliabilityScore");
2212
+ const tags = pickStringArray(o, "tags", "keywords");
2096
2213
  return {
2097
2214
  resource,
2098
2215
  source: "402index",
2099
2216
  rails,
2100
2217
  ...priceUsd !== void 0 ? { priceUsd } : {},
2218
+ ...reliabilityScore !== void 0 ? { reliabilityScore } : {},
2219
+ ...tags ? { tags } : {},
2101
2220
  ...optionalString("name", pickString(o, "name", "title")),
2102
2221
  ...optionalString("description", pickString(o, "description")),
2103
- ...optionalString("category", pickString(o, "category", "tag"))
2222
+ ...optionalString("category", pickString(o, "category", "tag")),
2223
+ ...optionalString("health", pickString(o, "health_status", "health")),
2224
+ // 402 Index reports domain_verified as 0/1; surface a boolean only when the field is present.
2225
+ ...o.domain_verified !== void 0 || o.verified !== void 0 ? { verified: isTruthyFlag(o.domain_verified) || isTruthyFlag(o.verified) } : {}
2104
2226
  };
2105
2227
  }
2228
+ function isTruthyFlag(v) {
2229
+ return v === 1 || v === true || v === "1" || v === "true";
2230
+ }
2106
2231
  function railFrom402IndexFields(o) {
2107
2232
  const network = pickString(o, "payment_network", "network");
2108
2233
  const asset = pickString(o, "payment_asset", "asset", "token");
@@ -2119,7 +2244,8 @@ function railFrom402IndexFields(o) {
2119
2244
  async function register402Index(input) {
2120
2245
  try {
2121
2246
  const attributionOn = input.attribution !== false;
2122
- const description = attributionOn ? appendAttribution(input.description) : input.description;
2247
+ const withTags = appendKeywords(input.description, input.tags);
2248
+ const description = attributionOn ? appendAttribution(withTags) : withTags;
2123
2249
  const payload = {
2124
2250
  url: input.url,
2125
2251
  name: input.name ?? hostOf(input.url),
@@ -2129,6 +2255,11 @@ async function register402Index(input) {
2129
2255
  ...input.asset ? { payment_asset: input.asset } : {},
2130
2256
  ...input.network ? { payment_network: input.network } : {},
2131
2257
  ...input.method ? { http_method: input.method.toUpperCase() } : {},
2258
+ ...input.category ? { category: input.category } : {},
2259
+ ...input.tags && input.tags.length > 0 ? { tags: input.tags } : {},
2260
+ ...input.provider ? { provider: input.provider } : {},
2261
+ ...input.contactEmail ? { contact_email: input.contactEmail } : {},
2262
+ ...input.probeBody !== void 0 ? { probe_body: input.probeBody } : {},
2132
2263
  ...attributionOn ? { via: "@piprail/sdk" } : {}
2133
2264
  };
2134
2265
  const res = await fetch(INDEX402_REGISTER, {
@@ -2335,8 +2466,24 @@ function mapRails(accepts) {
2335
2466
  return out;
2336
2467
  }
2337
2468
  function matchesQuery(r, query) {
2338
- const q = query.toLowerCase();
2339
- return r.resource.toLowerCase().includes(q) || (r.name?.toLowerCase().includes(q) ?? false) || (r.description?.toLowerCase().includes(q) ?? false);
2469
+ const haystack = [r.name, r.description, r.category, (r.tags ?? []).join(" "), r.resource].filter(Boolean).join(" ").toLowerCase();
2470
+ if (haystack.includes(query.toLowerCase())) return true;
2471
+ const qTokens = tokenize(query);
2472
+ const hayTokens = new Set(tokenize(haystack));
2473
+ return qTokens.some((t) => hayTokens.has(t));
2474
+ }
2475
+ function pickStringArray(o, ...keys) {
2476
+ for (const k of keys) {
2477
+ const v = o[k];
2478
+ if (Array.isArray(v)) {
2479
+ const arr = v.filter((x) => typeof x === "string" && x.length > 0);
2480
+ if (arr.length) return arr;
2481
+ } else if (typeof v === "string" && v.trim()) {
2482
+ const arr = v.split(/[,\s]+/).filter((x) => x.length > 0);
2483
+ if (arr.length) return arr;
2484
+ }
2485
+ }
2486
+ return void 0;
2340
2487
  }
2341
2488
  function pickString(o, ...keys) {
2342
2489
  for (const k of keys) {
@@ -2383,6 +2530,17 @@ function appendAttribution(description) {
2383
2530
  const next = `${description.trimEnd()} ${REGISTER_ATTRIBUTION}`;
2384
2531
  return next.length <= 500 ? next : description;
2385
2532
  }
2533
+ function appendKeywords(description, tags) {
2534
+ const clean = (tags ?? []).map((t) => t.trim()).filter((t) => t.length > 0);
2535
+ if (clean.length === 0) return description;
2536
+ const have = (description ?? "").toLowerCase();
2537
+ const fresh = [...new Set(clean.filter((t) => !have.includes(t.toLowerCase())))];
2538
+ if (fresh.length === 0) return description;
2539
+ const tail = `Keywords: ${fresh.join(", ")}`;
2540
+ if (!description) return tail;
2541
+ const next = `${description.trimEnd()} \xB7 ${tail}`;
2542
+ return next.length <= 500 ? next : description;
2543
+ }
2386
2544
  function encodeBase642(str) {
2387
2545
  if (typeof Buffer !== "undefined") return Buffer.from(str, "utf8").toString("base64");
2388
2546
  if (typeof btoa === "function" && typeof TextEncoder !== "undefined") {
@@ -2874,22 +3032,24 @@ var PipRailClient = class {
2874
3032
  const found = await searchOpenIndexes({
2875
3033
  ...opts.query !== void 0 ? { query: opts.query } : {},
2876
3034
  ...opts.sources ? { sources: opts.sources } : {},
2877
- ...opts.limit !== void 0 ? { limit: opts.limit } : {}
3035
+ ...opts.limit !== void 0 ? { limit: opts.limit } : {},
3036
+ ...opts.maxPrice !== void 0 ? { maxPrice: opts.maxPrice } : {},
3037
+ ...opts.category ? { category: opts.category } : {},
3038
+ ...opts.asset ? { asset: opts.asset } : {},
3039
+ ...opts.minReliability !== void 0 ? { minReliability: opts.minReliability } : {},
3040
+ ...opts.verified !== void 0 ? { verified: opts.verified } : {},
3041
+ ...opts.paymentValid !== void 0 ? { paymentValid: opts.paymentValid } : {},
3042
+ ...opts.sort ? { sort: opts.sort } : {},
3043
+ ...opts.order ? { order: opts.order } : {}
2878
3044
  });
2879
3045
  const scope = opts.network ?? "self";
2880
- let out = found;
3046
+ if (scope === "any") return found;
2881
3047
  if (scope === "self") {
2882
3048
  const { net } = await this.ensure();
2883
- out = out.filter((r) => r.rails.some((rail) => railOnNetwork(rail, (n) => net.supports(n))));
2884
- } else if (scope !== "any") {
2885
- const target = normalizeNetwork(scope);
2886
- out = out.filter((r) => r.rails.some((rail) => railOnNetwork(rail, (n) => n === target)));
2887
- }
2888
- if (opts.maxPrice !== void 0) {
2889
- const max = opts.maxPrice;
2890
- out = out.filter((r) => r.priceUsd === void 0 || r.priceUsd <= max);
3049
+ return found.filter((r) => r.rails.some((rail) => railOnNetwork(rail, (n) => net.supports(n))));
2891
3050
  }
2892
- return out;
3051
+ const target = normalizeNetwork(scope);
3052
+ return found.filter((r) => r.rails.some((rail) => railOnNetwork(rail, (n) => n === target)));
2893
3053
  }
2894
3054
  /**
2895
3055
  * List a resource you run on the OPEN x402 registries, so agents can find it.
@@ -2930,6 +3090,11 @@ var PipRailClient = class {
2930
3090
  ...opts.asset ? { asset: opts.asset } : {},
2931
3091
  ...networkSlug ? { network: networkSlug } : {},
2932
3092
  ...opts.method ? { method: opts.method } : {},
3093
+ ...opts.category ? { category: opts.category } : {},
3094
+ ...opts.tags ? { tags: opts.tags } : {},
3095
+ ...opts.provider ? { provider: opts.provider } : {},
3096
+ ...opts.contactEmail ? { contactEmail: opts.contactEmail } : {},
3097
+ ...opts.probeBody !== void 0 ? { probeBody: opts.probeBody } : {},
2933
3098
  // Attribution is default-ON; forward an explicit opt-out, else let register402Index default it.
2934
3099
  ...opts.attribution === false ? { attribution: false } : {}
2935
3100
  })
@@ -3906,6 +4071,7 @@ function buildSelfDescription(input) {
3906
4071
  protocol: "x402",
3907
4072
  version: "2",
3908
4073
  what: WHAT,
4074
+ ...input.endpoint && Object.keys(input.endpoint).length > 0 ? { endpoint: input.endpoint } : {},
3909
4075
  pay: input.accepts.map(railOf),
3910
4076
  sdk: { install: BRAND.sdkInstall, snippet: BRAND.sdkSnippet },
3911
4077
  mcp: { run: BRAND.mcpRun, tool: "piprail_pay_request" },
@@ -3914,6 +4080,19 @@ function buildSelfDescription(input) {
3914
4080
  ...input.instruction ? { instruction: input.instruction } : {}
3915
4081
  };
3916
4082
  }
4083
+ function buildEndpointInfo(input) {
4084
+ const d = input.descriptor;
4085
+ const summary = d?.summary ?? input.description;
4086
+ const hasInput = d?.queryParams && Object.keys(d.queryParams).length > 0;
4087
+ const endpoint = {
4088
+ ...summary ? { summary } : {},
4089
+ ...d?.method ? { method: d.method.toUpperCase() } : {},
4090
+ ...input.mimeType ? { mimeType: input.mimeType } : {},
4091
+ ...hasInput ? { input: d.queryParams } : {},
4092
+ ...d?.output ? { output: d.output } : {}
4093
+ };
4094
+ return Object.keys(endpoint).length > 0 ? endpoint : void 0;
4095
+ }
3917
4096
 
3918
4097
  // src/render.ts
3919
4098
  function summarizePlan(plan) {
@@ -4095,13 +4274,25 @@ function paymentTools(client) {
4095
4274
  parameters: {
4096
4275
  type: "object",
4097
4276
  properties: {
4098
- query: { type: "string", description: "Free-text topic to search for (optional)." },
4277
+ query: {
4278
+ type: "string",
4279
+ description: 'Free-text topic to search for (optional). Multi-word queries are fanned out per word and results are ranked by relevance, so "crypto price feed" finds the best matches even when no single listing contains that exact phrase.'
4280
+ },
4099
4281
  network: {
4100
4282
  type: "string",
4101
4283
  description: "CAIP-2 id, 'self' (your chain \u2014 default), or 'any' (all chains)."
4102
4284
  },
4285
+ category: { type: "string", description: "Keep ONLY this category, e.g. 'ai', 'finance', 'data' (strict)." },
4286
+ asset: { type: "string", description: "Keep only resources paying in this token symbol, e.g. 'USDC'." },
4103
4287
  maxPrice: { type: "number", description: "Drop results advertised above this USD price." },
4104
- limit: { type: "number", description: "Max results per index (default 20)." }
4288
+ minReliability: { type: "number", description: "Drop results below this health score (0\u2013100); unscored pass." },
4289
+ verified: { type: "boolean", description: "Prefer verified listings (402 Index)." },
4290
+ sort: {
4291
+ type: "string",
4292
+ enum: ["relevance", "reliability", "price", "uptime", "name"],
4293
+ description: "Ordering. Default 'relevance' with a query, else first-seen."
4294
+ },
4295
+ limit: { type: "number", description: "Max results to fetch per index (default 20)." }
4105
4296
  },
4106
4297
  additionalProperties: false
4107
4298
  },
@@ -4110,7 +4301,12 @@ function paymentTools(client) {
4110
4301
  const opts = {};
4111
4302
  if (typeof args.query === "string") opts.query = args.query;
4112
4303
  if (typeof args.network === "string") opts.network = args.network;
4304
+ if (typeof args.category === "string") opts.category = args.category;
4305
+ if (typeof args.asset === "string") opts.asset = args.asset;
4113
4306
  if (typeof args.maxPrice === "number") opts.maxPrice = args.maxPrice;
4307
+ if (typeof args.minReliability === "number") opts.minReliability = args.minReliability;
4308
+ if (typeof args.verified === "boolean") opts.verified = args.verified;
4309
+ if (typeof args.sort === "string") opts.sort = args.sort;
4114
4310
  if (typeof args.limit === "number") opts.limit = args.limit;
4115
4311
  const found = await client.discover(opts);
4116
4312
  return {
@@ -4120,7 +4316,11 @@ function paymentTools(client) {
4120
4316
  name: r.name,
4121
4317
  description: r.description,
4122
4318
  source: r.source,
4319
+ category: r.category,
4123
4320
  priceUsd: r.priceUsd,
4321
+ reliabilityScore: r.reliabilityScore,
4322
+ health: r.health,
4323
+ verified: r.verified,
4124
4324
  networks: [...new Set(r.rails.map((rail) => rail.network))]
4125
4325
  }))
4126
4326
  };
@@ -4302,13 +4502,20 @@ function paymentTools(client) {
4302
4502
  properties: {
4303
4503
  url: { type: "string", description: "Full URL of the resource to list." },
4304
4504
  name: { type: "string", description: "Display name (defaults to the host)." },
4305
- description: { type: "string", description: "What the resource offers." },
4505
+ description: {
4506
+ type: "string",
4507
+ description: "What the resource offers. Pack the words agents will search for INTO this text \u2014 index search is literal, so a keyword that isn't in the name/description won't be found."
4508
+ },
4509
+ category: { type: "string", description: "A category, e.g. 'ai', 'finance', 'data' \u2014 the top findability field (most listings have none)." },
4510
+ tags: { type: "array", items: { type: "string" }, description: "Keywords; folded into the description so they're searchable." },
4306
4511
  priceUsd: { type: "number", description: "Advertised price in USD (metadata)." },
4307
4512
  network: {
4308
4513
  type: "string",
4309
4514
  description: "Network slug to advertise, e.g. 'base' (defaults to the paying chain). Set it when registering from a multi-chain wallet so the listing names the right chain."
4310
4515
  },
4311
- asset: { type: "string", description: "Payment asset symbol, e.g. 'USDC' (metadata)." }
4516
+ asset: { type: "string", description: "Payment asset symbol, e.g. 'USDC' (metadata)." },
4517
+ provider: { type: "string", description: "Who runs the resource (provider/org name)." },
4518
+ contactEmail: { type: "string", description: "Contact email for the listing." }
4312
4519
  },
4313
4520
  required: ["url"],
4314
4521
  additionalProperties: false
@@ -4318,9 +4525,13 @@ function paymentTools(client) {
4318
4525
  const opts = {};
4319
4526
  if (typeof args.name === "string") opts.name = args.name;
4320
4527
  if (typeof args.description === "string") opts.description = args.description;
4528
+ if (typeof args.category === "string") opts.category = args.category;
4529
+ if (Array.isArray(args.tags)) opts.tags = args.tags.filter((t) => typeof t === "string");
4321
4530
  if (typeof args.priceUsd === "number") opts.priceUsd = args.priceUsd;
4322
4531
  if (typeof args.network === "string") opts.network = args.network;
4323
4532
  if (typeof args.asset === "string") opts.asset = args.asset;
4533
+ if (typeof args.provider === "string") opts.provider = args.provider;
4534
+ if (typeof args.contactEmail === "string") opts.contactEmail = args.contactEmail;
4324
4535
  const outcomes = await client.register(String(args.url), opts);
4325
4536
  return { outcomes };
4326
4537
  } catch (err) {
@@ -4846,9 +5057,15 @@ function createPaymentGate(options) {
4846
5057
  const nonce = genNonce();
4847
5058
  const bazaar = options.discovery ? { bazaar: buildBazaarExtension(options.discovery === true ? {} : options.discovery) } : void 0;
4848
5059
  const accepts = buildAccepts(specs, nonce);
5060
+ const endpointInfo = buildEndpointInfo({
5061
+ ...options.description ? { description: options.description } : {},
5062
+ ...options.mimeType ? { mimeType: options.mimeType } : {},
5063
+ ...typeof options.discovery === "object" ? { descriptor: options.discovery } : {}
5064
+ });
4849
5065
  const selfDescribe = options.selfDescribe === false ? void 0 : buildSelfDescription({
4850
5066
  accepts,
4851
- instruction: describeChallenge({ x402Version: 2, resource: { url: resourceUrl }, accepts })
5067
+ instruction: describeChallenge({ x402Version: 2, resource: { url: resourceUrl }, accepts }),
5068
+ ...endpointInfo ? { endpoint: endpointInfo } : {}
4852
5069
  });
4853
5070
  const rejectionExt = opts?.extensions ?? {};
4854
5071
  const rejectionPiprail = rejectionExt.piprail ?? {};
@@ -4866,7 +5083,8 @@ function createPaymentGate(options) {
4866
5083
  x402Version: 2,
4867
5084
  resource: {
4868
5085
  url: resourceUrl,
4869
- ...options.description ? { description: options.description } : {}
5086
+ ...options.description ? { description: options.description } : {},
5087
+ ...options.mimeType ? { mimeType: options.mimeType } : {}
4870
5088
  },
4871
5089
  accepts,
4872
5090
  ...opts?.error ? { error: opts.error } : {},
@@ -4956,6 +5174,7 @@ function createPaymentGate(options) {
4956
5174
  return {
4957
5175
  url: resourceUrl,
4958
5176
  ...options.description ? { description: options.description } : {},
5177
+ ...options.mimeType ? { mimeType: options.mimeType } : {},
4959
5178
  accepts
4960
5179
  };
4961
5180
  }
@@ -5323,8 +5542,10 @@ export {
5323
5542
  X402_EXACT_PERMIT2_PROXY,
5324
5543
  agentGuide,
5325
5544
  appendAttribution,
5545
+ appendKeywords,
5326
5546
  buildBazaarExtension,
5327
5547
  buildChallengeHeader,
5548
+ buildEndpointInfo,
5328
5549
  buildExactAuthorization,
5329
5550
  buildExactSignatureHeader,
5330
5551
  buildOpenApi,
@@ -5363,6 +5584,7 @@ export {
5363
5584
  paymentTools,
5364
5585
  pickAccept,
5365
5586
  planAcross,
5587
+ rankResources,
5366
5588
  readExactDomain,
5367
5589
  register402Index,
5368
5590
  registerDriver,
@@ -5370,6 +5592,7 @@ export {
5370
5592
  renderLandingPage,
5371
5593
  requirePayment,
5372
5594
  resolveChain,
5595
+ scoreResource,
5373
5596
  searchOpenIndexes,
5374
5597
  settleViaFacilitator,
5375
5598
  summarizePlan,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piprail/sdk",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "Accept x402 crypto payments across 29 chains — every major EVM chain plus Solana, TON, Tron, NEAR, Sui, Aptos, Algorand, Stellar & XRPL — in a couple of lines. No backend, no database, no fee; payments settle straight to your wallet.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",