@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.mjs
CHANGED
|
@@ -1889,6 +1889,9 @@ var FetchErrorResponseErrorEnum = {
|
|
|
1889
1889
|
UnknownParameter: "UNKNOWN_PARAMETER",
|
|
1890
1890
|
InvalidUrl: "INVALID_URL",
|
|
1891
1891
|
InvalidMaxCostUsd: "INVALID_MAX_COST_USD",
|
|
1892
|
+
InvalidAllowTempoRefill: "INVALID_ALLOW_TEMPO_REFILL",
|
|
1893
|
+
InvalidMaxTotalCostUsd: "INVALID_MAX_TOTAL_COST_USD",
|
|
1894
|
+
IncompatibleFetchControls: "INCOMPATIBLE_FETCH_CONTROLS",
|
|
1892
1895
|
UnsupportedMethod: "UNSUPPORTED_METHOD",
|
|
1893
1896
|
InvalidBody: "INVALID_BODY",
|
|
1894
1897
|
InvalidHeaders: "INVALID_HEADERS",
|
|
@@ -1896,6 +1899,7 @@ var FetchErrorResponseErrorEnum = {
|
|
|
1896
1899
|
IdempotencyConflict: "IDEMPOTENCY_CONFLICT",
|
|
1897
1900
|
AccountClosing: "ACCOUNT_CLOSING",
|
|
1898
1901
|
ExceededMaxCost: "EXCEEDED_MAX_COST",
|
|
1902
|
+
TotalCostUnverifiable: "TOTAL_COST_UNVERIFIABLE",
|
|
1899
1903
|
FundingPending: "FUNDING_PENDING",
|
|
1900
1904
|
InsufficientBalance: "INSUFFICIENT_BALANCE",
|
|
1901
1905
|
PaymentAuthorizationRequired: "PAYMENT_AUTHORIZATION_REQUIRED",
|
|
@@ -2080,6 +2084,8 @@ function FetchRequestFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
2080
2084
|
return {
|
|
2081
2085
|
"url": json["url"],
|
|
2082
2086
|
"maxCostUsd": json["max_cost_usd"] == null ? void 0 : json["max_cost_usd"],
|
|
2087
|
+
"allowTempoRefill": json["allow_tempo_refill"] == null ? void 0 : json["allow_tempo_refill"],
|
|
2088
|
+
"maxTotalCostUsd": json["max_total_cost_usd"] == null ? void 0 : json["max_total_cost_usd"],
|
|
2083
2089
|
"method": json["method"] == null ? void 0 : json["method"],
|
|
2084
2090
|
"body": json["body"] == null ? void 0 : FetchRequestBodyFromJSON(json["body"]),
|
|
2085
2091
|
"headers": json["headers"] == null ? void 0 : json["headers"],
|
|
@@ -2098,6 +2104,8 @@ function FetchRequestToJSONTyped(value, ignoreDiscriminator = false) {
|
|
|
2098
2104
|
return {
|
|
2099
2105
|
"url": value["url"],
|
|
2100
2106
|
"max_cost_usd": value["maxCostUsd"],
|
|
2107
|
+
"allow_tempo_refill": value["allowTempoRefill"],
|
|
2108
|
+
"max_total_cost_usd": value["maxTotalCostUsd"],
|
|
2101
2109
|
"method": value["method"],
|
|
2102
2110
|
"body": FetchRequestBodyToJSON(value["body"]),
|
|
2103
2111
|
"headers": value["headers"],
|
|
@@ -4602,7 +4610,7 @@ var DocumentationApi = class extends BaseAPI {
|
|
|
4602
4610
|
// src/generated/apis/FetchApi.ts
|
|
4603
4611
|
var FetchApi = class extends BaseAPI {
|
|
4604
4612
|
/**
|
|
4605
|
-
* Universal x402/MPP fetch proxy. The caller provides a target `url`, a
|
|
4613
|
+
* 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.
|
|
4606
4614
|
* Pay-and-fetch any URL (x402/MPP proxy)
|
|
4607
4615
|
*/
|
|
4608
4616
|
async fetchRaw(requestParameters, initOverrides) {
|
|
@@ -4636,7 +4644,7 @@ var FetchApi = class extends BaseAPI {
|
|
|
4636
4644
|
return new JSONApiResponse(response, (jsonValue) => FetchResponseFromJSON(jsonValue));
|
|
4637
4645
|
}
|
|
4638
4646
|
/**
|
|
4639
|
-
* Universal x402/MPP fetch proxy. The caller provides a target `url`, a
|
|
4647
|
+
* 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.
|
|
4640
4648
|
* Pay-and-fetch any URL (x402/MPP proxy)
|
|
4641
4649
|
*/
|
|
4642
4650
|
async fetch(requestParameters, initOverrides) {
|
|
@@ -4877,6 +4885,26 @@ var SearchApi = class extends BaseAPI {
|
|
|
4877
4885
|
};
|
|
4878
4886
|
|
|
4879
4887
|
// src/error.ts
|
|
4888
|
+
var PRE_SIGN_FETCH_CODES = /* @__PURE__ */ new Set([
|
|
4889
|
+
"EXCEEDED_MAX_COST",
|
|
4890
|
+
"MERCHANT_RETURNED_NON_402",
|
|
4891
|
+
"INSUFFICIENT_BALANCE",
|
|
4892
|
+
"DENYLISTED_RECIPIENT",
|
|
4893
|
+
"WALLET_ENVIRONMENT_MISMATCH",
|
|
4894
|
+
"UNSUPPORTED_ASSET",
|
|
4895
|
+
"INVALID_REQUEST",
|
|
4896
|
+
"UNKNOWN_PARAMETER",
|
|
4897
|
+
"INVALID_URL",
|
|
4898
|
+
"INVALID_MAX_COST_USD",
|
|
4899
|
+
"UNSUPPORTED_METHOD",
|
|
4900
|
+
"INVALID_BODY",
|
|
4901
|
+
"INVALID_HEADERS",
|
|
4902
|
+
"INVALID_IDEMPOTENCY_KEY"
|
|
4903
|
+
]);
|
|
4904
|
+
function fetchCharge(status, code) {
|
|
4905
|
+
const preSign = PRE_SIGN_FETCH_CODES.has(code) || code.startsWith("POLICY_VIOLATION_");
|
|
4906
|
+
return status >= 400 && status < 500 && preSign ? "none" : "possible";
|
|
4907
|
+
}
|
|
4880
4908
|
var WeftError = class extends Error {
|
|
4881
4909
|
constructor(options) {
|
|
4882
4910
|
super(options.message);
|
|
@@ -4886,19 +4914,32 @@ var WeftError = class extends Error {
|
|
|
4886
4914
|
this.requestId = options.requestId;
|
|
4887
4915
|
this.retryable = options.retryable;
|
|
4888
4916
|
this.details = options.details;
|
|
4917
|
+
this.charge = options.charge ?? "possible";
|
|
4889
4918
|
}
|
|
4890
4919
|
};
|
|
4891
|
-
async function normalizeWeftError(error) {
|
|
4920
|
+
async function normalizeWeftError(error, paid = false) {
|
|
4892
4921
|
if (error instanceof FetchError) {
|
|
4893
4922
|
return new WeftError({
|
|
4894
4923
|
status: 0,
|
|
4895
4924
|
code: "NETWORK_ERROR",
|
|
4896
4925
|
message: `Network failure before a Weft API response: ${error.cause?.message ?? error.message}`,
|
|
4897
4926
|
retryable: true,
|
|
4898
|
-
details: error.cause
|
|
4927
|
+
details: error.cause,
|
|
4928
|
+
charge: paid ? "possible" : "none"
|
|
4929
|
+
});
|
|
4930
|
+
}
|
|
4931
|
+
if (!(error instanceof ResponseError)) {
|
|
4932
|
+
if (!paid || error instanceof WeftError) return error;
|
|
4933
|
+
return new WeftError({
|
|
4934
|
+
status: 0,
|
|
4935
|
+
code: "RESPONSE_DECODE_ERROR",
|
|
4936
|
+
message: "Weft API returned a fetch response that could not be decoded",
|
|
4937
|
+
// A replay returns the same body; reconcile instead of retrying.
|
|
4938
|
+
retryable: false,
|
|
4939
|
+
details: error,
|
|
4940
|
+
charge: "possible"
|
|
4899
4941
|
});
|
|
4900
4942
|
}
|
|
4901
|
-
if (!(error instanceof ResponseError)) return error;
|
|
4902
4943
|
let details;
|
|
4903
4944
|
try {
|
|
4904
4945
|
details = await error.response.json();
|
|
@@ -4908,13 +4949,15 @@ async function normalizeWeftError(error) {
|
|
|
4908
4949
|
const body = details;
|
|
4909
4950
|
const nested = typeof body?.error === "object" ? body.error : void 0;
|
|
4910
4951
|
const status = error.response.status;
|
|
4952
|
+
const code = nested?.code ?? body?.code ?? (typeof body?.error === "string" ? body.error : `HTTP_${status}`);
|
|
4911
4953
|
return new WeftError({
|
|
4912
4954
|
status,
|
|
4913
|
-
code
|
|
4955
|
+
code,
|
|
4914
4956
|
message: nested?.message ?? body?.message ?? `Weft API returned HTTP ${status}`,
|
|
4915
4957
|
requestId: nested?.request_id ?? body?.request_id ?? error.response.headers.get("x-request-id") ?? void 0,
|
|
4916
4958
|
retryable: status === 429 || status >= 500,
|
|
4917
|
-
details
|
|
4959
|
+
details,
|
|
4960
|
+
charge: paid ? fetchCharge(status, String(code)) : "none"
|
|
4918
4961
|
});
|
|
4919
4962
|
}
|
|
4920
4963
|
|
|
@@ -4952,11 +4995,11 @@ var WeftClient = class {
|
|
|
4952
4995
|
this.fetches = new FetchApi(configuration);
|
|
4953
4996
|
this.purchaseHistory = new PurchasesApi(configuration);
|
|
4954
4997
|
}
|
|
4955
|
-
async call(operation) {
|
|
4998
|
+
async call(operation, paid = false) {
|
|
4956
4999
|
try {
|
|
4957
5000
|
return await operation();
|
|
4958
5001
|
} catch (error) {
|
|
4959
|
-
throw await normalizeWeftError(error);
|
|
5002
|
+
throw await normalizeWeftError(error, paid);
|
|
4960
5003
|
}
|
|
4961
5004
|
}
|
|
4962
5005
|
me() {
|
|
@@ -4975,12 +5018,27 @@ var WeftClient = class {
|
|
|
4975
5018
|
if (!options.idempotencyKey.trim()) {
|
|
4976
5019
|
throw new Error("idempotencyKey is required");
|
|
4977
5020
|
}
|
|
5021
|
+
if (!/^[!-~]{1,255}$/.test(options.idempotencyKey)) {
|
|
5022
|
+
throw new Error(
|
|
5023
|
+
"idempotencyKey must be 1-255 visible ASCII characters without spaces"
|
|
5024
|
+
);
|
|
5025
|
+
}
|
|
5026
|
+
const fetchRequest = request.body != null && typeof request.body === "object" ? { ...request, body: JSON.stringify(request.body) } : request;
|
|
4978
5027
|
return this.call(
|
|
4979
5028
|
() => this.fetches.fetch({
|
|
4980
|
-
fetchRequest
|
|
5029
|
+
fetchRequest,
|
|
4981
5030
|
idempotencyKey: options.idempotencyKey
|
|
4982
|
-
})
|
|
4983
|
-
|
|
5031
|
+
}),
|
|
5032
|
+
true
|
|
5033
|
+
).then(async (response) => {
|
|
5034
|
+
if (typeof response?.status !== "number") {
|
|
5035
|
+
throw await normalizeWeftError(
|
|
5036
|
+
new Error("unreadable fetch response"),
|
|
5037
|
+
true
|
|
5038
|
+
);
|
|
5039
|
+
}
|
|
5040
|
+
return response;
|
|
5041
|
+
});
|
|
4984
5042
|
}
|
|
4985
5043
|
purchases(options = {}) {
|
|
4986
5044
|
return this.call(() => this.purchaseHistory.listPurchases(options));
|