@pafi-dev/issuer 0.3.0-beta.8 → 0.3.0-beta.9

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.cjs CHANGED
@@ -34,7 +34,6 @@ __export(index_exports, {
34
34
  PAFI_ISSUER_SDK_VERSION: () => PAFI_ISSUER_SDK_VERSION,
35
35
  PTRedeemError: () => PTRedeemError,
36
36
  PTRedeemHandler: () => PTRedeemHandler,
37
- PafiBackendClient: () => PafiBackendClient,
38
37
  PafiBackendError: () => PafiBackendError,
39
38
  PointIndexer: () => PointIndexer,
40
39
  PrivateKeySigner: () => PrivateKeySigner,
@@ -1842,37 +1841,16 @@ var PafiBackendError = class extends Error {
1842
1841
  code;
1843
1842
  httpStatus;
1844
1843
  details;
1845
- /**
1846
- * Seconds to wait before retry. Populated from the server body
1847
- * (e.g. rate limit returns the number of seconds until UTC midnight).
1848
- */
1849
1844
  retryAfter;
1850
- /**
1851
- * `safeToRetry` as reported by the server body. Prefer this over the
1852
- * code-based heuristic when available — the server knows more about
1853
- * whether the same request will succeed on retry.
1854
- */
1855
1845
  serverSafeToRetry;
1856
- /**
1857
- * Whether the caller can safely retry the same request.
1858
- *
1859
- * If the server provided `safeToRetry` in the body, trust that.
1860
- * Otherwise fall back to a code-based heuristic.
1861
- */
1862
1846
  get safeToRetry() {
1863
1847
  if (this.serverSafeToRetry !== void 0) return this.serverSafeToRetry;
1864
1848
  switch (this.code) {
1865
- // Transient infra
1866
- case "PAYMASTER_UNAVAILABLE":
1867
- case "PAYMASTER_TIMEOUT":
1868
1849
  case "RATE_LIMITER_UNAVAILABLE":
1869
- case "KMS_UNAVAILABLE":
1870
- case "SPONSOR_AUTH_SIGNING_FAILED":
1871
1850
  case "INTERNAL_ERROR":
1872
1851
  case "TIMEOUT":
1873
1852
  case "NETWORK_ERROR":
1874
1853
  return true;
1875
- // Rate-limited — safe to retry after retryAfter window
1876
1854
  case "RATE_LIMIT_EXCEEDED":
1877
1855
  case "RATE_LIMIT_EXCEEDED_DAILY":
1878
1856
  case "RATE_LIMIT_EXCEEDED_PER_USER":
@@ -1884,195 +1862,6 @@ var PafiBackendError = class extends Error {
1884
1862
  }
1885
1863
  };
1886
1864
 
1887
- // src/pafi-backend/pafiBackendClient.ts
1888
- var DEFAULT_TIMEOUT_MS = 1e4;
1889
- var RETRY_DEFAULTS = {
1890
- maxAttempts: 1,
1891
- initialDelayMs: 500,
1892
- maxDelayMs: 1e4,
1893
- maxRetryAfterMs: 3e4
1894
- };
1895
- var PafiBackendClient = class {
1896
- url;
1897
- issuerId;
1898
- apiKey;
1899
- fetchImpl;
1900
- timeoutMs;
1901
- retry;
1902
- constructor(config) {
1903
- if (!config.url) {
1904
- throw new Error("PafiBackendClient: url is required");
1905
- }
1906
- if (!config.issuerId) {
1907
- throw new Error("PafiBackendClient: issuerId is required");
1908
- }
1909
- if (!config.apiKey) {
1910
- throw new Error("PafiBackendClient: apiKey is required");
1911
- }
1912
- this.url = config.url.replace(/\/+$/, "");
1913
- this.issuerId = config.issuerId;
1914
- this.apiKey = config.apiKey;
1915
- this.fetchImpl = config.fetchImpl ?? globalThis.fetch;
1916
- this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1917
- this.retry = { ...RETRY_DEFAULTS, ...config.retry ?? {} };
1918
- if (!this.fetchImpl) {
1919
- throw new Error(
1920
- "PafiBackendClient: no fetch implementation available \u2014 pass `fetchImpl` or run on Node 18+"
1921
- );
1922
- }
1923
- if (this.retry.maxAttempts < 1) {
1924
- throw new Error("PafiBackendClient: retry.maxAttempts must be >= 1");
1925
- }
1926
- }
1927
- /**
1928
- * Request a SponsorAuth signature from PAFI sponsor-relayer (beta.8+).
1929
- *
1930
- * The relayer:
1931
- * 1. Authenticates user (JWT) + issuer (API key)
1932
- * 2. Per-(user, scenario) rate limit + per-issuer daily budget
1933
- * 3. Scenario-specific intent validation (mint cap, KYC, etc.)
1934
- * 4. Allocates nonce + signs SponsorAuth payload via KMS PAFI key
1935
- * 5. Returns `{ sponsorAuth, payload }` for the FE to forward to
1936
- * Privy's `signUserOperation({ sponsorAuth, payload })`.
1937
- *
1938
- * Retries on transient failures (5xx, timeouts, KMS unavailable,
1939
- * rate-limit-with-retryAfter). 4xx that are not `safeToRetry` fail fast.
1940
- *
1941
- * See `pafi-backend/docs/SPONSOR_AUTH_DESIGN.md` for the full spec.
1942
- *
1943
- * @throws PafiBackendError on final failure after exhausting retries
1944
- */
1945
- async requestSponsorAuth(req) {
1946
- return this.postWithRetry(
1947
- "/sponsor-auth",
1948
- req
1949
- );
1950
- }
1951
- /**
1952
- * @deprecated Coinbase paymaster path — replaced by `requestSponsorAuth`
1953
- * in beta.8. Will be removed in 1.0. Migrate by:
1954
- * 1. Switch to `requestSponsorAuth` returning `{ sponsorAuth, payload }`
1955
- * 2. Pass both to Privy `signUserOperation` instead of merging
1956
- * paymasterData into the UserOp callData
1957
- */
1958
- async requestSponsorship(req) {
1959
- return this.postWithRetry(
1960
- "/paymaster/sponsor",
1961
- req
1962
- );
1963
- }
1964
- // -------------------------------------------------------------------------
1965
- // Internals
1966
- // -------------------------------------------------------------------------
1967
- async postWithRetry(path, body) {
1968
- let lastError;
1969
- for (let attempt = 1; attempt <= this.retry.maxAttempts; attempt++) {
1970
- try {
1971
- return await this.post(path, body);
1972
- } catch (err) {
1973
- if (!(err instanceof PafiBackendError)) throw err;
1974
- lastError = err;
1975
- const isLastAttempt = attempt >= this.retry.maxAttempts;
1976
- if (isLastAttempt || !err.safeToRetry) throw err;
1977
- const delay = this.computeBackoff(attempt, err.retryAfter);
1978
- if (delay === null) throw err;
1979
- await this.sleep(delay);
1980
- }
1981
- }
1982
- throw lastError;
1983
- }
1984
- /**
1985
- * Pick the delay before the next retry.
1986
- * - If the server sent `retryAfter` (seconds), honor it (capped by
1987
- * `maxRetryAfterMs`) — returns null if the server wait exceeds the
1988
- * cap, signalling the caller should give up.
1989
- * - Otherwise: exponential backoff with ±20% jitter, capped at
1990
- * `maxDelayMs`.
1991
- */
1992
- computeBackoff(attempt, retryAfter) {
1993
- if (retryAfter !== void 0) {
1994
- const serverMs = retryAfter * 1e3;
1995
- if (serverMs > this.retry.maxRetryAfterMs) return null;
1996
- return serverMs;
1997
- }
1998
- const exp = this.retry.initialDelayMs * 2 ** (attempt - 1);
1999
- const capped = Math.min(exp, this.retry.maxDelayMs);
2000
- const jitter = capped * (0.8 + Math.random() * 0.4);
2001
- return Math.round(jitter);
2002
- }
2003
- sleep(ms) {
2004
- return new Promise((resolve) => setTimeout(resolve, ms));
2005
- }
2006
- async post(path, body) {
2007
- const controller = new AbortController();
2008
- const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
2009
- let response;
2010
- try {
2011
- response = await this.fetchImpl(`${this.url}${path}`, {
2012
- method: "POST",
2013
- headers: {
2014
- "Content-Type": "application/json",
2015
- "Authorization": `Bearer ${this.apiKey}`,
2016
- "X-Issuer-Id": this.issuerId
2017
- },
2018
- body: JSON.stringify(body, this.bigintReplacer),
2019
- signal: controller.signal
2020
- });
2021
- } catch (err) {
2022
- if (err.name === "AbortError") {
2023
- throw new PafiBackendError(
2024
- "TIMEOUT",
2025
- `PAFI Backend request timed out after ${this.timeoutMs}ms`,
2026
- 0
2027
- );
2028
- }
2029
- throw new PafiBackendError(
2030
- "NETWORK_ERROR",
2031
- `PAFI Backend unreachable: ${err.message}`,
2032
- 0
2033
- );
2034
- } finally {
2035
- clearTimeout(timeoutId);
2036
- }
2037
- const text = await response.text();
2038
- if (!response.ok) {
2039
- let code = "INTERNAL_ERROR";
2040
- let message = text || response.statusText;
2041
- let details;
2042
- let retryAfter;
2043
- let serverSafeToRetry;
2044
- try {
2045
- const parsed = JSON.parse(text);
2046
- code = parsed.code ?? code;
2047
- message = parsed.message ?? message;
2048
- details = parsed.details;
2049
- if (typeof parsed.retryAfter === "number") retryAfter = parsed.retryAfter;
2050
- if (typeof parsed.safeToRetry === "boolean") serverSafeToRetry = parsed.safeToRetry;
2051
- } catch {
2052
- }
2053
- throw new PafiBackendError(code, message, response.status, details, {
2054
- ...retryAfter !== void 0 ? { retryAfter } : {},
2055
- ...serverSafeToRetry !== void 0 ? { safeToRetry: serverSafeToRetry } : {}
2056
- });
2057
- }
2058
- return JSON.parse(text, this.bigintReviver);
2059
- }
2060
- /** JSON replacer that stringifies bigints. Paired with bigintReviver. */
2061
- bigintReplacer = (_key, value) => {
2062
- return typeof value === "bigint" ? value.toString() : value;
2063
- };
2064
- /**
2065
- * JSON reviver that coerces specific numeric-string fields back to
2066
- * bigint. The server must send these fields as decimal strings.
2067
- */
2068
- bigintReviver = (key, value) => {
2069
- if (typeof value === "string" && (key.endsWith("GasLimit") || key === "nonce" || key === "callGasLimit" || key === "verificationGasLimit" || key === "preVerificationGas" || key === "maxFeePerGas" || key === "maxPriorityFeePerGas" || key === "paymasterVerificationGasLimit" || key === "paymasterPostOpGasLimit") && /^\d+$/.test(value)) {
2070
- return BigInt(value);
2071
- }
2072
- return value;
2073
- };
2074
- };
2075
-
2076
1865
  // src/config.ts
2077
1866
  var import_viem11 = require("viem");
2078
1867
  function createIssuerService(config) {
@@ -2185,7 +1974,6 @@ var PAFI_ISSUER_SDK_VERSION = "0.1.0";
2185
1974
  PAFI_ISSUER_SDK_VERSION,
2186
1975
  PTRedeemError,
2187
1976
  PTRedeemHandler,
2188
- PafiBackendClient,
2189
1977
  PafiBackendError,
2190
1978
  PointIndexer,
2191
1979
  PrivateKeySigner,