@weftlabs/sdk 0.30.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/docs/FetchApi.md CHANGED
@@ -14,7 +14,7 @@ All URIs are relative to *https://weft.network*
14
14
 
15
15
  Pay-and-fetch any URL (x402/MPP proxy)
16
16
 
17
- Universal x402/MPP fetch proxy. The caller provides a target `url`, a hard `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 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`. 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.
17
+ 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.
18
18
 
19
19
  ### Example
20
20
 
@@ -36,7 +36,7 @@ async function example() {
36
36
  const body = {
37
37
  // FetchRequest
38
38
  fetchRequest: ...,
39
- // string | Opaque caller-generated retry key. Reusing the same key for the same buyer converges on one paid fetch; keys are hashed and namespaced by buyer before storage. Send this header for every unattended or retryable paid request. (optional)
39
+ // string | Opaque caller-generated retry key. Reusing the same key for the same buyer converges on one paid fetch; keys are hashed and namespaced by buyer before storage. Send this header for every unattended or retryable paid request. Effective safety controls participate in retry identity. Changing them under a reserved key returns `IDEMPOTENCY_CONFLICT`; an older unconstrained payment cannot become a bounded success on retry. (optional)
40
40
  idempotencyKey: idempotencyKey_example,
41
41
  } satisfies FetchOperationRequest;
42
42
 
@@ -58,7 +58,7 @@ example().catch(console.error);
58
58
  | Name | Type | Description | Notes |
59
59
  |------------- | ------------- | ------------- | -------------|
60
60
  | **fetchRequest** | [FetchRequest](FetchRequest.md) | | |
61
- | **idempotencyKey** | `string` | Opaque caller-generated retry key. Reusing the same key for the same buyer converges on one paid fetch; keys are hashed and namespaced by buyer before storage. Send this header for every unattended or retryable paid request. | [Optional] [Defaults to `undefined`] |
61
+ | **idempotencyKey** | `string` | Opaque caller-generated retry key. Reusing the same key for the same buyer converges on one paid fetch; keys are hashed and namespaced by buyer before storage. Send this header for every unattended or retryable paid request. Effective safety controls participate in retry identity. Changing them under a reserved key returns `IDEMPOTENCY_CONFLICT`; an older unconstrained payment cannot become a bounded success on retry. | [Optional] [Defaults to `undefined`] |
62
62
 
63
63
  ### Return type
64
64
 
@@ -79,11 +79,11 @@ example().catch(console.error);
79
79
  |-------------|-------------|------------------|
80
80
  | **200** | Paid fetch succeeded; artifact streamed back base64-encoded. | - |
81
81
  | **401** | Unauthorized — missing or non-buyer-scoped API key | - |
82
- | **402** | Payment refused. `EXCEEDED_MAX_COST` (over the caller cap) or `INSUFFICIENT_BALANCE` (the buyer is genuinely short — `details.asset`, when present, names the exact token the failed check read). Both use `FetchErrorResponse`. | - |
82
+ | **402** | Payment refused. `EXCEEDED_MAX_COST` (over the caller cap) or `INSUFFICIENT_BALANCE` (the buyer is genuinely short — `details.asset`, when present, names the exact token the failed check read). `TOTAL_COST_UNVERIFIABLE` means no binding upper bound on all buyer costs is available; `details.reason` is `binding_cost_unavailable`. No payment operation or refill is authorized by this refusal. An earlier uncertain payment remains uncertain; the refusal does not cancel or release it. These errors use `FetchErrorResponse`. | - |
83
83
  | **403** | Policy violation, missing Crossmint payment permission (`PAYMENT_AUTHORIZATION_REQUIRED` — `details` carries the wallet-page URL where the authenticated user can enable payments), denylisted recipient, or a merchant challenge on a chain outside the wallet\'s own environment — a testnet wallet may not pay a mainnet challenge, nor the reverse (`WALLET_ENVIRONMENT_MISMATCH`; terminal, not retryable). All four use `FetchErrorResponse`. Alternatively an OAuth access token lacking the `fetch` scope (`InsufficientScopeResponse`, RFC 6750 `insufficient_scope`, with a `WWW-Authenticate` challenge). The two envelopes are disjoint; branch on the `error` value. | - |
84
84
  | **409** | `IDEMPOTENCY_CONFLICT` — this buyer already used the supplied `Idempotency-Key` for a different fetch request. Generate a new key for the new operation; retry the original operation unchanged. Or `WALLET_SETUP_INCOMPLETE` — the buyer\'s wallet has not been created yet, so there is nothing to pay from. `details.wallet_url` carries the page where the authenticated user finishes setup. No retry succeeds until they do. Or `ACCOUNT_CLOSING` — account closure has started, so the wallet cannot reserve a new payment. Or `FUNDING_PENDING` — retry after `details.retry_after_seconds`. `details.reason` is `funding_active` when a buyer-owned Base-to-Tempo refill exists, or `balance_changed` when an overlapping payment invalidated the balance observation before funding could start. Or `DELIVERY_REPLAY_UNAVAILABLE` — the merchant already returned a successful response for this settled MPP payment, but Weft could not persist its bytes for replay. The merchant is not called again; `details.tx_hash` identifies the settled payment. All five use `FetchErrorResponse`. | - |
85
85
  | **413** | Upstream artifact exceeded the proxy\'s size cap. | - |
86
- | **422** | Invalid request fields, method, cost, body, headers, idempotency key, or URL. `UNSUPPORTED_ASSET` means the merchant requested an asset this wallet cannot settle. `UNSUPPORTED_PAYMENT_METHOD` means the MPP challenge requested a method Weft cannot execute. | - |
86
+ | **422** | Invalid request fields, method, cost, body, headers, idempotency key, or URL. Safety controls use `INVALID_ALLOW_TEMPO_REFILL`, `INVALID_MAX_TOTAL_COST_USD`, or `INCOMPATIBLE_FETCH_CONTROLS`. `UNSUPPORTED_ASSET` means the merchant requested an asset this wallet cannot settle. `UNSUPPORTED_PAYMENT_METHOD` means the MPP challenge requested a method Weft cannot execute. | - |
87
87
  | **424** | `MERCHANT_RETURNED_NON_402` — the upstream merchant is at fault: it did not return a 402, or its 402 challenge was invalid. A 4xx (not 5xx) because Weft behaved correctly and the caller should act on `details.reason` (e.g. pick another merchant); it also keeps the error envelope intact through CDNs that replace 5xx bodies. `PAID_DELIVERY_FAILED` — the MPP payment settled, but the merchant did not deliver a successful response. `details.tx_hash` identifies the settled payment; `details.merchant_status` is present when the merchant returned an HTTP response. | - |
88
88
  | **502** | Merchant connection failure (`MERCHANT_CONNECTION_FAILED`) or settlement signing failed on Weft\'s side (`SETTLEMENT_FAILED`). For merchant failures, `details.phase` identifies challenge or paid; paid requests may have moved funds. Reuse the same idempotency key. `details.reason` carries a stable payment sentence. `details.protocol` names a direct payment rail when that is safe and useful. It is absent for automatic-funding failures so provider, bridge, and retry details stay internal. | - |
89
89
  | **504** | `MERCHANT_TIMEOUT` — the upstream merchant did not complete the challenge or paid request inside Weft\'s transport budget. `details.phase` names the request. When it is `paid`, `details.payment_may_have_moved` is true because the credential was already sent. Retry the identical operation with the same `Idempotency-Key`. `SETTLEMENT_PENDING` — the payment was submitted and the wallet provider had not reached a terminal state before Weft\'s polling budget ran out. NOTHING is known to have failed: the charge may already have settled, so this is not `SETTLEMENT_FAILED` and the amount is not lost. `details.retry_with_same_idempotency_key` is `true`. Retry the identical request shortly. Sending the same `Idempotency-Key` resumes the same provider operation; a caller that sends no key is also safe, because Weft resumes its own in-flight operation for the same merchant, amount and network rather than opening a second one. Either way the retry resolves the original payment instead of charging twice. | - |
@@ -8,6 +8,8 @@ Name | Type
8
8
  ------------ | -------------
9
9
  `url` | string
10
10
  `maxCostUsd` | string
11
+ `allowTempoRefill` | boolean
12
+ `maxTotalCostUsd` | string
11
13
  `method` | string
12
14
  `body` | [FetchRequestBody](FetchRequestBody.md)
13
15
  `headers` | { [key: string]: string; }
@@ -24,6 +26,8 @@ import type { FetchRequest } from '@weftlabs/sdk'
24
26
  const example = {
25
27
  "url": https://x402.api.agentmail.to/v0/inboxes,
26
28
  "maxCostUsd": 0.05,
29
+ "allowTempoRefill": false,
30
+ "maxTotalCostUsd": 0.05,
27
31
  "method": null,
28
32
  "body": null,
29
33
  "headers": {Accept=application/json, User-Agent=my-agent/1.0},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weftlabs/sdk",
3
- "version": "0.30.0",
3
+ "version": "0.31.0",
4
4
  "description": "Unified Weft SDK for the Weft API and x402 Facilitator",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",