@weftlabs/sdk 0.29.0 → 0.31.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/README.md +64 -23
- package/dist/facilitator/middleware/index.js +1 -1
- package/dist/facilitator/middleware/index.js.map +1 -1
- package/dist/facilitator/middleware/index.mjs +1 -1
- package/dist/facilitator/middleware/index.mjs.map +1 -1
- package/dist/index.d.mts +141 -102
- package/dist/index.d.ts +141 -102
- package/dist/index.js +70 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +70 -12
- package/dist/index.mjs.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +1 -1
- package/dist/server.mjs.map +1 -1
- package/docs/FetchApi.md +5 -5
- package/docs/FetchRequest.md +4 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1892,6 +1892,9 @@ var FetchErrorResponseErrorEnum = {
|
|
|
1892
1892
|
UnknownParameter: "UNKNOWN_PARAMETER",
|
|
1893
1893
|
InvalidUrl: "INVALID_URL",
|
|
1894
1894
|
InvalidMaxCostUsd: "INVALID_MAX_COST_USD",
|
|
1895
|
+
InvalidAllowTempoRefill: "INVALID_ALLOW_TEMPO_REFILL",
|
|
1896
|
+
InvalidMaxTotalCostUsd: "INVALID_MAX_TOTAL_COST_USD",
|
|
1897
|
+
IncompatibleFetchControls: "INCOMPATIBLE_FETCH_CONTROLS",
|
|
1895
1898
|
UnsupportedMethod: "UNSUPPORTED_METHOD",
|
|
1896
1899
|
InvalidBody: "INVALID_BODY",
|
|
1897
1900
|
InvalidHeaders: "INVALID_HEADERS",
|
|
@@ -1899,6 +1902,7 @@ var FetchErrorResponseErrorEnum = {
|
|
|
1899
1902
|
IdempotencyConflict: "IDEMPOTENCY_CONFLICT",
|
|
1900
1903
|
AccountClosing: "ACCOUNT_CLOSING",
|
|
1901
1904
|
ExceededMaxCost: "EXCEEDED_MAX_COST",
|
|
1905
|
+
TotalCostUnverifiable: "TOTAL_COST_UNVERIFIABLE",
|
|
1902
1906
|
FundingPending: "FUNDING_PENDING",
|
|
1903
1907
|
InsufficientBalance: "INSUFFICIENT_BALANCE",
|
|
1904
1908
|
PaymentAuthorizationRequired: "PAYMENT_AUTHORIZATION_REQUIRED",
|
|
@@ -2083,6 +2087,8 @@ function FetchRequestFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
2083
2087
|
return {
|
|
2084
2088
|
"url": json["url"],
|
|
2085
2089
|
"maxCostUsd": json["max_cost_usd"] == null ? void 0 : json["max_cost_usd"],
|
|
2090
|
+
"allowTempoRefill": json["allow_tempo_refill"] == null ? void 0 : json["allow_tempo_refill"],
|
|
2091
|
+
"maxTotalCostUsd": json["max_total_cost_usd"] == null ? void 0 : json["max_total_cost_usd"],
|
|
2086
2092
|
"method": json["method"] == null ? void 0 : json["method"],
|
|
2087
2093
|
"body": json["body"] == null ? void 0 : FetchRequestBodyFromJSON(json["body"]),
|
|
2088
2094
|
"headers": json["headers"] == null ? void 0 : json["headers"],
|
|
@@ -2101,6 +2107,8 @@ function FetchRequestToJSONTyped(value, ignoreDiscriminator = false) {
|
|
|
2101
2107
|
return {
|
|
2102
2108
|
"url": value["url"],
|
|
2103
2109
|
"max_cost_usd": value["maxCostUsd"],
|
|
2110
|
+
"allow_tempo_refill": value["allowTempoRefill"],
|
|
2111
|
+
"max_total_cost_usd": value["maxTotalCostUsd"],
|
|
2104
2112
|
"method": value["method"],
|
|
2105
2113
|
"body": FetchRequestBodyToJSON(value["body"]),
|
|
2106
2114
|
"headers": value["headers"],
|
|
@@ -4605,7 +4613,7 @@ var DocumentationApi = class extends BaseAPI {
|
|
|
4605
4613
|
// src/generated/apis/FetchApi.ts
|
|
4606
4614
|
var FetchApi = class extends BaseAPI {
|
|
4607
4615
|
/**
|
|
4608
|
-
* Universal x402/MPP fetch proxy. The caller provides a target `url`, a
|
|
4616
|
+
* Universal x402/MPP fetch proxy. The caller provides a target `url`, a merchant-principal `max_cost_usd` ceiling, and optional `method` / `body` / `headers`. Weft: 1. Issues the request. 2. On `402 Payment Required`, selects a supported x402 or MPP challenge. 3. Compares the asking price to `max_cost_usd` and the buyer\'s policy (`max_tx_usd`, daily/weekly limits). 4. If refill is allowed and an eligible mainnet MPP challenge finds its Tempo token short, creates or adopts a buyer-owned Base-to-Tempo refill and returns `409 FUNDING_PENDING` with `details.reason=funding_active`. If an overlapping payment invalidates the balance observation before a bridge is created, the same retryable response carries `details.reason=balance_changed`. The caller retries the identical fetch after `details.retry_after_seconds`; that later request obtains a fresh challenge and reruns rail selection and all payment controls. 5. Authorizes payment from the buyer\'s wallet on the selected rail. 6. Replays the request with the protocol-specific payment credential. 7. Streams the upstream artifact back, base64-encoded under `body_base64`, with `paid_usd`, `held_usd`, `payment_status`, `tx_hash`, and `protocol`. `paid_usd` is \"0.00\" until the charge is CONFIRMED settled — a signed-but- unsettled hold (the common case for x402, which settles asynchronously) reports its amount in `held_usd` instead, never in `paid_usd`. **Opt-in safety controls:** `allow_tempo_refill: false` prevents this request from creating, adopting, or enqueueing a Base-to-Tempo bridge. A Tempo shortfall returns `402 INSUFFICIENT_BALANCE`; unrelated bridges and their jobs remain unchanged. `access_method_id` is advisory and does not enforce a payment rail. `max_total_cost_usd` is an all-in ceiling covering merchant principal, network gas, provider fees, and prerequisite buyer-paid operations. It disables refill; explicitly combining it with `allow_tempo_refill: true` returns `422 INCOMPATIBLE_FETCH_CONTROLS`. Current wallet integrations provide no supported binding all-in fee guarantee. Therefore all-in requests return `402 TOTAL_COST_UNVERIFIABLE` before payment preparation, approval, reservation, or refill. This also refuses recovery of older payments and SIWX wallet signing; it admits no positive paid route. Increasing the ceiling does not resolve missing fee authority. Omitted controls preserve existing behavior. Ordinary non-402 merchant responses retain `MERCHANT_RETURNED_NON_402`. Stored-result replay is historical payment information, not a new bounded authorization. Errors are structured with a stable `error` code, and each error response carries the buyer\'s `policy`, `balance`, and a `dashboard_url` so a CLI can render an actionable message without a second round-trip. Account-scoped: the bearer must be a buyer-scoped API key, an OAuth access token carrying `fetch`, or a claimed `wbt_*` bearer. **Forwarded headers:** the caller\'s `headers` are passed through to the upstream, except a denylist of hop-by-hop and Weft-internal headers (`host`, `authorization`, `cookie`, `proxy-authorization`, `x-forwarded-*`, `x-real-ip`, `x-payment`, `connection`, `upgrade`). Up to 32 headers, 4 KB of combined value bytes.
|
|
4609
4617
|
* Pay-and-fetch any URL (x402/MPP proxy)
|
|
4610
4618
|
*/
|
|
4611
4619
|
async fetchRaw(requestParameters, initOverrides) {
|
|
@@ -4639,7 +4647,7 @@ var FetchApi = class extends BaseAPI {
|
|
|
4639
4647
|
return new JSONApiResponse(response, (jsonValue) => FetchResponseFromJSON(jsonValue));
|
|
4640
4648
|
}
|
|
4641
4649
|
/**
|
|
4642
|
-
* Universal x402/MPP fetch proxy. The caller provides a target `url`, a
|
|
4650
|
+
* Universal x402/MPP fetch proxy. The caller provides a target `url`, a merchant-principal `max_cost_usd` ceiling, and optional `method` / `body` / `headers`. Weft: 1. Issues the request. 2. On `402 Payment Required`, selects a supported x402 or MPP challenge. 3. Compares the asking price to `max_cost_usd` and the buyer\'s policy (`max_tx_usd`, daily/weekly limits). 4. If refill is allowed and an eligible mainnet MPP challenge finds its Tempo token short, creates or adopts a buyer-owned Base-to-Tempo refill and returns `409 FUNDING_PENDING` with `details.reason=funding_active`. If an overlapping payment invalidates the balance observation before a bridge is created, the same retryable response carries `details.reason=balance_changed`. The caller retries the identical fetch after `details.retry_after_seconds`; that later request obtains a fresh challenge and reruns rail selection and all payment controls. 5. Authorizes payment from the buyer\'s wallet on the selected rail. 6. Replays the request with the protocol-specific payment credential. 7. Streams the upstream artifact back, base64-encoded under `body_base64`, with `paid_usd`, `held_usd`, `payment_status`, `tx_hash`, and `protocol`. `paid_usd` is \"0.00\" until the charge is CONFIRMED settled — a signed-but- unsettled hold (the common case for x402, which settles asynchronously) reports its amount in `held_usd` instead, never in `paid_usd`. **Opt-in safety controls:** `allow_tempo_refill: false` prevents this request from creating, adopting, or enqueueing a Base-to-Tempo bridge. A Tempo shortfall returns `402 INSUFFICIENT_BALANCE`; unrelated bridges and their jobs remain unchanged. `access_method_id` is advisory and does not enforce a payment rail. `max_total_cost_usd` is an all-in ceiling covering merchant principal, network gas, provider fees, and prerequisite buyer-paid operations. It disables refill; explicitly combining it with `allow_tempo_refill: true` returns `422 INCOMPATIBLE_FETCH_CONTROLS`. Current wallet integrations provide no supported binding all-in fee guarantee. Therefore all-in requests return `402 TOTAL_COST_UNVERIFIABLE` before payment preparation, approval, reservation, or refill. This also refuses recovery of older payments and SIWX wallet signing; it admits no positive paid route. Increasing the ceiling does not resolve missing fee authority. Omitted controls preserve existing behavior. Ordinary non-402 merchant responses retain `MERCHANT_RETURNED_NON_402`. Stored-result replay is historical payment information, not a new bounded authorization. Errors are structured with a stable `error` code, and each error response carries the buyer\'s `policy`, `balance`, and a `dashboard_url` so a CLI can render an actionable message without a second round-trip. Account-scoped: the bearer must be a buyer-scoped API key, an OAuth access token carrying `fetch`, or a claimed `wbt_*` bearer. **Forwarded headers:** the caller\'s `headers` are passed through to the upstream, except a denylist of hop-by-hop and Weft-internal headers (`host`, `authorization`, `cookie`, `proxy-authorization`, `x-forwarded-*`, `x-real-ip`, `x-payment`, `connection`, `upgrade`). Up to 32 headers, 4 KB of combined value bytes.
|
|
4643
4651
|
* Pay-and-fetch any URL (x402/MPP proxy)
|
|
4644
4652
|
*/
|
|
4645
4653
|
async fetch(requestParameters, initOverrides) {
|
|
@@ -4880,6 +4888,26 @@ var SearchApi = class extends BaseAPI {
|
|
|
4880
4888
|
};
|
|
4881
4889
|
|
|
4882
4890
|
// src/error.ts
|
|
4891
|
+
var PRE_SIGN_FETCH_CODES = /* @__PURE__ */ new Set([
|
|
4892
|
+
"EXCEEDED_MAX_COST",
|
|
4893
|
+
"MERCHANT_RETURNED_NON_402",
|
|
4894
|
+
"INSUFFICIENT_BALANCE",
|
|
4895
|
+
"DENYLISTED_RECIPIENT",
|
|
4896
|
+
"WALLET_ENVIRONMENT_MISMATCH",
|
|
4897
|
+
"UNSUPPORTED_ASSET",
|
|
4898
|
+
"INVALID_REQUEST",
|
|
4899
|
+
"UNKNOWN_PARAMETER",
|
|
4900
|
+
"INVALID_URL",
|
|
4901
|
+
"INVALID_MAX_COST_USD",
|
|
4902
|
+
"UNSUPPORTED_METHOD",
|
|
4903
|
+
"INVALID_BODY",
|
|
4904
|
+
"INVALID_HEADERS",
|
|
4905
|
+
"INVALID_IDEMPOTENCY_KEY"
|
|
4906
|
+
]);
|
|
4907
|
+
function fetchCharge(status, code) {
|
|
4908
|
+
const preSign = PRE_SIGN_FETCH_CODES.has(code) || code.startsWith("POLICY_VIOLATION_");
|
|
4909
|
+
return status >= 400 && status < 500 && preSign ? "none" : "possible";
|
|
4910
|
+
}
|
|
4883
4911
|
var WeftError = class extends Error {
|
|
4884
4912
|
constructor(options) {
|
|
4885
4913
|
super(options.message);
|
|
@@ -4889,19 +4917,32 @@ var WeftError = class extends Error {
|
|
|
4889
4917
|
this.requestId = options.requestId;
|
|
4890
4918
|
this.retryable = options.retryable;
|
|
4891
4919
|
this.details = options.details;
|
|
4920
|
+
this.charge = options.charge ?? "possible";
|
|
4892
4921
|
}
|
|
4893
4922
|
};
|
|
4894
|
-
async function normalizeWeftError(error) {
|
|
4923
|
+
async function normalizeWeftError(error, paid = false) {
|
|
4895
4924
|
if (error instanceof FetchError) {
|
|
4896
4925
|
return new WeftError({
|
|
4897
4926
|
status: 0,
|
|
4898
4927
|
code: "NETWORK_ERROR",
|
|
4899
4928
|
message: `Network failure before a Weft API response: ${error.cause?.message ?? error.message}`,
|
|
4900
4929
|
retryable: true,
|
|
4901
|
-
details: error.cause
|
|
4930
|
+
details: error.cause,
|
|
4931
|
+
charge: paid ? "possible" : "none"
|
|
4932
|
+
});
|
|
4933
|
+
}
|
|
4934
|
+
if (!(error instanceof ResponseError)) {
|
|
4935
|
+
if (!paid || error instanceof WeftError) return error;
|
|
4936
|
+
return new WeftError({
|
|
4937
|
+
status: 0,
|
|
4938
|
+
code: "RESPONSE_DECODE_ERROR",
|
|
4939
|
+
message: "Weft API returned a fetch response that could not be decoded",
|
|
4940
|
+
// A replay returns the same body; reconcile instead of retrying.
|
|
4941
|
+
retryable: false,
|
|
4942
|
+
details: error,
|
|
4943
|
+
charge: "possible"
|
|
4902
4944
|
});
|
|
4903
4945
|
}
|
|
4904
|
-
if (!(error instanceof ResponseError)) return error;
|
|
4905
4946
|
let details;
|
|
4906
4947
|
try {
|
|
4907
4948
|
details = await error.response.json();
|
|
@@ -4911,13 +4952,15 @@ async function normalizeWeftError(error) {
|
|
|
4911
4952
|
const body = details;
|
|
4912
4953
|
const nested = typeof body?.error === "object" ? body.error : void 0;
|
|
4913
4954
|
const status = error.response.status;
|
|
4955
|
+
const code = nested?.code ?? body?.code ?? (typeof body?.error === "string" ? body.error : `HTTP_${status}`);
|
|
4914
4956
|
return new WeftError({
|
|
4915
4957
|
status,
|
|
4916
|
-
code
|
|
4958
|
+
code,
|
|
4917
4959
|
message: nested?.message ?? body?.message ?? `Weft API returned HTTP ${status}`,
|
|
4918
4960
|
requestId: nested?.request_id ?? body?.request_id ?? error.response.headers.get("x-request-id") ?? void 0,
|
|
4919
4961
|
retryable: status === 429 || status >= 500,
|
|
4920
|
-
details
|
|
4962
|
+
details,
|
|
4963
|
+
charge: paid ? fetchCharge(status, String(code)) : "none"
|
|
4921
4964
|
});
|
|
4922
4965
|
}
|
|
4923
4966
|
|
|
@@ -4955,11 +4998,11 @@ var WeftClient = class {
|
|
|
4955
4998
|
this.fetches = new FetchApi(configuration);
|
|
4956
4999
|
this.purchaseHistory = new PurchasesApi(configuration);
|
|
4957
5000
|
}
|
|
4958
|
-
async call(operation) {
|
|
5001
|
+
async call(operation, paid = false) {
|
|
4959
5002
|
try {
|
|
4960
5003
|
return await operation();
|
|
4961
5004
|
} catch (error) {
|
|
4962
|
-
throw await normalizeWeftError(error);
|
|
5005
|
+
throw await normalizeWeftError(error, paid);
|
|
4963
5006
|
}
|
|
4964
5007
|
}
|
|
4965
5008
|
me() {
|
|
@@ -4978,12 +5021,27 @@ var WeftClient = class {
|
|
|
4978
5021
|
if (!options.idempotencyKey.trim()) {
|
|
4979
5022
|
throw new Error("idempotencyKey is required");
|
|
4980
5023
|
}
|
|
5024
|
+
if (!/^[!-~]{1,255}$/.test(options.idempotencyKey)) {
|
|
5025
|
+
throw new Error(
|
|
5026
|
+
"idempotencyKey must be 1-255 visible ASCII characters without spaces"
|
|
5027
|
+
);
|
|
5028
|
+
}
|
|
5029
|
+
const fetchRequest = request.body != null && typeof request.body === "object" ? { ...request, body: JSON.stringify(request.body) } : request;
|
|
4981
5030
|
return this.call(
|
|
4982
5031
|
() => this.fetches.fetch({
|
|
4983
|
-
fetchRequest
|
|
5032
|
+
fetchRequest,
|
|
4984
5033
|
idempotencyKey: options.idempotencyKey
|
|
4985
|
-
})
|
|
4986
|
-
|
|
5034
|
+
}),
|
|
5035
|
+
true
|
|
5036
|
+
).then(async (response) => {
|
|
5037
|
+
if (typeof response?.status !== "number") {
|
|
5038
|
+
throw await normalizeWeftError(
|
|
5039
|
+
new Error("unreadable fetch response"),
|
|
5040
|
+
true
|
|
5041
|
+
);
|
|
5042
|
+
}
|
|
5043
|
+
return response;
|
|
5044
|
+
});
|
|
4987
5045
|
}
|
|
4988
5046
|
purchases(options = {}) {
|
|
4989
5047
|
return this.call(() => this.purchaseHistory.listPurchases(options));
|