@piprail/sdk 2.0.2 → 2.1.1
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/CHANGELOG.md +49 -0
- package/dist/index.cjs +307 -84
- package/dist/index.d.cts +202 -8
- package/dist/index.d.ts +202 -8
- package/dist/index.js +247 -24
- package/package.json +1 -1
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
|
-
|
|
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
|
|
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
|
|
2339
|
-
|
|
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
|
-
|
|
3046
|
+
if (scope === "any") return found;
|
|
2881
3047
|
if (scope === "self") {
|
|
2882
3048
|
const { net } = await this.ensure();
|
|
2883
|
-
|
|
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
|
-
|
|
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: {
|
|
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
|
-
|
|
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: {
|
|
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.
|
|
3
|
+
"version": "2.1.1",
|
|
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",
|