@pafi-dev/issuer 0.39.2 → 0.39.3

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
@@ -3,6 +3,7 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
7
  var __export = (target, all) => {
7
8
  for (var name in all)
8
9
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -104,6 +105,9 @@ var import_core = require("@pafi-dev/core");
104
105
  var import_core2 = require("@pafi-dev/core");
105
106
  var import_core3 = require("@pafi-dev/core");
106
107
  var ConfigurationError = class extends import_core2.PafiSdkError {
108
+ static {
109
+ __name(this, "ConfigurationError");
110
+ }
107
111
  httpStatus = "service_unavailable";
108
112
  code;
109
113
  details;
@@ -128,6 +132,7 @@ function buildSdkErrorBody(err) {
128
132
  if (err.details !== void 0) body.details = err.details;
129
133
  return body;
130
134
  }
135
+ __name(buildSdkErrorBody, "buildSdkErrorBody");
131
136
  function createSdkErrorMapper(factories) {
132
137
  return (err) => {
133
138
  if (!(err instanceof import_core.PafiSdkError)) {
@@ -146,17 +151,20 @@ function createSdkErrorMapper(factories) {
146
151
  }
147
152
  };
148
153
  }
154
+ __name(createSdkErrorMapper, "createSdkErrorMapper");
149
155
 
150
156
  // src/http/errorEnvelope.ts
151
157
  function isValidationPipeBody(body) {
152
158
  return Array.isArray(body["message"]) && typeof body["error"] === "string" && body["error"] === "Bad Request";
153
159
  }
160
+ __name(isValidationPipeBody, "isValidationPipeBody");
154
161
  function extractParamFromValidatorMessage(message) {
155
162
  const idx = message.indexOf(" ");
156
163
  if (idx <= 0) return void 0;
157
164
  const candidate = message.slice(0, idx);
158
165
  return /^[A-Za-z_][\w.]*$/.test(candidate) ? candidate : void 0;
159
166
  }
167
+ __name(extractParamFromValidatorMessage, "extractParamFromValidatorMessage");
160
168
  function normalizeValidationPipeBody(body) {
161
169
  const fields = {};
162
170
  for (const msg of body.message) {
@@ -171,11 +179,14 @@ function normalizeValidationPipeBody(body) {
171
179
  code: "VALIDATION_FAILED",
172
180
  message: body.message.join("; "),
173
181
  safeToRetry: false,
174
- metadata: { fieldErrors: fields }
182
+ metadata: {
183
+ fieldErrors: fields
184
+ }
175
185
  };
176
186
  if (param) payload.param = param;
177
187
  return payload;
178
188
  }
189
+ __name(normalizeValidationPipeBody, "normalizeValidationPipeBody");
179
190
  function normalizeHttpExceptionBody(desc) {
180
191
  const { statusCode, responseBody, exceptionName, fallbackMessage } = desc;
181
192
  const defaultType = (0, import_core.defaultErrorTypeForStatus)(statusCode);
@@ -216,6 +227,7 @@ function normalizeHttpExceptionBody(desc) {
216
227
  safeToRetry: false
217
228
  };
218
229
  }
230
+ __name(normalizeHttpExceptionBody, "normalizeHttpExceptionBody");
219
231
  function payloadFromPafiSdkError(err) {
220
232
  const body = buildSdkErrorBody(err);
221
233
  const payload = {
@@ -229,10 +241,12 @@ function payloadFromPafiSdkError(err) {
229
241
  if (body.details !== void 0) payload.details = body.details;
230
242
  return payload;
231
243
  }
244
+ __name(payloadFromPafiSdkError, "payloadFromPafiSdkError");
232
245
  function sanitizeDbErrorMessage(message) {
233
246
  if (/^[A-Z_]+: /.test(message) && message.length < 256) return message;
234
247
  return "Internal database error";
235
248
  }
249
+ __name(sanitizeDbErrorMessage, "sanitizeDbErrorMessage");
236
250
  function buildErrorEnvelope(input) {
237
251
  const now = (input.ctx.now ?? (() => /* @__PURE__ */ new Date()))();
238
252
  return {
@@ -246,9 +260,11 @@ function buildErrorEnvelope(input) {
246
260
  }
247
261
  };
248
262
  }
263
+ __name(buildErrorEnvelope, "buildErrorEnvelope");
249
264
  function payloadFromHttpException(desc) {
250
265
  return normalizeHttpExceptionBody(desc);
251
266
  }
267
+ __name(payloadFromHttpException, "payloadFromHttpException");
252
268
  function payloadFromGenericError(err) {
253
269
  const name = err.name || "INTERNAL_SERVER_ERROR";
254
270
  const isDbError = name === "QueryFailedError" || name === "EntityNotFoundError";
@@ -259,9 +275,13 @@ function payloadFromGenericError(err) {
259
275
  safeToRetry: false
260
276
  };
261
277
  }
278
+ __name(payloadFromGenericError, "payloadFromGenericError");
262
279
 
263
280
  // src/policy/defaultPolicy.ts
264
281
  var DefaultPolicyEngine = class {
282
+ static {
283
+ __name(this, "DefaultPolicyEngine");
284
+ }
265
285
  ledger;
266
286
  provider;
267
287
  mintingOracleAddress;
@@ -277,20 +297,18 @@ var DefaultPolicyEngine = class {
277
297
  if (opts.resolveIssuer) this.resolveIssuer = opts.resolveIssuer;
278
298
  if (!opts.mintingOracleAddress || !opts.provider || !opts.verifyMintCap || !opts.resolveIssuer) {
279
299
  if (process.env.NODE_ENV === "production") {
280
- throw new Error(
281
- "[PAFI] DefaultPolicyEngine: on-chain MintingOracle cap check is required in production. Configure mintingOracleAddress, provider, verifyMintCap, and resolveIssuer."
282
- );
300
+ throw new Error("[PAFI] DefaultPolicyEngine: on-chain MintingOracle cap check is required in production. Configure mintingOracleAddress, provider, verifyMintCap, and resolveIssuer.");
283
301
  }
284
302
  }
285
303
  }
286
304
  async evaluate(request) {
287
305
  if (request.amount <= 0n) {
288
- return { approved: false, reason: "Amount must be positive" };
306
+ return {
307
+ approved: false,
308
+ reason: "Amount must be positive"
309
+ };
289
310
  }
290
- const available = await this.ledger.getBalance(
291
- request.userAddress,
292
- request.pointTokenAddress
293
- );
311
+ const available = await this.ledger.getBalance(request.userAddress, request.pointTokenAddress);
294
312
  if (available < request.amount) {
295
313
  return {
296
314
  approved: false,
@@ -300,12 +318,7 @@ var DefaultPolicyEngine = class {
300
318
  if (this.mintingOracleAddress && this.provider && this.verifyMintCap && this.resolveIssuer) {
301
319
  try {
302
320
  const issuer = await this.resolveIssuer(request.pointTokenAddress);
303
- await this.verifyMintCap(
304
- this.provider,
305
- this.mintingOracleAddress,
306
- issuer,
307
- request.amount
308
- );
321
+ await this.verifyMintCap(this.provider, this.mintingOracleAddress, issuer, request.amount);
309
322
  } catch (err) {
310
323
  const msg = err instanceof Error ? err.message : String(err);
311
324
  return {
@@ -314,7 +327,9 @@ var DefaultPolicyEngine = class {
314
327
  };
315
328
  }
316
329
  }
317
- return { approved: true };
330
+ return {
331
+ approved: true
332
+ };
318
333
  }
319
334
  };
320
335
 
@@ -323,17 +338,16 @@ var import_node_crypto = require("crypto");
323
338
  var import_viem = require("viem");
324
339
  var DEFAULT_NONCE_TTL_MS = 5 * 60 * 1e3;
325
340
  var MemorySessionStore = class {
341
+ static {
342
+ __name(this, "MemorySessionStore");
343
+ }
326
344
  nonces = /* @__PURE__ */ new Map();
327
- // nonce → expiresAt
328
345
  sessions = /* @__PURE__ */ new Map();
329
- // tokenId → session
330
346
  nonceTtlMs;
331
347
  now;
332
348
  constructor(opts = {}) {
333
349
  if (process.env.NODE_ENV === "production" && !opts.dangerouslyAllowMemoryStoreInProduction) {
334
- throw new Error(
335
- "[PAFI] MemorySessionStore refuses to start in production (NODE_ENV=production). Multi-pod K8s deploys do not share Map state, so sessions are not revocable across replicas \u2014 `logout` on pod A leaves the token valid on pod B until expiry. Use a Redis-backed session store (see RedisSessionStoreService in gg56-backend or implement your own ISessionStore). To bypass for a single-pod deploy, pass `dangerouslyAllowMemoryStoreInProduction: true`."
336
- );
350
+ throw new Error("[PAFI] MemorySessionStore refuses to start in production (NODE_ENV=production). Multi-pod K8s deploys do not share Map state, so sessions are not revocable across replicas \u2014 `logout` on pod A leaves the token valid on pod B until expiry. Use a Redis-backed session store (see RedisSessionStoreService in gg56-backend or implement your own ISessionStore). To bypass for a single-pod deploy, pass `dangerouslyAllowMemoryStoreInProduction: true`.");
337
351
  }
338
352
  this.nonceTtlMs = opts.nonceTtlMs ?? DEFAULT_NONCE_TTL_MS;
339
353
  this.now = opts.now ?? (() => Date.now());
@@ -373,7 +387,9 @@ var MemorySessionStore = class {
373
387
  this.sessions.delete(tokenId);
374
388
  return null;
375
389
  }
376
- return { ...session };
390
+ return {
391
+ ...session
392
+ };
377
393
  }
378
394
  async revokeSession(tokenId) {
379
395
  this.sessions.delete(tokenId);
@@ -405,18 +421,21 @@ var MemorySessionStore = class {
405
421
 
406
422
  // src/auth/nonceManager.ts
407
423
  var NonceManager = class {
424
+ static {
425
+ __name(this, "NonceManager");
426
+ }
427
+ store;
408
428
  constructor(store) {
409
429
  this.store = store;
410
430
  }
411
- store;
412
431
  /** Generate a fresh login nonce. The store is responsible for TTL. */
413
432
  async generate() {
414
433
  return this.store.createNonce();
415
434
  }
416
435
  /**
417
- * Atomically validate + consume a nonce. Returns `true` iff the nonce
418
- * was known and unexpired (and is now removed from the store).
419
- */
436
+ * Atomically validate + consume a nonce. Returns `true` iff the nonce
437
+ * was known and unexpired (and is now removed from the store).
438
+ */
420
439
  async consume(nonce) {
421
440
  return this.store.consumeNonce(nonce);
422
441
  }
@@ -448,7 +467,11 @@ function statusForCode(code) {
448
467
  return "not_found";
449
468
  }
450
469
  }
470
+ __name(statusForCode, "statusForCode");
451
471
  var AuthError = class extends import_core.PafiSdkError {
472
+ static {
473
+ __name(this, "AuthError");
474
+ }
452
475
  code;
453
476
  httpStatus;
454
477
  constructor(code, message) {
@@ -461,37 +484,28 @@ var AuthError = class extends import_core.PafiSdkError {
461
484
  // src/auth/loginVerifier.ts
462
485
  function assertJwtSecretStrength(secret) {
463
486
  if (!secret) {
464
- throw new Error(
465
- "AuthService: jwtSecret is required. Generate via `node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\"`"
466
- );
487
+ throw new Error("AuthService: jwtSecret is required. Generate via `node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\"`");
467
488
  }
468
489
  if (secret.length < 32) {
469
- throw new Error(
470
- `AuthService: jwtSecret too short (${secret.length} chars; need \u2265 32). HS256 brute-force becomes feasible below this threshold.`
471
- );
490
+ throw new Error(`AuthService: jwtSecret too short (${secret.length} chars; need \u2265 32). HS256 brute-force becomes feasible below this threshold.`);
472
491
  }
473
492
  const uniqueChars = new Set(secret).size;
474
493
  if (uniqueChars < 16) {
475
- throw new Error(
476
- `AuthService: jwtSecret has only ${uniqueChars} unique characters; need \u2265 16. A trivially weak secret (e.g. "aaaaa...") will pass length but offer almost no entropy. Use \`crypto.randomBytes(32).toString('hex')\`.`
477
- );
494
+ throw new Error(`AuthService: jwtSecret has only ${uniqueChars} unique characters; need \u2265 16. A trivially weak secret (e.g. "aaaaa...") will pass length but offer almost no entropy. Use \`crypto.randomBytes(32).toString('hex')\`.`);
478
495
  }
479
496
  const entropy = shannonEntropyBitsPerChar(secret);
480
497
  if (entropy < 3.5) {
481
- throw new Error(
482
- `AuthService: jwtSecret entropy too low (${entropy.toFixed(2)} bits/char; need \u2265 3.5). Use \`crypto.randomBytes(32).toString('hex')\` (\u2248 4.0 bits/char).`
483
- );
498
+ throw new Error(`AuthService: jwtSecret entropy too low (${entropy.toFixed(2)} bits/char; need \u2265 3.5). Use \`crypto.randomBytes(32).toString('hex')\` (\u2248 4.0 bits/char).`);
484
499
  }
485
500
  for (let period = 1; period <= secret.length / 4; period++) {
486
501
  if (secret.length % period !== 0) continue;
487
502
  const head = secret.slice(0, period);
488
503
  if (secret === head.repeat(secret.length / period)) {
489
- throw new Error(
490
- `AuthService: jwtSecret is a repeating pattern of period ${period}. Use \`crypto.randomBytes(32).toString('hex')\`.`
491
- );
504
+ throw new Error(`AuthService: jwtSecret is a repeating pattern of period ${period}. Use \`crypto.randomBytes(32).toString('hex')\`.`);
492
505
  }
493
506
  }
494
507
  }
508
+ __name(assertJwtSecretStrength, "assertJwtSecretStrength");
495
509
  function shannonEntropyBitsPerChar(s) {
496
510
  const counts = /* @__PURE__ */ new Map();
497
511
  for (const c of s) counts.set(c, (counts.get(c) ?? 0) + 1);
@@ -503,6 +517,7 @@ function shannonEntropyBitsPerChar(s) {
503
517
  }
504
518
  return h;
505
519
  }
520
+ __name(shannonEntropyBitsPerChar, "shannonEntropyBitsPerChar");
506
521
  function decodeExpiredJwtJti(token) {
507
522
  try {
508
523
  const parts = token.split(".");
@@ -512,13 +527,19 @@ function decodeExpiredJwtJti(token) {
512
527
  const padded = payloadB64.replace(/-/g, "+").replace(/_/g, "/") + "===".slice((payloadB64.length + 3) % 4);
513
528
  const json = Buffer.from(padded, "base64").toString("utf-8");
514
529
  const claims = JSON.parse(json);
515
- return typeof claims.jti === "string" ? { jti: claims.jti } : {};
530
+ return typeof claims.jti === "string" ? {
531
+ jti: claims.jti
532
+ } : {};
516
533
  } catch {
517
534
  return {};
518
535
  }
519
536
  }
537
+ __name(decodeExpiredJwtJti, "decodeExpiredJwtJti");
520
538
  var DEFAULT_EXPIRES_IN = "24h";
521
539
  var AuthService = class {
540
+ static {
541
+ __name(this, "AuthService");
542
+ }
522
543
  sessionStore;
523
544
  jwtSecret;
524
545
  jwtExpiresIn;
@@ -548,9 +569,9 @@ var AuthService = class {
548
569
  return this.nonceManager.generate();
549
570
  }
550
571
  /**
551
- * Verify a signed login message and issue a JWT on success.
552
- * Throws an `AuthError` on any validation failure.
553
- */
572
+ * Verify a signed login message and issue a JWT on success.
573
+ * Throws an `AuthError` on any validation failure.
574
+ */
554
575
  async login(message, signature) {
555
576
  let parsed;
556
577
  try {
@@ -560,46 +581,28 @@ var AuthService = class {
560
581
  throw new AuthError("INVALID_MESSAGE", `Could not parse login message: ${msg}`);
561
582
  }
562
583
  if (parsed.expirationTime == null) {
563
- throw new AuthError(
564
- "INVALID_MESSAGE",
565
- "login message must include expirationTime"
566
- );
584
+ throw new AuthError("INVALID_MESSAGE", "login message must include expirationTime");
567
585
  }
568
586
  if (parsed.domain !== this.domain) {
569
- throw new AuthError(
570
- "DOMAIN_MISMATCH",
571
- `Expected domain "${this.domain}", got "${parsed.domain}"`
572
- );
587
+ throw new AuthError("DOMAIN_MISMATCH", `Expected domain "${this.domain}", got "${parsed.domain}"`);
573
588
  }
574
589
  if (parsed.chainId !== this.chainId) {
575
- throw new AuthError(
576
- "CHAIN_MISMATCH",
577
- `Expected chainId ${this.chainId}, got ${parsed.chainId}`
578
- );
590
+ throw new AuthError("CHAIN_MISMATCH", `Expected chainId ${this.chainId}, got ${parsed.chainId}`);
579
591
  }
580
592
  const now = this.now();
581
593
  if (parsed.notBefore && parsed.notBefore.getTime() > now.getTime()) {
582
- throw new AuthError(
583
- "MESSAGE_NOT_YET_VALID",
584
- "Login message is not yet valid"
585
- );
594
+ throw new AuthError("MESSAGE_NOT_YET_VALID", "Login message is not yet valid");
586
595
  }
587
596
  if (parsed.expirationTime && parsed.expirationTime.getTime() <= now.getTime()) {
588
597
  throw new AuthError("MESSAGE_EXPIRED", "Login message has expired");
589
598
  }
590
599
  const verifyResult = await (0, import_core4.verifyLoginMessage)(message, signature);
591
600
  if (!verifyResult.valid) {
592
- throw new AuthError(
593
- "SIGNATURE_INVALID",
594
- "Signature does not match the address in the login message"
595
- );
601
+ throw new AuthError("SIGNATURE_INVALID", "Signature does not match the address in the login message");
596
602
  }
597
603
  const nonceOk = await this.nonceManager.consume(parsed.nonce);
598
604
  if (!nonceOk) {
599
- throw new AuthError(
600
- "NONCE_INVALID",
601
- "Nonce is unknown, expired, or already used"
602
- );
605
+ throw new AuthError("NONCE_INVALID", "Nonce is unknown, expired, or already used");
603
606
  }
604
607
  const userAddress = (0, import_viem2.getAddress)(verifyResult.address);
605
608
  const tokenId = (0, import_node_crypto2.randomBytes)(16).toString("hex");
@@ -616,11 +619,18 @@ var AuthService = class {
616
619
  let signer = new import_jose.SignJWT({
617
620
  userAddress,
618
621
  chainId: this.chainId
619
- }).setProtectedHeader({ alg: "HS256" }).setJti(tokenId).setIssuedAt(Math.floor(issuedAt.getTime() / 1e3)).setExpirationTime(Math.floor(expiresAt.getTime() / 1e3));
622
+ }).setProtectedHeader({
623
+ alg: "HS256"
624
+ }).setJti(tokenId).setIssuedAt(Math.floor(issuedAt.getTime() / 1e3)).setExpirationTime(Math.floor(expiresAt.getTime() / 1e3));
620
625
  if (this.issuer) signer = signer.setIssuer(this.issuer);
621
626
  if (this.audience) signer = signer.setAudience(this.audience);
622
627
  const token = await signer.sign(this.jwtSecret);
623
- return { token, userAddress, tokenId, expiresAt };
628
+ return {
629
+ token,
630
+ userAddress,
631
+ tokenId,
632
+ expiresAt
633
+ };
624
634
  }
625
635
  /** Revoke the session backing the given JWT (logout). */
626
636
  async logout(token) {
@@ -628,9 +638,12 @@ var AuthService = class {
628
638
  try {
629
639
  const result = await (0, import_jose.jwtVerify)(token, this.jwtSecret, {
630
640
  clockTolerance: 60,
631
- // allow logout right after expiry
632
- ...this.issuer ? { issuer: this.issuer } : {},
633
- ...this.audience ? { audience: this.audience } : {}
641
+ ...this.issuer ? {
642
+ issuer: this.issuer
643
+ } : {},
644
+ ...this.audience ? {
645
+ audience: this.audience
646
+ } : {}
634
647
  });
635
648
  payload = result.payload;
636
649
  } catch (err) {
@@ -648,10 +661,7 @@ var AuthService = class {
648
661
  if (err instanceof import_jose.errors.JWSSignatureVerificationFailed || err instanceof import_jose.errors.JWSInvalid || err instanceof import_jose.errors.JWTInvalid) {
649
662
  throw new AuthError("TOKEN_INVALID", "JWT verification failed");
650
663
  }
651
- throw new AuthError(
652
- "TOKEN_INVALID",
653
- `JWT verification failed: ${err instanceof Error ? err.message : String(err)}`
654
- );
664
+ throw new AuthError("TOKEN_INVALID", `JWT verification failed: ${err instanceof Error ? err.message : String(err)}`);
655
665
  }
656
666
  if (payload.jti) {
657
667
  try {
@@ -667,16 +677,20 @@ var AuthService = class {
667
677
  console.error("[PAFI] AuthService logout: session store error", err);
668
678
  }
669
679
  /**
670
- * Verify a JWT and return the authenticated user context. Throws an
671
- * `AuthError` if the token is missing, malformed, expired, revoked, or
672
- * signed by a different key.
673
- */
680
+ * Verify a JWT and return the authenticated user context. Throws an
681
+ * `AuthError` if the token is missing, malformed, expired, revoked, or
682
+ * signed by a different key.
683
+ */
674
684
  async verifyToken(token) {
675
685
  let payload;
676
686
  try {
677
687
  const result = await (0, import_jose.jwtVerify)(token, this.jwtSecret, {
678
- ...this.issuer ? { issuer: this.issuer } : {},
679
- ...this.audience ? { audience: this.audience } : {}
688
+ ...this.issuer ? {
689
+ issuer: this.issuer
690
+ } : {},
691
+ ...this.audience ? {
692
+ audience: this.audience
693
+ } : {}
680
694
  });
681
695
  payload = result.payload;
682
696
  } catch (err) {
@@ -694,10 +708,7 @@ var AuthService = class {
694
708
  }
695
709
  const session = await this.sessionStore.getSession(tokenId);
696
710
  if (!session) {
697
- throw new AuthError(
698
- "SESSION_REVOKED",
699
- "Session is no longer active (revoked or expired)"
700
- );
711
+ throw new AuthError("SESSION_REVOKED", "Session is no longer active (revoked or expired)");
701
712
  }
702
713
  const userAddress = payload.userAddress;
703
714
  const chainId = payload.chainId;
@@ -714,51 +725,50 @@ var AuthService = class {
714
725
  function parseExpiry(from, expiresIn) {
715
726
  const match = expiresIn.match(/^(\d+)\s*(s|m|h|d)$/i);
716
727
  if (!match) {
717
- throw new Error(
718
- `AuthService: unsupported jwtExpiresIn "${expiresIn}" \u2014 use e.g. "24h"`
719
- );
728
+ throw new Error(`AuthService: unsupported jwtExpiresIn "${expiresIn}" \u2014 use e.g. "24h"`);
720
729
  }
721
730
  const n = Number(match[1]);
722
731
  const unit = match[2].toLowerCase();
723
732
  const multiplier = unit === "s" ? 1e3 : unit === "m" ? 6e4 : unit === "h" ? 36e5 : 864e5;
724
733
  return new Date(from.getTime() + n * multiplier);
725
734
  }
735
+ __name(parseExpiry, "parseExpiry");
726
736
 
727
737
  // src/auth/jwtMiddleware.ts
728
738
  async function authenticateRequest(authHeader, authService) {
729
739
  if (!authHeader) {
730
- throw new AuthError(
731
- "MISSING_TOKEN",
732
- "Authorization header is required"
733
- );
740
+ throw new AuthError("MISSING_TOKEN", "Authorization header is required");
734
741
  }
735
742
  const match = authHeader.match(/^Bearer\s+(\S+)\s*$/i);
736
743
  if (!match) {
737
- throw new AuthError(
738
- "MALFORMED_TOKEN",
739
- "Authorization header must be in the form 'Bearer <token>'"
740
- );
744
+ throw new AuthError("MALFORMED_TOKEN", "Authorization header must be in the form 'Bearer <token>'");
741
745
  }
742
746
  const token = match[1];
743
747
  return authService.verifyToken(token);
744
748
  }
749
+ __name(authenticateRequest, "authenticateRequest");
745
750
 
746
751
  // src/auth/rateLimiter.ts
747
752
  var DEFAULT_LIMITS = {
748
- auth_nonce: { max: 30, windowMs: 6e4 },
749
- // 30 nonces/min ≈ 1 per 2s
750
- auth_login: { max: 5, windowMs: 6e4 }
751
- // 5 logins/min
753
+ auth_nonce: {
754
+ max: 30,
755
+ windowMs: 6e4
756
+ },
757
+ auth_login: {
758
+ max: 5,
759
+ windowMs: 6e4
760
+ }
752
761
  };
753
762
  var MemoryRateLimiter = class {
763
+ static {
764
+ __name(this, "MemoryRateLimiter");
765
+ }
754
766
  buckets = /* @__PURE__ */ new Map();
755
767
  limits;
756
768
  now;
757
769
  constructor(config = {}) {
758
770
  if (process.env.NODE_ENV === "production" && !process.env.PAFI_ALLOW_MEMORY_RATE_LIMITER_IN_PROD) {
759
- console.warn(
760
- "[PAFI] MemoryRateLimiter not safe for multi-pod K8s deploys \u2014 rate counters are NOT shared across replicas, allowing round-robin bypass. Use a Redis-backed IRateLimiter in production."
761
- );
771
+ console.warn("[PAFI] MemoryRateLimiter not safe for multi-pod K8s deploys \u2014 rate counters are NOT shared across replicas, allowing round-robin bypass. Use a Redis-backed IRateLimiter in production.");
762
772
  }
763
773
  this.limits = {
764
774
  ...DEFAULT_LIMITS,
@@ -768,47 +778,62 @@ var MemoryRateLimiter = class {
768
778
  }
769
779
  async consume(key, action) {
770
780
  const limit = this.limits[action];
771
- if (!limit) return { allowed: true };
781
+ if (!limit) return {
782
+ allowed: true
783
+ };
772
784
  const bucketKey = `${action}:${key}`;
773
785
  const now = this.now();
774
786
  const bucket = this.buckets.get(bucketKey);
775
787
  if (!bucket || now - bucket.windowStartedAt >= limit.windowMs) {
776
- this.buckets.set(bucketKey, { count: 1, windowStartedAt: now });
777
- return { allowed: true };
788
+ this.buckets.set(bucketKey, {
789
+ count: 1,
790
+ windowStartedAt: now
791
+ });
792
+ return {
793
+ allowed: true
794
+ };
778
795
  }
779
796
  if (bucket.count < limit.max) {
780
797
  bucket.count += 1;
781
- return { allowed: true };
798
+ return {
799
+ allowed: true
800
+ };
782
801
  }
783
- const retryAfterMs = Math.max(
784
- 0,
785
- bucket.windowStartedAt + limit.windowMs - now
786
- );
787
- return { allowed: false, retryAfterMs };
802
+ const retryAfterMs = Math.max(0, bucket.windowStartedAt + limit.windowMs - now);
803
+ return {
804
+ allowed: false,
805
+ retryAfterMs
806
+ };
788
807
  }
789
808
  /**
790
- * Test helper — clear all buckets. Not part of `IRateLimiter`; only
791
- * exposed on the in-memory impl for unit tests.
792
- */
809
+ * Test helper — clear all buckets. Not part of `IRateLimiter`; only
810
+ * exposed on the in-memory impl for unit tests.
811
+ */
793
812
  reset() {
794
813
  this.buckets.clear();
795
814
  }
796
815
  };
797
816
  var NoopRateLimiter = class {
817
+ static {
818
+ __name(this, "NoopRateLimiter");
819
+ }
798
820
  warned = false;
799
821
  async consume() {
800
822
  if (!this.warned && process.env.NODE_ENV === "production") {
801
- console.warn(
802
- "[PAFI] NoopRateLimiter active \u2014 `/auth/nonce` and `/auth/login` are NOT throttled. Wire a `MemoryRateLimiter` (dev) or Redis-backed impl (prod) via `IssuerApiHandlersConfig.rateLimiter`."
803
- );
823
+ console.warn("[PAFI] NoopRateLimiter active \u2014 `/auth/nonce` and `/auth/login` are NOT throttled. Wire a `MemoryRateLimiter` (dev) or Redis-backed impl (prod) via `IssuerApiHandlersConfig.rateLimiter`.");
804
824
  this.warned = true;
805
825
  }
806
- return { allowed: true };
826
+ return {
827
+ allowed: true
828
+ };
807
829
  }
808
830
  };
809
831
 
810
832
  // src/relay/types.ts
811
833
  var RelayError = class extends import_core.PafiSdkError {
834
+ static {
835
+ __name(this, "RelayError");
836
+ }
812
837
  httpStatus = "unprocessable";
813
838
  code;
814
839
  constructor(code, message, cause) {
@@ -824,6 +849,9 @@ var RelayError = class extends import_core.PafiSdkError {
824
849
  var import_viem3 = require("viem");
825
850
  var import_core5 = require("@pafi-dev/core");
826
851
  var RelayService = class {
852
+ static {
853
+ __name(this, "RelayService");
854
+ }
827
855
  provider;
828
856
  chainId;
829
857
  constructor(config = {}) {
@@ -831,25 +859,28 @@ var RelayService = class {
831
859
  this.chainId = config.chainId;
832
860
  }
833
861
  /**
834
- * Resolve the fee recipient + amount applied to the next UserOp:
835
- *
836
- * - If caller passed an explicit `feeRecipient`, use it (testing
837
- * only — sponsor-relayer's L1 will reject any non-canonical
838
- * recipient with `INSUFFICIENT_FEE`). Otherwise, default to
839
- * `getContractAddresses(chainId).pafiFeeRecipient` when the
840
- * service has a `chainId` configured.
841
- * - If caller passed `feeAmount`, use it. Otherwise, when the
842
- * service has both `provider` + `chainId`, auto-quote via
843
- * `quoteOperatorFeePt`.
844
- * - When the service is unconfigured AND caller passed nothing,
845
- * return `{ feeAmount: 0n, feeRecipient: undefined }` — legacy
846
- * "no fee" behavior, caller must opt in for the gas-reimbursement
847
- * transfer to be added to the batch.
848
- */
862
+ * Resolve the fee recipient + amount applied to the next UserOp:
863
+ *
864
+ * - If caller passed an explicit `feeRecipient`, use it (testing
865
+ * only — sponsor-relayer's L1 will reject any non-canonical
866
+ * recipient with `INSUFFICIENT_FEE`). Otherwise, default to
867
+ * `getContractAddresses(chainId).pafiFeeRecipient` when the
868
+ * service has a `chainId` configured.
869
+ * - If caller passed `feeAmount`, use it. Otherwise, when the
870
+ * service has both `provider` + `chainId`, auto-quote via
871
+ * `quoteOperatorFeePt`.
872
+ * - When the service is unconfigured AND caller passed nothing,
873
+ * return `{ feeAmount: 0n, feeRecipient: undefined }` — legacy
874
+ * "no fee" behavior, caller must opt in for the gas-reimbursement
875
+ * transfer to be added to the batch.
876
+ */
849
877
  async resolveFee(params) {
850
878
  const feeRecipient = params.feeRecipient ?? (this.chainId !== void 0 ? (0, import_core5.getContractAddresses)(this.chainId).pafiFeeRecipient : void 0);
851
879
  if (params.feeAmount !== void 0) {
852
- return { feeAmount: params.feeAmount, feeRecipient };
880
+ return {
881
+ feeAmount: params.feeAmount,
882
+ feeRecipient
883
+ };
853
884
  }
854
885
  if (this.provider && this.chainId !== void 0) {
855
886
  const feeAmount = await (0, import_core5.quoteOperatorFeePt)({
@@ -857,44 +888,39 @@ var RelayService = class {
857
888
  chainId: this.chainId,
858
889
  pointTokenAddress: params.pointTokenAddress,
859
890
  allowStaleFallback: true,
860
- onFallback: (info) => {
861
- console.warn(
862
- `[RelayService] operatorFeeQuoter fallback (${info.source}): ${info.reason} \u2192 using ${info.fallbackValue}`
863
- );
864
- }
891
+ onFallback: /* @__PURE__ */ __name((info) => {
892
+ console.warn(`[RelayService] operatorFeeQuoter fallback (${info.source}): ${info.reason} \u2192 using ${info.fallbackValue}`);
893
+ }, "onFallback")
865
894
  });
866
- return { feeAmount, feeRecipient };
895
+ return {
896
+ feeAmount,
897
+ feeRecipient
898
+ };
867
899
  }
868
- return { feeAmount: 0n, feeRecipient };
900
+ return {
901
+ feeAmount: 0n,
902
+ feeRecipient
903
+ };
869
904
  }
870
905
  /**
871
- * Build an unsigned UserOp for Scenario 1 (Mint) — sig-gated
872
- * `PointToken.mint(to, amount, deadline, minterSig)`.
873
- */
906
+ * Build an unsigned UserOp for Scenario 1 (Mint) — sig-gated
907
+ * `PointToken.mint(to, amount, deadline, minterSig)`.
908
+ */
874
909
  async prepareMint(params) {
875
910
  if (!params.batchExecutorAddress) {
876
- throw new RelayError(
877
- "ENCODE_FAILED",
878
- "prepareMint: batchExecutorAddress required"
879
- );
911
+ throw new RelayError("ENCODE_FAILED", "prepareMint: batchExecutorAddress required");
880
912
  }
881
913
  if (!params.userAddress) {
882
914
  throw new RelayError("ENCODE_FAILED", "prepareMint: userAddress required");
883
915
  }
884
916
  if (!params.pointTokenAddress) {
885
- throw new RelayError(
886
- "ENCODE_FAILED",
887
- "prepareMint: pointTokenAddress required"
888
- );
917
+ throw new RelayError("ENCODE_FAILED", "prepareMint: pointTokenAddress required");
889
918
  }
890
919
  if (params.amount <= 0n) {
891
920
  throw new RelayError("ENCODE_FAILED", "prepareMint: amount must be positive");
892
921
  }
893
922
  if (!params.issuerSignerWallet) {
894
- throw new RelayError(
895
- "ENCODE_FAILED",
896
- "prepareMint: issuerSignerWallet required (for MintRequest EIP-712 signature)"
897
- );
923
+ throw new RelayError("ENCODE_FAILED", "prepareMint: issuerSignerWallet required (for MintRequest EIP-712 signature)");
898
924
  }
899
925
  if (params.deadline <= 0n) {
900
926
  throw new RelayError("ENCODE_FAILED", "prepareMint: deadline must be positive");
@@ -905,35 +931,24 @@ var RelayService = class {
905
931
  }
906
932
  const MAX_DEADLINE_WINDOW = 3600n;
907
933
  if (params.deadline > nowSecs + MAX_DEADLINE_WINDOW) {
908
- throw new RelayError(
909
- "ENCODE_FAILED",
910
- "prepareMint: deadline exceeds maximum allowed window (1 hour)"
911
- );
934
+ throw new RelayError("ENCODE_FAILED", "prepareMint: deadline exceeds maximum allowed window (1 hour)");
912
935
  }
913
936
  const MINT_SOURCE = import_core5.Source.EQUITY;
914
937
  const useWrapper = params.mintFeeWrapperAddress !== void 0;
915
938
  const receiverForSig = useWrapper ? params.mintFeeWrapperAddress : params.userAddress;
916
939
  let minterSig;
917
940
  try {
918
- const sig = await (0, import_core5.signMintRequest)(
919
- params.issuerSignerWallet,
920
- params.domain,
921
- {
922
- user: params.userAddress,
923
- receiver: receiverForSig,
924
- amount: params.amount,
925
- source: MINT_SOURCE,
926
- nonce: params.mintRequestNonce,
927
- deadline: params.deadline
928
- }
929
- );
941
+ const sig = await (0, import_core5.signMintRequest)(params.issuerSignerWallet, params.domain, {
942
+ user: params.userAddress,
943
+ receiver: receiverForSig,
944
+ amount: params.amount,
945
+ source: MINT_SOURCE,
946
+ nonce: params.mintRequestNonce,
947
+ deadline: params.deadline
948
+ });
930
949
  minterSig = sig.serialized;
931
950
  } catch (err) {
932
- throw new RelayError(
933
- "ENCODE_FAILED",
934
- `prepareMint: failed to sign MintForRequest: ${errorMessage(err)}`,
935
- err
936
- );
951
+ throw new RelayError("ENCODE_FAILED", `prepareMint: failed to sign MintForRequest: ${errorMessage(err)}`, err);
937
952
  }
938
953
  let mintCallData;
939
954
  let mintTarget;
@@ -966,11 +981,7 @@ var RelayService = class {
966
981
  mintTarget = params.pointTokenAddress;
967
982
  }
968
983
  } catch (err) {
969
- throw new RelayError(
970
- "ENCODE_FAILED",
971
- `prepareMint: failed to encode mint call: ${errorMessage(err)}`,
972
- err
973
- );
984
+ throw new RelayError("ENCODE_FAILED", `prepareMint: failed to encode mint call: ${errorMessage(err)}`, err);
974
985
  }
975
986
  const operations = [
976
987
  {
@@ -986,16 +997,10 @@ var RelayService = class {
986
997
  });
987
998
  if (feeAmount > 0n) {
988
999
  if (!feeRecipient) {
989
- throw new RelayError(
990
- "ENCODE_FAILED",
991
- "prepareMint: feeRecipient could not be resolved \u2014 pass `feeRecipient` explicitly or construct RelayService with a `chainId`."
992
- );
1000
+ throw new RelayError("ENCODE_FAILED", "prepareMint: feeRecipient could not be resolved \u2014 pass `feeRecipient` explicitly or construct RelayService with a `chainId`.");
993
1001
  }
994
1002
  if (feeRecipient === "0x0000000000000000000000000000000000000000") {
995
- throw new RelayError(
996
- "ENCODE_FAILED",
997
- "prepareMint: feeRecipient must not be zero address"
998
- );
1003
+ throw new RelayError("ENCODE_FAILED", "prepareMint: feeRecipient must not be zero address");
999
1004
  }
1000
1005
  operations.push({
1001
1006
  target: params.pointTokenAddress,
@@ -1003,7 +1008,10 @@ var RelayService = class {
1003
1008
  data: (0, import_viem3.encodeFunctionData)({
1004
1009
  abi: import_viem3.erc20Abi,
1005
1010
  functionName: "transfer",
1006
- args: [feeRecipient, feeAmount]
1011
+ args: [
1012
+ feeRecipient,
1013
+ feeAmount
1014
+ ]
1007
1015
  })
1008
1016
  });
1009
1017
  }
@@ -1019,29 +1027,23 @@ var RelayService = class {
1019
1027
  });
1020
1028
  }
1021
1029
  /**
1022
- * Build an unsigned UserOp for Scenario 2 (Burn/Redeem) — sig-gated
1023
- * `PointToken.burn(from, amount, deadline, burnerSig)`. Caller
1024
- * provides a pre-signed `BurnRequest` + sig bytes (typically from
1025
- * `PTRedeemHandler`).
1026
- *
1027
- * Direct burn (no sig) is not used — every burn goes through the
1028
- * issuer-signed `BurnRequest` path.
1029
- */
1030
+ * Build an unsigned UserOp for Scenario 2 (Burn/Redeem) — sig-gated
1031
+ * `PointToken.burn(from, amount, deadline, burnerSig)`. Caller
1032
+ * provides a pre-signed `BurnRequest` + sig bytes (typically from
1033
+ * `PTRedeemHandler`).
1034
+ *
1035
+ * Direct burn (no sig) is not used — every burn goes through the
1036
+ * issuer-signed `BurnRequest` path.
1037
+ */
1030
1038
  async prepareBurn(params) {
1031
1039
  if (!params.pointTokenAddress) {
1032
1040
  throw new RelayError("ENCODE_FAILED", "prepareBurn: pointTokenAddress required");
1033
1041
  }
1034
1042
  if (!params.batchExecutorAddress) {
1035
- throw new RelayError(
1036
- "ENCODE_FAILED",
1037
- "prepareBurn: batchExecutorAddress required"
1038
- );
1043
+ throw new RelayError("ENCODE_FAILED", "prepareBurn: batchExecutorAddress required");
1039
1044
  }
1040
1045
  if (!params.burnRequest || !params.burnerSignature) {
1041
- throw new RelayError(
1042
- "ENCODE_FAILED",
1043
- "prepareBurn: burnRequest + burnerSignature required"
1044
- );
1046
+ throw new RelayError("ENCODE_FAILED", "prepareBurn: burnRequest + burnerSignature required");
1045
1047
  }
1046
1048
  let burnCallData;
1047
1049
  try {
@@ -1057,11 +1059,7 @@ var RelayService = class {
1057
1059
  ]
1058
1060
  });
1059
1061
  } catch (err) {
1060
- throw new RelayError(
1061
- "ENCODE_FAILED",
1062
- `prepareBurn: failed to encode burn call: ${errorMessage(err)}`,
1063
- err
1064
- );
1062
+ throw new RelayError("ENCODE_FAILED", `prepareBurn: failed to encode burn call: ${errorMessage(err)}`, err);
1065
1063
  }
1066
1064
  const operations = [];
1067
1065
  const { feeAmount, feeRecipient } = await this.resolveFee({
@@ -1071,16 +1069,10 @@ var RelayService = class {
1071
1069
  });
1072
1070
  if (feeAmount > 0n) {
1073
1071
  if (!feeRecipient) {
1074
- throw new RelayError(
1075
- "ENCODE_FAILED",
1076
- "prepareBurn: feeRecipient could not be resolved \u2014 pass `feeRecipient` explicitly or construct RelayService with a `chainId`."
1077
- );
1072
+ throw new RelayError("ENCODE_FAILED", "prepareBurn: feeRecipient could not be resolved \u2014 pass `feeRecipient` explicitly or construct RelayService with a `chainId`.");
1078
1073
  }
1079
1074
  if (feeRecipient === "0x0000000000000000000000000000000000000000") {
1080
- throw new RelayError(
1081
- "ENCODE_FAILED",
1082
- "prepareBurn: feeRecipient must not be zero address"
1083
- );
1075
+ throw new RelayError("ENCODE_FAILED", "prepareBurn: feeRecipient must not be zero address");
1084
1076
  }
1085
1077
  operations.push({
1086
1078
  target: params.pointTokenAddress,
@@ -1088,7 +1080,10 @@ var RelayService = class {
1088
1080
  data: (0, import_viem3.encodeFunctionData)({
1089
1081
  abi: import_viem3.erc20Abi,
1090
1082
  functionName: "transfer",
1091
- args: [feeRecipient, feeAmount]
1083
+ args: [
1084
+ feeRecipient,
1085
+ feeAmount
1086
+ ]
1092
1087
  })
1093
1088
  });
1094
1089
  }
@@ -1123,10 +1118,10 @@ var RelayService = class {
1123
1118
  // call seeds the cache; subsequent ones hit it.
1124
1119
  // =========================================================================
1125
1120
  /**
1126
- * Build a dummy `PartialUserOperation` for the mint scenario, suitable
1127
- * for `feeManager.estimateGasFee({ partialUserOp, ... })`. NO signing —
1128
- * uses a 65-byte zero signature placeholder.
1129
- */
1121
+ * Build a dummy `PartialUserOperation` for the mint scenario, suitable
1122
+ * for `feeManager.estimateGasFee({ partialUserOp, ... })`. NO signing —
1123
+ * uses a 65-byte zero signature placeholder.
1124
+ */
1130
1125
  previewMintUserOp(params) {
1131
1126
  const useWrapper = params.mintFeeWrapperAddress !== void 0;
1132
1127
  let mintCallData;
@@ -1161,7 +1156,13 @@ var RelayService = class {
1161
1156
  return (0, import_core5.buildPartialUserOperation)({
1162
1157
  sender: params.userAddress,
1163
1158
  nonce: params.aaNonce,
1164
- operations: [{ target: mintTarget, value: 0n, data: mintCallData }],
1159
+ operations: [
1160
+ {
1161
+ target: mintTarget,
1162
+ value: 0n,
1163
+ data: mintCallData
1164
+ }
1165
+ ],
1165
1166
  // Gas limits ignored by bundler estimate — it computes them.
1166
1167
  gasLimits: {
1167
1168
  callGasLimit: 1n,
@@ -1187,7 +1188,11 @@ var RelayService = class {
1187
1188
  sender: params.userAddress,
1188
1189
  nonce: params.aaNonce,
1189
1190
  operations: [
1190
- { target: params.pointTokenAddress, value: 0n, data: burnCallData }
1191
+ {
1192
+ target: params.pointTokenAddress,
1193
+ value: 0n,
1194
+ data: burnCallData
1195
+ }
1191
1196
  ],
1192
1197
  gasLimits: {
1193
1198
  callGasLimit: 1n,
@@ -1201,11 +1206,15 @@ var PLACEHOLDER_SIG_65 = `0x${"00".repeat(65)}`;
1201
1206
  function errorMessage(err) {
1202
1207
  return err instanceof Error ? err.message : String(err);
1203
1208
  }
1209
+ __name(errorMessage, "errorMessage");
1204
1210
 
1205
1211
  // src/relay/feeManager.ts
1206
1212
  var DEFAULT_GAS_UNITS = 500000n;
1207
1213
  var DEFAULT_PREMIUM_BPS = 1e4;
1208
1214
  var FeeManager = class _FeeManager {
1215
+ static {
1216
+ __name(this, "FeeManager");
1217
+ }
1209
1218
  provider;
1210
1219
  fallbackGasUnits;
1211
1220
  gasPremiumBps;
@@ -1222,8 +1231,7 @@ var FeeManager = class _FeeManager {
1222
1231
  static FEE_CACHE_TTL_MS = 1e4;
1223
1232
  constructor(config) {
1224
1233
  if (!config.provider) throw new Error("FeeManager: provider required");
1225
- if (!config.quoteNativeToFee)
1226
- throw new Error("FeeManager: quoteNativeToFee required");
1234
+ if (!config.quoteNativeToFee) throw new Error("FeeManager: quoteNativeToFee required");
1227
1235
  this.provider = config.provider;
1228
1236
  this.fallbackGasUnits = config.gasUnits ?? DEFAULT_GAS_UNITS;
1229
1237
  this.gasPremiumBps = config.gasPremiumBps ?? DEFAULT_PREMIUM_BPS;
@@ -1232,16 +1240,16 @@ var FeeManager = class _FeeManager {
1232
1240
  this.metrics = config.metrics;
1233
1241
  }
1234
1242
  /**
1235
- * Estimate the operator fee for the next sponsored UserOp.
1236
- *
1237
- * Without `opts` → legacy path: `gasUnits × gasPrice × premium →
1238
- * quoteNativeToFee`. Cached for 10 s to absorb bursts.
1239
- *
1240
- * With `opts` AND `bundlerClient` → estimator path. Each call may
1241
- * hit a different bundler-cached result; the SDK does NOT add its
1242
- * own value cache because the estimator's cache TTL is the source
1243
- * of truth for "how long is this estimate good for".
1244
- */
1243
+ * Estimate the operator fee for the next sponsored UserOp.
1244
+ *
1245
+ * Without `opts` → legacy path: `gasUnits × gasPrice × premium →
1246
+ * quoteNativeToFee`. Cached for 10 s to absorb bursts.
1247
+ *
1248
+ * With `opts` AND `bundlerClient` → estimator path. Each call may
1249
+ * hit a different bundler-cached result; the SDK does NOT add its
1250
+ * own value cache because the estimator's cache TTL is the source
1251
+ * of truth for "how long is this estimate good for".
1252
+ */
1245
1253
  async estimateGasFee(opts = {}) {
1246
1254
  const isLegacyCall = !opts.partialUserOp && !opts.scenario && !opts.contractAddress;
1247
1255
  const now = Date.now();
@@ -1251,14 +1259,12 @@ var FeeManager = class _FeeManager {
1251
1259
  const t0 = Date.now();
1252
1260
  const { gasUnits, source } = await this.resolveGasUnits(opts);
1253
1261
  const latencyMs = Date.now() - t0;
1254
- this.safeEmit(
1255
- () => this.metrics?.onEstimate?.({
1256
- source,
1257
- scenario: opts.scenario,
1258
- gasUnits,
1259
- latencyMs
1260
- })
1261
- );
1262
+ this.safeEmit(() => this.metrics?.onEstimate?.({
1263
+ source,
1264
+ scenario: opts.scenario,
1265
+ gasUnits,
1266
+ latencyMs
1267
+ }));
1262
1268
  const gasPrice = await this.provider.getGasPrice();
1263
1269
  const nativeCost = gasPrice * gasUnits;
1264
1270
  const withPremium = nativeCost * BigInt(this.gasPremiumBps) / 10000n;
@@ -1276,7 +1282,10 @@ var FeeManager = class _FeeManager {
1276
1282
  }
1277
1283
  async resolveGasUnits(opts) {
1278
1284
  if (!this.bundlerClient || !opts.partialUserOp || !opts.scenario || !opts.contractAddress) {
1279
- return { gasUnits: this.fallbackGasUnits, source: "fallback" };
1285
+ return {
1286
+ gasUnits: this.fallbackGasUnits,
1287
+ source: "fallback"
1288
+ };
1280
1289
  }
1281
1290
  try {
1282
1291
  const result = await this.bundlerClient.getGasUnits({
@@ -1285,16 +1294,20 @@ var FeeManager = class _FeeManager {
1285
1294
  paymasterAddress: opts.paymasterAddress,
1286
1295
  partialUserOp: opts.partialUserOp
1287
1296
  });
1288
- return { gasUnits: result.gasUnits, source: "estimator" };
1297
+ return {
1298
+ gasUnits: result.gasUnits,
1299
+ source: "estimator"
1300
+ };
1289
1301
  } catch (err) {
1290
1302
  const reason = err instanceof Error ? err.message : String(err);
1291
- this.safeEmit(
1292
- () => this.metrics?.onEstimatorError?.({
1293
- scenario: opts.scenario,
1294
- reason
1295
- })
1296
- );
1297
- return { gasUnits: this.fallbackGasUnits, source: "fallback" };
1303
+ this.safeEmit(() => this.metrics?.onEstimatorError?.({
1304
+ scenario: opts.scenario,
1305
+ reason
1306
+ }));
1307
+ return {
1308
+ gasUnits: this.fallbackGasUnits,
1309
+ source: "fallback"
1310
+ };
1298
1311
  }
1299
1312
  }
1300
1313
  safeEmit(fn) {
@@ -1307,6 +1320,9 @@ var FeeManager = class _FeeManager {
1307
1320
 
1308
1321
  // src/relay/bundlerEstimator.ts
1309
1322
  var PafiEstimatorHttpError = class extends Error {
1323
+ static {
1324
+ __name(this, "PafiEstimatorHttpError");
1325
+ }
1310
1326
  status;
1311
1327
  body;
1312
1328
  constructor(status, body, message) {
@@ -1322,9 +1338,7 @@ function createPafiEstimatorClient(config) {
1322
1338
  if (!issuerId) throw new Error("createPafiEstimatorClient: issuerId required");
1323
1339
  const fetchImpl = config.fetchImpl ?? globalThis.fetch;
1324
1340
  if (!fetchImpl) {
1325
- throw new Error(
1326
- "createPafiEstimatorClient: no fetch implementation available \u2014 pass `fetchImpl`"
1327
- );
1341
+ throw new Error("createPafiEstimatorClient: no fetch implementation available \u2014 pass `fetchImpl`");
1328
1342
  }
1329
1343
  const url = `${baseUrl.replace(/\/$/, "")}/v1/estimate-gas-fee`;
1330
1344
  return {
@@ -1368,15 +1382,19 @@ function createPafiEstimatorClient(config) {
1368
1382
  }
1369
1383
  };
1370
1384
  }
1385
+ __name(createPafiEstimatorClient, "createPafiEstimatorClient");
1371
1386
 
1372
1387
  // src/indexer/types.ts
1373
1388
  var InMemoryCursorStore = class _InMemoryCursorStore {
1389
+ static {
1390
+ __name(this, "InMemoryCursorStore");
1391
+ }
1374
1392
  cursor;
1375
1393
  /**
1376
- * Child stores keyed by `forKey()`. Each child has its own cursor,
1377
- * so a single InMemoryCursorStore can back N PointIndexers in tests
1378
- * / single-process callers.
1379
- */
1394
+ * Child stores keyed by `forKey()`. Each child has its own cursor,
1395
+ * so a single InMemoryCursorStore can back N PointIndexers in tests
1396
+ * / single-process callers.
1397
+ */
1380
1398
  children = /* @__PURE__ */ new Map();
1381
1399
  async load() {
1382
1400
  return this.cursor;
@@ -1397,21 +1415,18 @@ var InMemoryCursorStore = class _InMemoryCursorStore {
1397
1415
  // src/indexer/pointIndexer.ts
1398
1416
  var import_viem4 = require("viem");
1399
1417
  var PointIndexerFinalizeError = class extends Error {
1400
- constructor(message, context, cause) {
1401
- super(message);
1402
- this.context = context;
1403
- this.cause = cause;
1404
- this.name = "PointIndexerFinalizeError";
1418
+ static {
1419
+ __name(this, "PointIndexerFinalizeError");
1405
1420
  }
1406
1421
  context;
1407
1422
  cause;
1423
+ constructor(message, context, cause) {
1424
+ super(message), this.context = context, this.cause = cause;
1425
+ this.name = "PointIndexerFinalizeError";
1426
+ }
1408
1427
  };
1409
- var TRANSFER_EVENT = (0, import_viem4.parseAbiItem)(
1410
- "event Transfer(address indexed from, address indexed to, uint256 value)"
1411
- );
1412
- var MINT_WITH_FEE_EVENT = (0, import_viem4.parseAbiItem)(
1413
- "event MintWithFee(address indexed pointToken, address indexed to, uint256 grossAmount, uint256 netAmount, uint256 feeAmount)"
1414
- );
1428
+ var TRANSFER_EVENT = (0, import_viem4.parseAbiItem)("event Transfer(address indexed from, address indexed to, uint256 value)");
1429
+ var MINT_WITH_FEE_EVENT = (0, import_viem4.parseAbiItem)("event MintWithFee(address indexed pointToken, address indexed to, uint256 grossAmount, uint256 netAmount, uint256 feeAmount)");
1415
1430
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
1416
1431
  var DEAD_ADDRESS = "0x000000000000000000000000000000000000dEaD";
1417
1432
  var DEFAULT_CONFIRMATIONS = 3;
@@ -1422,7 +1437,11 @@ function isNoWrapper(addr) {
1422
1437
  const checksummed = (0, import_viem4.getAddress)(addr);
1423
1438
  return checksummed === ZERO_ADDRESS || checksummed === DEAD_ADDRESS;
1424
1439
  }
1440
+ __name(isNoWrapper, "isNoWrapper");
1425
1441
  var PointIndexer = class {
1442
+ static {
1443
+ __name(this, "PointIndexer");
1444
+ }
1426
1445
  provider;
1427
1446
  pointTokenAddress;
1428
1447
  mintFeeWrapperAddress;
@@ -1437,8 +1456,7 @@ var PointIndexer = class {
1437
1456
  timer;
1438
1457
  constructor(config) {
1439
1458
  if (!config.provider) throw new Error("PointIndexer: provider required");
1440
- if (!config.pointTokenAddress)
1441
- throw new Error("PointIndexer: pointTokenAddress required");
1459
+ if (!config.pointTokenAddress) throw new Error("PointIndexer: pointTokenAddress required");
1442
1460
  if (!config.ledger) throw new Error("PointIndexer: ledger required");
1443
1461
  this.provider = config.provider;
1444
1462
  this.pointTokenAddress = (0, import_viem4.getAddress)(config.pointTokenAddress);
@@ -1469,10 +1487,10 @@ var PointIndexer = class {
1469
1487
  }
1470
1488
  }
1471
1489
  /**
1472
- * Run one poll cycle: load cursor → scan [cursor, safeHead] in
1473
- * `batchSize` chunks → persist new cursor. Swallows any error and
1474
- * schedules the next tick. Visible for test harnesses via a public name.
1475
- */
1490
+ * Run one poll cycle: load cursor → scan [cursor, safeHead] in
1491
+ * `batchSize` chunks → persist new cursor. Swallows any error and
1492
+ * schedules the next tick. Visible for test harnesses via a public name.
1493
+ */
1476
1494
  async tick() {
1477
1495
  if (!this.running) return;
1478
1496
  try {
@@ -1507,19 +1525,16 @@ var PointIndexer = class {
1507
1525
  }
1508
1526
  scheduleNext() {
1509
1527
  if (!this.running) return;
1510
- this.timer = setTimeout(
1511
- () => this.tick().catch((err) => this.handleTickError(err)),
1512
- this.pollIntervalMs
1513
- );
1528
+ this.timer = setTimeout(() => this.tick().catch((err) => this.handleTickError(err)), this.pollIntervalMs);
1514
1529
  }
1515
1530
  // -------------------------------------------------------------------------
1516
1531
  // Block scanning
1517
1532
  // -------------------------------------------------------------------------
1518
1533
  /**
1519
- * Scan `[from, to]` inclusive for mint events in `batchSize` chunks.
1520
- * Callers can use this directly to backfill a specific range without
1521
- * engaging `start()`. On completion, the cursor is advanced to `to + 1`.
1522
- */
1534
+ * Scan `[from, to]` inclusive for mint events in `batchSize` chunks.
1535
+ * Callers can use this directly to backfill a specific range without
1536
+ * engaging `start()`. On completion, the cursor is advanced to `to + 1`.
1537
+ */
1523
1538
  async processBlockRange(from, to) {
1524
1539
  if (from > to) return;
1525
1540
  let cursor = from;
@@ -1543,15 +1558,17 @@ var PointIndexer = class {
1543
1558
  // Event fetching — two modes (wrapper vs direct)
1544
1559
  // -------------------------------------------------------------------------
1545
1560
  /**
1546
- * Wrapper mode: listen for `MintWithFee` on the wrapper,
1547
- * filtered to events for THIS pointToken only. The event's `to` field
1548
- * is the actual end user, and `grossAmount` matches the lock amount.
1549
- */
1561
+ * Wrapper mode: listen for `MintWithFee` on the wrapper,
1562
+ * filtered to events for THIS pointToken only. The event's `to` field
1563
+ * is the actual end user, and `grossAmount` matches the lock amount.
1564
+ */
1550
1565
  async fetchWrapperMintEvents(fromBlock, toBlock) {
1551
1566
  const logs = await this.provider.getLogs({
1552
1567
  address: this.mintFeeWrapperAddress,
1553
1568
  event: MINT_WITH_FEE_EVENT,
1554
- args: { pointToken: this.pointTokenAddress },
1569
+ args: {
1570
+ pointToken: this.pointTokenAddress
1571
+ },
1555
1572
  fromBlock,
1556
1573
  toBlock
1557
1574
  });
@@ -1573,14 +1590,16 @@ var PointIndexer = class {
1573
1590
  return out;
1574
1591
  }
1575
1592
  /**
1576
- * Direct mode (legacy / chains without wrapper): listen for
1577
- * `Transfer(from=0x0 → to)` on the PointToken itself.
1578
- */
1593
+ * Direct mode (legacy / chains without wrapper): listen for
1594
+ * `Transfer(from=0x0 → to)` on the PointToken itself.
1595
+ */
1579
1596
  async fetchTransferMintEvents(fromBlock, toBlock) {
1580
1597
  const logs = await this.provider.getLogs({
1581
1598
  address: this.pointTokenAddress,
1582
1599
  event: TRANSFER_EVENT,
1583
- args: { from: ZERO_ADDRESS },
1600
+ args: {
1601
+ from: ZERO_ADDRESS
1602
+ },
1584
1603
  fromBlock,
1585
1604
  toBlock
1586
1605
  });
@@ -1607,42 +1626,30 @@ var PointIndexer = class {
1607
1626
  // Finalization
1608
1627
  // -------------------------------------------------------------------------
1609
1628
  /**
1610
- * Finalize a single mint event: match it to a PENDING lock in the
1611
- * ledger, then call `deductBalance` (which also resolves the lock in
1612
- * the default `MemoryPointLedger`).
1613
- *
1614
- * No-matching-lock is a valid state: it means either the lock already
1615
- * expired, or the mint was authorized out-of-band (e.g. a direct
1616
- * `PointToken.mint()` from an EOA minter for testing). In that case we
1617
- * do NOT touch the ledger — crediting here would silently allow the
1618
- * issuer to mint without going through the gateway.
1619
- */
1629
+ * Finalize a single mint event: match it to a PENDING lock in the
1630
+ * ledger, then call `deductBalance` (which also resolves the lock in
1631
+ * the default `MemoryPointLedger`).
1632
+ *
1633
+ * No-matching-lock is a valid state: it means either the lock already
1634
+ * expired, or the mint was authorized out-of-band (e.g. a direct
1635
+ * `PointToken.mint()` from an EOA minter for testing). In that case we
1636
+ * do NOT touch the ledger — crediting here would silently allow the
1637
+ * issuer to mint without going through the gateway.
1638
+ */
1620
1639
  async finalize(evt) {
1621
- const locks = await this.ledger.getLockedRequests(
1622
- evt.to,
1623
- this.pointTokenAddress
1624
- );
1640
+ const locks = await this.ledger.getLockedRequests(evt.to, this.pointTokenAddress);
1625
1641
  const match = pickMatchingLock(locks, evt.amount);
1626
1642
  if (!match) return;
1627
1643
  try {
1628
- await this.ledger.deductBalance(
1629
- evt.to,
1630
- evt.amount,
1631
- evt.txHash,
1632
- this.pointTokenAddress
1633
- );
1644
+ await this.ledger.deductBalance(evt.to, evt.amount, evt.txHash, this.pointTokenAddress);
1634
1645
  } catch (err) {
1635
- throw new PointIndexerFinalizeError(
1636
- `PointIndexer.deductBalance failed for tx ${evt.txHash} (to=${evt.to}, amount=${evt.amount}, block=${evt.blockNumber}); cursor will NOT advance, next tick retries.`,
1637
- {
1638
- pointToken: this.pointTokenAddress,
1639
- to: evt.to,
1640
- amount: evt.amount,
1641
- txHash: evt.txHash,
1642
- blockNumber: evt.blockNumber
1643
- },
1644
- err
1645
- );
1646
+ throw new PointIndexerFinalizeError(`PointIndexer.deductBalance failed for tx ${evt.txHash} (to=${evt.to}, amount=${evt.amount}, block=${evt.blockNumber}); cursor will NOT advance, next tick retries.`, {
1647
+ pointToken: this.pointTokenAddress,
1648
+ to: evt.to,
1649
+ amount: evt.amount,
1650
+ txHash: evt.txHash,
1651
+ blockNumber: evt.blockNumber
1652
+ }, err);
1646
1653
  }
1647
1654
  try {
1648
1655
  await this.ledger.updateMintStatus(match.lockId, "MINTED", evt.txHash);
@@ -1661,32 +1668,35 @@ function pickMatchingLock(locks, amount) {
1661
1668
  }
1662
1669
  return best;
1663
1670
  }
1671
+ __name(pickMatchingLock, "pickMatchingLock");
1664
1672
 
1665
1673
  // src/indexer/burnIndexer.ts
1666
1674
  var import_viem5 = require("viem");
1667
1675
  var BurnIndexerFinalizeError = class extends Error {
1668
- constructor(message, context, cause) {
1669
- super(message);
1670
- this.context = context;
1671
- this.cause = cause;
1672
- this.name = "BurnIndexerFinalizeError";
1676
+ static {
1677
+ __name(this, "BurnIndexerFinalizeError");
1673
1678
  }
1674
1679
  context;
1675
1680
  cause;
1681
+ constructor(message, context, cause) {
1682
+ super(message), this.context = context, this.cause = cause;
1683
+ this.name = "BurnIndexerFinalizeError";
1684
+ }
1676
1685
  };
1677
- var TRANSFER_EVENT2 = (0, import_viem5.parseAbiItem)(
1678
- "event Transfer(address indexed from, address indexed to, uint256 value)"
1679
- );
1686
+ var TRANSFER_EVENT2 = (0, import_viem5.parseAbiItem)("event Transfer(address indexed from, address indexed to, uint256 value)");
1680
1687
  var ZERO_ADDRESS2 = "0x0000000000000000000000000000000000000000";
1681
1688
  var DEFAULT_CONFIRMATIONS2 = 3;
1682
1689
  var DEFAULT_BATCH_SIZE2 = 2000n;
1683
1690
  var DEFAULT_POLL_INTERVAL_MS2 = 5e3;
1684
1691
  var BurnIndexer = class {
1692
+ static {
1693
+ __name(this, "BurnIndexer");
1694
+ }
1685
1695
  provider;
1686
1696
  /**
1687
- * The PointToken this indexer watches. Exposed so callers can key
1688
- * leader-election locks / cursor stores by token
1689
- */
1697
+ * The PointToken this indexer watches. Exposed so callers can key
1698
+ * leader-election locks / cursor stores by token
1699
+ */
1690
1700
  pointTokenAddress;
1691
1701
  ledger;
1692
1702
  cursorStore;
@@ -1700,24 +1710,19 @@ var BurnIndexer = class {
1700
1710
  timer;
1701
1711
  constructor(config) {
1702
1712
  if (!config.provider) throw new Error("BurnIndexer: provider required");
1703
- if (!config.pointTokenAddress)
1704
- throw new Error("BurnIndexer: pointTokenAddress required");
1713
+ if (!config.pointTokenAddress) throw new Error("BurnIndexer: pointTokenAddress required");
1705
1714
  if (!config.ledger) throw new Error("BurnIndexer: ledger required");
1706
1715
  this.provider = config.provider;
1707
1716
  this.pointTokenAddress = config.pointTokenAddress;
1708
1717
  this.ledger = config.ledger;
1709
1718
  this.cursorStore = config.cursorStore ?? new InMemoryCursorStore();
1710
1719
  this.startBlock = config.fromBlock ?? 0n;
1711
- this.confirmations = BigInt(
1712
- config.confirmations ?? DEFAULT_CONFIRMATIONS2
1713
- );
1720
+ this.confirmations = BigInt(config.confirmations ?? DEFAULT_CONFIRMATIONS2);
1714
1721
  this.batchSize = BigInt(config.batchSize ?? Number(DEFAULT_BATCH_SIZE2));
1715
1722
  this.pollIntervalMs = config.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
1716
1723
  if (config.onTickError) this.onTickError = config.onTickError;
1717
1724
  if (!config.matchLockId) {
1718
- throw new Error(
1719
- "BurnIndexer: matchLockId is required. Provide a function that maps a burn event to its pending credit lockId. Without it, no on-chain burns will ever grant off-chain credits."
1720
- );
1725
+ throw new Error("BurnIndexer: matchLockId is required. Provide a function that maps a burn event to its pending credit lockId. Without it, no on-chain burns will ever grant off-chain credits.");
1721
1726
  }
1722
1727
  this.matchLockId = config.matchLockId;
1723
1728
  }
@@ -1767,16 +1772,13 @@ var BurnIndexer = class {
1767
1772
  }
1768
1773
  scheduleNext() {
1769
1774
  if (!this.running) return;
1770
- this.timer = setTimeout(
1771
- () => this.tick().catch((err) => this.handleTickError(err)),
1772
- this.pollIntervalMs
1773
- );
1775
+ this.timer = setTimeout(() => this.tick().catch((err) => this.handleTickError(err)), this.pollIntervalMs);
1774
1776
  }
1775
1777
  /**
1776
- * Scan `[from, to]` inclusive for burn events. Callers can drive this
1777
- * directly to backfill a specific range without `start()`. Cursor is
1778
- * advanced to `to + 1` on completion.
1779
- */
1778
+ * Scan `[from, to]` inclusive for burn events. Callers can drive this
1779
+ * directly to backfill a specific range without `start()`. Cursor is
1780
+ * advanced to `to + 1` on completion.
1781
+ */
1780
1782
  async processBlockRange(from, to) {
1781
1783
  if (from > to) return;
1782
1784
  let cursor = from;
@@ -1785,8 +1787,9 @@ var BurnIndexer = class {
1785
1787
  const logs = await this.provider.getLogs({
1786
1788
  address: this.pointTokenAddress,
1787
1789
  event: TRANSFER_EVENT2,
1788
- args: { to: ZERO_ADDRESS2 },
1789
- // filter: burn = transfer to zero
1790
+ args: {
1791
+ to: ZERO_ADDRESS2
1792
+ },
1790
1793
  fromBlock: cursor,
1791
1794
  toBlock: chunkEnd
1792
1795
  });
@@ -1822,17 +1825,15 @@ var BurnIndexer = class {
1822
1825
  return out;
1823
1826
  }
1824
1827
  /**
1825
- * Resolve a matching pending credit for this burn event and call
1826
- * `ledger.resolveCreditByBurnTx(lockId, txHash)`. If no match found,
1827
- * log + skip.
1828
- */
1828
+ * Resolve a matching pending credit for this burn event and call
1829
+ * `ledger.resolveCreditByBurnTx(lockId, txHash)`. If no match found,
1830
+ * log + skip.
1831
+ */
1829
1832
  async finalize(evt) {
1830
1833
  const txHash = evt.txHash;
1831
1834
  const lockId = await this.matchLockId(evt);
1832
1835
  if (lockId === void 0) {
1833
- console.warn(
1834
- "[PAFI] BurnIndexer: matchLockId returned undefined for burn tx " + txHash + ". This burn will NOT be credited. Implement matchLockId to map burn events to lock IDs."
1835
- );
1836
+ console.warn("[PAFI] BurnIndexer: matchLockId returned undefined for burn tx " + txHash + ". This burn will NOT be credited. Implement matchLockId to map burn events to lock IDs.");
1836
1837
  return;
1837
1838
  }
1838
1839
  if (!this.ledger.resolveCreditByBurnTx) {
@@ -1841,18 +1842,14 @@ var BurnIndexer = class {
1841
1842
  try {
1842
1843
  await this.ledger.resolveCreditByBurnTx(lockId, evt.txHash);
1843
1844
  } catch (err) {
1844
- throw new BurnIndexerFinalizeError(
1845
- `BurnIndexer.resolveCreditByBurnTx failed for tx ${evt.txHash} (lockId=${lockId}, from=${evt.from}, amount=${evt.amount}, block=${evt.blockNumber}); cursor will NOT advance, next tick retries.`,
1846
- {
1847
- pointToken: this.pointTokenAddress,
1848
- from: evt.from,
1849
- amount: evt.amount,
1850
- txHash: evt.txHash,
1851
- blockNumber: evt.blockNumber,
1852
- lockId
1853
- },
1854
- err
1855
- );
1845
+ throw new BurnIndexerFinalizeError(`BurnIndexer.resolveCreditByBurnTx failed for tx ${evt.txHash} (lockId=${lockId}, from=${evt.from}, amount=${evt.amount}, block=${evt.blockNumber}); cursor will NOT advance, next tick retries.`, {
1846
+ pointToken: this.pointTokenAddress,
1847
+ from: evt.from,
1848
+ amount: evt.amount,
1849
+ txHash: evt.txHash,
1850
+ blockNumber: evt.blockNumber,
1851
+ lockId
1852
+ }, err);
1856
1853
  }
1857
1854
  }
1858
1855
  };
@@ -1862,10 +1859,9 @@ function makePostgresSingletonLock(runner) {
1862
1859
  return {
1863
1860
  async acquire(key) {
1864
1861
  const lockId = hashKeyToInt64(key);
1865
- const rows = await runner.query(
1866
- "SELECT pg_try_advisory_lock($1::bigint) AS got",
1867
- [lockId]
1868
- );
1862
+ const rows = await runner.query("SELECT pg_try_advisory_lock($1::bigint) AS got", [
1863
+ lockId
1864
+ ]);
1869
1865
  const got = rows[0]?.got === true;
1870
1866
  if (!got) return null;
1871
1867
  return {
@@ -1881,6 +1877,7 @@ function makePostgresSingletonLock(runner) {
1881
1877
  }
1882
1878
  };
1883
1879
  }
1880
+ __name(makePostgresSingletonLock, "makePostgresSingletonLock");
1884
1881
  function hashKeyToInt64(key) {
1885
1882
  const FNV_OFFSET = 0xcbf29ce484222325n;
1886
1883
  const FNV_PRIME = 0x100000001b3n;
@@ -1895,18 +1892,22 @@ function hashKeyToInt64(key) {
1895
1892
  const signed = hash > SIGNED_MAX ? hash - TWO64 : hash;
1896
1893
  return signed.toString();
1897
1894
  }
1895
+ __name(hashKeyToInt64, "hashKeyToInt64");
1898
1896
 
1899
1897
  // src/api/handlers.ts
1900
1898
  var import_viem6 = require("viem");
1901
1899
  var import_core6 = require("@pafi-dev/core");
1902
1900
  var IssuerApiHandlers = class _IssuerApiHandlers {
1901
+ static {
1902
+ __name(this, "IssuerApiHandlers");
1903
+ }
1903
1904
  authService;
1904
1905
  ledger;
1905
1906
  provider;
1906
1907
  /**
1907
- * Set of supported PointToken addresses (checksum-normalized). Handlers
1908
- * validate the request's `pointTokenAddress` against this set.
1909
- */
1908
+ * Set of supported PointToken addresses (checksum-normalized). Handlers
1909
+ * validate the request's `pointTokenAddress` against this set.
1910
+ */
1910
1911
  supportedTokens;
1911
1912
  chainId;
1912
1913
  contracts;
@@ -1917,10 +1918,10 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
1917
1918
  rateLimiter;
1918
1919
  mintFeeWrapperAddress;
1919
1920
  /**
1920
- * Per-token feeBps cache. Refreshed on /config when stale. feeBps
1921
- * changes only when ops calls `wrapper.setRecipients`, so 5-min TTL
1922
- * is more than safe for FE display purposes.
1923
- */
1921
+ * Per-token feeBps cache. Refreshed on /config when stale. feeBps
1922
+ * changes only when ops calls `wrapper.setRecipients`, so 5-min TTL
1923
+ * is more than safe for FE display purposes.
1924
+ */
1924
1925
  feeBpsCache = /* @__PURE__ */ new Map();
1925
1926
  static FEE_BPS_TTL_MS = 5 * 60 * 1e3;
1926
1927
  constructor(config) {
@@ -1928,11 +1929,11 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
1928
1929
  this.ledger = config.ledger;
1929
1930
  this.provider = config.provider;
1930
1931
  this.rateLimiter = config.rateLimiter ?? new NoopRateLimiter();
1931
- const raw = config.pointTokenAddresses && config.pointTokenAddresses.length > 0 ? config.pointTokenAddresses : config.pointTokenAddress ? [config.pointTokenAddress] : [];
1932
+ const raw = config.pointTokenAddresses && config.pointTokenAddresses.length > 0 ? config.pointTokenAddresses : config.pointTokenAddress ? [
1933
+ config.pointTokenAddress
1934
+ ] : [];
1932
1935
  if (raw.length === 0) {
1933
- throw new Error(
1934
- "IssuerApiHandlers: pointTokenAddress or pointTokenAddresses required"
1935
- );
1936
+ throw new Error("IssuerApiHandlers: pointTokenAddress or pointTokenAddresses required");
1936
1937
  }
1937
1938
  const normalized = raw.map((a) => (0, import_viem6.getAddress)(a));
1938
1939
  this.supportedTokens = new Set(normalized);
@@ -1950,63 +1951,48 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
1950
1951
  // Public handlers (no auth required)
1951
1952
  // =========================================================================
1952
1953
  /**
1953
- * `GET /auth/nonce`
1954
- *
1955
- * @param rateLimitKey Caller-side rate-limit key (typically client IP).
1956
- * The HTTP layer (controller/middleware) extracts
1957
- * this from the request and passes it through.
1958
- * When omitted, no rate limit applies — production
1959
- * callers SHOULD always pass a key.
1960
- */
1954
+ * `GET /auth/nonce`
1955
+ *
1956
+ * @param rateLimitKey Caller-side rate-limit key (typically client IP).
1957
+ * The HTTP layer (controller/middleware) extracts
1958
+ * this from the request and passes it through.
1959
+ * When omitted, no rate limit applies — production
1960
+ * callers SHOULD always pass a key.
1961
+ */
1961
1962
  async handleGetNonce(rateLimitKey) {
1962
1963
  if (rateLimitKey) {
1963
- const result = await this.rateLimiter.consume(
1964
- rateLimitKey,
1965
- "auth_nonce"
1966
- );
1964
+ const result = await this.rateLimiter.consume(rateLimitKey, "auth_nonce");
1967
1965
  if (!result.allowed) {
1968
- throw new import_core3.ValidationError(
1969
- "RATE_LIMIT_EXCEEDED",
1970
- "handleGetNonce: too many requests",
1971
- {
1972
- retryAfterMs: result.retryAfterMs ?? 0,
1973
- action: "auth_nonce"
1974
- }
1975
- );
1966
+ throw new import_core3.ValidationError("RATE_LIMIT_EXCEEDED", "handleGetNonce: too many requests", {
1967
+ retryAfterMs: result.retryAfterMs ?? 0,
1968
+ action: "auth_nonce"
1969
+ });
1976
1970
  }
1977
1971
  }
1978
1972
  const nonce = await this.authService.getNonce();
1979
- return { nonce };
1973
+ return {
1974
+ nonce
1975
+ };
1980
1976
  }
1981
1977
  /**
1982
- * `POST /auth/login`
1983
- *
1984
- * @param body Login message + signature.
1985
- * @param rateLimitKey Caller-side rate-limit key (typically client IP
1986
- * or `body.userAddress` if known). See `handleGetNonce`.
1987
- */
1978
+ * `POST /auth/login`
1979
+ *
1980
+ * @param body Login message + signature.
1981
+ * @param rateLimitKey Caller-side rate-limit key (typically client IP
1982
+ * or `body.userAddress` if known). See `handleGetNonce`.
1983
+ */
1988
1984
  async handleLogin(body, rateLimitKey) {
1989
1985
  if (rateLimitKey) {
1990
- const result2 = await this.rateLimiter.consume(
1991
- rateLimitKey,
1992
- "auth_login"
1993
- );
1986
+ const result2 = await this.rateLimiter.consume(rateLimitKey, "auth_login");
1994
1987
  if (!result2.allowed) {
1995
- throw new import_core3.ValidationError(
1996
- "RATE_LIMIT_EXCEEDED",
1997
- "handleLogin: too many requests",
1998
- {
1999
- retryAfterMs: result2.retryAfterMs ?? 0,
2000
- action: "auth_login"
2001
- }
2002
- );
1988
+ throw new import_core3.ValidationError("RATE_LIMIT_EXCEEDED", "handleLogin: too many requests", {
1989
+ retryAfterMs: result2.retryAfterMs ?? 0,
1990
+ action: "auth_login"
1991
+ });
2003
1992
  }
2004
1993
  }
2005
1994
  if (!body || typeof body.message !== "string" || body.message.length === 0 || typeof body.signature !== "string" || body.signature.length <= 2) {
2006
- throw new import_core3.ValidationError(
2007
- "INVALID_LOGIN_BODY",
2008
- "handleLogin: message and signature are required"
2009
- );
1995
+ throw new import_core3.ValidationError("INVALID_LOGIN_BODY", "handleLogin: message and signature are required");
2010
1996
  }
2011
1997
  if (body.message.length > 4096) {
2012
1998
  throw new import_core3.ValidationError("MESSAGE_TOO_LONG", "message too long");
@@ -2022,11 +2008,11 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
2022
2008
  };
2023
2009
  }
2024
2010
  /**
2025
- * `GET /config?chainId=<id>`
2026
- *
2027
- * Returns the contract addresses and chain id that the frontend SDK
2028
- * needs to build EIP-712 messages and interact with on-chain.
2029
- */
2011
+ * `GET /config?chainId=<id>`
2012
+ *
2013
+ * Returns the contract addresses and chain id that the frontend SDK
2014
+ * needs to build EIP-712 messages and interact with on-chain.
2015
+ */
2030
2016
  async handleConfig(chainId) {
2031
2017
  if (!Number.isInteger(chainId) || chainId <= 0) {
2032
2018
  throw new import_core3.ValidationError("INVALID_CHAIN_ID", "invalid chainId", {
@@ -2034,11 +2020,10 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
2034
2020
  });
2035
2021
  }
2036
2022
  if (chainId !== this.chainId) {
2037
- throw new import_core3.ValidationError(
2038
- "UNSUPPORTED_CHAIN_ID",
2039
- `handleConfig: unsupported chainId ${chainId}`,
2040
- { requested: chainId, supported: this.chainId }
2041
- );
2023
+ throw new import_core3.ValidationError("UNSUPPORTED_CHAIN_ID", `handleConfig: unsupported chainId ${chainId}`, {
2024
+ requested: chainId,
2025
+ supported: this.chainId
2026
+ });
2042
2027
  }
2043
2028
  const contracts = {
2044
2029
  ...this.contracts,
@@ -2052,60 +2037,55 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
2052
2037
  contracts
2053
2038
  };
2054
2039
  if (this.mintFeeWrapperAddress) {
2055
- const byToken = await this.resolveFeeBpsByToken(
2056
- this.mintFeeWrapperAddress
2057
- );
2040
+ const byToken = await this.resolveFeeBpsByToken(this.mintFeeWrapperAddress);
2058
2041
  if (byToken) response.mintFeeBpsByToken = byToken;
2059
2042
  }
2060
2043
  if (this.pafiWebUrl) response.pafiWebUrl = this.pafiWebUrl;
2061
2044
  return response;
2062
2045
  }
2063
2046
  /**
2064
- * Read `totalFeeBps(pointToken)` for every supported PointToken from
2065
- * the wrapper. Cached per-token for 5 minutes. Returns `undefined`
2066
- * (caller drops the field) if every read fails — FE must treat
2067
- * "field missing" as "fee unknown, do not display".
2068
- */
2047
+ * Read `totalFeeBps(pointToken)` for every supported PointToken from
2048
+ * the wrapper. Cached per-token for 5 minutes. Returns `undefined`
2049
+ * (caller drops the field) if every read fails — FE must treat
2050
+ * "field missing" as "fee unknown, do not display".
2051
+ */
2069
2052
  async resolveFeeBpsByToken(wrapper) {
2070
2053
  const now = Date.now();
2071
2054
  const out = {};
2072
2055
  let anyFresh = false;
2073
- await Promise.all(
2074
- Array.from(this.supportedTokens).map(async (token) => {
2075
- const cached = this.feeBpsCache.get(token);
2076
- if (cached && cached.expiresAt > now) {
2056
+ await Promise.all(Array.from(this.supportedTokens).map(async (token) => {
2057
+ const cached = this.feeBpsCache.get(token);
2058
+ if (cached && cached.expiresAt > now) {
2059
+ out[token.toLowerCase()] = cached.value;
2060
+ anyFresh = true;
2061
+ return;
2062
+ }
2063
+ try {
2064
+ const bps = await (0, import_core6.getMintFeeBps)(this.provider, wrapper, token);
2065
+ this.feeBpsCache.set(token, {
2066
+ value: bps,
2067
+ expiresAt: now + _IssuerApiHandlers.FEE_BPS_TTL_MS
2068
+ });
2069
+ out[token.toLowerCase()] = bps;
2070
+ anyFresh = true;
2071
+ } catch {
2072
+ if (cached) {
2077
2073
  out[token.toLowerCase()] = cached.value;
2078
2074
  anyFresh = true;
2079
- return;
2080
- }
2081
- try {
2082
- const bps = await (0, import_core6.getMintFeeBps)(this.provider, wrapper, token);
2083
- this.feeBpsCache.set(token, {
2084
- value: bps,
2085
- expiresAt: now + _IssuerApiHandlers.FEE_BPS_TTL_MS
2086
- });
2087
- out[token.toLowerCase()] = bps;
2088
- anyFresh = true;
2089
- } catch {
2090
- if (cached) {
2091
- out[token.toLowerCase()] = cached.value;
2092
- anyFresh = true;
2093
- }
2094
2075
  }
2095
- })
2096
- );
2076
+ }
2077
+ }));
2097
2078
  return anyFresh ? out : void 0;
2098
2079
  }
2099
2080
  /** `GET /gas-fee` — quoted in USDT (6-decimal base units). */
2100
2081
  async handleGasFee() {
2101
2082
  if (!this.feeManager) {
2102
- throw new ConfigurationError(
2103
- "FEE_MANAGER_NOT_CONFIGURED",
2104
- "handleGasFee: feeManager is not configured on this issuer"
2105
- );
2083
+ throw new ConfigurationError("FEE_MANAGER_NOT_CONFIGURED", "handleGasFee: feeManager is not configured on this issuer");
2106
2084
  }
2107
2085
  const gasFeeUsdt = await this.feeManager.estimateGasFee();
2108
- return { gasFeeUsdt };
2086
+ return {
2087
+ gasFeeUsdt
2088
+ };
2109
2089
  }
2110
2090
  // =========================================================================
2111
2091
  // Protected handlers (JWT required — userAddress extracted by middleware)
@@ -2115,57 +2095,49 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
2115
2095
  await this.authService.logout(token);
2116
2096
  }
2117
2097
  /**
2118
- * `GET /pools?chainId=<id>&pointToken=<addr>`
2119
- *
2120
- * Delegates to the injected `PoolsProvider`. The handler itself does
2121
- * not know where pools come from — that's an issuer decision.
2122
- */
2098
+ * `GET /pools?chainId=<id>&pointToken=<addr>`
2099
+ *
2100
+ * Delegates to the injected `PoolsProvider`. The handler itself does
2101
+ * not know where pools come from — that's an issuer decision.
2102
+ */
2123
2103
  async handlePools(_userAddress, request) {
2124
2104
  if (!this.poolsProvider) {
2125
- throw new ConfigurationError(
2126
- "POOLS_PROVIDER_NOT_CONFIGURED",
2127
- "handlePools: poolsProvider is not configured on this issuer"
2128
- );
2105
+ throw new ConfigurationError("POOLS_PROVIDER_NOT_CONFIGURED", "handlePools: poolsProvider is not configured on this issuer");
2129
2106
  }
2130
2107
  if (request.chainId !== this.chainId) {
2131
- throw new import_core3.ValidationError(
2132
- "UNSUPPORTED_CHAIN_ID",
2133
- `handlePools: unsupported chainId ${request.chainId}`,
2134
- { requested: request.chainId, supported: this.chainId }
2135
- );
2108
+ throw new import_core3.ValidationError("UNSUPPORTED_CHAIN_ID", `handlePools: unsupported chainId ${request.chainId}`, {
2109
+ requested: request.chainId,
2110
+ supported: this.chainId
2111
+ });
2136
2112
  }
2137
2113
  return this.poolsProvider(request);
2138
2114
  }
2139
2115
  /**
2140
- * `GET /user?chainId=<id>&user=<addr>&pointToken=<addr>`
2141
- *
2142
- * Returns per-user state the frontend needs to build a fresh mint:
2143
- * on-chain nonces + minter status + off-chain balance.
2144
- */
2116
+ * `GET /user?chainId=<id>&user=<addr>&pointToken=<addr>`
2117
+ *
2118
+ * Returns per-user state the frontend needs to build a fresh mint:
2119
+ * on-chain nonces + minter status + off-chain balance.
2120
+ */
2145
2121
  async handleUser(userAddress, request) {
2146
2122
  if (request.chainId !== this.chainId) {
2147
- throw new import_core3.ValidationError(
2148
- "UNSUPPORTED_CHAIN_ID",
2149
- `handleUser: unsupported chainId ${request.chainId}`,
2150
- { requested: request.chainId, supported: this.chainId }
2151
- );
2123
+ throw new import_core3.ValidationError("UNSUPPORTED_CHAIN_ID", `handleUser: unsupported chainId ${request.chainId}`, {
2124
+ requested: request.chainId,
2125
+ supported: this.chainId
2126
+ });
2152
2127
  }
2153
2128
  const normalizedAuthed = (0, import_viem6.getAddress)(userAddress);
2154
2129
  const normalizedRequest = (0, import_viem6.getAddress)(request.userAddress);
2155
2130
  if (normalizedAuthed !== normalizedRequest) {
2156
- throw new import_core3.ValidationError(
2157
- "USER_ADDRESS_MISMATCH",
2158
- "handleUser: request userAddress must match authenticated user",
2159
- { authenticated: normalizedAuthed, requested: normalizedRequest }
2160
- );
2131
+ throw new import_core3.ValidationError("USER_ADDRESS_MISMATCH", "handleUser: request userAddress must match authenticated user", {
2132
+ authenticated: normalizedAuthed,
2133
+ requested: normalizedRequest
2134
+ });
2161
2135
  }
2162
2136
  const pointToken = (0, import_viem6.getAddress)(request.pointTokenAddress);
2163
2137
  if (!this.supportedTokens.has(pointToken)) {
2164
- throw new import_core3.ValidationError(
2165
- "UNSUPPORTED_POINT_TOKEN",
2166
- `handleUser: unsupported pointToken ${pointToken}`,
2167
- { requested: pointToken }
2168
- );
2138
+ throw new import_core3.ValidationError("UNSUPPORTED_POINT_TOKEN", `handleUser: unsupported pointToken ${pointToken}`, {
2139
+ requested: pointToken
2140
+ });
2169
2141
  }
2170
2142
  const [offChainBalance, onChainBalance, minter] = await Promise.all([
2171
2143
  this.ledger.getBalance(normalizedAuthed, pointToken),
@@ -2177,7 +2149,6 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
2177
2149
  onChainBalance,
2178
2150
  totalBalance: offChainBalance + onChainBalance,
2179
2151
  balance: offChainBalance,
2180
- // deprecated alias
2181
2152
  isMinter: minter
2182
2153
  };
2183
2154
  }
@@ -2185,56 +2156,41 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
2185
2156
  // removed in 0.5.43 — callers should use `PTClaimHandler` directly or
2186
2157
  // wire `IssuerApiAdapter.claim()` which composes the full flow.
2187
2158
  /**
2188
- * `GET /redemption/preview?pointToken=<addr>`
2189
- *
2190
- * Returns the headroom currently available to `userAddress` under the
2191
- * configured RedemptionPolicy. Pure read — does not record anything.
2192
- * Use this for UI to render "X PT redeemable now / next available at …".
2193
- */
2159
+ * `GET /redemption/preview?pointToken=<addr>`
2160
+ *
2161
+ * Returns the headroom currently available to `userAddress` under the
2162
+ * configured RedemptionPolicy. Pure read — does not record anything.
2163
+ * Use this for UI to render "X PT redeemable now / next available at …".
2164
+ */
2194
2165
  async handleRedemptionPreview(userAddress, request) {
2195
2166
  if (!this.redemption) {
2196
- throw new ConfigurationError(
2197
- "REDEMPTION_NOT_CONFIGURED",
2198
- "handleRedemptionPreview: redemption is not configured on this issuer"
2199
- );
2167
+ throw new ConfigurationError("REDEMPTION_NOT_CONFIGURED", "handleRedemptionPreview: redemption is not configured on this issuer");
2200
2168
  }
2201
2169
  const tokenAddress = request.pointTokenAddress ? this.requireSupportedToken((0, import_viem6.getAddress)(request.pointTokenAddress), "handleRedemptionPreview") : void 0;
2202
- const preview = await this.redemption.preview(
2203
- (0, import_viem6.getAddress)(userAddress),
2204
- tokenAddress
2205
- );
2170
+ const preview = await this.redemption.preview((0, import_viem6.getAddress)(userAddress), tokenAddress);
2206
2171
  return preview;
2207
2172
  }
2208
2173
  /**
2209
- * `POST /redemption/evaluate`
2210
- *
2211
- * Pre-flight check before the issuer signs a BurnRequest. Returns
2212
- * { allowed, denial?, preview }. Caller (the burn-orchestrator) MUST
2213
- * re-check on the actual initiate path — evaluate is read-only and a
2214
- * caller could race two requests under the same headroom. The intended
2215
- * write path is: evaluate → sign BurnRequest → reserve pending credit
2216
- * → call `service.redemption.recordSuccessfulInitiate()`.
2217
- */
2174
+ * `POST /redemption/evaluate`
2175
+ *
2176
+ * Pre-flight check before the issuer signs a BurnRequest. Returns
2177
+ * { allowed, denial?, preview }. Caller (the burn-orchestrator) MUST
2178
+ * re-check on the actual initiate path — evaluate is read-only and a
2179
+ * caller could race two requests under the same headroom. The intended
2180
+ * write path is: evaluate → sign BurnRequest → reserve pending credit
2181
+ * → call `service.redemption.recordSuccessfulInitiate()`.
2182
+ */
2218
2183
  async handleRedemptionEvaluate(userAddress, request) {
2219
2184
  if (!this.redemption) {
2220
- throw new ConfigurationError(
2221
- "REDEMPTION_NOT_CONFIGURED",
2222
- "handleRedemptionEvaluate: redemption is not configured on this issuer"
2223
- );
2185
+ throw new ConfigurationError("REDEMPTION_NOT_CONFIGURED", "handleRedemptionEvaluate: redemption is not configured on this issuer");
2224
2186
  }
2225
2187
  if (request.amountPt <= 0n) {
2226
- throw new import_core3.ValidationError(
2227
- "INVALID_AMOUNT",
2228
- "handleRedemptionEvaluate: amountPt must be positive",
2229
- { amountPt: request.amountPt.toString() }
2230
- );
2188
+ throw new import_core3.ValidationError("INVALID_AMOUNT", "handleRedemptionEvaluate: amountPt must be positive", {
2189
+ amountPt: request.amountPt.toString()
2190
+ });
2231
2191
  }
2232
2192
  const tokenAddress = request.pointTokenAddress ? this.requireSupportedToken((0, import_viem6.getAddress)(request.pointTokenAddress), "handleRedemptionEvaluate") : void 0;
2233
- const decision = await this.redemption.evaluate(
2234
- (0, import_viem6.getAddress)(userAddress),
2235
- request.amountPt,
2236
- tokenAddress
2237
- );
2193
+ const decision = await this.redemption.evaluate((0, import_viem6.getAddress)(userAddress), request.amountPt, tokenAddress);
2238
2194
  const response = {
2239
2195
  allowed: decision.allowed,
2240
2196
  preview: decision.preview
@@ -2244,11 +2200,9 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
2244
2200
  }
2245
2201
  requireSupportedToken(pointToken, handler) {
2246
2202
  if (!this.supportedTokens.has(pointToken)) {
2247
- throw new import_core3.ValidationError(
2248
- "UNSUPPORTED_POINT_TOKEN",
2249
- `${handler}: unsupported pointToken ${pointToken}`,
2250
- { requested: pointToken }
2251
- );
2203
+ throw new import_core3.ValidationError("UNSUPPORTED_POINT_TOKEN", `${handler}: unsupported pointToken ${pointToken}`, {
2204
+ requested: pointToken
2205
+ });
2252
2206
  }
2253
2207
  return pointToken;
2254
2208
  }
@@ -2262,10 +2216,17 @@ var NAME_ABI = [
2262
2216
  name: "name",
2263
2217
  stateMutability: "view",
2264
2218
  inputs: [],
2265
- outputs: [{ type: "string" }]
2219
+ outputs: [
2220
+ {
2221
+ type: "string"
2222
+ }
2223
+ ]
2266
2224
  }
2267
2225
  ];
2268
2226
  var PointTokenDomainResolver = class {
2227
+ static {
2228
+ __name(this, "PointTokenDomainResolver");
2229
+ }
2269
2230
  provider;
2270
2231
  overrides;
2271
2232
  cache = /* @__PURE__ */ new Map();
@@ -2312,6 +2273,9 @@ var DEFAULT_REDEEM_LOCK_MS = 15 * 60 * 1e3;
2312
2273
  var M11_SAFETY_MARGIN_MS = 30 * 1e3;
2313
2274
  var DEFAULT_SIG_DEADLINE_SEC = (DEFAULT_REDEEM_LOCK_MS - M11_SAFETY_MARGIN_MS) / 1e3;
2314
2275
  var PTRedeemError = class extends import_core.PafiSdkError {
2276
+ static {
2277
+ __name(this, "PTRedeemError");
2278
+ }
2315
2279
  httpStatus = "unprocessable";
2316
2280
  code;
2317
2281
  policyDenialCode;
@@ -2324,6 +2288,9 @@ var PTRedeemError = class extends import_core.PafiSdkError {
2324
2288
  }
2325
2289
  };
2326
2290
  var PTRedeemHandler = class {
2291
+ static {
2292
+ __name(this, "PTRedeemHandler");
2293
+ }
2327
2294
  ledger;
2328
2295
  relayService;
2329
2296
  provider;
@@ -2338,31 +2305,25 @@ var PTRedeemHandler = class {
2338
2305
  now;
2339
2306
  redemptionService;
2340
2307
  /**
2341
- * Per-user in-flight nonce guard (single-process only).
2342
- *
2343
- * Prevents two concurrent requests from reading the same on-chain
2344
- * burnRequestNonce before either has completed, which would produce two
2345
- * signed UserOps with the same nonce — only one succeeds on-chain; the
2346
- * other leaves an orphaned pending credit and a wasted signer call.
2347
- *
2348
- * NOTE: This guard is effective only within a single Node.js process. For
2349
- * multi-instance deployments (k8s, PM2 cluster), enforce mutual exclusion
2350
- * via a distributed lock (Redis SETNX / Postgres advisory lock) keyed on
2351
- * `(userAddress, pointTokenAddress)` BEFORE calling `handle()`.
2352
- */
2308
+ * Per-user in-flight nonce guard (single-process only).
2309
+ *
2310
+ * Prevents two concurrent requests from reading the same on-chain
2311
+ * burnRequestNonce before either has completed, which would produce two
2312
+ * signed UserOps with the same nonce — only one succeeds on-chain; the
2313
+ * other leaves an orphaned pending credit and a wasted signer call.
2314
+ *
2315
+ * NOTE: This guard is effective only within a single Node.js process. For
2316
+ * multi-instance deployments (k8s, PM2 cluster), enforce mutual exclusion
2317
+ * via a distributed lock (Redis SETNX / Postgres advisory lock) keyed on
2318
+ * `(userAddress, pointTokenAddress)` BEFORE calling `handle()`.
2319
+ */
2353
2320
  inFlightNonces = /* @__PURE__ */ new Map();
2354
2321
  constructor(config) {
2355
2322
  if (!config.ledger.reservePendingCredit) {
2356
- throw new PTRedeemError(
2357
- "LEDGER_NOT_SUPPORTED",
2358
- "PTRedeemHandler requires a ledger that implements reservePendingCredit() (v0.3.0+)"
2359
- );
2323
+ throw new PTRedeemError("LEDGER_NOT_SUPPORTED", "PTRedeemHandler requires a ledger that implements reservePendingCredit() (v0.3.0+)");
2360
2324
  }
2361
2325
  if (!config.burnerSignerWallet) {
2362
- throw new PTRedeemError(
2363
- "SIGNING_FAILED",
2364
- "PTRedeemHandler requires burnerSignerWallet (issuer burner signer)"
2365
- );
2326
+ throw new PTRedeemError("SIGNING_FAILED", "PTRedeemHandler requires burnerSignerWallet (issuer burner signer)");
2366
2327
  }
2367
2328
  this.ledger = config.ledger;
2368
2329
  this.relayService = config.relayService;
@@ -2373,10 +2334,7 @@ var PTRedeemHandler = class {
2373
2334
  this.domainResolver = config.domainResolver;
2374
2335
  this.burnerSignerWallet = config.burnerSignerWallet;
2375
2336
  if (!config.supportedTokens) {
2376
- throw new PTRedeemError(
2377
- "UNSUPPORTED_POINT_TOKEN",
2378
- "PTRedeemHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts)."
2379
- );
2337
+ throw new PTRedeemError("UNSUPPORTED_POINT_TOKEN", "PTRedeemHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts).");
2380
2338
  }
2381
2339
  this.supportedTokens = config.supportedTokens;
2382
2340
  if (this.burnerSignerWallet?.account?.type === "local") {
@@ -2387,10 +2345,7 @@ var PTRedeemHandler = class {
2387
2345
  this.now = config.now ?? (() => Date.now());
2388
2346
  const maxAllowedSignatureMs = this.redeemLockDurationMs - M11_SAFETY_MARGIN_MS;
2389
2347
  if (this.signatureDeadlineSeconds * 1e3 > maxAllowedSignatureMs) {
2390
- throw new PTRedeemError(
2391
- "INVALID_AMOUNT",
2392
- `PTRedeemHandler config: signatureDeadlineSeconds (${this.signatureDeadlineSeconds}s) must be at most redeemLockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (redeemLockDurationMs=${this.redeemLockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS / 1e3}s).`
2393
- );
2348
+ throw new PTRedeemError("INVALID_AMOUNT", `PTRedeemHandler config: signatureDeadlineSeconds (${this.signatureDeadlineSeconds}s) must be at most redeemLockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (redeemLockDurationMs=${this.redeemLockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS / 1e3}s).`);
2394
2349
  }
2395
2350
  if (config.redemptionService) {
2396
2351
  this.redemptionService = config.redemptionService;
@@ -2398,46 +2353,31 @@ var PTRedeemHandler = class {
2398
2353
  }
2399
2354
  async handle(request) {
2400
2355
  if ((0, import_viem8.getAddress)(request.authenticatedAddress) !== (0, import_viem8.getAddress)(request.userAddress)) {
2401
- throw new PTRedeemError(
2402
- "UNAUTHORIZED",
2403
- `userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`
2404
- );
2356
+ throw new PTRedeemError("UNAUTHORIZED", `userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`);
2405
2357
  }
2406
2358
  if (request.amount <= 0n) {
2407
2359
  throw new PTRedeemError("INVALID_AMOUNT", "redeem amount must be positive");
2408
2360
  }
2409
2361
  const pointTokenAddress = (0, import_viem8.getAddress)(request.pointTokenAddress);
2410
2362
  if (!this.supportedTokens.has(pointTokenAddress)) {
2411
- throw new PTRedeemError(
2412
- "UNSUPPORTED_POINT_TOKEN",
2413
- `redeem: pointTokenAddress ${pointTokenAddress} is not in the issuer's supported-token allowlist. Check IssuerApiHandlers.supportedTokens and PTRedeemHandler.config.supportedTokens point at the same set.`
2414
- );
2363
+ throw new PTRedeemError("UNSUPPORTED_POINT_TOKEN", `redeem: pointTokenAddress ${pointTokenAddress} is not in the issuer's supported-token allowlist. Check IssuerApiHandlers.supportedTokens and PTRedeemHandler.config.supportedTokens point at the same set.`);
2415
2364
  }
2416
2365
  if (this.redemptionService) {
2417
2366
  let decision;
2418
2367
  try {
2419
- decision = await this.redemptionService.evaluate(
2420
- request.userAddress,
2421
- request.amount,
2422
- pointTokenAddress
2423
- );
2368
+ decision = await this.redemptionService.evaluate(request.userAddress, request.amount, pointTokenAddress);
2424
2369
  } catch (err) {
2425
2370
  const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
2426
2371
  if (code === "POLICY_PROVIDER_UNAVAILABLE") {
2427
- throw new PTRedeemError(
2428
- "REDEMPTION_POLICY_UNAVAILABLE",
2429
- "Redemption policy temporarily unavailable \u2014 please try again shortly."
2430
- );
2372
+ throw new PTRedeemError("REDEMPTION_POLICY_UNAVAILABLE", "Redemption policy temporarily unavailable \u2014 please try again shortly.");
2431
2373
  }
2432
2374
  throw err;
2433
2375
  }
2434
2376
  if (!decision.allowed) {
2435
2377
  const denial = decision.denial;
2436
- throw new PTRedeemError(
2437
- "REDEMPTION_POLICY_DENIED",
2438
- `redemption denied: ${denial.message}`,
2439
- { policyDenialCode: denial.code }
2440
- );
2378
+ throw new PTRedeemError("REDEMPTION_POLICY_DENIED", `redemption denied: ${denial.message}`, {
2379
+ policyDenialCode: denial.code
2380
+ });
2441
2381
  }
2442
2382
  }
2443
2383
  let burnNonce;
@@ -2446,13 +2386,12 @@ var PTRedeemHandler = class {
2446
2386
  address: pointTokenAddress,
2447
2387
  abi: import_core7.POINT_TOKEN_ABI,
2448
2388
  functionName: "burnRequestNonces",
2449
- args: [request.userAddress]
2389
+ args: [
2390
+ request.userAddress
2391
+ ]
2450
2392
  });
2451
2393
  } catch (err) {
2452
- throw new PTRedeemError(
2453
- "NONCE_READ_FAILED",
2454
- `failed to read burnRequestNonces(${request.userAddress}): ${err instanceof Error ? err.message : String(err)}`
2455
- );
2394
+ throw new PTRedeemError("NONCE_READ_FAILED", `failed to read burnRequestNonces(${request.userAddress}): ${err instanceof Error ? err.message : String(err)}`);
2456
2395
  }
2457
2396
  const nonceKey = `${(0, import_viem8.getAddress)(request.userAddress).toLowerCase()}:${pointTokenAddress.toLowerCase()}`;
2458
2397
  let userNonces = this.inFlightNonces.get(nonceKey);
@@ -2461,10 +2400,7 @@ var PTRedeemHandler = class {
2461
2400
  this.inFlightNonces.set(nonceKey, userNonces);
2462
2401
  }
2463
2402
  if (userNonces.has(burnNonce)) {
2464
- throw new PTRedeemError(
2465
- "NONCE_IN_FLIGHT",
2466
- `A burn request for nonce ${burnNonce} is already in progress for ${request.userAddress} on ${pointTokenAddress}. Retry after the current request completes.`
2467
- );
2403
+ throw new PTRedeemError("NONCE_IN_FLIGHT", `A burn request for nonce ${burnNonce} is already in progress for ${request.userAddress} on ${pointTokenAddress}. Retry after the current request completes.`);
2468
2404
  }
2469
2405
  userNonces.add(burnNonce);
2470
2406
  try {
@@ -2478,12 +2414,8 @@ var PTRedeemHandler = class {
2478
2414
  const referenceMs = this.now();
2479
2415
  const projectedLockExpiresAtMs = referenceMs + this.redeemLockDurationMs;
2480
2416
  const requestedDeadlineSec = Math.floor(referenceMs / 1e3) + this.signatureDeadlineSeconds;
2481
- const lockBoundedDeadlineSec = Math.floor(
2482
- (projectedLockExpiresAtMs - M11_SAFETY_MARGIN_MS) / 1e3
2483
- );
2484
- const previewDeadline = BigInt(
2485
- Math.min(requestedDeadlineSec, lockBoundedDeadlineSec)
2486
- );
2417
+ const lockBoundedDeadlineSec = Math.floor((projectedLockExpiresAtMs - M11_SAFETY_MARGIN_MS) / 1e3);
2418
+ const previewDeadline = BigInt(Math.min(requestedDeadlineSec, lockBoundedDeadlineSec));
2487
2419
  let fee;
2488
2420
  if (request.feeAmount !== void 0) {
2489
2421
  fee = request.feeAmount > 0n ? request.feeAmount : 0n;
@@ -2509,21 +2441,11 @@ var PTRedeemHandler = class {
2509
2441
  }
2510
2442
  const feeRecipient = request.feeRecipient ?? (request.chainId !== void 0 ? (0, import_core7.getContractAddresses)(request.chainId).pafiFeeRecipient : (0, import_core7.getContractAddresses)(this.chainId).pafiFeeRecipient);
2511
2443
  if (fee > 0n && fee >= request.amount) {
2512
- throw new PTRedeemError(
2513
- "INVALID_AMOUNT",
2514
- `fee (${fee}) must be strictly less than redeem amount (${request.amount})`
2515
- );
2444
+ throw new PTRedeemError("INVALID_AMOUNT", `fee (${fee}) must be strictly less than redeem amount (${request.amount})`);
2516
2445
  }
2517
- const onChainBalance = await (0, import_core7.getPointTokenBalance)(
2518
- this.provider,
2519
- pointTokenAddress,
2520
- request.userAddress
2521
- );
2446
+ const onChainBalance = await (0, import_core7.getPointTokenBalance)(this.provider, pointTokenAddress, request.userAddress);
2522
2447
  if (onChainBalance < request.amount) {
2523
- throw new PTRedeemError(
2524
- "INVALID_AMOUNT",
2525
- `insufficient on-chain PT balance: have ${onChainBalance}, need ${request.amount}`
2526
- );
2448
+ throw new PTRedeemError("INVALID_AMOUNT", `insufficient on-chain PT balance: have ${onChainBalance}, need ${request.amount}`);
2527
2449
  }
2528
2450
  const deadline = previewDeadline;
2529
2451
  const domainName = await this.domainResolver.resolve(pointTokenAddress);
@@ -2545,17 +2467,9 @@ var PTRedeemHandler = class {
2545
2467
  try {
2546
2468
  sponsoredSig = (await (0, import_core7.signBurnRequest)(this.burnerSignerWallet, domain, sponsoredBurnRequest)).serialized;
2547
2469
  } catch (err) {
2548
- throw new PTRedeemError(
2549
- "SIGNING_FAILED",
2550
- `failed to sign sponsored BurnRequest: ${err instanceof Error ? err.message : String(err)}`
2551
- );
2552
- }
2553
- const sponsoredLockId = await this.ledger.reservePendingCredit(
2554
- request.userAddress,
2555
- sponsoredBurnAmount,
2556
- this.redeemLockDurationMs,
2557
- pointTokenAddress
2558
- );
2470
+ throw new PTRedeemError("SIGNING_FAILED", `failed to sign sponsored BurnRequest: ${err instanceof Error ? err.message : String(err)}`);
2471
+ }
2472
+ const sponsoredLockId = await this.ledger.reservePendingCredit(request.userAddress, sponsoredBurnAmount, this.redeemLockDurationMs, pointTokenAddress);
2559
2473
  try {
2560
2474
  const sponsoredUserOp = await this.relayService.prepareBurn({
2561
2475
  mode: "burnWithSig",
@@ -2581,17 +2495,9 @@ var PTRedeemHandler = class {
2581
2495
  try {
2582
2496
  fallbackSig = (await (0, import_core7.signBurnRequest)(this.burnerSignerWallet, domain, fallbackBurnRequest)).serialized;
2583
2497
  } catch (err) {
2584
- throw new PTRedeemError(
2585
- "SIGNING_FAILED",
2586
- `failed to sign fallback BurnRequest: ${err instanceof Error ? err.message : String(err)}`
2587
- );
2498
+ throw new PTRedeemError("SIGNING_FAILED", `failed to sign fallback BurnRequest: ${err instanceof Error ? err.message : String(err)}`);
2588
2499
  }
2589
- const fallbackLockId = await this.ledger.reservePendingCredit(
2590
- request.userAddress,
2591
- request.amount,
2592
- this.redeemLockDurationMs,
2593
- pointTokenAddress
2594
- );
2500
+ const fallbackLockId = await this.ledger.reservePendingCredit(request.userAddress, request.amount, this.redeemLockDurationMs, pointTokenAddress);
2595
2501
  let fallbackUserOp;
2596
2502
  try {
2597
2503
  fallbackUserOp = await this.relayService.prepareBurn({
@@ -2649,15 +2555,11 @@ var PTRedeemHandler = class {
2649
2555
  var DEFAULT_STATUS_CONFIRMATIONS = 3;
2650
2556
  async function isReceiptPastConfirmations(receipt, provider, confirmations, onWarning, handlerName) {
2651
2557
  if (!provider) {
2652
- onWarning?.(
2653
- `${handlerName}: provider missing \u2014 cannot enforce confirmation depth; deferring receipt fallback to on-chain indexer.`
2654
- );
2558
+ onWarning?.(`${handlerName}: provider missing \u2014 cannot enforce confirmation depth; deferring receipt fallback to on-chain indexer.`);
2655
2559
  return false;
2656
2560
  }
2657
2561
  if (!receipt.blockNumber) {
2658
- onWarning?.(
2659
- `${handlerName}: receipt has no blockNumber \u2014 cannot enforce confirmation depth; deferring to indexer.`
2660
- );
2562
+ onWarning?.(`${handlerName}: receipt has no blockNumber \u2014 cannot enforce confirmation depth; deferring to indexer.`);
2661
2563
  return false;
2662
2564
  }
2663
2565
  const requiredConfs = BigInt(confirmations ?? DEFAULT_STATUS_CONFIRMATIONS);
@@ -2665,18 +2567,14 @@ async function isReceiptPastConfirmations(receipt, provider, confirmations, onWa
2665
2567
  try {
2666
2568
  receiptBlock = BigInt(receipt.blockNumber);
2667
2569
  } catch {
2668
- onWarning?.(
2669
- `${handlerName}: malformed receipt blockNumber (${receipt.blockNumber}) \u2014 deferring to indexer.`
2670
- );
2570
+ onWarning?.(`${handlerName}: malformed receipt blockNumber (${receipt.blockNumber}) \u2014 deferring to indexer.`);
2671
2571
  return false;
2672
2572
  }
2673
2573
  let head;
2674
2574
  try {
2675
2575
  head = await provider.getBlockNumber();
2676
2576
  } catch (err) {
2677
- onWarning?.(
2678
- `${handlerName}: getBlockNumber failed (${err instanceof Error ? err.message : String(err)}) \u2014 deferring to indexer.`
2679
- );
2577
+ onWarning?.(`${handlerName}: getBlockNumber failed (${err instanceof Error ? err.message : String(err)}) \u2014 deferring to indexer.`);
2680
2578
  return false;
2681
2579
  }
2682
2580
  const depth = head - receiptBlock;
@@ -2685,7 +2583,11 @@ async function isReceiptPastConfirmations(receipt, provider, confirmations, onWa
2685
2583
  }
2686
2584
  return true;
2687
2585
  }
2688
- var LockNotFoundError = class extends import_core.PafiSdkError {
2586
+ __name(isReceiptPastConfirmations, "isReceiptPastConfirmations");
2587
+ var LockNotFoundError = class LockNotFoundError2 extends import_core.PafiSdkError {
2588
+ static {
2589
+ __name(this, "LockNotFoundError");
2590
+ }
2689
2591
  code = "LOCK_NOT_FOUND";
2690
2592
  httpStatus = "not_found";
2691
2593
  constructor() {
@@ -2694,14 +2596,9 @@ var LockNotFoundError = class extends import_core.PafiSdkError {
2694
2596
  };
2695
2597
  async function handleClaimStatus(params) {
2696
2598
  if (!params.ledger.getMintLock) {
2697
- throw new Error(
2698
- "handleClaimStatus: ledger does not implement `getMintLock` \u2014 implement the optional method on `IPointLedger` or write a custom status handler."
2699
- );
2700
- }
2701
- const lock = await params.ledger.getMintLock(
2702
- params.lockId,
2703
- params.userAddress
2704
- );
2599
+ throw new Error("handleClaimStatus: ledger does not implement `getMintLock` \u2014 implement the optional method on `IPointLedger` or write a custom status handler.");
2600
+ }
2601
+ const lock = await params.ledger.getMintLock(params.lockId, params.userAddress);
2705
2602
  if (!lock || lock.userAddress.toLowerCase() !== params.userAddress.toLowerCase()) {
2706
2603
  throw new LockNotFoundError();
2707
2604
  }
@@ -2709,17 +2606,9 @@ async function handleClaimStatus(params) {
2709
2606
  let txHash = lock.txHash ?? null;
2710
2607
  if (status === "PENDING" && lock.userOpHash && params.pafiBackendClient) {
2711
2608
  try {
2712
- const receipt = await params.pafiBackendClient.getUserOpReceipt(
2713
- lock.userOpHash
2714
- );
2609
+ const receipt = await params.pafiBackendClient.getUserOpReceipt(lock.userOpHash);
2715
2610
  if (receipt) {
2716
- const passesConfirmationDepth = await isReceiptPastConfirmations(
2717
- receipt,
2718
- params.provider,
2719
- params.confirmations,
2720
- params.onWarning,
2721
- "handleClaimStatus"
2722
- );
2611
+ const passesConfirmationDepth = await isReceiptPastConfirmations(receipt, params.provider, params.confirmations, params.onWarning, "handleClaimStatus");
2723
2612
  if (!passesConfirmationDepth) {
2724
2613
  return {
2725
2614
  lockId: lock.lockId,
@@ -2732,46 +2621,31 @@ async function handleClaimStatus(params) {
2732
2621
  }
2733
2622
  if (receipt.success && receipt.txHash) {
2734
2623
  if (!lock.tokenAddress) {
2735
- params.onWarning?.(
2736
- `handleClaimStatus: lock ${lock.lockId} has no tokenAddress; falling back to status-only flip \u2014 atomic debit+flip cannot run on a legacy single-token row. Migrate the ledger to the multi-token schema.`
2737
- );
2624
+ params.onWarning?.(`handleClaimStatus: lock ${lock.lockId} has no tokenAddress; falling back to status-only flip \u2014 atomic debit+flip cannot run on a legacy single-token row. Migrate the ledger to the multi-token schema.`);
2738
2625
  await params.ledger.updateMintStatus(lock.lockId, "MINTED", receipt.txHash).catch((err) => {
2739
- params.onWarning?.(
2740
- `handleClaimStatus: ledger updateMintStatus failed for lock ${lock.lockId}: ${err}`
2741
- );
2626
+ params.onWarning?.(`handleClaimStatus: ledger updateMintStatus failed for lock ${lock.lockId}: ${err}`);
2742
2627
  });
2743
2628
  status = "MINTED";
2744
2629
  txHash = receipt.txHash;
2745
2630
  } else {
2746
2631
  try {
2747
- await params.ledger.deductBalance(
2748
- lock.userAddress,
2749
- lock.amount,
2750
- receipt.txHash,
2751
- lock.tokenAddress
2752
- );
2632
+ await params.ledger.deductBalance(lock.userAddress, lock.amount, receipt.txHash, lock.tokenAddress);
2753
2633
  status = "MINTED";
2754
2634
  txHash = receipt.txHash;
2755
2635
  } catch (deductErr) {
2756
- params.onWarning?.(
2757
- `handleClaimStatus: deductBalance failed for lock ${lock.lockId}: ${deductErr}`
2758
- );
2636
+ params.onWarning?.(`handleClaimStatus: deductBalance failed for lock ${lock.lockId}: ${deductErr}`);
2759
2637
  }
2760
2638
  }
2761
2639
  } else {
2762
2640
  await params.ledger.updateMintStatus(lock.lockId, "FAILED", receipt.txHash).catch((err) => {
2763
- params.onWarning?.(
2764
- `handleClaimStatus: ledger updateMintStatus failed for lock ${lock.lockId}: ${err}`
2765
- );
2641
+ params.onWarning?.(`handleClaimStatus: ledger updateMintStatus failed for lock ${lock.lockId}: ${err}`);
2766
2642
  });
2767
2643
  status = "FAILED";
2768
2644
  txHash = receipt.txHash;
2769
2645
  }
2770
2646
  }
2771
2647
  } catch (err) {
2772
- params.onWarning?.(
2773
- `handleClaimStatus: bundler-receipt fallback failed for lock ${lock.lockId}: ${err}`
2774
- );
2648
+ params.onWarning?.(`handleClaimStatus: bundler-receipt fallback failed for lock ${lock.lockId}: ${err}`);
2775
2649
  }
2776
2650
  }
2777
2651
  return {
@@ -2783,16 +2657,12 @@ async function handleClaimStatus(params) {
2783
2657
  expiresAt: new Date(lock.expiresAt).toISOString()
2784
2658
  };
2785
2659
  }
2660
+ __name(handleClaimStatus, "handleClaimStatus");
2786
2661
  async function handleRedeemStatus(params) {
2787
2662
  if (!params.ledger.getPendingCredit) {
2788
- throw new Error(
2789
- "handleRedeemStatus: ledger does not implement `getPendingCredit` \u2014 implement the optional method on `IPointLedger` or write a custom status handler."
2790
- );
2791
- }
2792
- const credit = await params.ledger.getPendingCredit(
2793
- params.lockId,
2794
- params.userAddress
2795
- );
2663
+ throw new Error("handleRedeemStatus: ledger does not implement `getPendingCredit` \u2014 implement the optional method on `IPointLedger` or write a custom status handler.");
2664
+ }
2665
+ const credit = await params.ledger.getPendingCredit(params.lockId, params.userAddress);
2796
2666
  if (!credit || credit.userAddress.toLowerCase() !== params.userAddress.toLowerCase()) {
2797
2667
  throw new LockNotFoundError();
2798
2668
  }
@@ -2800,33 +2670,21 @@ async function handleRedeemStatus(params) {
2800
2670
  let txHash = credit.txHash ?? null;
2801
2671
  if (status === "PENDING" && credit.userOpHash && params.pafiBackendClient) {
2802
2672
  try {
2803
- const receipt = await params.pafiBackendClient.getUserOpReceipt(
2804
- credit.userOpHash
2805
- );
2673
+ const receipt = await params.pafiBackendClient.getUserOpReceipt(credit.userOpHash);
2806
2674
  if (receipt && receipt.success) {
2807
- const passesConfirmationDepth = await isReceiptPastConfirmations(
2808
- receipt,
2809
- params.provider,
2810
- params.confirmations,
2811
- params.onWarning,
2812
- "handleRedeemStatus"
2813
- );
2675
+ const passesConfirmationDepth = await isReceiptPastConfirmations(receipt, params.provider, params.confirmations, params.onWarning, "handleRedeemStatus");
2814
2676
  if (passesConfirmationDepth) {
2815
2677
  status = "RESOLVED";
2816
2678
  txHash = receipt.txHash;
2817
2679
  if (params.ledger.resolveCreditByBurnTx) {
2818
2680
  await params.ledger.resolveCreditByBurnTx(credit.lockId, receipt.txHash).catch((err) => {
2819
- params.onWarning?.(
2820
- `handleRedeemStatus: resolveCreditByBurnTx failed for lock ${credit.lockId}: ${err}`
2821
- );
2681
+ params.onWarning?.(`handleRedeemStatus: resolveCreditByBurnTx failed for lock ${credit.lockId}: ${err}`);
2822
2682
  });
2823
2683
  }
2824
2684
  }
2825
2685
  }
2826
2686
  } catch (err) {
2827
- params.onWarning?.(
2828
- `handleRedeemStatus: bundler-receipt fallback failed for lock ${credit.lockId}: ${err}`
2829
- );
2687
+ params.onWarning?.(`handleRedeemStatus: bundler-receipt fallback failed for lock ${credit.lockId}: ${err}`);
2830
2688
  }
2831
2689
  }
2832
2690
  return {
@@ -2839,6 +2697,7 @@ async function handleRedeemStatus(params) {
2839
2697
  resolvedAt: credit.resolvedAt ? new Date(credit.resolvedAt).toISOString() : null
2840
2698
  };
2841
2699
  }
2700
+ __name(handleRedeemStatus, "handleRedeemStatus");
2842
2701
 
2843
2702
  // src/api/mobileHandlers.ts
2844
2703
  var import_viem9 = require("viem");
@@ -2849,46 +2708,41 @@ var import_core8 = require("@pafi-dev/core");
2849
2708
  function serializeEntryToJsonRpc(entry, signature, variant = "sponsored") {
2850
2709
  if (variant === "fallback") {
2851
2710
  if (!entry.fallback) {
2852
- throw new Error(
2853
- "serializeEntryToJsonRpc: variant=fallback requested but the stored entry has no `fallback` branch \u2014 caller should resubmit with variant='sponsored' or re-prepare with a fee configured."
2854
- );
2711
+ throw new Error("serializeEntryToJsonRpc: variant=fallback requested but the stored entry has no `fallback` branch \u2014 caller should resubmit with variant='sponsored' or re-prepare with a fee configured.");
2855
2712
  }
2856
- return (0, import_core8.serializeUserOpToJsonRpc)(
2857
- {
2858
- sender: entry.sender,
2859
- nonce: BigInt(entry.nonce),
2860
- callData: entry.fallback.callData,
2861
- callGasLimit: BigInt(entry.fallback.callGasLimit),
2862
- verificationGasLimit: BigInt(entry.fallback.verificationGasLimit),
2863
- preVerificationGas: BigInt(entry.fallback.preVerificationGas),
2864
- maxFeePerGas: BigInt(entry.maxFeePerGas),
2865
- maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas)
2866
- // intentionally no paymaster — user pays ETH gas
2867
- },
2868
- signature
2869
- );
2870
- }
2871
- return (0, import_core8.serializeUserOpToJsonRpc)(
2872
- {
2713
+ return (0, import_core8.serializeUserOpToJsonRpc)({
2873
2714
  sender: entry.sender,
2874
2715
  nonce: BigInt(entry.nonce),
2875
- callData: entry.callData,
2876
- callGasLimit: BigInt(entry.callGasLimit),
2877
- verificationGasLimit: BigInt(entry.verificationGasLimit),
2878
- preVerificationGas: BigInt(entry.preVerificationGas),
2716
+ callData: entry.fallback.callData,
2717
+ callGasLimit: BigInt(entry.fallback.callGasLimit),
2718
+ verificationGasLimit: BigInt(entry.fallback.verificationGasLimit),
2719
+ preVerificationGas: BigInt(entry.fallback.preVerificationGas),
2879
2720
  maxFeePerGas: BigInt(entry.maxFeePerGas),
2880
- maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas),
2881
- paymaster: entry.paymaster,
2882
- paymasterVerificationGasLimit: entry.paymasterVerificationGasLimit != null ? BigInt(entry.paymasterVerificationGasLimit) : void 0,
2883
- paymasterPostOpGasLimit: entry.paymasterPostOpGasLimit != null ? BigInt(entry.paymasterPostOpGasLimit) : void 0,
2884
- paymasterData: entry.paymasterData
2885
- },
2886
- signature
2887
- );
2721
+ maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas)
2722
+ }, signature);
2723
+ }
2724
+ return (0, import_core8.serializeUserOpToJsonRpc)({
2725
+ sender: entry.sender,
2726
+ nonce: BigInt(entry.nonce),
2727
+ callData: entry.callData,
2728
+ callGasLimit: BigInt(entry.callGasLimit),
2729
+ verificationGasLimit: BigInt(entry.verificationGasLimit),
2730
+ preVerificationGas: BigInt(entry.preVerificationGas),
2731
+ maxFeePerGas: BigInt(entry.maxFeePerGas),
2732
+ maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas),
2733
+ paymaster: entry.paymaster,
2734
+ paymasterVerificationGasLimit: entry.paymasterVerificationGasLimit != null ? BigInt(entry.paymasterVerificationGasLimit) : void 0,
2735
+ paymasterPostOpGasLimit: entry.paymasterPostOpGasLimit != null ? BigInt(entry.paymasterPostOpGasLimit) : void 0,
2736
+ paymasterData: entry.paymasterData
2737
+ }, signature);
2888
2738
  }
2739
+ __name(serializeEntryToJsonRpc, "serializeEntryToJsonRpc");
2889
2740
 
2890
2741
  // src/userop-store/memoryStore.ts
2891
2742
  var MemoryPendingUserOpStore = class {
2743
+ static {
2744
+ __name(this, "MemoryPendingUserOpStore");
2745
+ }
2892
2746
  entries = /* @__PURE__ */ new Map();
2893
2747
  now;
2894
2748
  constructor(now = () => Date.now()) {
@@ -2927,14 +2781,13 @@ function serializeUserOpTypedData(td) {
2927
2781
  initCode: td.message.initCode,
2928
2782
  callData: td.message.callData,
2929
2783
  accountGasLimits: td.message.accountGasLimits,
2930
- preVerificationGas: `0x${td.message.preVerificationGas.toString(
2931
- 16
2932
- )}`,
2784
+ preVerificationGas: `0x${td.message.preVerificationGas.toString(16)}`,
2933
2785
  gasFees: td.message.gasFees,
2934
2786
  paymasterAndData: td.message.paymasterAndData
2935
2787
  }
2936
2788
  };
2937
2789
  }
2790
+ __name(serializeUserOpTypedData, "serializeUserOpTypedData");
2938
2791
  function mergePaymasterFields(userOp, paymasterFields) {
2939
2792
  if (!paymasterFields) return userOp;
2940
2793
  const merged = {
@@ -2945,36 +2798,27 @@ function mergePaymasterFields(userOp, paymasterFields) {
2945
2798
  }
2946
2799
  return merged;
2947
2800
  }
2801
+ __name(mergePaymasterFields, "mergePaymasterFields");
2948
2802
  function applyPaymasterGasEstimates(partialUserOp, paymasterFields, chainId) {
2949
- const userOp = mergePaymasterFields(
2950
- partialUserOp,
2951
- paymasterFields
2952
- );
2803
+ const userOp = mergePaymasterFields(partialUserOp, paymasterFields);
2953
2804
  return {
2954
2805
  userOp,
2955
2806
  userOpHash: (0, import_core9.computeUserOpHash)(userOp, chainId),
2956
2807
  typedData: serializeUserOpTypedData((0, import_core9.buildUserOpTypedData)(userOp, chainId))
2957
2808
  };
2958
2809
  }
2810
+ __name(applyPaymasterGasEstimates, "applyPaymasterGasEstimates");
2959
2811
  async function prepareMobileUserOp(params) {
2960
- const sponsored = applyPaymasterGasEstimates(
2961
- params.partialUserOp,
2962
- params.paymasterFields,
2963
- params.chainId
2964
- );
2812
+ const sponsored = applyPaymasterGasEstimates(params.partialUserOp, params.paymasterFields, params.chainId);
2965
2813
  const { userOp, userOpHash } = sponsored;
2966
2814
  let fallback;
2967
2815
  let fallbackEntry;
2968
2816
  if (params.partialUserOpFallback) {
2969
- fallback = applyPaymasterGasEstimates(
2970
- {
2971
- ...params.partialUserOpFallback,
2972
- maxFeePerGas: userOp.maxFeePerGas,
2973
- maxPriorityFeePerGas: userOp.maxPriorityFeePerGas
2974
- },
2975
- void 0,
2976
- params.chainId
2977
- );
2817
+ fallback = applyPaymasterGasEstimates({
2818
+ ...params.partialUserOpFallback,
2819
+ maxFeePerGas: userOp.maxFeePerGas,
2820
+ maxPriorityFeePerGas: userOp.maxPriorityFeePerGas
2821
+ }, void 0, params.chainId);
2978
2822
  fallbackEntry = {
2979
2823
  callData: fallback.userOp.callData,
2980
2824
  callGasLimit: fallback.userOp.callGasLimit.toString(),
@@ -3011,23 +2855,24 @@ async function prepareMobileUserOp(params) {
3011
2855
  entry
3012
2856
  };
3013
2857
  }
2858
+ __name(prepareMobileUserOp, "prepareMobileUserOp");
3014
2859
 
3015
2860
  // src/pafi-backend/types.ts
3016
2861
  var PafiBackendError = class extends Error {
3017
- constructor(code, message, httpStatus, details, opts) {
3018
- super(message);
3019
- this.code = code;
3020
- this.httpStatus = httpStatus;
3021
- this.details = details;
3022
- this.name = "PafiBackendError";
3023
- if (opts?.retryAfter !== void 0) this.retryAfter = opts.retryAfter;
3024
- if (opts?.safeToRetry !== void 0) this.serverSafeToRetry = opts.safeToRetry;
2862
+ static {
2863
+ __name(this, "PafiBackendError");
3025
2864
  }
3026
2865
  code;
3027
2866
  httpStatus;
3028
2867
  details;
3029
2868
  retryAfter;
3030
2869
  serverSafeToRetry;
2870
+ constructor(code, message, httpStatus, details, opts) {
2871
+ super(message), this.code = code, this.httpStatus = httpStatus, this.details = details;
2872
+ this.name = "PafiBackendError";
2873
+ if (opts?.retryAfter !== void 0) this.retryAfter = opts.retryAfter;
2874
+ if (opts?.safeToRetry !== void 0) this.serverSafeToRetry = opts.safeToRetry;
2875
+ }
3031
2876
  get safeToRetry() {
3032
2877
  if (this.serverSafeToRetry !== void 0) return this.serverSafeToRetry;
3033
2878
  switch (this.code) {
@@ -3049,15 +2894,19 @@ var PafiBackendError = class extends Error {
3049
2894
 
3050
2895
  // src/pafi-backend/helpers.ts
3051
2896
  var BundlerNotConfiguredError = class extends import_core.PafiSdkError {
2897
+ static {
2898
+ __name(this, "BundlerNotConfiguredError");
2899
+ }
3052
2900
  code = "BUNDLER_NOT_CONFIGURED";
3053
2901
  httpStatus = "service_unavailable";
3054
2902
  constructor() {
3055
- super(
3056
- "PAFI backend client not configured \u2014 set PAFI_BACKEND_URL, PAFI_ISSUER_ID, PAFI_API_KEY to enable mobile submit."
3057
- );
2903
+ super("PAFI backend client not configured \u2014 set PAFI_BACKEND_URL, PAFI_ISSUER_ID, PAFI_API_KEY to enable mobile submit.");
3058
2904
  }
3059
2905
  };
3060
2906
  var BundlerRejectedError = class extends import_core.PafiSdkError {
2907
+ static {
2908
+ __name(this, "BundlerRejectedError");
2909
+ }
3061
2910
  code = "BUNDLER_REJECTED";
3062
2911
  httpStatus = "unprocessable";
3063
2912
  cause;
@@ -3079,7 +2928,9 @@ async function requestPaymaster(params) {
3079
2928
  function: fn,
3080
2929
  pointToken: params.pointTokenAddress
3081
2930
  },
3082
- ...params.eip7702Auth ? { eip7702Auth: params.eip7702Auth } : {}
2931
+ ...params.eip7702Auth ? {
2932
+ eip7702Auth: params.eip7702Auth
2933
+ } : {}
3083
2934
  });
3084
2935
  } catch (err) {
3085
2936
  const msg = err instanceof Error ? err.message : String(err);
@@ -3090,6 +2941,7 @@ async function requestPaymaster(params) {
3090
2941
  throw err;
3091
2942
  }
3092
2943
  }
2944
+ __name(requestPaymaster, "requestPaymaster");
3093
2945
  function isTransientPaymasterError(code) {
3094
2946
  switch (code) {
3095
2947
  case "NETWORK_ERROR":
@@ -3102,6 +2954,7 @@ function isTransientPaymasterError(code) {
3102
2954
  return false;
3103
2955
  }
3104
2956
  }
2957
+ __name(isTransientPaymasterError, "isTransientPaymasterError");
3105
2958
  function defaultFunctionForScenario(scenario) {
3106
2959
  switch (scenario) {
3107
2960
  case "mint":
@@ -3116,6 +2969,7 @@ function defaultFunctionForScenario(scenario) {
3116
2969
  return scenario;
3117
2970
  }
3118
2971
  }
2972
+ __name(defaultFunctionForScenario, "defaultFunctionForScenario");
3119
2973
  async function relayUserOp(params) {
3120
2974
  if (!params.client) {
3121
2975
  throw new BundlerNotConfiguredError();
@@ -3126,36 +2980,43 @@ async function relayUserOp(params) {
3126
2980
  entryPoint: params.entryPoint,
3127
2981
  eip7702Auth: params.eip7702Auth
3128
2982
  });
3129
- return { userOpHash: result.userOpHash };
2983
+ return {
2984
+ userOpHash: result.userOpHash
2985
+ };
3130
2986
  } catch (err) {
3131
2987
  const msg = err instanceof Error ? err.message : String(err);
3132
2988
  throw new BundlerRejectedError(msg, err);
3133
2989
  }
3134
2990
  }
2991
+ __name(relayUserOp, "relayUserOp");
3135
2992
 
3136
2993
  // src/api/mobileHandlers.ts
3137
2994
  var PendingUserOpNotFoundError = class extends import_core.PafiSdkError {
2995
+ static {
2996
+ __name(this, "PendingUserOpNotFoundError");
2997
+ }
3138
2998
  code = "PENDING_USEROP_NOT_FOUND";
3139
2999
  httpStatus = "not_found";
3140
3000
  constructor(lockId) {
3141
- super(
3142
- `No pending UserOp found for lockId ${lockId} \u2014 it may have expired or already been submitted.`
3143
- );
3001
+ super(`No pending UserOp found for lockId ${lockId} \u2014 it may have expired or already been submitted.`);
3144
3002
  }
3145
3003
  };
3146
3004
  var PendingUserOpForbiddenError = class extends import_core.PafiSdkError {
3005
+ static {
3006
+ __name(this, "PendingUserOpForbiddenError");
3007
+ }
3147
3008
  code = "PENDING_USEROP_FORBIDDEN";
3148
3009
  httpStatus = "forbidden";
3149
3010
  constructor(lockId) {
3150
- super(
3151
- `Pending UserOp ${lockId} does not belong to the authenticated user.`
3152
- );
3011
+ super(`Pending UserOp ${lockId} does not belong to the authenticated user.`);
3153
3012
  }
3154
3013
  };
3155
3014
  async function handleMobilePrepare(params) {
3156
3015
  const [fees, userCode] = await Promise.all([
3157
3016
  params.provider.estimateFeesPerGas(),
3158
- params.provider.getCode({ address: params.userAddress })
3017
+ params.provider.getCode({
3018
+ address: params.userAddress
3019
+ })
3159
3020
  ]);
3160
3021
  const needsDelegation = !params.eip7702Auth && (0, import_core10.parseEip7702DelegatedAddress)(userCode) === null;
3161
3022
  const sponsoredOp = {
@@ -3189,6 +3050,7 @@ async function handleMobilePrepare(params) {
3189
3050
  needsDelegation
3190
3051
  };
3191
3052
  }
3053
+ __name(handleMobilePrepare, "handleMobilePrepare");
3192
3054
  async function handleMobileSubmit(params) {
3193
3055
  const entry = await params.store.get(params.lockId);
3194
3056
  if (!entry) {
@@ -3208,8 +3070,11 @@ async function handleMobileSubmit(params) {
3208
3070
  const targetLockId = variant === "fallback" && entry.fallback?.lockId ? entry.fallback.lockId : params.lockId;
3209
3071
  await params.bindUserOpHash(targetLockId, result.userOpHash);
3210
3072
  await params.store.delete(params.lockId);
3211
- return { userOpHash: result.userOpHash };
3073
+ return {
3074
+ userOpHash: result.userOpHash
3075
+ };
3212
3076
  }
3077
+ __name(handleMobileSubmit, "handleMobileSubmit");
3213
3078
 
3214
3079
  // src/api/handlers/ptClaimHandler.ts
3215
3080
  var import_viem10 = require("viem");
@@ -3217,6 +3082,9 @@ var import_core11 = require("@pafi-dev/core");
3217
3082
 
3218
3083
  // src/issuer-state/types.ts
3219
3084
  var IssuerStateError = class extends import_core.PafiSdkError {
3085
+ static {
3086
+ __name(this, "IssuerStateError");
3087
+ }
3220
3088
  httpStatus = "unprocessable";
3221
3089
  code;
3222
3090
  details;
@@ -3231,6 +3099,9 @@ var IssuerStateError = class extends import_core.PafiSdkError {
3231
3099
 
3232
3100
  // src/api/handlers/ptClaimHandler.ts
3233
3101
  var PTClaimError = class extends import_core.PafiSdkError {
3102
+ static {
3103
+ __name(this, "PTClaimError");
3104
+ }
3234
3105
  httpStatus = "unprocessable";
3235
3106
  code;
3236
3107
  details;
@@ -3245,32 +3116,29 @@ function isNoWrapper2(address) {
3245
3116
  const lower = address.toLowerCase();
3246
3117
  return lower === "0x0000000000000000000000000000000000000000" || lower === "0x000000000000000000000000000000000000dead";
3247
3118
  }
3119
+ __name(isNoWrapper2, "isNoWrapper");
3248
3120
  var DEFAULT_LOCK_MS = 15 * 60 * 1e3;
3249
3121
  var M11_SAFETY_MARGIN_MS2 = 30 * 1e3;
3250
3122
  var DEFAULT_SIG_DEADLINE_SEC2 = (DEFAULT_LOCK_MS - M11_SAFETY_MARGIN_MS2) / 1e3;
3251
3123
  var PTClaimHandler = class {
3124
+ static {
3125
+ __name(this, "PTClaimHandler");
3126
+ }
3252
3127
  cfg;
3253
3128
  inFlightNonces = /* @__PURE__ */ new Map();
3254
3129
  constructor(config) {
3255
3130
  if (!config.supportedTokens) {
3256
- throw new PTClaimError(
3257
- "UNSUPPORTED_POINT_TOKEN",
3258
- "PTClaimHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts)."
3259
- );
3131
+ throw new PTClaimError("UNSUPPORTED_POINT_TOKEN", "PTClaimHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts).");
3260
3132
  }
3261
3133
  const lockDurationMs = config.lockDurationMs ?? DEFAULT_LOCK_MS;
3262
3134
  const signatureDeadlineSeconds = config.signatureDeadlineSeconds ?? DEFAULT_SIG_DEADLINE_SEC2;
3263
3135
  const maxAllowedSignatureMs = lockDurationMs - M11_SAFETY_MARGIN_MS2;
3264
3136
  if (signatureDeadlineSeconds * 1e3 > maxAllowedSignatureMs) {
3265
- throw new PTClaimError(
3266
- "VALIDATION_FAILED",
3267
- `PTClaimHandler config: signatureDeadlineSeconds (${signatureDeadlineSeconds}s) must be at most lockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (lockDurationMs=${lockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS2 / 1e3}s).`,
3268
- {
3269
- lockDurationMs,
3270
- signatureDeadlineSeconds,
3271
- maxAllowedSignatureSec: maxAllowedSignatureMs / 1e3
3272
- }
3273
- );
3137
+ throw new PTClaimError("VALIDATION_FAILED", `PTClaimHandler config: signatureDeadlineSeconds (${signatureDeadlineSeconds}s) must be at most lockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (lockDurationMs=${lockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS2 / 1e3}s).`, {
3138
+ lockDurationMs,
3139
+ signatureDeadlineSeconds,
3140
+ maxAllowedSignatureSec: maxAllowedSignatureMs / 1e3
3141
+ });
3274
3142
  }
3275
3143
  this.cfg = {
3276
3144
  ...config,
@@ -3281,34 +3149,23 @@ var PTClaimHandler = class {
3281
3149
  }
3282
3150
  async handle(request) {
3283
3151
  if ((0, import_viem10.getAddress)(request.authenticatedAddress) !== (0, import_viem10.getAddress)(request.userAddress)) {
3284
- throw new PTClaimError(
3285
- "VALIDATION_FAILED",
3286
- `userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`
3287
- );
3152
+ throw new PTClaimError("VALIDATION_FAILED", `userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`);
3288
3153
  }
3289
3154
  if (request.amount <= 0n) {
3290
3155
  throw new PTClaimError("INVALID_AMOUNT", "claim amount must be positive");
3291
3156
  }
3292
3157
  const pointTokenAddress = (0, import_viem10.getAddress)(request.pointTokenAddress);
3293
3158
  if (!this.cfg.supportedTokens.has(pointTokenAddress)) {
3294
- throw new PTClaimError(
3295
- "UNSUPPORTED_POINT_TOKEN",
3296
- `claim: pointTokenAddress ${pointTokenAddress} is not in the issuer's supported-token allowlist. Check IssuerApiHandlers.supportedTokens and PTClaimHandler.config.supportedTokens point at the same set.`,
3297
- { requested: pointTokenAddress }
3298
- );
3159
+ throw new PTClaimError("UNSUPPORTED_POINT_TOKEN", `claim: pointTokenAddress ${pointTokenAddress} is not in the issuer's supported-token allowlist. Check IssuerApiHandlers.supportedTokens and PTClaimHandler.config.supportedTokens point at the same set.`, {
3160
+ requested: pointTokenAddress
3161
+ });
3299
3162
  }
3300
3163
  if (this.cfg.issuerStateValidator) {
3301
3164
  try {
3302
- await this.cfg.issuerStateValidator.preValidateMint(
3303
- request.pointTokenAddress,
3304
- request.amount
3305
- );
3165
+ await this.cfg.issuerStateValidator.preValidateMint(request.pointTokenAddress, request.amount);
3306
3166
  } catch (err) {
3307
3167
  if (err instanceof IssuerStateError) throw err;
3308
- throw new PTClaimError(
3309
- "VALIDATION_FAILED",
3310
- `issuer-state pre-validate failed: ${err instanceof Error ? err.message : String(err)}`
3311
- );
3168
+ throw new PTClaimError("VALIDATION_FAILED", `issuer-state pre-validate failed: ${err instanceof Error ? err.message : String(err)}`);
3312
3169
  }
3313
3170
  }
3314
3171
  const chainAddresses = (0, import_core11.getContractAddresses)(request.chainId);
@@ -3319,13 +3176,12 @@ var PTClaimHandler = class {
3319
3176
  address: request.pointTokenAddress,
3320
3177
  abi: import_core11.POINT_TOKEN_ABI,
3321
3178
  functionName: "mintRequestNonces",
3322
- args: [request.userAddress]
3179
+ args: [
3180
+ request.userAddress
3181
+ ]
3323
3182
  });
3324
3183
  } catch (err) {
3325
- throw new PTClaimError(
3326
- "NONCE_READ_FAILED",
3327
- `failed to read mintRequestNonces(${request.userAddress}): ${err instanceof Error ? err.message : String(err)}`
3328
- );
3184
+ throw new PTClaimError("NONCE_READ_FAILED", `failed to read mintRequestNonces(${request.userAddress}): ${err instanceof Error ? err.message : String(err)}`);
3329
3185
  }
3330
3186
  const nonceKey = `${(0, import_viem10.getAddress)(request.userAddress).toLowerCase()}:${request.pointTokenAddress.toLowerCase()}`;
3331
3187
  let userNonces = this.inFlightNonces.get(nonceKey);
@@ -3334,11 +3190,11 @@ var PTClaimHandler = class {
3334
3190
  this.inFlightNonces.set(nonceKey, userNonces);
3335
3191
  }
3336
3192
  if (userNonces.has(mintRequestNonce)) {
3337
- throw new PTClaimError(
3338
- "NONCE_IN_FLIGHT",
3339
- `concurrent claim for nonce ${mintRequestNonce} in progress; retry after the prior request completes`,
3340
- { userAddress: request.userAddress, pointToken: request.pointTokenAddress, nonce: mintRequestNonce.toString() }
3341
- );
3193
+ throw new PTClaimError("NONCE_IN_FLIGHT", `concurrent claim for nonce ${mintRequestNonce} in progress; retry after the prior request completes`, {
3194
+ userAddress: request.userAddress,
3195
+ pointToken: request.pointTokenAddress,
3196
+ nonce: mintRequestNonce.toString()
3197
+ });
3342
3198
  }
3343
3199
  userNonces.add(mintRequestNonce);
3344
3200
  const wrapperOverride = this.cfg.mintFeeWrapperAddress;
@@ -3347,20 +3203,11 @@ var PTClaimHandler = class {
3347
3203
  try {
3348
3204
  const lockCreatedAtMs = this.cfg.now();
3349
3205
  const lockExpiresAtMs = lockCreatedAtMs + this.cfg.lockDurationMs;
3350
- const lockId = await this.cfg.ledger.lockForMinting(
3351
- request.userAddress,
3352
- request.amount,
3353
- this.cfg.lockDurationMs,
3354
- request.pointTokenAddress
3355
- );
3206
+ const lockId = await this.cfg.ledger.lockForMinting(request.userAddress, request.amount, this.cfg.lockDurationMs, request.pointTokenAddress);
3356
3207
  try {
3357
3208
  const requestedDeadlineSec = Math.floor(lockCreatedAtMs / 1e3) + this.cfg.signatureDeadlineSeconds;
3358
- const lockBoundedDeadlineSec = Math.floor(
3359
- (lockExpiresAtMs - M11_SAFETY_MARGIN_MS2) / 1e3
3360
- );
3361
- const signatureDeadline = BigInt(
3362
- Math.min(requestedDeadlineSec, lockBoundedDeadlineSec)
3363
- );
3209
+ const lockBoundedDeadlineSec = Math.floor((lockExpiresAtMs - M11_SAFETY_MARGIN_MS2) / 1e3);
3210
+ const signatureDeadline = BigInt(Math.min(requestedDeadlineSec, lockBoundedDeadlineSec));
3364
3211
  const previewUserOp = this.cfg.relayService.previewMintUserOp({
3365
3212
  userAddress: request.userAddress,
3366
3213
  aaNonce: request.aaNonce,
@@ -3379,15 +3226,12 @@ var PTClaimHandler = class {
3379
3226
  }
3380
3227
  }) : 0n;
3381
3228
  if (feeAmount > 0n && feeAmount >= request.amount) {
3382
- throw new PTClaimError(
3383
- "INVALID_AMOUNT",
3384
- `fee (${feeAmount}) must be strictly less than claim amount (${request.amount})`,
3385
- { feeAmount: feeAmount.toString(), amount: request.amount.toString() }
3386
- );
3229
+ throw new PTClaimError("INVALID_AMOUNT", `fee (${feeAmount}) must be strictly less than claim amount (${request.amount})`, {
3230
+ feeAmount: feeAmount.toString(),
3231
+ amount: request.amount.toString()
3232
+ });
3387
3233
  }
3388
- const domainName = await this.cfg.domainResolver.resolve(
3389
- request.pointTokenAddress
3390
- );
3234
+ const domainName = await this.cfg.domainResolver.resolve(request.pointTokenAddress);
3391
3235
  const domain = {
3392
3236
  name: domainName,
3393
3237
  chainId: request.chainId,
@@ -3417,10 +3261,7 @@ var PTClaimHandler = class {
3417
3261
  feeAmount
3418
3262
  });
3419
3263
  } catch (err) {
3420
- throw new PTClaimError(
3421
- "BUILD_FAILED",
3422
- `prepareMint failed: ${err instanceof Error ? err.message : String(err)}`
3423
- );
3264
+ throw new PTClaimError("BUILD_FAILED", `prepareMint failed: ${err instanceof Error ? err.message : String(err)}`);
3424
3265
  }
3425
3266
  let fallback;
3426
3267
  if (feeAmount > 0n) {
@@ -3439,10 +3280,7 @@ var PTClaimHandler = class {
3439
3280
  mintFeeWrapperAddress: resolvedWrapper
3440
3281
  });
3441
3282
  } catch (err) {
3442
- throw new PTClaimError(
3443
- "BUILD_FAILED",
3444
- `prepareMint (fallback) failed: ${err instanceof Error ? err.message : String(err)}`
3445
- );
3283
+ throw new PTClaimError("BUILD_FAILED", `prepareMint (fallback) failed: ${err instanceof Error ? err.message : String(err)}`);
3446
3284
  }
3447
3285
  }
3448
3286
  const calls = (0, import_core11.decodeBatchExecuteCalls)(userOp.callData);
@@ -3472,6 +3310,9 @@ var PTClaimHandler = class {
3472
3310
  // src/api/handlers/perpDepositHandler.ts
3473
3311
  var import_core12 = require("@pafi-dev/core");
3474
3312
  var PerpDepositError = class extends import_core.PafiSdkError {
3313
+ static {
3314
+ __name(this, "PerpDepositError");
3315
+ }
3475
3316
  httpStatus = "unprocessable";
3476
3317
  code;
3477
3318
  safeToRetry;
@@ -3483,6 +3324,9 @@ var PerpDepositError = class extends import_core.PafiSdkError {
3483
3324
  };
3484
3325
  var DEFAULT_MAX_FEE_PREMIUM_BPS = 5e3;
3485
3326
  var PerpDepositHandler = class {
3327
+ static {
3328
+ __name(this, "PerpDepositHandler");
3329
+ }
3486
3330
  cfg;
3487
3331
  constructor(config) {
3488
3332
  this.cfg = {
@@ -3498,10 +3342,7 @@ var PerpDepositHandler = class {
3498
3342
  const tokenHash = import_core12.TOKEN_HASHES.USDC;
3499
3343
  const vault = import_core12.ORDERLY_VAULT_ADDRESSES[request.chainId];
3500
3344
  if (!vault) {
3501
- throw new PerpDepositError(
3502
- "PERP_DEPOSIT_UNAVAILABLE",
3503
- `no Orderly Vault for chainId ${request.chainId}`
3504
- );
3345
+ throw new PerpDepositError("PERP_DEPOSIT_UNAVAILABLE", `no Orderly Vault for chainId ${request.chainId}`);
3505
3346
  }
3506
3347
  const { orderlyRelay: relayAddress, pafiFeeRecipient } = (0, import_core12.getContractAddresses)(request.chainId);
3507
3348
  const [usdcAddress, brokerAllowed] = await Promise.all([
@@ -3509,20 +3350,21 @@ var PerpDepositHandler = class {
3509
3350
  address: vault,
3510
3351
  abi: import_core12.ORDERLY_VAULT_ABI,
3511
3352
  functionName: "getAllowedToken",
3512
- args: [tokenHash]
3353
+ args: [
3354
+ tokenHash
3355
+ ]
3513
3356
  }),
3514
3357
  this.cfg.provider.readContract({
3515
3358
  address: vault,
3516
3359
  abi: import_core12.ORDERLY_VAULT_ABI,
3517
3360
  functionName: "getAllowedBroker",
3518
- args: [brokerHash]
3361
+ args: [
3362
+ brokerHash
3363
+ ]
3519
3364
  })
3520
3365
  ]);
3521
3366
  if (!brokerAllowed) {
3522
- throw new PerpDepositError(
3523
- "BROKER_NOT_WHITELISTED",
3524
- `broker "${request.brokerId}" is not whitelisted on Orderly Vault`
3525
- );
3367
+ throw new PerpDepositError("BROKER_NOT_WHITELISTED", `broker "${request.brokerId}" is not whitelisted on Orderly Vault`);
3526
3368
  }
3527
3369
  const accountId = (0, import_core12.computeAccountId)(request.userAddress, brokerHash);
3528
3370
  const requestForQuote = {
@@ -3537,7 +3379,9 @@ var PerpDepositHandler = class {
3537
3379
  address: relayAddress,
3538
3380
  abi: import_core12.ORDERLY_RELAY_ABI,
3539
3381
  functionName: "quoteTokenFee",
3540
- args: [requestForQuote]
3382
+ args: [
3383
+ requestForQuote
3384
+ ]
3541
3385
  }),
3542
3386
  (0, import_core12.quoteOperatorFeeUsdt)({
3543
3387
  provider: this.cfg.provider,
@@ -3547,16 +3391,10 @@ var PerpDepositHandler = class {
3547
3391
  })
3548
3392
  ]);
3549
3393
  if (relayTokenFee >= request.amount) {
3550
- throw new PerpDepositError(
3551
- "RELAY_FEE_EXCEEDS_AMOUNT",
3552
- `Relay quoted fee ${relayTokenFee} >= deposit amount ${request.amount}`
3553
- );
3394
+ throw new PerpDepositError("RELAY_FEE_EXCEEDS_AMOUNT", `Relay quoted fee ${relayTokenFee} >= deposit amount ${request.amount}`);
3554
3395
  }
3555
3396
  if (usdcGasFee > 0n && usdcGasFee >= request.amount) {
3556
- throw new PerpDepositError(
3557
- "FEE_EXCEEDS_AMOUNT",
3558
- `USDC gas fee ${usdcGasFee} >= deposit amount ${request.amount}`
3559
- );
3397
+ throw new PerpDepositError("FEE_EXCEEDS_AMOUNT", `USDC gas fee ${usdcGasFee} >= deposit amount ${request.amount}`);
3560
3398
  }
3561
3399
  const maxFee = relayTokenFee * BigInt(1e4 + this.cfg.maxFeePremiumBps) / 10000n;
3562
3400
  const depositReq = {
@@ -3641,38 +3479,34 @@ async function handleDelegatePrepare(params) {
3641
3479
  eip7702Auth: authorization,
3642
3480
  onWarning: params.onWarning
3643
3481
  });
3644
- const prepared = applyPaymasterGasEstimates(
3645
- userOp,
3646
- paymasterFields,
3647
- params.chainId
3648
- );
3482
+ const prepared = applyPaymasterGasEstimates(userOp, paymasterFields, params.chainId);
3649
3483
  const merged = prepared.userOp;
3650
3484
  const userOpHash = prepared.userOpHash;
3651
- await params.store.save(
3652
- params.lockId,
3653
- {
3654
- sender: merged.sender,
3655
- nonce: merged.nonce.toString(10),
3656
- callData: merged.callData,
3657
- callGasLimit: merged.callGasLimit.toString(10),
3658
- verificationGasLimit: merged.verificationGasLimit.toString(10),
3659
- preVerificationGas: merged.preVerificationGas.toString(10),
3660
- maxFeePerGas: merged.maxFeePerGas.toString(10),
3661
- maxPriorityFeePerGas: merged.maxPriorityFeePerGas.toString(10),
3662
- ...merged.paymaster ? { paymaster: merged.paymaster } : {},
3663
- ...merged.paymasterVerificationGasLimit ? {
3664
- paymasterVerificationGasLimit: merged.paymasterVerificationGasLimit.toString(10)
3665
- } : {},
3666
- ...merged.paymasterPostOpGasLimit ? {
3667
- paymasterPostOpGasLimit: merged.paymasterPostOpGasLimit.toString(10)
3668
- } : {},
3669
- ...merged.paymasterData ? { paymasterData: merged.paymasterData } : {},
3670
- chainId: params.chainId,
3671
- userOpHash,
3672
- eip7702Auth: authorization
3673
- },
3674
- params.ttlSeconds
3675
- );
3485
+ await params.store.save(params.lockId, {
3486
+ sender: merged.sender,
3487
+ nonce: merged.nonce.toString(10),
3488
+ callData: merged.callData,
3489
+ callGasLimit: merged.callGasLimit.toString(10),
3490
+ verificationGasLimit: merged.verificationGasLimit.toString(10),
3491
+ preVerificationGas: merged.preVerificationGas.toString(10),
3492
+ maxFeePerGas: merged.maxFeePerGas.toString(10),
3493
+ maxPriorityFeePerGas: merged.maxPriorityFeePerGas.toString(10),
3494
+ ...merged.paymaster ? {
3495
+ paymaster: merged.paymaster
3496
+ } : {},
3497
+ ...merged.paymasterVerificationGasLimit ? {
3498
+ paymasterVerificationGasLimit: merged.paymasterVerificationGasLimit.toString(10)
3499
+ } : {},
3500
+ ...merged.paymasterPostOpGasLimit ? {
3501
+ paymasterPostOpGasLimit: merged.paymasterPostOpGasLimit.toString(10)
3502
+ } : {},
3503
+ ...merged.paymasterData ? {
3504
+ paymasterData: merged.paymasterData
3505
+ } : {},
3506
+ chainId: params.chainId,
3507
+ userOpHash,
3508
+ eip7702Auth: authorization
3509
+ }, params.ttlSeconds);
3676
3510
  return {
3677
3511
  lockId: params.lockId,
3678
3512
  userOpHash,
@@ -3681,6 +3515,7 @@ async function handleDelegatePrepare(params) {
3681
3515
  isSponsored: !!paymasterFields
3682
3516
  };
3683
3517
  }
3518
+ __name(handleDelegatePrepare, "handleDelegatePrepare");
3684
3519
  async function handleDelegateSubmit(params) {
3685
3520
  const entry = await params.store.get(params.lockId);
3686
3521
  if (!entry) {
@@ -3690,9 +3525,7 @@ async function handleDelegateSubmit(params) {
3690
3525
  throw new PendingUserOpForbiddenError(params.lockId);
3691
3526
  }
3692
3527
  if (!entry.eip7702Auth) {
3693
- throw new Error(
3694
- `delegate entry ${params.lockId} missing eip7702Auth \u2014 prepare step did not run correctly`
3695
- );
3528
+ throw new Error(`delegate entry ${params.lockId} missing eip7702Auth \u2014 prepare step did not run correctly`);
3696
3529
  }
3697
3530
  const userOpJson = serializeEntryToJsonRpc(entry, params.userOpSig, "sponsored");
3698
3531
  const result = await relayUserOp({
@@ -3702,14 +3535,20 @@ async function handleDelegateSubmit(params) {
3702
3535
  eip7702Auth: entry.eip7702Auth
3703
3536
  });
3704
3537
  await params.store.delete(params.lockId);
3705
- return { userOpHash: result.userOpHash };
3538
+ return {
3539
+ userOpHash: result.userOpHash
3540
+ };
3706
3541
  }
3542
+ __name(handleDelegateSubmit, "handleDelegateSubmit");
3707
3543
 
3708
3544
  // src/api/issuerApiAdapter.ts
3709
3545
  var import_node_crypto3 = require("crypto");
3710
3546
  var import_viem12 = require("viem");
3711
3547
  var import_core14 = require("@pafi-dev/core");
3712
3548
  var AdapterMisconfiguredError = class extends Error {
3549
+ static {
3550
+ __name(this, "AdapterMisconfiguredError");
3551
+ }
3713
3552
  code = "ADAPTER_MISCONFIGURED";
3714
3553
  constructor(message) {
3715
3554
  super(message);
@@ -3717,35 +3556,28 @@ var AdapterMisconfiguredError = class extends Error {
3717
3556
  }
3718
3557
  };
3719
3558
  var IssuerApiAdapter = class {
3559
+ static {
3560
+ __name(this, "IssuerApiAdapter");
3561
+ }
3720
3562
  cfg;
3721
3563
  constructor(config) {
3722
3564
  if (config.ptClaimHandler) {
3723
3565
  if (typeof config.ledger.bindMintUserOpHash !== "function") {
3724
- throw new AdapterMisconfiguredError(
3725
- "ledger.bindMintUserOpHash is required when ptClaimHandler is wired (mobile claim flow). Implement it on your IPointLedger or omit ptClaimHandler from IssuerApiAdapter config."
3726
- );
3566
+ throw new AdapterMisconfiguredError("ledger.bindMintUserOpHash is required when ptClaimHandler is wired (mobile claim flow). Implement it on your IPointLedger or omit ptClaimHandler from IssuerApiAdapter config.");
3727
3567
  }
3728
3568
  if (typeof config.ledger.getMintLock !== "function") {
3729
- throw new AdapterMisconfiguredError(
3730
- "ledger.getMintLock is required when ptClaimHandler is wired \u2014 claimStatus uses it to look up the lock."
3731
- );
3569
+ throw new AdapterMisconfiguredError("ledger.getMintLock is required when ptClaimHandler is wired \u2014 claimStatus uses it to look up the lock.");
3732
3570
  }
3733
3571
  }
3734
3572
  if (config.ptRedeemHandler) {
3735
3573
  if (typeof config.ledger.reservePendingCredit !== "function") {
3736
- throw new AdapterMisconfiguredError(
3737
- "ledger.reservePendingCredit is required when ptRedeemHandler is wired (burn/redeem reverse flow). PTRedeemHandler also enforces this at construction; see ledger/types.ts comments."
3738
- );
3574
+ throw new AdapterMisconfiguredError("ledger.reservePendingCredit is required when ptRedeemHandler is wired (burn/redeem reverse flow). PTRedeemHandler also enforces this at construction; see ledger/types.ts comments.");
3739
3575
  }
3740
3576
  if (typeof config.ledger.bindCreditUserOpHash !== "function") {
3741
- throw new AdapterMisconfiguredError(
3742
- "ledger.bindCreditUserOpHash is required when ptRedeemHandler is wired (mobile redeem flow)."
3743
- );
3577
+ throw new AdapterMisconfiguredError("ledger.bindCreditUserOpHash is required when ptRedeemHandler is wired (mobile redeem flow).");
3744
3578
  }
3745
3579
  if (typeof config.ledger.getPendingCredit !== "function") {
3746
- throw new AdapterMisconfiguredError(
3747
- "ledger.getPendingCredit is required when ptRedeemHandler is wired \u2014 redeemStatus uses it to look up the credit."
3748
- );
3580
+ throw new AdapterMisconfiguredError("ledger.getPendingCredit is required when ptRedeemHandler is wired \u2014 redeemStatus uses it to look up the credit.");
3749
3581
  }
3750
3582
  }
3751
3583
  this.cfg = config;
@@ -3760,24 +3592,25 @@ var IssuerApiAdapter = class {
3760
3592
  }
3761
3593
  async gasFee() {
3762
3594
  const result = await this.cfg.issuerService.api.handleGasFee();
3763
- return { gasFeeUsdt: result.gasFeeUsdt.toString() };
3595
+ return {
3596
+ gasFeeUsdt: result.gasFeeUsdt.toString()
3597
+ };
3764
3598
  }
3765
3599
  async pools(authenticatedAddress, chainId, pointTokenAddress) {
3766
- const result = await this.cfg.issuerService.api.handlePools(
3767
- authenticatedAddress,
3768
- { chainId, pointTokenAddress: (0, import_viem12.getAddress)(pointTokenAddress) }
3769
- );
3770
- return { pools: result.pools };
3600
+ const result = await this.cfg.issuerService.api.handlePools(authenticatedAddress, {
3601
+ chainId,
3602
+ pointTokenAddress: (0, import_viem12.getAddress)(pointTokenAddress)
3603
+ });
3604
+ return {
3605
+ pools: result.pools
3606
+ };
3771
3607
  }
3772
3608
  async user(authenticatedAddress, chainId, userAddress, pointTokenAddress) {
3773
- const result = await this.cfg.issuerService.api.handleUser(
3774
- authenticatedAddress,
3775
- {
3776
- chainId,
3777
- userAddress: (0, import_viem12.getAddress)(userAddress),
3778
- pointTokenAddress: (0, import_viem12.getAddress)(pointTokenAddress)
3779
- }
3780
- );
3609
+ const result = await this.cfg.issuerService.api.handleUser(authenticatedAddress, {
3610
+ chainId,
3611
+ userAddress: (0, import_viem12.getAddress)(userAddress),
3612
+ pointTokenAddress: (0, import_viem12.getAddress)(pointTokenAddress)
3613
+ });
3781
3614
  return {
3782
3615
  offChainBalance: result.offChainBalance.toString(),
3783
3616
  onChainBalance: result.onChainBalance.toString(),
@@ -3790,11 +3623,7 @@ var IssuerApiAdapter = class {
3790
3623
  // directly. Issuer SDK doesn't ship swap/quote anymore.
3791
3624
  // ------------------------------ Action endpoints -------------------------
3792
3625
  async claim(input) {
3793
- const ptClaimHandler = this.assertHandler(
3794
- this.cfg.ptClaimHandler,
3795
- "ptClaimHandler",
3796
- "claim"
3797
- );
3626
+ const ptClaimHandler = this.assertHandler(this.cfg.ptClaimHandler, "ptClaimHandler", "claim");
3798
3627
  const pointTokenAddress = (0, import_viem12.getAddress)(input.pointTokenAddress);
3799
3628
  const result = await ptClaimHandler.handle({
3800
3629
  authenticatedAddress: input.authenticatedAddress,
@@ -3804,12 +3633,7 @@ var IssuerApiAdapter = class {
3804
3633
  chainId: input.chainId,
3805
3634
  aaNonce: input.aaNonce
3806
3635
  });
3807
- const sponsorAuth = await this.buildSponsorAuth(
3808
- input.authenticatedAddress,
3809
- result.userOp.callData,
3810
- input.chainId,
3811
- "mint"
3812
- );
3636
+ const sponsorAuth = await this.buildSponsorAuth(input.authenticatedAddress, result.userOp.callData, input.chainId, "mint");
3813
3637
  return {
3814
3638
  calls: result.calls,
3815
3639
  callsFallback: result.callsFallback,
@@ -3830,12 +3654,7 @@ var IssuerApiAdapter = class {
3830
3654
  aaNonce: input.aaNonce,
3831
3655
  chainId: input.chainId
3832
3656
  });
3833
- const sponsorAuth = await this.buildSponsorAuth(
3834
- input.authenticatedAddress,
3835
- response.userOp.callData,
3836
- input.chainId,
3837
- "burn"
3838
- );
3657
+ const sponsorAuth = await this.buildSponsorAuth(input.authenticatedAddress, response.userOp.callData, input.chainId, "burn");
3839
3658
  return {
3840
3659
  calls: (0, import_core14.decodeBatchExecuteCalls)(response.userOp.callData),
3841
3660
  callsFallback: response.fallback ? (0, import_core14.decodeBatchExecuteCalls)(response.fallback.userOp.callData) : void 0,
@@ -3852,11 +3671,7 @@ var IssuerApiAdapter = class {
3852
3671
  // swap() removed (2026-04-27) — moved to @pafi-dev/trading.
3853
3672
  // PAFI's web FE calls TradingHandlers.handleSwap directly.
3854
3673
  async perpDeposit(input) {
3855
- const perpHandler = this.assertHandler(
3856
- this.cfg.perpHandler,
3857
- "perpHandler",
3858
- "perpDeposit"
3859
- );
3674
+ const perpHandler = this.assertHandler(this.cfg.perpHandler, "perpHandler", "perpDeposit");
3860
3675
  const result = await perpHandler.handle({
3861
3676
  userAddress: input.authenticatedAddress,
3862
3677
  chainId: input.chainId,
@@ -3864,12 +3679,7 @@ var IssuerApiAdapter = class {
3864
3679
  brokerId: input.brokerId,
3865
3680
  aaNonce: input.aaNonce
3866
3681
  });
3867
- const sponsorAuth = await this.buildSponsorAuth(
3868
- input.authenticatedAddress,
3869
- result.userOp.callData,
3870
- input.chainId,
3871
- "perp-deposit"
3872
- );
3682
+ const sponsorAuth = await this.buildSponsorAuth(input.authenticatedAddress, result.userOp.callData, input.chainId, "perp-deposit");
3873
3683
  return {
3874
3684
  calls: result.calls,
3875
3685
  callsFallback: result.callsFallback,
@@ -3886,11 +3696,7 @@ var IssuerApiAdapter = class {
3886
3696
  }
3887
3697
  // ------------------------------ Mobile endpoints -------------------------
3888
3698
  async claimPrepare(input) {
3889
- const ptClaimHandler = this.assertHandler(
3890
- this.cfg.ptClaimHandler,
3891
- "ptClaimHandler",
3892
- "claimPrepare"
3893
- );
3699
+ const ptClaimHandler = this.assertHandler(this.cfg.ptClaimHandler, "ptClaimHandler", "claimPrepare");
3894
3700
  const pointTokenAddress = (0, import_viem12.getAddress)(input.pointTokenAddress);
3895
3701
  const claimResult = await ptClaimHandler.handle({
3896
3702
  authenticatedAddress: input.authenticatedAddress,
@@ -3900,17 +3706,7 @@ var IssuerApiAdapter = class {
3900
3706
  chainId: input.chainId,
3901
3707
  aaNonce: input.aaNonce
3902
3708
  });
3903
- const prepared = await this.runMobilePrepare(
3904
- input.authenticatedAddress,
3905
- input.chainId,
3906
- claimResult.lockId,
3907
- claimResult.userOp,
3908
- claimResult.fallback,
3909
- "mint",
3910
- pointTokenAddress,
3911
- claimResult.expiresInSeconds,
3912
- input.eip7702Auth
3913
- );
3709
+ const prepared = await this.runMobilePrepare(input.authenticatedAddress, input.chainId, claimResult.lockId, claimResult.userOp, claimResult.fallback, "mint", pointTokenAddress, claimResult.expiresInSeconds, input.eip7702Auth);
3914
3710
  return {
3915
3711
  lockId: claimResult.lockId,
3916
3712
  userOpHash: prepared.sponsored.userOpHash,
@@ -3931,7 +3727,7 @@ var IssuerApiAdapter = class {
3931
3727
  signature: input.signature,
3932
3728
  variant: input.variant,
3933
3729
  store: this.cfg.pendingUserOpStore,
3934
- bindUserOpHash: (lockId, hash) => this.cfg.ledger.bindMintUserOpHash(lockId, hash),
3730
+ bindUserOpHash: /* @__PURE__ */ __name((lockId, hash) => this.cfg.ledger.bindMintUserOpHash(lockId, hash), "bindUserOpHash"),
3935
3731
  pafiBackendClient: this.cfg.pafiBackendClient
3936
3732
  });
3937
3733
  }
@@ -3946,18 +3742,7 @@ var IssuerApiAdapter = class {
3946
3742
  aaNonce: input.aaNonce,
3947
3743
  chainId: input.chainId
3948
3744
  });
3949
- const prepared = await this.runMobilePrepare(
3950
- input.authenticatedAddress,
3951
- input.chainId,
3952
- redeemResponse.lockId,
3953
- redeemResponse.userOp,
3954
- redeemResponse.fallback?.userOp,
3955
- "burn",
3956
- pointTokenAddress,
3957
- redeemResponse.expiresInSeconds,
3958
- input.eip7702Auth,
3959
- redeemResponse.fallback?.lockId
3960
- );
3745
+ const prepared = await this.runMobilePrepare(input.authenticatedAddress, input.chainId, redeemResponse.lockId, redeemResponse.userOp, redeemResponse.fallback?.userOp, "burn", pointTokenAddress, redeemResponse.expiresInSeconds, input.eip7702Auth, redeemResponse.fallback?.lockId);
3961
3746
  return {
3962
3747
  lockId: redeemResponse.lockId,
3963
3748
  lockIdFallback: redeemResponse.fallback?.lockId,
@@ -3981,7 +3766,7 @@ var IssuerApiAdapter = class {
3981
3766
  signature: input.signature,
3982
3767
  variant: input.variant,
3983
3768
  store: this.cfg.pendingUserOpStore,
3984
- bindUserOpHash: (lockId, hash) => this.cfg.ledger.bindCreditUserOpHash(lockId, hash),
3769
+ bindUserOpHash: /* @__PURE__ */ __name((lockId, hash) => this.cfg.ledger.bindCreditUserOpHash(lockId, hash), "bindUserOpHash"),
3985
3770
  pafiBackendClient: this.cfg.pafiBackendClient
3986
3771
  });
3987
3772
  }
@@ -4009,7 +3794,9 @@ var IssuerApiAdapter = class {
4009
3794
  async delegateStatus(authenticatedAddress, chainId) {
4010
3795
  const { batchExecutor } = (0, import_core14.getContractAddresses)(chainId);
4011
3796
  const [code, nonce] = await Promise.all([
4012
- this.cfg.provider.getCode({ address: authenticatedAddress }),
3797
+ this.cfg.provider.getCode({
3798
+ address: authenticatedAddress
3799
+ }),
4013
3800
  this.cfg.provider.getTransactionCount({
4014
3801
  address: authenticatedAddress,
4015
3802
  blockTag: "pending"
@@ -4023,21 +3810,21 @@ var IssuerApiAdapter = class {
4023
3810
  };
4024
3811
  }
4025
3812
  /**
4026
- * Build the delegation-anchor UserOp + obtain paymaster sponsorship
4027
- * + persist as a pending entry. Mobile must:
4028
- *
4029
- * 1. Sign EIP-7702 authorization LOCALLY (Privy `signAuthorization`
4030
- * with `{contractAddress: batchExecutorAddress, chainId,
4031
- * nonce: delegationNonce}`) → 65-byte authSig hex.
4032
- * 2. POST `/delegate/prepare` with `{ chainId, delegationNonce,
4033
- * authSig }` → this method.
4034
- * 3. Sign returned `userOpHash` LOCALLY (`signTypedData(typedData)`).
4035
- * 4. POST `/delegate/submit` with `{ lockId, userOpSig }`.
4036
- *
4037
- * v0.7.7 — replaces single-shot delegateSubmit that tried to relay
4038
- * a UserOp with empty `signature: "0x"` (Simple7702Account's
4039
- * validateUserOp reverts `ECDSAInvalidSignatureLength` 0xfce698f7).
4040
- */
3813
+ * Build the delegation-anchor UserOp + obtain paymaster sponsorship
3814
+ * + persist as a pending entry. Mobile must:
3815
+ *
3816
+ * 1. Sign EIP-7702 authorization LOCALLY (Privy `signAuthorization`
3817
+ * with `{contractAddress: batchExecutorAddress, chainId,
3818
+ * nonce: delegationNonce}`) → 65-byte authSig hex.
3819
+ * 2. POST `/delegate/prepare` with `{ chainId, delegationNonce,
3820
+ * authSig }` → this method.
3821
+ * 3. Sign returned `userOpHash` LOCALLY (`signTypedData(typedData)`).
3822
+ * 4. POST `/delegate/submit` with `{ lockId, userOpSig }`.
3823
+ *
3824
+ * v0.7.7 — replaces single-shot delegateSubmit that tried to relay
3825
+ * a UserOp with empty `signature: "0x"` (Simple7702Account's
3826
+ * validateUserOp reverts `ECDSAInvalidSignatureLength` 0xfce698f7).
3827
+ */
4041
3828
  async delegatePrepare(authenticatedAddress, input) {
4042
3829
  const { batchExecutor } = (0, import_core14.getContractAddresses)(input.chainId);
4043
3830
  const fees = await this.cfg.provider.estimateFeesPerGas();
@@ -4052,7 +3839,6 @@ var IssuerApiAdapter = class {
4052
3839
  lockId,
4053
3840
  store: this.cfg.pendingUserOpStore,
4054
3841
  ttlSeconds: 15 * 60,
4055
- // 15min — match claim/redeem mobile lock duration
4056
3842
  pafiBackendClient: this.cfg.pafiBackendClient,
4057
3843
  onWarning: this.cfg.onWarning
4058
3844
  });
@@ -4075,13 +3861,15 @@ var IssuerApiAdapter = class {
4075
3861
  store: this.cfg.pendingUserOpStore,
4076
3862
  pafiBackendClient: this.cfg.pafiBackendClient
4077
3863
  });
4078
- return { userOpHash: result.userOpHash };
3864
+ return {
3865
+ userOpHash: result.userOpHash
3866
+ };
4079
3867
  }
4080
3868
  // ------------------------------ Internal helpers -------------------------
4081
3869
  /**
4082
- * Build + sign a SponsorAuth payload. Returns `undefined` when no
4083
- * issuer id is configured, so the controller can skip the field.
4084
- */
3870
+ * Build + sign a SponsorAuth payload. Returns `undefined` when no
3871
+ * issuer id is configured, so the controller can skip the field.
3872
+ */
4085
3873
  async buildSponsorAuth(authenticatedAddress, callData, chainId, scenario) {
4086
3874
  if (!this.cfg.pafiIssuerId) return void 0;
4087
3875
  return (0, import_core14.buildAndSignSponsorAuth)({
@@ -4113,22 +3901,18 @@ var IssuerApiAdapter = class {
4113
3901
  }
4114
3902
  assertRedeemHandler() {
4115
3903
  if (!this.cfg.ptRedeemHandler) {
4116
- throw new Error(
4117
- "PTRedeemHandler not wired \u2014 IssuerApiAdapter.redeem* require a configured ptRedeemHandler."
4118
- );
3904
+ throw new Error("PTRedeemHandler not wired \u2014 IssuerApiAdapter.redeem* require a configured ptRedeemHandler.");
4119
3905
  }
4120
3906
  }
4121
3907
  /**
4122
- * Narrow an optional handler to non-null and throw a clear error when
4123
- * the issuer wired the adapter without it. Lets issuers opt out of
4124
- * flows they don't expose (gg56 ships only mobile claim/redeem, so
4125
- * `swapHandler` + `perpHandler` aren't constructed).
4126
- */
3908
+ * Narrow an optional handler to non-null and throw a clear error when
3909
+ * the issuer wired the adapter without it. Lets issuers opt out of
3910
+ * flows they don't expose (gg56 ships only mobile claim/redeem, so
3911
+ * `swapHandler` + `perpHandler` aren't constructed).
3912
+ */
4127
3913
  assertHandler(handler, fieldName, methodName) {
4128
3914
  if (handler === null || handler === void 0) {
4129
- throw new Error(
4130
- `${fieldName} not wired \u2014 IssuerApiAdapter.${methodName}() requires a configured ${fieldName}.`
4131
- );
3915
+ throw new Error(`${fieldName} not wired \u2014 IssuerApiAdapter.${methodName}() requires a configured ${fieldName}.`);
4132
3916
  }
4133
3917
  return handler;
4134
3918
  }
@@ -4161,9 +3945,7 @@ function createSubgraphPoolsProvider(config = {}) {
4161
3945
  }
4162
3946
  } catch (err) {
4163
3947
  if (err instanceof TypeError) {
4164
- throw new Error(
4165
- `subgraphPoolsProvider: invalid subgraphUrl: ${subgraphUrl}`
4166
- );
3948
+ throw new Error(`subgraphPoolsProvider: invalid subgraphUrl: ${subgraphUrl}`);
4167
3949
  }
4168
3950
  throw err;
4169
3951
  }
@@ -4173,64 +3955,61 @@ function createSubgraphPoolsProvider(config = {}) {
4173
3955
  const onError = config.onError;
4174
3956
  const cache = /* @__PURE__ */ new Map();
4175
3957
  if (!fetchImpl) {
4176
- throw new Error(
4177
- "createSubgraphPoolsProvider: no fetch implementation available \u2014 pass `fetchImpl` or run on Node 18+"
4178
- );
3958
+ throw new Error("createSubgraphPoolsProvider: no fetch implementation available \u2014 pass `fetchImpl` or run on Node 18+");
4179
3959
  }
4180
- const reportError = (err) => {
3960
+ const reportError = /* @__PURE__ */ __name((err) => {
4181
3961
  if (!onError) return;
4182
3962
  try {
4183
3963
  onError(err);
4184
3964
  } catch {
4185
3965
  }
4186
- };
3966
+ }, "reportError");
4187
3967
  return async (request) => {
4188
3968
  const cacheKey = `${request.chainId}:${request.pointTokenAddress.toLowerCase()}`;
4189
3969
  if (cacheTtl > 0) {
4190
3970
  const cached = cache.get(cacheKey);
4191
3971
  if (cached && cached.expiresAt > now()) {
4192
- return { pools: cached.pools };
3972
+ return {
3973
+ pools: cached.pools
3974
+ };
4193
3975
  }
4194
3976
  }
4195
- const pools = await fetchPoolsFromSubgraph(
4196
- fetchImpl,
4197
- subgraphUrl,
4198
- request.pointTokenAddress,
4199
- reportError
4200
- );
3977
+ const pools = await fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, request.pointTokenAddress, reportError);
4201
3978
  if (cacheTtl > 0) {
4202
3979
  cache.set(cacheKey, {
4203
3980
  expiresAt: now() + cacheTtl,
4204
3981
  pools
4205
3982
  });
4206
3983
  }
4207
- return { pools };
3984
+ return {
3985
+ pools
3986
+ };
4208
3987
  };
4209
3988
  }
3989
+ __name(createSubgraphPoolsProvider, "createSubgraphPoolsProvider");
4210
3990
  async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress, reportError) {
4211
3991
  let response;
4212
3992
  try {
4213
3993
  response = await fetchImpl(subgraphUrl, {
4214
3994
  method: "POST",
4215
- headers: { "Content-Type": "application/json" },
3995
+ headers: {
3996
+ "Content-Type": "application/json"
3997
+ },
4216
3998
  body: JSON.stringify({
4217
3999
  query: POOL_QUERY,
4218
- variables: { id: pointTokenAddress.toLowerCase() }
4000
+ variables: {
4001
+ id: pointTokenAddress.toLowerCase()
4002
+ }
4219
4003
  })
4220
4004
  });
4221
4005
  } catch (err) {
4222
4006
  const error = err instanceof Error ? err : new Error(String(err));
4223
- console.warn(
4224
- "[subgraphPoolsProvider] subgraph unreachable:",
4225
- error.message
4226
- );
4007
+ console.warn("[subgraphPoolsProvider] subgraph unreachable:", error.message);
4227
4008
  reportError(error);
4228
4009
  return [];
4229
4010
  }
4230
4011
  if (!response.ok) {
4231
- const error = new Error(
4232
- `subgraph returned HTTP ${response.status}`
4233
- );
4012
+ const error = new Error(`subgraph returned HTTP ${response.status}`);
4234
4013
  console.warn(`[subgraphPoolsProvider] ${error.message}`);
4235
4014
  reportError(error);
4236
4015
  return [];
@@ -4240,10 +4019,7 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress,
4240
4019
  json = await response.json();
4241
4020
  } catch (err) {
4242
4021
  const error = err instanceof Error ? err : new Error(String(err));
4243
- console.warn(
4244
- "[subgraphPoolsProvider] subgraph returned non-JSON:",
4245
- error.message
4246
- );
4022
+ console.warn("[subgraphPoolsProvider] subgraph returned non-JSON:", error.message);
4247
4023
  reportError(error);
4248
4024
  return [];
4249
4025
  }
@@ -4259,36 +4035,39 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress,
4259
4035
  }
4260
4036
  const { pool } = token;
4261
4037
  if (!(0, import_viem13.isAddress)(pool.token0.id) || !(0, import_viem13.isAddress)(pool.token1.id)) {
4262
- const error = new Error(
4263
- "[PAFI] SubgraphPoolsProvider: invalid token address in response"
4264
- );
4038
+ const error = new Error("[PAFI] SubgraphPoolsProvider: invalid token address in response");
4265
4039
  console.error(error.message, "\u2014 skipping pool");
4266
4040
  reportError(error);
4267
4041
  return [];
4268
4042
  }
4269
4043
  const feeNum = Number(pool.feeTier);
4270
4044
  if (!Number.isInteger(feeNum) || feeNum < 0 || feeNum >= MAX_REASONABLE_FEE_TIER) {
4271
- const error = new Error(
4272
- `[PAFI] SubgraphPoolsProvider: invalid feeTier value: ${pool.feeTier}`
4273
- );
4045
+ const error = new Error(`[PAFI] SubgraphPoolsProvider: invalid feeTier value: ${pool.feeTier}`);
4274
4046
  console.error(error.message, "\u2014 skipping pool");
4275
4047
  reportError(error);
4276
4048
  return [];
4277
4049
  }
4278
- const [token0, token1] = sortTokens(
4279
- pool.token0.id,
4280
- pool.token1.id
4281
- );
4050
+ const [token0, token1] = sortTokens(pool.token0.id, pool.token1.id);
4282
4051
  const poolKey = {
4283
4052
  token0,
4284
4053
  token1,
4285
4054
  fee: feeNum
4286
4055
  };
4287
- return [poolKey];
4056
+ return [
4057
+ poolKey
4058
+ ];
4288
4059
  }
4060
+ __name(fetchPoolsFromSubgraph, "fetchPoolsFromSubgraph");
4289
4061
  function sortTokens(a, b) {
4290
- return a.toLowerCase() < b.toLowerCase() ? [a, b] : [b, a];
4062
+ return a.toLowerCase() < b.toLowerCase() ? [
4063
+ a,
4064
+ b
4065
+ ] : [
4066
+ b,
4067
+ a
4068
+ ];
4291
4069
  }
4070
+ __name(sortTokens, "sortTokens");
4292
4071
 
4293
4072
  // src/pools/subgraphNativeUsdtQuoter.ts
4294
4073
  var DEFAULT_CACHE_TTL_MS2 = 3e4;
@@ -4311,9 +4090,7 @@ function createSubgraphNativeUsdtQuoter(config = {}) {
4311
4090
  }
4312
4091
  } catch (err) {
4313
4092
  if (err instanceof TypeError) {
4314
- throw new Error(
4315
- `createSubgraphNativeUsdtQuoter: invalid subgraphUrl: ${subgraphUrl}`
4316
- );
4093
+ throw new Error(`createSubgraphNativeUsdtQuoter: invalid subgraphUrl: ${subgraphUrl}`);
4317
4094
  }
4318
4095
  throw err;
4319
4096
  }
@@ -4324,23 +4101,15 @@ function createSubgraphNativeUsdtQuoter(config = {}) {
4324
4101
  const fetchImpl = config.fetchImpl ?? globalThis.fetch;
4325
4102
  const now = config.now ?? (() => Date.now());
4326
4103
  if (!fetchImpl) {
4327
- throw new Error(
4328
- "createSubgraphNativeUsdtQuoter: no fetch implementation available \u2014 pass `fetchImpl` or run on Node 18+"
4329
- );
4104
+ throw new Error("createSubgraphNativeUsdtQuoter: no fetch implementation available \u2014 pass `fetchImpl` or run on Node 18+");
4330
4105
  }
4331
4106
  let cached;
4332
4107
  async function getUsdtPerNative() {
4333
4108
  if (cacheTtl > 0 && cached && cached.expiresAt > now()) {
4334
4109
  return cached.usdtPerNative;
4335
4110
  }
4336
- const price = await fetchEthPriceFromSubgraph(
4337
- fetchImpl,
4338
- subgraphUrl
4339
- );
4340
- const usdtPerNative = toUsdtPerNative(
4341
- price ?? fallbackPrice,
4342
- usdtDecimals
4343
- );
4111
+ const price = await fetchEthPriceFromSubgraph(fetchImpl, subgraphUrl);
4112
+ const usdtPerNative = toUsdtPerNative(price ?? fallbackPrice, usdtDecimals);
4344
4113
  if (cacheTtl > 0) {
4345
4114
  cached = {
4346
4115
  usdtPerNative,
@@ -4349,66 +4118,62 @@ function createSubgraphNativeUsdtQuoter(config = {}) {
4349
4118
  }
4350
4119
  return usdtPerNative;
4351
4120
  }
4121
+ __name(getUsdtPerNative, "getUsdtPerNative");
4352
4122
  return async (amountNative) => {
4353
4123
  if (amountNative === 0n) return 0n;
4354
4124
  const usdtPerNative = await getUsdtPerNative();
4355
4125
  return amountNative * usdtPerNative / 10n ** BigInt(nativeDecimals);
4356
4126
  };
4357
4127
  }
4128
+ __name(createSubgraphNativeUsdtQuoter, "createSubgraphNativeUsdtQuoter");
4358
4129
  async function fetchEthPriceFromSubgraph(fetchImpl, subgraphUrl) {
4359
4130
  let response;
4360
4131
  try {
4361
4132
  response = await fetchImpl(subgraphUrl, {
4362
4133
  method: "POST",
4363
- headers: { "Content-Type": "application/json" },
4364
- body: JSON.stringify({ query: PRICE_QUERY })
4134
+ headers: {
4135
+ "Content-Type": "application/json"
4136
+ },
4137
+ body: JSON.stringify({
4138
+ query: PRICE_QUERY
4139
+ })
4365
4140
  });
4366
4141
  } catch (err) {
4367
- console.warn(
4368
- "[subgraphNativeUsdtQuoter] subgraph unreachable:",
4369
- err.message
4370
- );
4142
+ console.warn("[subgraphNativeUsdtQuoter] subgraph unreachable:", err.message);
4371
4143
  return null;
4372
4144
  }
4373
4145
  if (!response.ok) {
4374
- console.warn(
4375
- `[subgraphNativeUsdtQuoter] subgraph returned ${response.status}`
4376
- );
4146
+ console.warn(`[subgraphNativeUsdtQuoter] subgraph returned ${response.status}`);
4377
4147
  return null;
4378
4148
  }
4379
4149
  const json = await response.json();
4380
4150
  if (json.errors && json.errors.length > 0) {
4381
- console.warn(
4382
- "[subgraphNativeUsdtQuoter] subgraph errors:",
4383
- json.errors.map((e) => e.message).join("; ")
4384
- );
4151
+ console.warn("[subgraphNativeUsdtQuoter] subgraph errors:", json.errors.map((e) => e.message).join("; "));
4385
4152
  return null;
4386
4153
  }
4387
4154
  const raw = json.data?.bundle?.ethPriceUSD;
4388
4155
  if (!raw) return null;
4389
4156
  const parsed = Number(raw);
4390
4157
  if (!Number.isFinite(parsed) || parsed <= 0) {
4391
- console.warn(
4392
- `[subgraphNativeUsdtQuoter] invalid ethPriceUSD from subgraph: ${raw}`
4393
- );
4158
+ console.warn(`[subgraphNativeUsdtQuoter] invalid ethPriceUSD from subgraph: ${raw}`);
4394
4159
  return null;
4395
4160
  }
4396
4161
  const MIN_REASONABLE_ETH_PRICE = 100;
4397
4162
  const MAX_REASONABLE_ETH_PRICE = 1e5;
4398
4163
  if (parsed < MIN_REASONABLE_ETH_PRICE || parsed > MAX_REASONABLE_ETH_PRICE) {
4399
- console.warn(
4400
- `[PAFI] SubgraphNativeUsdtQuoter: ETH/USD price ${parsed} is outside reasonable range. Using fallback.`
4401
- );
4164
+ console.warn(`[PAFI] SubgraphNativeUsdtQuoter: ETH/USD price ${parsed} is outside reasonable range. Using fallback.`);
4402
4165
  return null;
4403
4166
  }
4404
4167
  return parsed;
4405
4168
  }
4169
+ __name(fetchEthPriceFromSubgraph, "fetchEthPriceFromSubgraph");
4406
4170
  function toUsdtPerNative(priceFloat, usdtDecimals) {
4407
4171
  const fixed = priceFloat.toFixed(usdtDecimals);
4408
4172
  const [whole, fraction = ""] = fixed.split(".");
4409
4173
  const padded = (fraction + "0".repeat(usdtDecimals)).slice(0, usdtDecimals);
4410
4174
  return BigInt(whole + padded);
4411
4175
  }
4176
+ __name(toUsdtPerNative, "toUsdtPerNative");
4412
4177
 
4413
4178
  // src/pools/nativePtQuoter.ts
4414
4179
  var import_viem14 = require("viem");
@@ -4429,18 +4194,7 @@ var POOL_PRICE_QUERY = `
4429
4194
  }
4430
4195
  `;
4431
4196
  function createNativePtQuoter(config) {
4432
- const {
4433
- provider,
4434
- pointTokenAddress,
4435
- chainlinkFeedAddress = "0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70",
4436
- subgraphUrl = import_core15.PAFI_SUBGRAPH_URL,
4437
- cacheTtlMs = 3e4,
4438
- fallbackEthPriceUsd = 3e3,
4439
- fallbackPtPriceUsdt = 0.1,
4440
- failClosed = false,
4441
- fetchImpl = globalThis.fetch,
4442
- now = () => Date.now()
4443
- } = config;
4197
+ const { provider, pointTokenAddress, chainlinkFeedAddress = "0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70", subgraphUrl = import_core15.PAFI_SUBGRAPH_URL, cacheTtlMs = 3e4, fallbackEthPriceUsd = 3e3, fallbackPtPriceUsdt = 0.1, failClosed = false, fetchImpl = globalThis.fetch, now = /* @__PURE__ */ __name(() => Date.now(), "now") } = config;
4444
4198
  let ethPriceCache;
4445
4199
  let ptPriceCache;
4446
4200
  async function getEthPrice8dec() {
@@ -4459,28 +4213,34 @@ function createNativePtQuoter(config) {
4459
4213
  if (ageS > CHAINLINK_MAX_AGE_S) {
4460
4214
  throw new Error(`Chainlink: price stale by ${ageS}s`);
4461
4215
  }
4462
- ethPriceCache = { value: answer, expiresAt: ts + cacheTtlMs };
4216
+ ethPriceCache = {
4217
+ value: answer,
4218
+ expiresAt: ts + cacheTtlMs
4219
+ };
4463
4220
  return answer;
4464
4221
  } catch (err) {
4465
4222
  if (failClosed) {
4466
- throw new Error(
4467
- `[nativePtQuoter] Chainlink unavailable in fail-closed mode: ${err.message}`
4468
- );
4223
+ throw new Error(`[nativePtQuoter] Chainlink unavailable in fail-closed mode: ${err.message}`);
4469
4224
  }
4470
4225
  console.warn("[nativePtQuoter] Chainlink unavailable, using fallback:", err.message);
4471
4226
  return BigInt(Math.round(fallbackEthPriceUsd * 1e8));
4472
4227
  }
4473
4228
  }
4229
+ __name(getEthPrice8dec, "getEthPrice8dec");
4474
4230
  async function getPtPerUsdt18dec() {
4475
4231
  const ts = now();
4476
4232
  if (ptPriceCache && ptPriceCache.expiresAt > ts) return ptPriceCache.value;
4477
4233
  try {
4478
4234
  const response = await fetchImpl(subgraphUrl, {
4479
4235
  method: "POST",
4480
- headers: { "Content-Type": "application/json" },
4236
+ headers: {
4237
+ "Content-Type": "application/json"
4238
+ },
4481
4239
  body: JSON.stringify({
4482
4240
  query: POOL_PRICE_QUERY,
4483
- variables: { id: pointTokenAddress.toLowerCase() }
4241
+ variables: {
4242
+ id: pointTokenAddress.toLowerCase()
4243
+ }
4484
4244
  })
4485
4245
  });
4486
4246
  if (!response.ok) throw new Error(`subgraph HTTP ${response.status}`);
@@ -4496,19 +4256,21 @@ function createNativePtQuoter(config) {
4496
4256
  const raw = parseBigDecimalTo18(ptPerUsdtStr);
4497
4257
  if (raw === 0n) throw new Error(`pool price parsed to zero: ${ptPerUsdtStr}`);
4498
4258
  const value = 10n ** 24n / raw;
4499
- ptPriceCache = { value, expiresAt: ts + cacheTtlMs };
4259
+ ptPriceCache = {
4260
+ value,
4261
+ expiresAt: ts + cacheTtlMs
4262
+ };
4500
4263
  return value;
4501
4264
  } catch (err) {
4502
4265
  if (failClosed) {
4503
- throw new Error(
4504
- `[nativePtQuoter] subgraph miss for ${pointTokenAddress} in fail-closed mode: ${err.message}`
4505
- );
4266
+ throw new Error(`[nativePtQuoter] subgraph miss for ${pointTokenAddress} in fail-closed mode: ${err.message}`);
4506
4267
  }
4507
4268
  console.warn("[nativePtQuoter] subgraph unavailable, using fallback:", err.message);
4508
4269
  const ptPerUsdtHuman = 1 / fallbackPtPriceUsdt;
4509
4270
  return parseBigDecimalTo18(ptPerUsdtHuman.toFixed(18));
4510
4271
  }
4511
4272
  }
4273
+ __name(getPtPerUsdt18dec, "getPtPerUsdt18dec");
4512
4274
  return async (amountNative) => {
4513
4275
  if (amountNative === 0n) return 0n;
4514
4276
  const [ethPrice8dec, ptPerUsdt18dec] = await Promise.all([
@@ -4518,12 +4280,14 @@ function createNativePtQuoter(config) {
4518
4280
  return amountNative * ethPrice8dec * ptPerUsdt18dec / 10n ** 26n;
4519
4281
  };
4520
4282
  }
4283
+ __name(createNativePtQuoter, "createNativePtQuoter");
4521
4284
  function parseBigDecimalTo18(s) {
4522
4285
  const SCALE = 18;
4523
4286
  const [whole = "0", frac = ""] = s.split(".");
4524
4287
  const padded = (frac + "0".repeat(SCALE)).slice(0, SCALE);
4525
4288
  return BigInt(whole + padded);
4526
4289
  }
4290
+ __name(parseBigDecimalTo18, "parseBigDecimalTo18");
4527
4291
 
4528
4292
  // src/pafi-backend/client.ts
4529
4293
  var import_core16 = require("@pafi-dev/core");
@@ -4531,15 +4295,24 @@ function extractPafiErrorFields(json, status) {
4531
4295
  const inner = typeof json.error === "object" && json.error !== null ? json.error : null;
4532
4296
  const code = inner?.code ?? json.code ?? "INTERNAL_ERROR";
4533
4297
  const message = inner?.message ?? json.message ?? `HTTP ${status}`;
4534
- return { code, message };
4298
+ return {
4299
+ code,
4300
+ message
4301
+ };
4535
4302
  }
4303
+ __name(extractPafiErrorFields, "extractPafiErrorFields");
4536
4304
  function serializeBigInt(_key, value) {
4537
4305
  return typeof value === "bigint" ? value.toString(10) : value;
4538
4306
  }
4307
+ __name(serializeBigInt, "serializeBigInt");
4539
4308
  function sleep(ms) {
4540
4309
  return new Promise((resolve) => setTimeout(resolve, ms));
4541
4310
  }
4311
+ __name(sleep, "sleep");
4542
4312
  var PafiBackendClient = class {
4313
+ static {
4314
+ __name(this, "PafiBackendClient");
4315
+ }
4543
4316
  config;
4544
4317
  baseUrl;
4545
4318
  constructor(config) {
@@ -4577,11 +4350,11 @@ var PafiBackendClient = class {
4577
4350
  throw lastError;
4578
4351
  }
4579
4352
  /**
4580
- * Fetch ERC-4337 UserOp receipt via PAFI's authenticated bundler proxy.
4581
- * Returns `null` when the bundler hasn't seen the userOp yet — caller
4582
- * should keep polling. Used by status endpoints to short-circuit the
4583
- * on-chain indexer when several PENDING locks share the same amount.
4584
- */
4353
+ * Fetch ERC-4337 UserOp receipt via PAFI's authenticated bundler proxy.
4354
+ * Returns `null` when the bundler hasn't seen the userOp yet — caller
4355
+ * should keep polling. Used by status endpoints to short-circuit the
4356
+ * on-chain indexer when several PENDING locks share the same amount.
4357
+ */
4585
4358
  async getUserOpReceipt(userOpHash) {
4586
4359
  const fetchFn = this.config.fetchImpl ?? fetch;
4587
4360
  const url = `${this.baseUrl}/bundler/receipt`;
@@ -4594,14 +4367,12 @@ var PafiBackendClient = class {
4594
4367
  Authorization: `Bearer ${this.config.apiKey}`,
4595
4368
  "X-Issuer-Id": this.config.issuerId
4596
4369
  },
4597
- body: JSON.stringify({ userOpHash })
4370
+ body: JSON.stringify({
4371
+ userOpHash
4372
+ })
4598
4373
  });
4599
4374
  } catch (err) {
4600
- throw new PafiBackendError(
4601
- "NETWORK_ERROR",
4602
- `Network error: ${err instanceof Error ? err.message : String(err)}`,
4603
- 0
4604
- );
4375
+ throw new PafiBackendError("NETWORK_ERROR", `Network error: ${err instanceof Error ? err.message : String(err)}`, 0);
4605
4376
  }
4606
4377
  const text = await response.text();
4607
4378
  let json = {};
@@ -4635,11 +4406,7 @@ var PafiBackendClient = class {
4635
4406
  body: JSON.stringify(request)
4636
4407
  });
4637
4408
  } catch (err) {
4638
- throw new PafiBackendError(
4639
- "NETWORK_ERROR",
4640
- `Network error: ${err instanceof Error ? err.message : String(err)}`,
4641
- 0
4642
- );
4409
+ throw new PafiBackendError("NETWORK_ERROR", `Network error: ${err instanceof Error ? err.message : String(err)}`, 0);
4643
4410
  }
4644
4411
  const text = await response.text();
4645
4412
  let json = {};
@@ -4651,7 +4418,9 @@ var PafiBackendClient = class {
4651
4418
  const { code, message } = extractPafiErrorFields(json, response.status);
4652
4419
  throw new PafiBackendError(code, message, response.status, json);
4653
4420
  }
4654
- return { userOpHash: json.userOpHash };
4421
+ return {
4422
+ userOpHash: json.userOpHash
4423
+ };
4655
4424
  }
4656
4425
  async _doRequest(request) {
4657
4426
  const fetchFn = this.config.fetchImpl ?? fetch;
@@ -4669,11 +4438,7 @@ var PafiBackendClient = class {
4669
4438
  body
4670
4439
  });
4671
4440
  } catch (err) {
4672
- throw new PafiBackendError(
4673
- "NETWORK_ERROR",
4674
- `Network error: ${err instanceof Error ? err.message : String(err)}`,
4675
- 0
4676
- );
4441
+ throw new PafiBackendError("NETWORK_ERROR", `Network error: ${err instanceof Error ? err.message : String(err)}`, 0);
4677
4442
  }
4678
4443
  const text = await response.text();
4679
4444
  let json = {};
@@ -4694,9 +4459,7 @@ var PafiBackendClient = class {
4694
4459
  return {
4695
4460
  paymaster: json.paymaster,
4696
4461
  paymasterData: json.paymasterData,
4697
- paymasterVerificationGasLimit: BigInt(
4698
- json.paymasterVerificationGasLimit
4699
- ),
4462
+ paymasterVerificationGasLimit: BigInt(json.paymasterVerificationGasLimit),
4700
4463
  paymasterPostOpGasLimit: BigInt(json.paymasterPostOpGasLimit),
4701
4464
  callGasLimit: json.callGasLimit != null ? BigInt(json.callGasLimit) : void 0,
4702
4465
  verificationGasLimit: json.verificationGasLimit != null ? BigInt(json.verificationGasLimit) : void 0,
@@ -4720,10 +4483,7 @@ function evaluateRedemption(input) {
4720
4483
  const cooldownUntilUnixSec = history.lastRedeemedAtUnixSec !== null ? history.lastRedeemedAtUnixSec + policy.cooldownSec : null;
4721
4484
  const inCooldown = cooldownUntilUnixSec !== null && cooldownUntilUnixSec > nowUnixSec;
4722
4485
  const activeBlackout = findActiveBlackout(policy.blackoutWindows, nowUnixSec);
4723
- const nextBlackoutEnd = nextBlackoutEndAfter(
4724
- policy.blackoutWindows,
4725
- nowUnixSec
4726
- );
4486
+ const nextBlackoutEnd = nextBlackoutEndAfter(policy.blackoutWindows, nowUnixSec);
4727
4487
  let availableAmountPt = 0n;
4728
4488
  if (!inCooldown && !activeBlackout) {
4729
4489
  const headroom = dailyRemaining < policy.perTxMaxPt ? dailyRemaining : policy.perTxMaxPt;
@@ -4740,7 +4500,11 @@ function evaluateRedemption(input) {
4740
4500
  policySource
4741
4501
  };
4742
4502
  if (amountPt <= 0n) {
4743
- return { allowed: false, preview, denial: rejectAmountBelowMin(policy) };
4503
+ return {
4504
+ allowed: false,
4505
+ preview,
4506
+ denial: rejectAmountBelowMin(policy)
4507
+ };
4744
4508
  }
4745
4509
  const denial = firstDenial({
4746
4510
  amountPt,
@@ -4750,25 +4514,29 @@ function evaluateRedemption(input) {
4750
4514
  cooldownUntilUnixSec,
4751
4515
  activeBlackout
4752
4516
  });
4753
- if (denial) return { allowed: false, denial, preview };
4754
- return { allowed: true, preview };
4517
+ if (denial) return {
4518
+ allowed: false,
4519
+ denial,
4520
+ preview
4521
+ };
4522
+ return {
4523
+ allowed: true,
4524
+ preview
4525
+ };
4755
4526
  }
4527
+ __name(evaluateRedemption, "evaluateRedemption");
4756
4528
  function firstDenial(args) {
4757
4529
  const { amountPt, policy, dailyRemaining, inCooldown, cooldownUntilUnixSec, activeBlackout } = args;
4758
4530
  if (activeBlackout) {
4759
4531
  return {
4760
4532
  code: "BLACKOUT_WINDOW",
4761
- message: `Redemption is blocked until ${new Date(
4762
- activeBlackout.endUnixSec * 1e3
4763
- ).toISOString()}${activeBlackout.reason ? ` (${activeBlackout.reason})` : ""}`
4533
+ message: `Redemption is blocked until ${new Date(activeBlackout.endUnixSec * 1e3).toISOString()}${activeBlackout.reason ? ` (${activeBlackout.reason})` : ""}`
4764
4534
  };
4765
4535
  }
4766
4536
  if (inCooldown && cooldownUntilUnixSec !== null) {
4767
4537
  return {
4768
4538
  code: "COOLDOWN_ACTIVE",
4769
- message: `Cooldown active until ${new Date(
4770
- cooldownUntilUnixSec * 1e3
4771
- ).toISOString()}`
4539
+ message: `Cooldown active until ${new Date(cooldownUntilUnixSec * 1e3).toISOString()}`
4772
4540
  };
4773
4541
  }
4774
4542
  if (amountPt < policy.perTxMinPt) {
@@ -4791,18 +4559,21 @@ function firstDenial(args) {
4791
4559
  }
4792
4560
  return null;
4793
4561
  }
4562
+ __name(firstDenial, "firstDenial");
4794
4563
  function rejectAmountBelowMin(policy) {
4795
4564
  return {
4796
4565
  code: "AMOUNT_BELOW_MIN",
4797
4566
  message: `amount must be >= ${policy.perTxMinPt}`
4798
4567
  };
4799
4568
  }
4569
+ __name(rejectAmountBelowMin, "rejectAmountBelowMin");
4800
4570
  function findActiveBlackout(windows, nowUnixSec) {
4801
4571
  for (const w of windows) {
4802
4572
  if (w.startUnixSec <= nowUnixSec && nowUnixSec < w.endUnixSec) return w;
4803
4573
  }
4804
4574
  return null;
4805
4575
  }
4576
+ __name(findActiveBlackout, "findActiveBlackout");
4806
4577
  function nextBlackoutEndAfter(windows, nowUnixSec) {
4807
4578
  let earliest = null;
4808
4579
  for (const w of windows) {
@@ -4812,6 +4583,7 @@ function nextBlackoutEndAfter(windows, nowUnixSec) {
4812
4583
  }
4813
4584
  return earliest;
4814
4585
  }
4586
+ __name(nextBlackoutEndAfter, "nextBlackoutEndAfter");
4815
4587
  var REDEMPTION_HISTORY_WINDOW_SEC = SECONDS_PER_DAY;
4816
4588
 
4817
4589
  // src/redemption/policyProvider.ts
@@ -4821,6 +4593,9 @@ var import_core18 = require("@pafi-dev/core");
4821
4593
  var import_core17 = require("@pafi-dev/core");
4822
4594
  var DEFAULT_TIMEOUT_MS = 1e3;
4823
4595
  var SettlementClient = class {
4596
+ static {
4597
+ __name(this, "SettlementClient");
4598
+ }
4824
4599
  config;
4825
4600
  constructor(config) {
4826
4601
  if (!config.chainId) throw new Error("SettlementClient: chainId is required");
@@ -4840,10 +4615,7 @@ var SettlementClient = class {
4840
4615
  const fetchFn = this.config.fetchImpl ?? fetch;
4841
4616
  const url = `${this.config.baseUrl}/issuers/${encodeURIComponent(this.config.issuerId)}/redemption-policy`;
4842
4617
  const controller = new AbortController();
4843
- const timer = setTimeout(
4844
- () => controller.abort(),
4845
- this.config.fetchTimeoutMs
4846
- );
4618
+ const timer = setTimeout(() => controller.abort(), this.config.fetchTimeoutMs);
4847
4619
  let response;
4848
4620
  try {
4849
4621
  response = await fetchFn(url, {
@@ -4857,30 +4629,56 @@ var SettlementClient = class {
4857
4629
  });
4858
4630
  } catch (err) {
4859
4631
  const isAbort = err instanceof Error && (err.name === "AbortError" || /aborted|timeout/i.test(err.message ?? ""));
4860
- return { ok: false, reason: isAbort ? "TIMEOUT" : "NETWORK" };
4632
+ return {
4633
+ ok: false,
4634
+ reason: isAbort ? "TIMEOUT" : "NETWORK"
4635
+ };
4861
4636
  } finally {
4862
4637
  clearTimeout(timer);
4863
4638
  }
4864
4639
  if (response.status === 404) {
4865
- return { ok: false, reason: "NOT_FOUND", status: 404 };
4640
+ return {
4641
+ ok: false,
4642
+ reason: "NOT_FOUND",
4643
+ status: 404
4644
+ };
4866
4645
  }
4867
4646
  if (response.status === 401 || response.status === 403) {
4868
- return { ok: false, reason: "UNAUTHORIZED", status: response.status };
4647
+ return {
4648
+ ok: false,
4649
+ reason: "UNAUTHORIZED",
4650
+ status: response.status
4651
+ };
4869
4652
  }
4870
4653
  if (!response.ok) {
4871
- return { ok: false, reason: "SERVER_ERROR", status: response.status };
4654
+ return {
4655
+ ok: false,
4656
+ reason: "SERVER_ERROR",
4657
+ status: response.status
4658
+ };
4872
4659
  }
4873
4660
  let raw;
4874
4661
  try {
4875
4662
  raw = await response.json();
4876
4663
  } catch {
4877
- return { ok: false, reason: "INVALID_RESPONSE", status: response.status };
4664
+ return {
4665
+ ok: false,
4666
+ reason: "INVALID_RESPONSE",
4667
+ status: response.status
4668
+ };
4878
4669
  }
4879
4670
  const parsed = parsePolicyDto(raw);
4880
4671
  if (!parsed) {
4881
- return { ok: false, reason: "INVALID_RESPONSE", status: response.status };
4672
+ return {
4673
+ ok: false,
4674
+ reason: "INVALID_RESPONSE",
4675
+ status: response.status
4676
+ };
4882
4677
  }
4883
- return { ok: true, policy: parsed };
4678
+ return {
4679
+ ok: true,
4680
+ policy: parsed
4681
+ };
4884
4682
  }
4885
4683
  };
4886
4684
  function parsePolicyDto(raw) {
@@ -4903,6 +4701,7 @@ function parsePolicyDto(raw) {
4903
4701
  return null;
4904
4702
  }
4905
4703
  }
4704
+ __name(parsePolicyDto, "parsePolicyDto");
4906
4705
  function normalizeBlackout(raw) {
4907
4706
  if (!raw || typeof raw !== "object") return null;
4908
4707
  const win = raw;
@@ -4915,6 +4714,7 @@ function normalizeBlackout(raw) {
4915
4714
  reason: typeof win.reason === "string" ? win.reason : void 0
4916
4715
  };
4917
4716
  }
4717
+ __name(normalizeBlackout, "normalizeBlackout");
4918
4718
 
4919
4719
  // src/redemption/defaults.ts
4920
4720
  var PT_DECIMALS = 10n ** 18n;
@@ -4928,23 +4728,34 @@ var DEFAULT_REDEMPTION_POLICY = {
4928
4728
  version: "default-v1"
4929
4729
  };
4930
4730
  function defaultPolicyFor(issuerId) {
4931
- return { ...DEFAULT_REDEMPTION_POLICY, issuerId };
4731
+ return {
4732
+ ...DEFAULT_REDEMPTION_POLICY,
4733
+ issuerId
4734
+ };
4932
4735
  }
4736
+ __name(defaultPolicyFor, "defaultPolicyFor");
4933
4737
 
4934
4738
  // src/redemption/policyProvider.ts
4935
4739
  var DEFAULT_CACHE_TTL_MS3 = 5 * 60 * 1e3;
4936
4740
  var PolicyProviderUnavailableError = class extends import_core18.PafiSdkError {
4741
+ static {
4742
+ __name(this, "PolicyProviderUnavailableError");
4743
+ }
4937
4744
  code = "POLICY_PROVIDER_UNAVAILABLE";
4938
4745
  httpStatus = "service_unavailable";
4939
4746
  details;
4940
4747
  constructor(issuerId, reason) {
4941
- super(
4942
- `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.`
4943
- );
4944
- this.details = { issuerId, reason };
4748
+ super(`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.`);
4749
+ this.details = {
4750
+ issuerId,
4751
+ reason
4752
+ };
4945
4753
  }
4946
4754
  };
4947
4755
  var PolicyProvider = class {
4756
+ static {
4757
+ __name(this, "PolicyProvider");
4758
+ }
4948
4759
  client;
4949
4760
  issuerId;
4950
4761
  cacheTtlMs;
@@ -4963,7 +4774,10 @@ var PolicyProvider = class {
4963
4774
  }
4964
4775
  async getPolicy() {
4965
4776
  const fresh = this.readCache();
4966
- if (fresh) return { policy: fresh, source: "cache" };
4777
+ if (fresh) return {
4778
+ policy: fresh,
4779
+ source: "cache"
4780
+ };
4967
4781
  if (this.inflight) return this.inflight;
4968
4782
  this.inflight = this.fetchAndStore().finally(() => {
4969
4783
  this.inflight = null;
@@ -4989,19 +4803,22 @@ var PolicyProvider = class {
4989
4803
  policy: result.policy,
4990
4804
  expiresAtMs: this.now() + this.cacheTtlMs
4991
4805
  };
4992
- return { policy: result.policy, source: "settlement" };
4806
+ return {
4807
+ policy: result.policy,
4808
+ source: "settlement"
4809
+ };
4993
4810
  }
4994
4811
  const reason = "reason" in result && typeof result.reason === "string" ? result.reason : "unknown";
4995
4812
  if (this.onFetchFailure === "permissive-default") {
4996
- this.onWarning?.(
4997
- "PolicyProvider: settlement-api unreachable, falling back to permissive default. Pre-flight redeem limit is DEGRADED until settlement-api recovers.",
4998
- {
4999
- event: "policy_provider_fallback",
5000
- issuerId: this.issuerId,
5001
- reason
5002
- }
5003
- );
5004
- return { policy: defaultPolicyFor(this.issuerId), source: "default" };
4813
+ this.onWarning?.("PolicyProvider: settlement-api unreachable, falling back to permissive default. Pre-flight redeem limit is DEGRADED until settlement-api recovers.", {
4814
+ event: "policy_provider_fallback",
4815
+ issuerId: this.issuerId,
4816
+ reason
4817
+ });
4818
+ return {
4819
+ policy: defaultPolicyFor(this.issuerId),
4820
+ source: "default"
4821
+ };
5005
4822
  }
5006
4823
  throw new PolicyProviderUnavailableError(this.issuerId, reason);
5007
4824
  }
@@ -5009,6 +4826,9 @@ var PolicyProvider = class {
5009
4826
 
5010
4827
  // src/redemption/service.ts
5011
4828
  var RedemptionService = class {
4829
+ static {
4830
+ __name(this, "RedemptionService");
4831
+ }
5012
4832
  policyProvider;
5013
4833
  historyStore;
5014
4834
  nowUnixSec;
@@ -5025,17 +4845,16 @@ var RedemptionService = class {
5025
4845
  const { policy, source } = await this.policyProvider.getPolicy();
5026
4846
  const now = this.nowUnixSec();
5027
4847
  const [redeemedLast24hPt, lastRedeemedAtUnixSec] = await Promise.all([
5028
- this.historyStore.sumRedeemedSince(
5029
- user,
5030
- now - REDEMPTION_HISTORY_WINDOW_SEC,
5031
- pointTokenAddress
5032
- ),
4848
+ this.historyStore.sumRedeemedSince(user, now - REDEMPTION_HISTORY_WINDOW_SEC, pointTokenAddress),
5033
4849
  this.historyStore.getLastRedeemedAtUnixSec(user, pointTokenAddress)
5034
4850
  ]);
5035
4851
  return evaluateRedemption({
5036
4852
  policy,
5037
4853
  policySource: source,
5038
- history: { redeemedLast24hPt, lastRedeemedAtUnixSec },
4854
+ history: {
4855
+ redeemedLast24hPt,
4856
+ lastRedeemedAtUnixSec
4857
+ },
5039
4858
  amountPt,
5040
4859
  nowUnixSec: now
5041
4860
  });
@@ -5062,16 +4881,18 @@ async function createIssuerService(config) {
5062
4881
  if (!config.auth?.domain) {
5063
4882
  throw new Error("createIssuerService: auth.domain is required");
5064
4883
  }
5065
- const rawAddresses = config.pointTokenAddresses && config.pointTokenAddresses.length > 0 ? config.pointTokenAddresses : config.pointTokenAddress ? [config.pointTokenAddress] : [];
4884
+ const rawAddresses = config.pointTokenAddresses && config.pointTokenAddresses.length > 0 ? config.pointTokenAddresses : config.pointTokenAddress ? [
4885
+ config.pointTokenAddress
4886
+ ] : [];
5066
4887
  if (rawAddresses.length === 0) {
5067
- throw new Error(
5068
- "createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
5069
- );
4888
+ throw new Error("createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required");
5070
4889
  }
5071
4890
  const tokenAddresses = rawAddresses.map((a) => (0, import_viem15.getAddress)(a));
5072
4891
  const ledger = config.ledger;
5073
4892
  const sessionStore = config.sessionStore ?? new MemorySessionStore();
5074
- const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
4893
+ const policy = config.policy ?? new DefaultPolicyEngine({
4894
+ ledger
4895
+ });
5075
4896
  const authServiceConfig = {
5076
4897
  sessionStore,
5077
4898
  jwtSecret: config.auth.jwtSecret,
@@ -5099,9 +4920,7 @@ async function createIssuerService(config) {
5099
4920
  const baseCursorStore = config.indexer?.cursorStore;
5100
4921
  const sharedCursorWithMultipleTokens = baseCursorStore !== void 0 && typeof baseCursorStore.forKey !== "function" && tokenAddresses.length > 1;
5101
4922
  if (sharedCursorWithMultipleTokens) {
5102
- console.warn(
5103
- `[@pafi-dev/issuer] cursorStore lacks forKey() and ${tokenAddresses.length} PointTokens are configured. All PointIndexers will share one cursor row, causing token-skipping. Implement IIndexerCursorStore.forKey to return per-token derived stores. This permissive path will be removed in a future major release.`
5104
- );
4923
+ console.warn(`[@pafi-dev/issuer] cursorStore lacks forKey() and ${tokenAddresses.length} PointTokens are configured. All PointIndexers will share one cursor row, causing token-skipping. Implement IIndexerCursorStore.forKey to return per-token derived stores. This permissive path will be removed in a future major release.`);
5105
4924
  }
5106
4925
  const indexers = /* @__PURE__ */ new Map();
5107
4926
  for (const tokenAddress of tokenAddresses) {
@@ -5117,9 +4936,7 @@ async function createIssuerService(config) {
5117
4936
  indexerConfig.fromBlock = config.indexer.fromBlock;
5118
4937
  }
5119
4938
  if (baseCursorStore) {
5120
- indexerConfig.cursorStore = typeof baseCursorStore.forKey === "function" ? baseCursorStore.forKey(
5121
- `point-indexer:${tokenAddress.toLowerCase()}`
5122
- ) : baseCursorStore;
4939
+ indexerConfig.cursorStore = typeof baseCursorStore.forKey === "function" ? baseCursorStore.forKey(`point-indexer:${tokenAddress.toLowerCase()}`) : baseCursorStore;
5123
4940
  }
5124
4941
  if (config.indexer?.confirmations !== void 0) {
5125
4942
  indexerConfig.confirmations = config.indexer.confirmations;
@@ -5190,9 +5007,7 @@ async function createIssuerService(config) {
5190
5007
  if (config.indexer?.autoStart) {
5191
5008
  const lock = config.indexer.singletonLock;
5192
5009
  if (!lock) {
5193
- console.warn(
5194
- "[@pafi-dev/issuer] indexer.autoStart=true without singletonLock \u2014 this is UNSAFE in multi-replica deployments. Either set replicas=1 + INDEXER_AUTOSTART=false on non-leader pods, or pass `singletonLock: makePostgresSingletonLock(dataSource)`. This permissive path will be removed in a future major release."
5195
- );
5010
+ console.warn("[@pafi-dev/issuer] indexer.autoStart=true without singletonLock \u2014 this is UNSAFE in multi-replica deployments. Either set replicas=1 + INDEXER_AUTOSTART=false on non-leader pods, or pass `singletonLock: makePostgresSingletonLock(dataSource)`. This permissive path will be removed in a future major release.");
5196
5011
  for (const idx of indexers.values()) {
5197
5012
  idx.start();
5198
5013
  }
@@ -5221,35 +5036,39 @@ async function createIssuerService(config) {
5221
5036
  redemption
5222
5037
  };
5223
5038
  }
5039
+ __name(createIssuerService, "createIssuerService");
5224
5040
 
5225
5041
  // src/issuer-state/validator.ts
5226
5042
  var import_viem16 = require("viem");
5227
5043
  var import_core20 = require("@pafi-dev/core");
5228
5044
  var ISSUER_RECORD_TTL_MS = 1e4;
5229
5045
  var IssuerStateValidator = class _IssuerStateValidator {
5230
- constructor(provider, registryAddress) {
5231
- this.provider = provider;
5232
- this.registryAddress = registryAddress;
5046
+ static {
5047
+ __name(this, "IssuerStateValidator");
5233
5048
  }
5234
5049
  provider;
5235
5050
  registryAddress;
5236
5051
  pointTokenIssuerCache = /* @__PURE__ */ new Map();
5237
5052
  stateCache = /* @__PURE__ */ new Map();
5238
5053
  inflight = /* @__PURE__ */ new Map();
5054
+ constructor(provider, registryAddress) {
5055
+ this.provider = provider;
5056
+ this.registryAddress = registryAddress;
5057
+ }
5239
5058
  /**
5240
- * Convenience factory — reads `registryAddress` from the SDK
5241
- * `CONTRACT_ADDRESSES` map for the given chain.
5242
- */
5059
+ * Convenience factory — reads `registryAddress` from the SDK
5060
+ * `CONTRACT_ADDRESSES` map for the given chain.
5061
+ */
5243
5062
  static forChain(provider, chainId) {
5244
5063
  const { issuerRegistry } = (0, import_core20.getContractAddresses)(chainId);
5245
5064
  return new _IssuerStateValidator(provider, issuerRegistry);
5246
5065
  }
5247
5066
  /**
5248
- * Invalidate cached state for one PointToken, or everything if omitted.
5249
- * Call after admin txs that change registry or cap settings — closes
5250
- * the split-brain window described
5251
- * passive TTL. Idempotent: safe to call when no entry exists.
5252
- */
5067
+ * Invalidate cached state for one PointToken, or everything if omitted.
5068
+ * Call after admin txs that change registry or cap settings — closes
5069
+ * the split-brain window described
5070
+ * passive TTL. Idempotent: safe to call when no entry exists.
5071
+ */
5253
5072
  invalidate(pointToken) {
5254
5073
  if (pointToken) {
5255
5074
  const key = (0, import_viem16.getAddress)(pointToken);
@@ -5263,9 +5082,9 @@ var IssuerStateValidator = class _IssuerStateValidator {
5263
5082
  }
5264
5083
  }
5265
5084
  /**
5266
- * Resolve `PointToken.issuer()` once per token and memoize.
5267
- * The issuer field is set at `initialize()` and never changes.
5268
- */
5085
+ * Resolve `PointToken.issuer()` once per token and memoize.
5086
+ * The issuer field is set at `initialize()` and never changes.
5087
+ */
5269
5088
  async getIssuerAddressForPointToken(pointToken) {
5270
5089
  const key = (0, import_viem16.getAddress)(pointToken);
5271
5090
  const cached = this.pointTokenIssuerCache.get(key);
@@ -5279,9 +5098,9 @@ var IssuerStateValidator = class _IssuerStateValidator {
5279
5098
  return (0, import_viem16.getAddress)(issuer);
5280
5099
  }
5281
5100
  /**
5282
- * Read registry record + totalSupply, with 30s cache and in-flight
5283
- * deduplication. Does NOT throw on inactive/missing — returns raw state.
5284
- */
5101
+ * Read registry record + totalSupply, with 30s cache and in-flight
5102
+ * deduplication. Does NOT throw on inactive/missing — returns raw state.
5103
+ */
5285
5104
  async getIssuerState(pointToken) {
5286
5105
  const tokenAddr = (0, import_viem16.getAddress)(pointToken);
5287
5106
  const now = Date.now();
@@ -5302,49 +5121,41 @@ var IssuerStateValidator = class _IssuerStateValidator {
5302
5121
  return promise;
5303
5122
  }
5304
5123
  /**
5305
- * Validate that `amount` PT can be minted on `pointToken` right now.
5306
- *
5307
- * Throws `IssuerStateError` with:
5308
- * - `ISSUER_NOT_REGISTERED` — registry has no record for this issuer
5309
- * - `ISSUER_INACTIVE` — issuer.active is false
5310
- * - `MINT_CAP_EXCEEDED` — totalSupply + amount would exceed hardCap
5311
- *
5312
- * Returns the fetched state on success so callers can log without a
5313
- * second RPC round-trip.
5314
- */
5124
+ * Validate that `amount` PT can be minted on `pointToken` right now.
5125
+ *
5126
+ * Throws `IssuerStateError` with:
5127
+ * - `ISSUER_NOT_REGISTERED` — registry has no record for this issuer
5128
+ * - `ISSUER_INACTIVE` — issuer.active is false
5129
+ * - `MINT_CAP_EXCEEDED` — totalSupply + amount would exceed hardCap
5130
+ *
5131
+ * Returns the fetched state on success so callers can log without a
5132
+ * second RPC round-trip.
5133
+ */
5315
5134
  async preValidateMint(pointToken, amount) {
5316
5135
  let state;
5317
5136
  try {
5318
5137
  state = await this.getIssuerState(pointToken);
5319
5138
  } catch (err) {
5320
5139
  if (err.message.includes("IssuerNotFound")) {
5321
- throw new IssuerStateError(
5322
- "ISSUER_NOT_REGISTERED",
5323
- `IssuerRegistry has no record for PointToken ${pointToken}`,
5324
- { pointToken }
5325
- );
5140
+ throw new IssuerStateError("ISSUER_NOT_REGISTERED", `IssuerRegistry has no record for PointToken ${pointToken}`, {
5141
+ pointToken
5142
+ });
5326
5143
  }
5327
5144
  throw err;
5328
5145
  }
5329
5146
  const { issuer, equityCap, equitySupply, remaining } = state;
5330
5147
  if (!issuer.active) {
5331
- throw new IssuerStateError(
5332
- "ISSUER_INACTIVE",
5333
- `Issuer "${issuer.name}" is deactivated on IssuerRegistry`,
5334
- { pointToken }
5335
- );
5148
+ throw new IssuerStateError("ISSUER_INACTIVE", `Issuer "${issuer.name}" is deactivated on IssuerRegistry`, {
5149
+ pointToken
5150
+ });
5336
5151
  }
5337
5152
  if (equitySupply + amount > equityCap.hardCap) {
5338
- throw new IssuerStateError(
5339
- "MINT_CAP_EXCEEDED",
5340
- `Requested ${amount} PT would exceed EQUITY mint cap. Cap=${equityCap.hardCap}, equityMinted=${equitySupply}, remaining=${remaining}`,
5341
- {
5342
- requested: amount.toString(),
5343
- cap: equityCap.hardCap.toString(),
5344
- equityMinted: equitySupply.toString(),
5345
- remaining: remaining.toString()
5346
- }
5347
- );
5153
+ throw new IssuerStateError("MINT_CAP_EXCEEDED", `Requested ${amount} PT would exceed EQUITY mint cap. Cap=${equityCap.hardCap}, equityMinted=${equitySupply}, remaining=${remaining}`, {
5154
+ requested: amount.toString(),
5155
+ cap: equityCap.hardCap.toString(),
5156
+ equityMinted: equitySupply.toString(),
5157
+ remaining: remaining.toString()
5158
+ });
5348
5159
  }
5349
5160
  return state;
5350
5161
  }
@@ -5354,7 +5165,9 @@ var IssuerStateValidator = class _IssuerStateValidator {
5354
5165
  address: this.registryAddress,
5355
5166
  abi: import_core20.issuerRegistryAbi,
5356
5167
  functionName: "getIssuer",
5357
- args: [issuerAddr]
5168
+ args: [
5169
+ issuerAddr
5170
+ ]
5358
5171
  });
5359
5172
  const issuer = {
5360
5173
  signerAddress: issuerStruct.signerAddress,
@@ -5386,6 +5199,9 @@ var IssuerStateValidator = class _IssuerStateValidator {
5386
5199
 
5387
5200
  // src/redemption/memoryHistoryStore.ts
5388
5201
  var MemoryRedemptionHistoryStore = class {
5202
+ static {
5203
+ __name(this, "MemoryRedemptionHistoryStore");
5204
+ }
5389
5205
  entries = [];
5390
5206
  async sumRedeemedSince(user, sinceUnixSec, pointTokenAddress) {
5391
5207
  const userKey = user.toLowerCase();
@@ -5421,7 +5237,7 @@ var MemoryRedemptionHistoryStore = class {
5421
5237
  };
5422
5238
 
5423
5239
  // src/index.ts
5424
- var PAFI_ISSUER_SDK_VERSION = true ? "0.39.2" : "dev";
5240
+ var PAFI_ISSUER_SDK_VERSION = true ? "0.39.3" : "dev";
5425
5241
  // Annotate the CommonJS export names for ESM import in node:
5426
5242
  0 && (module.exports = {
5427
5243
  AdapterMisconfiguredError,