@pafi-dev/issuer 0.3.0-beta.7 → 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 +1 -188
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -129
- package/dist/index.d.ts +3 -129
- package/dist/index.js +1 -187
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
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,28 +1841,11 @@ 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
|
-
case "PAYMASTER_UNAVAILABLE":
|
|
1866
|
-
case "PAYMASTER_TIMEOUT":
|
|
1867
1849
|
case "RATE_LIMITER_UNAVAILABLE":
|
|
1868
1850
|
case "INTERNAL_ERROR":
|
|
1869
1851
|
case "TIMEOUT":
|
|
@@ -1872,182 +1854,14 @@ var PafiBackendError = class extends Error {
|
|
|
1872
1854
|
case "RATE_LIMIT_EXCEEDED":
|
|
1873
1855
|
case "RATE_LIMIT_EXCEEDED_DAILY":
|
|
1874
1856
|
case "RATE_LIMIT_EXCEEDED_PER_USER":
|
|
1857
|
+
case "ISSUER_BUDGET_EXCEEDED":
|
|
1875
1858
|
return true;
|
|
1876
|
-
// after retryAfter
|
|
1877
1859
|
default:
|
|
1878
1860
|
return false;
|
|
1879
1861
|
}
|
|
1880
1862
|
}
|
|
1881
1863
|
};
|
|
1882
1864
|
|
|
1883
|
-
// src/pafi-backend/pafiBackendClient.ts
|
|
1884
|
-
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
1885
|
-
var RETRY_DEFAULTS = {
|
|
1886
|
-
maxAttempts: 1,
|
|
1887
|
-
initialDelayMs: 500,
|
|
1888
|
-
maxDelayMs: 1e4,
|
|
1889
|
-
maxRetryAfterMs: 3e4
|
|
1890
|
-
};
|
|
1891
|
-
var PafiBackendClient = class {
|
|
1892
|
-
url;
|
|
1893
|
-
issuerId;
|
|
1894
|
-
apiKey;
|
|
1895
|
-
fetchImpl;
|
|
1896
|
-
timeoutMs;
|
|
1897
|
-
retry;
|
|
1898
|
-
constructor(config) {
|
|
1899
|
-
if (!config.url) {
|
|
1900
|
-
throw new Error("PafiBackendClient: url is required");
|
|
1901
|
-
}
|
|
1902
|
-
if (!config.issuerId) {
|
|
1903
|
-
throw new Error("PafiBackendClient: issuerId is required");
|
|
1904
|
-
}
|
|
1905
|
-
if (!config.apiKey) {
|
|
1906
|
-
throw new Error("PafiBackendClient: apiKey is required");
|
|
1907
|
-
}
|
|
1908
|
-
this.url = config.url.replace(/\/+$/, "");
|
|
1909
|
-
this.issuerId = config.issuerId;
|
|
1910
|
-
this.apiKey = config.apiKey;
|
|
1911
|
-
this.fetchImpl = config.fetchImpl ?? globalThis.fetch;
|
|
1912
|
-
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
1913
|
-
this.retry = { ...RETRY_DEFAULTS, ...config.retry ?? {} };
|
|
1914
|
-
if (!this.fetchImpl) {
|
|
1915
|
-
throw new Error(
|
|
1916
|
-
"PafiBackendClient: no fetch implementation available \u2014 pass `fetchImpl` or run on Node 18+"
|
|
1917
|
-
);
|
|
1918
|
-
}
|
|
1919
|
-
if (this.retry.maxAttempts < 1) {
|
|
1920
|
-
throw new Error("PafiBackendClient: retry.maxAttempts must be >= 1");
|
|
1921
|
-
}
|
|
1922
|
-
}
|
|
1923
|
-
/**
|
|
1924
|
-
* Request paymaster sponsorship for a pre-built UserOperation.
|
|
1925
|
-
* See [SPONSORED_PATH_FLOW.md §4.1] for the API contract.
|
|
1926
|
-
*
|
|
1927
|
-
* Retries automatically on transient failures (5xx, timeouts, network
|
|
1928
|
-
* errors, and errors the server flags with `safeToRetry: true`) up to
|
|
1929
|
-
* `retry.maxAttempts`. 4xx errors that are not `safeToRetry` fail fast.
|
|
1930
|
-
*
|
|
1931
|
-
* @throws PafiBackendError on final failure after exhausting retries
|
|
1932
|
-
*/
|
|
1933
|
-
async requestSponsorship(req) {
|
|
1934
|
-
return this.postWithRetry(
|
|
1935
|
-
"/paymaster/sponsor",
|
|
1936
|
-
req
|
|
1937
|
-
);
|
|
1938
|
-
}
|
|
1939
|
-
// -------------------------------------------------------------------------
|
|
1940
|
-
// Internals
|
|
1941
|
-
// -------------------------------------------------------------------------
|
|
1942
|
-
async postWithRetry(path, body) {
|
|
1943
|
-
let lastError;
|
|
1944
|
-
for (let attempt = 1; attempt <= this.retry.maxAttempts; attempt++) {
|
|
1945
|
-
try {
|
|
1946
|
-
return await this.post(path, body);
|
|
1947
|
-
} catch (err) {
|
|
1948
|
-
if (!(err instanceof PafiBackendError)) throw err;
|
|
1949
|
-
lastError = err;
|
|
1950
|
-
const isLastAttempt = attempt >= this.retry.maxAttempts;
|
|
1951
|
-
if (isLastAttempt || !err.safeToRetry) throw err;
|
|
1952
|
-
const delay = this.computeBackoff(attempt, err.retryAfter);
|
|
1953
|
-
if (delay === null) throw err;
|
|
1954
|
-
await this.sleep(delay);
|
|
1955
|
-
}
|
|
1956
|
-
}
|
|
1957
|
-
throw lastError;
|
|
1958
|
-
}
|
|
1959
|
-
/**
|
|
1960
|
-
* Pick the delay before the next retry.
|
|
1961
|
-
* - If the server sent `retryAfter` (seconds), honor it (capped by
|
|
1962
|
-
* `maxRetryAfterMs`) — returns null if the server wait exceeds the
|
|
1963
|
-
* cap, signalling the caller should give up.
|
|
1964
|
-
* - Otherwise: exponential backoff with ±20% jitter, capped at
|
|
1965
|
-
* `maxDelayMs`.
|
|
1966
|
-
*/
|
|
1967
|
-
computeBackoff(attempt, retryAfter) {
|
|
1968
|
-
if (retryAfter !== void 0) {
|
|
1969
|
-
const serverMs = retryAfter * 1e3;
|
|
1970
|
-
if (serverMs > this.retry.maxRetryAfterMs) return null;
|
|
1971
|
-
return serverMs;
|
|
1972
|
-
}
|
|
1973
|
-
const exp = this.retry.initialDelayMs * 2 ** (attempt - 1);
|
|
1974
|
-
const capped = Math.min(exp, this.retry.maxDelayMs);
|
|
1975
|
-
const jitter = capped * (0.8 + Math.random() * 0.4);
|
|
1976
|
-
return Math.round(jitter);
|
|
1977
|
-
}
|
|
1978
|
-
sleep(ms) {
|
|
1979
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1980
|
-
}
|
|
1981
|
-
async post(path, body) {
|
|
1982
|
-
const controller = new AbortController();
|
|
1983
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
1984
|
-
let response;
|
|
1985
|
-
try {
|
|
1986
|
-
response = await this.fetchImpl(`${this.url}${path}`, {
|
|
1987
|
-
method: "POST",
|
|
1988
|
-
headers: {
|
|
1989
|
-
"Content-Type": "application/json",
|
|
1990
|
-
"Authorization": `Bearer ${this.apiKey}`,
|
|
1991
|
-
"X-Issuer-Id": this.issuerId
|
|
1992
|
-
},
|
|
1993
|
-
body: JSON.stringify(body, this.bigintReplacer),
|
|
1994
|
-
signal: controller.signal
|
|
1995
|
-
});
|
|
1996
|
-
} catch (err) {
|
|
1997
|
-
if (err.name === "AbortError") {
|
|
1998
|
-
throw new PafiBackendError(
|
|
1999
|
-
"TIMEOUT",
|
|
2000
|
-
`PAFI Backend request timed out after ${this.timeoutMs}ms`,
|
|
2001
|
-
0
|
|
2002
|
-
);
|
|
2003
|
-
}
|
|
2004
|
-
throw new PafiBackendError(
|
|
2005
|
-
"NETWORK_ERROR",
|
|
2006
|
-
`PAFI Backend unreachable: ${err.message}`,
|
|
2007
|
-
0
|
|
2008
|
-
);
|
|
2009
|
-
} finally {
|
|
2010
|
-
clearTimeout(timeoutId);
|
|
2011
|
-
}
|
|
2012
|
-
const text = await response.text();
|
|
2013
|
-
if (!response.ok) {
|
|
2014
|
-
let code = "INTERNAL_ERROR";
|
|
2015
|
-
let message = text || response.statusText;
|
|
2016
|
-
let details;
|
|
2017
|
-
let retryAfter;
|
|
2018
|
-
let serverSafeToRetry;
|
|
2019
|
-
try {
|
|
2020
|
-
const parsed = JSON.parse(text);
|
|
2021
|
-
code = parsed.code ?? code;
|
|
2022
|
-
message = parsed.message ?? message;
|
|
2023
|
-
details = parsed.details;
|
|
2024
|
-
if (typeof parsed.retryAfter === "number") retryAfter = parsed.retryAfter;
|
|
2025
|
-
if (typeof parsed.safeToRetry === "boolean") serverSafeToRetry = parsed.safeToRetry;
|
|
2026
|
-
} catch {
|
|
2027
|
-
}
|
|
2028
|
-
throw new PafiBackendError(code, message, response.status, details, {
|
|
2029
|
-
...retryAfter !== void 0 ? { retryAfter } : {},
|
|
2030
|
-
...serverSafeToRetry !== void 0 ? { safeToRetry: serverSafeToRetry } : {}
|
|
2031
|
-
});
|
|
2032
|
-
}
|
|
2033
|
-
return JSON.parse(text, this.bigintReviver);
|
|
2034
|
-
}
|
|
2035
|
-
/** JSON replacer that stringifies bigints. Paired with bigintReviver. */
|
|
2036
|
-
bigintReplacer = (_key, value) => {
|
|
2037
|
-
return typeof value === "bigint" ? value.toString() : value;
|
|
2038
|
-
};
|
|
2039
|
-
/**
|
|
2040
|
-
* JSON reviver that coerces specific numeric-string fields back to
|
|
2041
|
-
* bigint. The server must send these fields as decimal strings.
|
|
2042
|
-
*/
|
|
2043
|
-
bigintReviver = (key, value) => {
|
|
2044
|
-
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)) {
|
|
2045
|
-
return BigInt(value);
|
|
2046
|
-
}
|
|
2047
|
-
return value;
|
|
2048
|
-
};
|
|
2049
|
-
};
|
|
2050
|
-
|
|
2051
1865
|
// src/config.ts
|
|
2052
1866
|
var import_viem11 = require("viem");
|
|
2053
1867
|
function createIssuerService(config) {
|
|
@@ -2160,7 +1974,6 @@ var PAFI_ISSUER_SDK_VERSION = "0.1.0";
|
|
|
2160
1974
|
PAFI_ISSUER_SDK_VERSION,
|
|
2161
1975
|
PTRedeemError,
|
|
2162
1976
|
PTRedeemHandler,
|
|
2163
|
-
PafiBackendClient,
|
|
2164
1977
|
PafiBackendError,
|
|
2165
1978
|
PointIndexer,
|
|
2166
1979
|
PrivateKeySigner,
|