@pafi-dev/issuer 0.31.0 → 0.32.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/dist/index.cjs +75 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -9
- package/dist/index.d.ts +75 -9
- package/dist/index.js +67 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1551,9 +1551,18 @@ interface SettlementClientConfig {
|
|
|
1551
1551
|
/**
|
|
1552
1552
|
* chainId — used to derive the issuer-api base URL via
|
|
1553
1553
|
* `getPafiServiceUrls(chainId).issuerApi`. SDK ships with the URL
|
|
1554
|
-
* per chainId; bump SDK version to retarget
|
|
1554
|
+
* per chainId; bump SDK version to retarget — OR pass `baseUrl`
|
|
1555
|
+
* to override per-deployment.
|
|
1555
1556
|
*/
|
|
1556
1557
|
chainId: number;
|
|
1558
|
+
/**
|
|
1559
|
+
* Optional override for the issuer-api base URL. Audit PACI5-17 —
|
|
1560
|
+
* production issuer backends should set this from an env var
|
|
1561
|
+
* (e.g. `PAFI_ISSUER_API_URL`) so the deployed binary doesn't
|
|
1562
|
+
* depend on the SDK ship-default that may target dev infrastructure.
|
|
1563
|
+
* Undefined / empty → use the ship-default for `chainId`.
|
|
1564
|
+
*/
|
|
1565
|
+
baseUrl?: string;
|
|
1557
1566
|
/** PAFI-assigned issuer id used in `X-Issuer-Id` header. */
|
|
1558
1567
|
issuerId: string;
|
|
1559
1568
|
/** Raw API key sent as `Authorization: Bearer <apiKey>`. */
|
|
@@ -1566,6 +1575,34 @@ interface SettlementClientConfig {
|
|
|
1566
1575
|
interface PolicyProviderConfig extends SettlementClientConfig {
|
|
1567
1576
|
/** Cache TTL in milliseconds. Default 5 * 60 * 1000 (5min). */
|
|
1568
1577
|
cacheTtlMs?: number;
|
|
1578
|
+
/**
|
|
1579
|
+
* Behavior khi settlement-api fetch fail (network blip, 5xx, timeout).
|
|
1580
|
+
*
|
|
1581
|
+
* Audit PACI5-17 — the pre-flight redeem limit is the SOLE gate
|
|
1582
|
+
* before the issuer signer mints a BurnRequest. Silently degrading
|
|
1583
|
+
* to a permissive default during settlement outages let users
|
|
1584
|
+
* exceed their configured limit until the outage cleared.
|
|
1585
|
+
*
|
|
1586
|
+
* - `'fail-closed'` (DEFAULT, recommended): throw
|
|
1587
|
+
* `PolicyProviderUnavailableError`. Caller maps to HTTP 503 so
|
|
1588
|
+
* the FE can retry; redemptions are blocked until policy fetch
|
|
1589
|
+
* succeeds.
|
|
1590
|
+
*
|
|
1591
|
+
* - `'permissive-default'`: return `defaultPolicyFor(issuerId)` and
|
|
1592
|
+
* fire `onWarning`. Pre-fix behavior. Operators who genuinely
|
|
1593
|
+
* prefer availability over enforcement (e.g. test issuers, low-
|
|
1594
|
+
* risk PT) MUST opt in explicitly AND wire `onWarning` to a
|
|
1595
|
+
* pager / Slack / Sentry alert. Silent permissive fallback is no
|
|
1596
|
+
* longer the default.
|
|
1597
|
+
*/
|
|
1598
|
+
onFetchFailure?: "fail-closed" | "permissive-default";
|
|
1599
|
+
/**
|
|
1600
|
+
* Observability hook for non-fatal events: permissive-default
|
|
1601
|
+
* fallbacks (when explicitly opted in). Wire to your logger /
|
|
1602
|
+
* Sentry / Datadog so the `policy_provider_fallback` event reaches
|
|
1603
|
+
* the on-call dashboard.
|
|
1604
|
+
*/
|
|
1605
|
+
onWarning?: (msg: string, ctx: Record<string, unknown>) => void;
|
|
1569
1606
|
/**
|
|
1570
1607
|
* Optional clock for testability. Returns unix milliseconds.
|
|
1571
1608
|
* Defaults to () => Date.now().
|
|
@@ -1596,6 +1633,8 @@ declare class PolicyProvider {
|
|
|
1596
1633
|
private readonly client;
|
|
1597
1634
|
private readonly issuerId;
|
|
1598
1635
|
private readonly cacheTtlMs;
|
|
1636
|
+
private readonly onFetchFailure;
|
|
1637
|
+
private readonly onWarning?;
|
|
1599
1638
|
private readonly now;
|
|
1600
1639
|
private cache;
|
|
1601
1640
|
private inflight;
|
|
@@ -1987,7 +2026,7 @@ interface PTRedeemResponse {
|
|
|
1987
2026
|
/** The BurnRequest deadline (unix seconds) — FE uses this to surface a countdown. */
|
|
1988
2027
|
signatureDeadline: bigint;
|
|
1989
2028
|
}
|
|
1990
|
-
type PTRedeemErrorCode = "UNAUTHORIZED" | "INVALID_AMOUNT" | "NONCE_READ_FAILED" | "NONCE_IN_FLIGHT" | "LEDGER_NOT_SUPPORTED" | "SIGNING_FAILED" | "REDEMPTION_POLICY_DENIED" | "UNSUPPORTED_POINT_TOKEN";
|
|
2029
|
+
type PTRedeemErrorCode = "UNAUTHORIZED" | "INVALID_AMOUNT" | "NONCE_READ_FAILED" | "NONCE_IN_FLIGHT" | "LEDGER_NOT_SUPPORTED" | "SIGNING_FAILED" | "REDEMPTION_POLICY_DENIED" | "REDEMPTION_POLICY_UNAVAILABLE" | "UNSUPPORTED_POINT_TOKEN";
|
|
1991
2030
|
declare class PTRedeemError extends PafiSdkError {
|
|
1992
2031
|
readonly httpStatus: "unprocessable";
|
|
1993
2032
|
readonly code: PTRedeemErrorCode;
|
|
@@ -2039,9 +2078,18 @@ interface PafiBackendConfig {
|
|
|
2039
2078
|
/**
|
|
2040
2079
|
* chainId — used to derive the sponsor-relayer base URL via
|
|
2041
2080
|
* `getPafiServiceUrls(chainId).sponsorRelayer`. SDK ships with the
|
|
2042
|
-
* URL per chainId; bump SDK version to retarget
|
|
2081
|
+
* URL per chainId; bump SDK version to retarget — OR pass
|
|
2082
|
+
* `baseUrl` to override per-deployment.
|
|
2043
2083
|
*/
|
|
2044
2084
|
chainId: number;
|
|
2085
|
+
/**
|
|
2086
|
+
* Optional override for the sponsor-relayer base URL. Audit
|
|
2087
|
+
* PACI5-17 — production issuer backends should set this from an env
|
|
2088
|
+
* var (e.g. `PAFI_SPONSOR_RELAYER_URL`) so the binary doesn't depend
|
|
2089
|
+
* on the SDK ship-default that may target dev infrastructure.
|
|
2090
|
+
* Undefined / empty → use the ship-default for `chainId`.
|
|
2091
|
+
*/
|
|
2092
|
+
baseUrl?: string;
|
|
2045
2093
|
issuerId: string;
|
|
2046
2094
|
apiKey: string;
|
|
2047
2095
|
fetchImpl?: typeof fetch;
|
|
@@ -3185,6 +3233,30 @@ interface IssuerServiceConfig {
|
|
|
3185
3233
|
issuerId: string;
|
|
3186
3234
|
apiKey: string;
|
|
3187
3235
|
historyStore: IRedemptionHistoryStore;
|
|
3236
|
+
/**
|
|
3237
|
+
* Optional override for the PAFI issuer-api base URL. Audit
|
|
3238
|
+
* PACI5-17 — production issuer backends should set this from an
|
|
3239
|
+
* env var (e.g. `PAFI_ISSUER_API_URL`) so policy fetch hits the
|
|
3240
|
+
* canonical environment for the deploy. Undefined → SDK
|
|
3241
|
+
* ship-default per chainId.
|
|
3242
|
+
*/
|
|
3243
|
+
baseUrl?: string;
|
|
3244
|
+
/**
|
|
3245
|
+
* Behavior khi settlement-api fetch fail. Default `'fail-closed'`
|
|
3246
|
+
* (audit PACI5-17 — pre-flight redeem limit is the sole gate; do
|
|
3247
|
+
* not silently degrade to a permissive default).
|
|
3248
|
+
*
|
|
3249
|
+
* Opt in to `'permissive-default'` ONLY when paired with an alert
|
|
3250
|
+
* on the `policy_provider_fallback` event surfaced via
|
|
3251
|
+
* `onPolicyWarning`.
|
|
3252
|
+
*/
|
|
3253
|
+
onFetchFailure?: "fail-closed" | "permissive-default";
|
|
3254
|
+
/**
|
|
3255
|
+
* Observability hook for `policy_provider_fallback` events. Wire
|
|
3256
|
+
* to your logger / Sentry / Datadog so the on-call dashboard sees
|
|
3257
|
+
* settlement-api degradation.
|
|
3258
|
+
*/
|
|
3259
|
+
onPolicyWarning?: (msg: string, ctx: Record<string, unknown>) => void;
|
|
3188
3260
|
/** Override fetch (testing). */
|
|
3189
3261
|
fetchImpl?: typeof fetch;
|
|
3190
3262
|
/** Per-fetch timeout in ms. Default 1000. */
|
|
@@ -3354,12 +3426,6 @@ interface RedeemPrepareDto extends MobilePrepareDto {
|
|
|
3354
3426
|
* Lock id reserved for the FALLBACK redeem path (= full `amount`).
|
|
3355
3427
|
* Mobile FE polls `/redeem/status/:lockIdFallback` when it submits
|
|
3356
3428
|
* the fallback variant (`variant: 'fallback'` on `/redeem/submit`).
|
|
3357
|
-
*
|
|
3358
|
-
* Audit PACI5-21 — pre-fix the adapter exposed only the sponsored
|
|
3359
|
-
* `lockId` (= `amount - fee`), so the bundler-receipt fallback in
|
|
3360
|
-
* `handleRedeemStatus` resolved the smaller credit against the
|
|
3361
|
-
* on-chain burn of the full amount → user under-credited by exactly
|
|
3362
|
-
* the fee on every fallback redeem.
|
|
3363
3429
|
*/
|
|
3364
3430
|
lockIdFallback?: string;
|
|
3365
3431
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1551,9 +1551,18 @@ interface SettlementClientConfig {
|
|
|
1551
1551
|
/**
|
|
1552
1552
|
* chainId — used to derive the issuer-api base URL via
|
|
1553
1553
|
* `getPafiServiceUrls(chainId).issuerApi`. SDK ships with the URL
|
|
1554
|
-
* per chainId; bump SDK version to retarget
|
|
1554
|
+
* per chainId; bump SDK version to retarget — OR pass `baseUrl`
|
|
1555
|
+
* to override per-deployment.
|
|
1555
1556
|
*/
|
|
1556
1557
|
chainId: number;
|
|
1558
|
+
/**
|
|
1559
|
+
* Optional override for the issuer-api base URL. Audit PACI5-17 —
|
|
1560
|
+
* production issuer backends should set this from an env var
|
|
1561
|
+
* (e.g. `PAFI_ISSUER_API_URL`) so the deployed binary doesn't
|
|
1562
|
+
* depend on the SDK ship-default that may target dev infrastructure.
|
|
1563
|
+
* Undefined / empty → use the ship-default for `chainId`.
|
|
1564
|
+
*/
|
|
1565
|
+
baseUrl?: string;
|
|
1557
1566
|
/** PAFI-assigned issuer id used in `X-Issuer-Id` header. */
|
|
1558
1567
|
issuerId: string;
|
|
1559
1568
|
/** Raw API key sent as `Authorization: Bearer <apiKey>`. */
|
|
@@ -1566,6 +1575,34 @@ interface SettlementClientConfig {
|
|
|
1566
1575
|
interface PolicyProviderConfig extends SettlementClientConfig {
|
|
1567
1576
|
/** Cache TTL in milliseconds. Default 5 * 60 * 1000 (5min). */
|
|
1568
1577
|
cacheTtlMs?: number;
|
|
1578
|
+
/**
|
|
1579
|
+
* Behavior khi settlement-api fetch fail (network blip, 5xx, timeout).
|
|
1580
|
+
*
|
|
1581
|
+
* Audit PACI5-17 — the pre-flight redeem limit is the SOLE gate
|
|
1582
|
+
* before the issuer signer mints a BurnRequest. Silently degrading
|
|
1583
|
+
* to a permissive default during settlement outages let users
|
|
1584
|
+
* exceed their configured limit until the outage cleared.
|
|
1585
|
+
*
|
|
1586
|
+
* - `'fail-closed'` (DEFAULT, recommended): throw
|
|
1587
|
+
* `PolicyProviderUnavailableError`. Caller maps to HTTP 503 so
|
|
1588
|
+
* the FE can retry; redemptions are blocked until policy fetch
|
|
1589
|
+
* succeeds.
|
|
1590
|
+
*
|
|
1591
|
+
* - `'permissive-default'`: return `defaultPolicyFor(issuerId)` and
|
|
1592
|
+
* fire `onWarning`. Pre-fix behavior. Operators who genuinely
|
|
1593
|
+
* prefer availability over enforcement (e.g. test issuers, low-
|
|
1594
|
+
* risk PT) MUST opt in explicitly AND wire `onWarning` to a
|
|
1595
|
+
* pager / Slack / Sentry alert. Silent permissive fallback is no
|
|
1596
|
+
* longer the default.
|
|
1597
|
+
*/
|
|
1598
|
+
onFetchFailure?: "fail-closed" | "permissive-default";
|
|
1599
|
+
/**
|
|
1600
|
+
* Observability hook for non-fatal events: permissive-default
|
|
1601
|
+
* fallbacks (when explicitly opted in). Wire to your logger /
|
|
1602
|
+
* Sentry / Datadog so the `policy_provider_fallback` event reaches
|
|
1603
|
+
* the on-call dashboard.
|
|
1604
|
+
*/
|
|
1605
|
+
onWarning?: (msg: string, ctx: Record<string, unknown>) => void;
|
|
1569
1606
|
/**
|
|
1570
1607
|
* Optional clock for testability. Returns unix milliseconds.
|
|
1571
1608
|
* Defaults to () => Date.now().
|
|
@@ -1596,6 +1633,8 @@ declare class PolicyProvider {
|
|
|
1596
1633
|
private readonly client;
|
|
1597
1634
|
private readonly issuerId;
|
|
1598
1635
|
private readonly cacheTtlMs;
|
|
1636
|
+
private readonly onFetchFailure;
|
|
1637
|
+
private readonly onWarning?;
|
|
1599
1638
|
private readonly now;
|
|
1600
1639
|
private cache;
|
|
1601
1640
|
private inflight;
|
|
@@ -1987,7 +2026,7 @@ interface PTRedeemResponse {
|
|
|
1987
2026
|
/** The BurnRequest deadline (unix seconds) — FE uses this to surface a countdown. */
|
|
1988
2027
|
signatureDeadline: bigint;
|
|
1989
2028
|
}
|
|
1990
|
-
type PTRedeemErrorCode = "UNAUTHORIZED" | "INVALID_AMOUNT" | "NONCE_READ_FAILED" | "NONCE_IN_FLIGHT" | "LEDGER_NOT_SUPPORTED" | "SIGNING_FAILED" | "REDEMPTION_POLICY_DENIED" | "UNSUPPORTED_POINT_TOKEN";
|
|
2029
|
+
type PTRedeemErrorCode = "UNAUTHORIZED" | "INVALID_AMOUNT" | "NONCE_READ_FAILED" | "NONCE_IN_FLIGHT" | "LEDGER_NOT_SUPPORTED" | "SIGNING_FAILED" | "REDEMPTION_POLICY_DENIED" | "REDEMPTION_POLICY_UNAVAILABLE" | "UNSUPPORTED_POINT_TOKEN";
|
|
1991
2030
|
declare class PTRedeemError extends PafiSdkError {
|
|
1992
2031
|
readonly httpStatus: "unprocessable";
|
|
1993
2032
|
readonly code: PTRedeemErrorCode;
|
|
@@ -2039,9 +2078,18 @@ interface PafiBackendConfig {
|
|
|
2039
2078
|
/**
|
|
2040
2079
|
* chainId — used to derive the sponsor-relayer base URL via
|
|
2041
2080
|
* `getPafiServiceUrls(chainId).sponsorRelayer`. SDK ships with the
|
|
2042
|
-
* URL per chainId; bump SDK version to retarget
|
|
2081
|
+
* URL per chainId; bump SDK version to retarget — OR pass
|
|
2082
|
+
* `baseUrl` to override per-deployment.
|
|
2043
2083
|
*/
|
|
2044
2084
|
chainId: number;
|
|
2085
|
+
/**
|
|
2086
|
+
* Optional override for the sponsor-relayer base URL. Audit
|
|
2087
|
+
* PACI5-17 — production issuer backends should set this from an env
|
|
2088
|
+
* var (e.g. `PAFI_SPONSOR_RELAYER_URL`) so the binary doesn't depend
|
|
2089
|
+
* on the SDK ship-default that may target dev infrastructure.
|
|
2090
|
+
* Undefined / empty → use the ship-default for `chainId`.
|
|
2091
|
+
*/
|
|
2092
|
+
baseUrl?: string;
|
|
2045
2093
|
issuerId: string;
|
|
2046
2094
|
apiKey: string;
|
|
2047
2095
|
fetchImpl?: typeof fetch;
|
|
@@ -3185,6 +3233,30 @@ interface IssuerServiceConfig {
|
|
|
3185
3233
|
issuerId: string;
|
|
3186
3234
|
apiKey: string;
|
|
3187
3235
|
historyStore: IRedemptionHistoryStore;
|
|
3236
|
+
/**
|
|
3237
|
+
* Optional override for the PAFI issuer-api base URL. Audit
|
|
3238
|
+
* PACI5-17 — production issuer backends should set this from an
|
|
3239
|
+
* env var (e.g. `PAFI_ISSUER_API_URL`) so policy fetch hits the
|
|
3240
|
+
* canonical environment for the deploy. Undefined → SDK
|
|
3241
|
+
* ship-default per chainId.
|
|
3242
|
+
*/
|
|
3243
|
+
baseUrl?: string;
|
|
3244
|
+
/**
|
|
3245
|
+
* Behavior khi settlement-api fetch fail. Default `'fail-closed'`
|
|
3246
|
+
* (audit PACI5-17 — pre-flight redeem limit is the sole gate; do
|
|
3247
|
+
* not silently degrade to a permissive default).
|
|
3248
|
+
*
|
|
3249
|
+
* Opt in to `'permissive-default'` ONLY when paired with an alert
|
|
3250
|
+
* on the `policy_provider_fallback` event surfaced via
|
|
3251
|
+
* `onPolicyWarning`.
|
|
3252
|
+
*/
|
|
3253
|
+
onFetchFailure?: "fail-closed" | "permissive-default";
|
|
3254
|
+
/**
|
|
3255
|
+
* Observability hook for `policy_provider_fallback` events. Wire
|
|
3256
|
+
* to your logger / Sentry / Datadog so the on-call dashboard sees
|
|
3257
|
+
* settlement-api degradation.
|
|
3258
|
+
*/
|
|
3259
|
+
onPolicyWarning?: (msg: string, ctx: Record<string, unknown>) => void;
|
|
3188
3260
|
/** Override fetch (testing). */
|
|
3189
3261
|
fetchImpl?: typeof fetch;
|
|
3190
3262
|
/** Per-fetch timeout in ms. Default 1000. */
|
|
@@ -3354,12 +3426,6 @@ interface RedeemPrepareDto extends MobilePrepareDto {
|
|
|
3354
3426
|
* Lock id reserved for the FALLBACK redeem path (= full `amount`).
|
|
3355
3427
|
* Mobile FE polls `/redeem/status/:lockIdFallback` when it submits
|
|
3356
3428
|
* the fallback variant (`variant: 'fallback'` on `/redeem/submit`).
|
|
3357
|
-
*
|
|
3358
|
-
* Audit PACI5-21 — pre-fix the adapter exposed only the sponsored
|
|
3359
|
-
* `lockId` (= `amount - fee`), so the bundler-receipt fallback in
|
|
3360
|
-
* `handleRedeemStatus` resolved the smaller credit against the
|
|
3361
|
-
* on-chain burn of the full amount → user under-credited by exactly
|
|
3362
|
-
* the fee on every fallback redeem.
|
|
3363
3429
|
*/
|
|
3364
3430
|
lockIdFallback?: string;
|
|
3365
3431
|
}
|
package/dist/index.js
CHANGED
|
@@ -2190,11 +2190,23 @@ var PTRedeemHandler = class {
|
|
|
2190
2190
|
);
|
|
2191
2191
|
}
|
|
2192
2192
|
if (this.redemptionService) {
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2193
|
+
let decision;
|
|
2194
|
+
try {
|
|
2195
|
+
decision = await this.redemptionService.evaluate(
|
|
2196
|
+
request.userAddress,
|
|
2197
|
+
request.amount,
|
|
2198
|
+
pointTokenAddress
|
|
2199
|
+
);
|
|
2200
|
+
} catch (err) {
|
|
2201
|
+
const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
|
|
2202
|
+
if (code === "POLICY_PROVIDER_UNAVAILABLE") {
|
|
2203
|
+
throw new PTRedeemError(
|
|
2204
|
+
"REDEMPTION_POLICY_UNAVAILABLE",
|
|
2205
|
+
"Redemption policy temporarily unavailable \u2014 please try again shortly."
|
|
2206
|
+
);
|
|
2207
|
+
}
|
|
2208
|
+
throw err;
|
|
2209
|
+
}
|
|
2198
2210
|
if (!decision.allowed) {
|
|
2199
2211
|
const denial = decision.denial;
|
|
2200
2212
|
throw new PTRedeemError(
|
|
@@ -3682,10 +3694,6 @@ var IssuerApiAdapter = class {
|
|
|
3682
3694
|
pointTokenAddress,
|
|
3683
3695
|
redeemResponse.expiresInSeconds,
|
|
3684
3696
|
input.eip7702Auth,
|
|
3685
|
-
// Audit PACI5-21 — fallback path reserves a separate
|
|
3686
|
-
// PendingCredit row for the full `amount`. Surface its lockId so
|
|
3687
|
-
// mobile FE can poll the correct row + `handleMobileSubmit`
|
|
3688
|
-
// routes the userOpHash bind to it on fallback submit.
|
|
3689
3697
|
redeemResponse.fallback?.lockId
|
|
3690
3698
|
);
|
|
3691
3699
|
return {
|
|
@@ -4264,7 +4272,9 @@ var PafiBackendClient = class {
|
|
|
4264
4272
|
if (!config.issuerId) throw new Error("PafiBackendClient: issuerId is required");
|
|
4265
4273
|
if (!config.apiKey) throw new Error("PafiBackendClient: apiKey is required");
|
|
4266
4274
|
this.config = config;
|
|
4267
|
-
this.baseUrl = getPafiServiceUrls(config.chainId
|
|
4275
|
+
this.baseUrl = getPafiServiceUrls(config.chainId, {
|
|
4276
|
+
sponsorRelayer: config.baseUrl
|
|
4277
|
+
}).sponsorRelayer;
|
|
4268
4278
|
}
|
|
4269
4279
|
async requestSponsorship(request) {
|
|
4270
4280
|
const maxAttempts = this.config.retry?.maxAttempts ?? 1;
|
|
@@ -4529,6 +4539,9 @@ function nextBlackoutEndAfter(windows, nowUnixSec) {
|
|
|
4529
4539
|
}
|
|
4530
4540
|
var REDEMPTION_HISTORY_WINDOW_SEC = SECONDS_PER_DAY;
|
|
4531
4541
|
|
|
4542
|
+
// src/redemption/policyProvider.ts
|
|
4543
|
+
import { PafiSdkError as PafiSdkError2 } from "@pafi-dev/core";
|
|
4544
|
+
|
|
4532
4545
|
// src/redemption/settlementClient.ts
|
|
4533
4546
|
import {
|
|
4534
4547
|
getPafiServiceUrls as getPafiServiceUrls2
|
|
@@ -4541,7 +4554,12 @@ var SettlementClient = class {
|
|
|
4541
4554
|
if (!config.issuerId) throw new Error("SettlementClient: issuerId is required");
|
|
4542
4555
|
if (!config.apiKey) throw new Error("SettlementClient: apiKey is required");
|
|
4543
4556
|
this.config = {
|
|
4544
|
-
baseUrl
|
|
4557
|
+
// Audit PACI5-17 — honor optional baseUrl override wired from
|
|
4558
|
+
// an env var (e.g. PAFI_ISSUER_API_URL). Empty / undefined →
|
|
4559
|
+
// ship-default for chainId.
|
|
4560
|
+
baseUrl: getPafiServiceUrls2(config.chainId, {
|
|
4561
|
+
issuerApi: config.baseUrl
|
|
4562
|
+
}).issuerApi.replace(/\/+$/, ""),
|
|
4545
4563
|
issuerId: config.issuerId,
|
|
4546
4564
|
apiKey: config.apiKey,
|
|
4547
4565
|
fetchTimeoutMs: config.fetchTimeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
@@ -4645,10 +4663,23 @@ function defaultPolicyFor(issuerId) {
|
|
|
4645
4663
|
|
|
4646
4664
|
// src/redemption/policyProvider.ts
|
|
4647
4665
|
var DEFAULT_CACHE_TTL_MS3 = 5 * 60 * 1e3;
|
|
4666
|
+
var PolicyProviderUnavailableError = class extends PafiSdkError2 {
|
|
4667
|
+
code = "POLICY_PROVIDER_UNAVAILABLE";
|
|
4668
|
+
httpStatus = "service_unavailable";
|
|
4669
|
+
details;
|
|
4670
|
+
constructor(issuerId, reason) {
|
|
4671
|
+
super(
|
|
4672
|
+
`Redemption policy provider unavailable for issuer ${issuerId}: ${reason}. Pre-flight redeem limit cannot be enforced \u2014 refusing to sign BurnRequest. Mobile FE: surface "try again shortly" and retry with backoff.`
|
|
4673
|
+
);
|
|
4674
|
+
this.details = { issuerId, reason };
|
|
4675
|
+
}
|
|
4676
|
+
};
|
|
4648
4677
|
var PolicyProvider = class {
|
|
4649
4678
|
client;
|
|
4650
4679
|
issuerId;
|
|
4651
4680
|
cacheTtlMs;
|
|
4681
|
+
onFetchFailure;
|
|
4682
|
+
onWarning;
|
|
4652
4683
|
now;
|
|
4653
4684
|
cache = null;
|
|
4654
4685
|
inflight = null;
|
|
@@ -4656,6 +4687,8 @@ var PolicyProvider = class {
|
|
|
4656
4687
|
this.client = new SettlementClient(config);
|
|
4657
4688
|
this.issuerId = config.issuerId;
|
|
4658
4689
|
this.cacheTtlMs = config.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS3;
|
|
4690
|
+
this.onFetchFailure = config.onFetchFailure ?? "fail-closed";
|
|
4691
|
+
this.onWarning = config.onWarning;
|
|
4659
4692
|
this.now = config.now ?? (() => Date.now());
|
|
4660
4693
|
}
|
|
4661
4694
|
async getPolicy() {
|
|
@@ -4688,7 +4721,19 @@ var PolicyProvider = class {
|
|
|
4688
4721
|
};
|
|
4689
4722
|
return { policy: result.policy, source: "settlement" };
|
|
4690
4723
|
}
|
|
4691
|
-
|
|
4724
|
+
const reason = "reason" in result && typeof result.reason === "string" ? result.reason : "unknown";
|
|
4725
|
+
if (this.onFetchFailure === "permissive-default") {
|
|
4726
|
+
this.onWarning?.(
|
|
4727
|
+
"PolicyProvider: settlement-api unreachable, falling back to permissive default. Pre-flight redeem limit is DEGRADED until settlement-api recovers.",
|
|
4728
|
+
{
|
|
4729
|
+
event: "policy_provider_fallback",
|
|
4730
|
+
issuerId: this.issuerId,
|
|
4731
|
+
reason
|
|
4732
|
+
}
|
|
4733
|
+
);
|
|
4734
|
+
return { policy: defaultPolicyFor(this.issuerId), source: "default" };
|
|
4735
|
+
}
|
|
4736
|
+
throw new PolicyProviderUnavailableError(this.issuerId, reason);
|
|
4692
4737
|
}
|
|
4693
4738
|
};
|
|
4694
4739
|
|
|
@@ -4835,6 +4880,15 @@ async function createIssuerService(config) {
|
|
|
4835
4880
|
issuerId: config.redemption.issuerId,
|
|
4836
4881
|
apiKey: config.redemption.apiKey
|
|
4837
4882
|
};
|
|
4883
|
+
if (config.redemption.baseUrl) {
|
|
4884
|
+
policyConfig.baseUrl = config.redemption.baseUrl;
|
|
4885
|
+
}
|
|
4886
|
+
if (config.redemption.onFetchFailure) {
|
|
4887
|
+
policyConfig.onFetchFailure = config.redemption.onFetchFailure;
|
|
4888
|
+
}
|
|
4889
|
+
if (config.redemption.onPolicyWarning) {
|
|
4890
|
+
policyConfig.onWarning = config.redemption.onPolicyWarning;
|
|
4891
|
+
}
|
|
4838
4892
|
if (config.redemption.fetchImpl) policyConfig.fetchImpl = config.redemption.fetchImpl;
|
|
4839
4893
|
if (config.redemption.fetchTimeoutMs !== void 0) {
|
|
4840
4894
|
policyConfig.fetchTimeoutMs = config.redemption.fetchTimeoutMs;
|
|
@@ -5099,7 +5153,7 @@ var MemoryRedemptionHistoryStore = class {
|
|
|
5099
5153
|
};
|
|
5100
5154
|
|
|
5101
5155
|
// src/index.ts
|
|
5102
|
-
var PAFI_ISSUER_SDK_VERSION = true ? "0.
|
|
5156
|
+
var PAFI_ISSUER_SDK_VERSION = true ? "0.32.0" : "dev";
|
|
5103
5157
|
export {
|
|
5104
5158
|
AdapterMisconfiguredError,
|
|
5105
5159
|
AuthError,
|