@pafi-dev/issuer 0.24.1 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1465,7 +1465,6 @@ interface ApiUserRequest {
1465
1465
  pointTokenAddress: Address;
1466
1466
  }
1467
1467
  interface ApiUserResponse {
1468
- mintRequestNonce: bigint;
1469
1468
  /**
1470
1469
  * Off-chain point balance from the issuer's ledger (excludes PENDING locks).
1471
1470
  * This is what the user can claim into on-chain PT via `/claim`.
@@ -2695,7 +2694,7 @@ interface IssuerStateValidatorLike {
2695
2694
  * own composer — gg56 uses a timestamp-key 2D nonce). Caller layers
2696
2695
  * paymaster sponsorship + sponsorAuth on top of the returned UserOps.
2697
2696
  */
2698
- type PTClaimErrorCode = "INVALID_AMOUNT" | "VALIDATION_FAILED" | "BUILD_FAILED";
2697
+ type PTClaimErrorCode = "INVALID_AMOUNT" | "VALIDATION_FAILED" | "BUILD_FAILED" | "NONCE_READ_FAILED" | "NONCE_IN_FLIGHT";
2699
2698
  declare class PTClaimError extends PafiSdkError {
2700
2699
  readonly httpStatus: "unprocessable";
2701
2700
  readonly code: PTClaimErrorCode;
@@ -2752,8 +2751,6 @@ interface PTClaimRequest {
2752
2751
  chainId: number;
2753
2752
  /** ERC-4337 account nonce for the user's EOA. */
2754
2753
  aaNonce: bigint;
2755
- /** Current `mintRequestNonces[userAddress]` from PointToken. */
2756
- mintRequestNonce: bigint;
2757
2754
  }
2758
2755
  interface PTClaimResponse {
2759
2756
  /** Sponsored UserOp — mint + PT fee transfer (when feeAmount > 0). */
@@ -2774,6 +2771,7 @@ interface PTClaimResponse {
2774
2771
  }
2775
2772
  declare class PTClaimHandler {
2776
2773
  private readonly cfg;
2774
+ private readonly inFlightNonces;
2777
2775
  constructor(config: PTClaimHandlerConfig);
2778
2776
  handle(request: PTClaimRequest): Promise<PTClaimResponse>;
2779
2777
  }
@@ -3187,7 +3185,6 @@ interface PoolsDto {
3187
3185
  pools: unknown[];
3188
3186
  }
3189
3187
  interface UserDto {
3190
- mintRequestNonce: string;
3191
3188
  offChainBalance: string;
3192
3189
  onChainBalance: string;
3193
3190
  totalBalance: string;
@@ -3305,7 +3302,6 @@ declare class IssuerApiAdapter {
3305
3302
  pointTokenAddress: Address;
3306
3303
  amount: bigint;
3307
3304
  aaNonce: bigint;
3308
- mintRequestNonce: bigint;
3309
3305
  }): Promise<ClaimDto>;
3310
3306
  redeem(input: {
3311
3307
  authenticatedAddress: Address;
@@ -3327,7 +3323,6 @@ declare class IssuerApiAdapter {
3327
3323
  pointTokenAddress: Address;
3328
3324
  amount: bigint;
3329
3325
  aaNonce: bigint;
3330
- mintRequestNonce: bigint;
3331
3326
  }): Promise<MobilePrepareDto>;
3332
3327
  claimSubmit(input: {
3333
3328
  authenticatedAddress: Address;
package/dist/index.d.ts CHANGED
@@ -1465,7 +1465,6 @@ interface ApiUserRequest {
1465
1465
  pointTokenAddress: Address;
1466
1466
  }
1467
1467
  interface ApiUserResponse {
1468
- mintRequestNonce: bigint;
1469
1468
  /**
1470
1469
  * Off-chain point balance from the issuer's ledger (excludes PENDING locks).
1471
1470
  * This is what the user can claim into on-chain PT via `/claim`.
@@ -2695,7 +2694,7 @@ interface IssuerStateValidatorLike {
2695
2694
  * own composer — gg56 uses a timestamp-key 2D nonce). Caller layers
2696
2695
  * paymaster sponsorship + sponsorAuth on top of the returned UserOps.
2697
2696
  */
2698
- type PTClaimErrorCode = "INVALID_AMOUNT" | "VALIDATION_FAILED" | "BUILD_FAILED";
2697
+ type PTClaimErrorCode = "INVALID_AMOUNT" | "VALIDATION_FAILED" | "BUILD_FAILED" | "NONCE_READ_FAILED" | "NONCE_IN_FLIGHT";
2699
2698
  declare class PTClaimError extends PafiSdkError {
2700
2699
  readonly httpStatus: "unprocessable";
2701
2700
  readonly code: PTClaimErrorCode;
@@ -2752,8 +2751,6 @@ interface PTClaimRequest {
2752
2751
  chainId: number;
2753
2752
  /** ERC-4337 account nonce for the user's EOA. */
2754
2753
  aaNonce: bigint;
2755
- /** Current `mintRequestNonces[userAddress]` from PointToken. */
2756
- mintRequestNonce: bigint;
2757
2754
  }
2758
2755
  interface PTClaimResponse {
2759
2756
  /** Sponsored UserOp — mint + PT fee transfer (when feeAmount > 0). */
@@ -2774,6 +2771,7 @@ interface PTClaimResponse {
2774
2771
  }
2775
2772
  declare class PTClaimHandler {
2776
2773
  private readonly cfg;
2774
+ private readonly inFlightNonces;
2777
2775
  constructor(config: PTClaimHandlerConfig);
2778
2776
  handle(request: PTClaimRequest): Promise<PTClaimResponse>;
2779
2777
  }
@@ -3187,7 +3185,6 @@ interface PoolsDto {
3187
3185
  pools: unknown[];
3188
3186
  }
3189
3187
  interface UserDto {
3190
- mintRequestNonce: string;
3191
3188
  offChainBalance: string;
3192
3189
  onChainBalance: string;
3193
3190
  totalBalance: string;
@@ -3305,7 +3302,6 @@ declare class IssuerApiAdapter {
3305
3302
  pointTokenAddress: Address;
3306
3303
  amount: bigint;
3307
3304
  aaNonce: bigint;
3308
- mintRequestNonce: bigint;
3309
3305
  }): Promise<ClaimDto>;
3310
3306
  redeem(input: {
3311
3307
  authenticatedAddress: Address;
@@ -3327,7 +3323,6 @@ declare class IssuerApiAdapter {
3327
3323
  pointTokenAddress: Address;
3328
3324
  amount: bigint;
3329
3325
  aaNonce: bigint;
3330
- mintRequestNonce: bigint;
3331
3326
  }): Promise<MobilePrepareDto>;
3332
3327
  claimSubmit(input: {
3333
3328
  authenticatedAddress: Address;
package/dist/index.js CHANGED
@@ -1665,7 +1665,6 @@ function hashKeyToInt64(key) {
1665
1665
  import { getAddress as getAddress5 } from "viem";
1666
1666
  import {
1667
1667
  getMintFeeBps,
1668
- getMintRequestNonce,
1669
1668
  getPointTokenBalance,
1670
1669
  isMinter
1671
1670
  } from "@pafi-dev/core";
@@ -1937,14 +1936,12 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
1937
1936
  { requested: pointToken }
1938
1937
  );
1939
1938
  }
1940
- const [mintRequestNonce, offChainBalance, onChainBalance, minter] = await Promise.all([
1941
- getMintRequestNonce(this.provider, pointToken, normalizedAuthed),
1939
+ const [offChainBalance, onChainBalance, minter] = await Promise.all([
1942
1940
  this.ledger.getBalance(normalizedAuthed, pointToken),
1943
1941
  getPointTokenBalance(this.provider, pointToken, normalizedAuthed),
1944
1942
  isMinter(this.provider, pointToken, normalizedAuthed)
1945
1943
  ]);
1946
1944
  return {
1947
- mintRequestNonce,
1948
1945
  offChainBalance,
1949
1946
  onChainBalance,
1950
1947
  totalBalance: offChainBalance + onChainBalance,
@@ -2087,7 +2084,8 @@ import {
2087
2084
  Source as Source2
2088
2085
  } from "@pafi-dev/core";
2089
2086
  var DEFAULT_REDEEM_LOCK_MS = 15 * 60 * 1e3;
2090
- var DEFAULT_SIG_DEADLINE_SEC = 15 * 60;
2087
+ var M11_SAFETY_MARGIN_MS = 30 * 1e3;
2088
+ var DEFAULT_SIG_DEADLINE_SEC = (DEFAULT_REDEEM_LOCK_MS - M11_SAFETY_MARGIN_MS) / 1e3;
2091
2089
  var PTRedeemError = class extends PafiSdkError {
2092
2090
  httpStatus = "unprocessable";
2093
2091
  code;
@@ -2154,6 +2152,13 @@ var PTRedeemHandler = class {
2154
2152
  this.redeemLockDurationMs = config.redeemLockDurationMs ?? DEFAULT_REDEEM_LOCK_MS;
2155
2153
  this.signatureDeadlineSeconds = config.signatureDeadlineSeconds ?? DEFAULT_SIG_DEADLINE_SEC;
2156
2154
  this.now = config.now ?? (() => Date.now());
2155
+ const maxAllowedSignatureMs = this.redeemLockDurationMs - M11_SAFETY_MARGIN_MS;
2156
+ if (this.signatureDeadlineSeconds * 1e3 > maxAllowedSignatureMs) {
2157
+ throw new PTRedeemError(
2158
+ "INVALID_AMOUNT",
2159
+ `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). See audit M-11.`
2160
+ );
2161
+ }
2157
2162
  if (config.redemptionService) {
2158
2163
  this.redemptionService = config.redemptionService;
2159
2164
  }
@@ -2219,8 +2224,14 @@ var PTRedeemHandler = class {
2219
2224
  }
2220
2225
  }
2221
2226
  async _handleAfterNonceLock(request, burnNonce, pointTokenAddress) {
2227
+ const referenceMs = this.now();
2228
+ const projectedLockExpiresAtMs = referenceMs + this.redeemLockDurationMs;
2229
+ const requestedDeadlineSec = Math.floor(referenceMs / 1e3) + this.signatureDeadlineSeconds;
2230
+ const lockBoundedDeadlineSec = Math.floor(
2231
+ (projectedLockExpiresAtMs - M11_SAFETY_MARGIN_MS) / 1e3
2232
+ );
2222
2233
  const previewDeadline = BigInt(
2223
- Math.floor(this.now() / 1e3) + this.signatureDeadlineSeconds
2234
+ Math.min(requestedDeadlineSec, lockBoundedDeadlineSec)
2224
2235
  );
2225
2236
  let fee;
2226
2237
  if (request.feeAmount !== void 0) {
@@ -2228,7 +2239,7 @@ var PTRedeemHandler = class {
2228
2239
  } else if (this.feeService) {
2229
2240
  const previewUserOp = this.relayService.previewBurnUserOp({
2230
2241
  userAddress: request.userAddress,
2231
- aaNonce: burnNonce,
2242
+ aaNonce: request.aaNonce,
2232
2243
  pointTokenAddress,
2233
2244
  amount: request.amount,
2234
2245
  deadline: previewDeadline
@@ -2854,6 +2865,7 @@ async function handleMobileSubmit(params) {
2854
2865
  // src/api/handlers/ptClaimHandler.ts
2855
2866
  import { getAddress as getAddress9 } from "viem";
2856
2867
  import {
2868
+ POINT_TOKEN_ABI as POINT_TOKEN_ABI2,
2857
2869
  decodeBatchExecuteCalls,
2858
2870
  getContractAddresses as getContractAddresses3
2859
2871
  } from "@pafi-dev/core";
@@ -2889,14 +2901,30 @@ function isNoWrapper2(address) {
2889
2901
  return lower === "0x0000000000000000000000000000000000000000" || lower === "0x000000000000000000000000000000000000dead";
2890
2902
  }
2891
2903
  var DEFAULT_LOCK_MS = 15 * 60 * 1e3;
2892
- var DEFAULT_SIG_DEADLINE_SEC2 = 15 * 60;
2904
+ var M11_SAFETY_MARGIN_MS2 = 30 * 1e3;
2905
+ var DEFAULT_SIG_DEADLINE_SEC2 = (DEFAULT_LOCK_MS - M11_SAFETY_MARGIN_MS2) / 1e3;
2893
2906
  var PTClaimHandler = class {
2894
2907
  cfg;
2908
+ inFlightNonces = /* @__PURE__ */ new Map();
2895
2909
  constructor(config) {
2910
+ const lockDurationMs = config.lockDurationMs ?? DEFAULT_LOCK_MS;
2911
+ const signatureDeadlineSeconds = config.signatureDeadlineSeconds ?? DEFAULT_SIG_DEADLINE_SEC2;
2912
+ const maxAllowedSignatureMs = lockDurationMs - M11_SAFETY_MARGIN_MS2;
2913
+ if (signatureDeadlineSeconds * 1e3 > maxAllowedSignatureMs) {
2914
+ throw new PTClaimError(
2915
+ "VALIDATION_FAILED",
2916
+ `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). See audit M-11.`,
2917
+ {
2918
+ lockDurationMs,
2919
+ signatureDeadlineSeconds,
2920
+ maxAllowedSignatureSec: maxAllowedSignatureMs / 1e3
2921
+ }
2922
+ );
2923
+ }
2896
2924
  this.cfg = {
2897
2925
  ...config,
2898
- lockDurationMs: config.lockDurationMs ?? DEFAULT_LOCK_MS,
2899
- signatureDeadlineSeconds: config.signatureDeadlineSeconds ?? DEFAULT_SIG_DEADLINE_SEC2,
2926
+ lockDurationMs,
2927
+ signatureDeadlineSeconds,
2900
2928
  now: config.now ?? (() => Date.now())
2901
2929
  };
2902
2930
  }
@@ -2926,77 +2954,82 @@ var PTClaimHandler = class {
2926
2954
  }
2927
2955
  const chainAddresses = getContractAddresses3(request.chainId);
2928
2956
  const { batchExecutor: batchExecutorAddress } = chainAddresses;
2957
+ let mintRequestNonce;
2958
+ try {
2959
+ mintRequestNonce = await this.cfg.provider.readContract({
2960
+ address: request.pointTokenAddress,
2961
+ abi: POINT_TOKEN_ABI2,
2962
+ functionName: "mintRequestNonces",
2963
+ args: [request.userAddress]
2964
+ });
2965
+ } catch (err) {
2966
+ throw new PTClaimError(
2967
+ "NONCE_READ_FAILED",
2968
+ `failed to read mintRequestNonces(${request.userAddress}): ${err instanceof Error ? err.message : String(err)}`
2969
+ );
2970
+ }
2971
+ const nonceKey = `${getAddress9(request.userAddress).toLowerCase()}:${request.pointTokenAddress.toLowerCase()}`;
2972
+ let userNonces = this.inFlightNonces.get(nonceKey);
2973
+ if (!userNonces) {
2974
+ userNonces = /* @__PURE__ */ new Set();
2975
+ this.inFlightNonces.set(nonceKey, userNonces);
2976
+ }
2977
+ if (userNonces.has(mintRequestNonce)) {
2978
+ throw new PTClaimError(
2979
+ "NONCE_IN_FLIGHT",
2980
+ `concurrent claim for nonce ${mintRequestNonce} in progress; retry after the prior request completes`,
2981
+ { userAddress: request.userAddress, pointToken: request.pointTokenAddress, nonce: mintRequestNonce.toString() }
2982
+ );
2983
+ }
2984
+ userNonces.add(mintRequestNonce);
2929
2985
  const wrapperOverride = this.cfg.mintFeeWrapperAddress;
2930
2986
  const wrapperFromSdk = chainAddresses.mintFeeWrapper;
2931
2987
  const resolvedWrapper = wrapperOverride !== void 0 ? isNoWrapper2(wrapperOverride) ? void 0 : wrapperOverride : isNoWrapper2(wrapperFromSdk) ? void 0 : wrapperFromSdk;
2932
- const lockId = await this.cfg.ledger.lockForMinting(
2933
- request.userAddress,
2934
- request.amount,
2935
- this.cfg.lockDurationMs,
2936
- request.pointTokenAddress
2937
- );
2938
2988
  try {
2939
- const signatureDeadline = BigInt(
2940
- Math.floor(this.cfg.now() / 1e3) + this.cfg.signatureDeadlineSeconds
2941
- );
2942
- const previewUserOp = this.cfg.relayService.previewMintUserOp({
2943
- userAddress: request.userAddress,
2944
- aaNonce: request.aaNonce,
2945
- pointTokenAddress: request.pointTokenAddress,
2946
- amount: request.amount,
2947
- deadline: signatureDeadline,
2948
- mintFeeWrapperAddress: resolvedWrapper
2949
- });
2950
- const feeAmount = this.cfg.feeService ? await this.cfg.feeService.estimateGasFee({
2951
- scenario: resolvedWrapper ? "mint-wrapped" : "mint",
2952
- contractAddress: request.pointTokenAddress,
2953
- partialUserOp: {
2954
- sender: previewUserOp.sender,
2955
- nonce: previewUserOp.nonce,
2956
- callData: previewUserOp.callData
2957
- }
2958
- }) : 0n;
2959
- const domainName = await this.cfg.domainResolver.resolve(
2989
+ const lockCreatedAtMs = this.cfg.now();
2990
+ const lockExpiresAtMs = lockCreatedAtMs + this.cfg.lockDurationMs;
2991
+ const lockId = await this.cfg.ledger.lockForMinting(
2992
+ request.userAddress,
2993
+ request.amount,
2994
+ this.cfg.lockDurationMs,
2960
2995
  request.pointTokenAddress
2961
2996
  );
2962
- const domain = {
2963
- name: domainName,
2964
- chainId: request.chainId,
2965
- verifyingContract: request.pointTokenAddress
2966
- };
2967
- let userOp;
2968
2997
  try {
2969
- userOp = await this.cfg.relayService.prepareMint({
2998
+ const requestedDeadlineSec = Math.floor(lockCreatedAtMs / 1e3) + this.cfg.signatureDeadlineSeconds;
2999
+ const lockBoundedDeadlineSec = Math.floor(
3000
+ (lockExpiresAtMs - M11_SAFETY_MARGIN_MS2) / 1e3
3001
+ );
3002
+ const signatureDeadline = BigInt(
3003
+ Math.min(requestedDeadlineSec, lockBoundedDeadlineSec)
3004
+ );
3005
+ const previewUserOp = this.cfg.relayService.previewMintUserOp({
2970
3006
  userAddress: request.userAddress,
2971
3007
  aaNonce: request.aaNonce,
2972
- batchExecutorAddress,
2973
3008
  pointTokenAddress: request.pointTokenAddress,
2974
3009
  amount: request.amount,
2975
- issuerSignerWallet: this.cfg.issuerSignerWallet,
2976
- domain,
2977
- mintRequestNonce: request.mintRequestNonce,
2978
3010
  deadline: signatureDeadline,
2979
- mintFeeWrapperAddress: resolvedWrapper,
2980
- // Pass the bundler-estimated `feeAmount` explicitly so the
2981
- // RelayService skips its legacy `quoteOperatorFeePt` path
2982
- // (which uses the SDK's old 12_000 bps premium default).
2983
- // Without this, the response's `feeAmount` (from FeeManager,
2984
- // 100% premium on top of PAFI's 110% server-side estimate)
2985
- // would diverge from the actual PT.transfer amount in the
2986
- // UserOp batch (`quoteOperatorFeePt`'s 120%), and the user
2987
- // would see one value while the wallet transferred another.
2988
- feeAmount
3011
+ mintFeeWrapperAddress: resolvedWrapper
2989
3012
  });
2990
- } catch (err) {
2991
- throw new PTClaimError(
2992
- "BUILD_FAILED",
2993
- `prepareMint failed: ${err instanceof Error ? err.message : String(err)}`
3013
+ const feeAmount = this.cfg.feeService ? await this.cfg.feeService.estimateGasFee({
3014
+ scenario: resolvedWrapper ? "mint-wrapped" : "mint",
3015
+ contractAddress: request.pointTokenAddress,
3016
+ partialUserOp: {
3017
+ sender: previewUserOp.sender,
3018
+ nonce: previewUserOp.nonce,
3019
+ callData: previewUserOp.callData
3020
+ }
3021
+ }) : 0n;
3022
+ const domainName = await this.cfg.domainResolver.resolve(
3023
+ request.pointTokenAddress
2994
3024
  );
2995
- }
2996
- let fallback;
2997
- if (feeAmount > 0n) {
3025
+ const domain = {
3026
+ name: domainName,
3027
+ chainId: request.chainId,
3028
+ verifyingContract: request.pointTokenAddress
3029
+ };
3030
+ let userOp;
2998
3031
  try {
2999
- fallback = await this.cfg.relayService.prepareMint({
3032
+ userOp = await this.cfg.relayService.prepareMint({
3000
3033
  userAddress: request.userAddress,
3001
3034
  aaNonce: request.aaNonce,
3002
3035
  batchExecutorAddress,
@@ -3004,34 +3037,68 @@ var PTClaimHandler = class {
3004
3037
  amount: request.amount,
3005
3038
  issuerSignerWallet: this.cfg.issuerSignerWallet,
3006
3039
  domain,
3007
- mintRequestNonce: request.mintRequestNonce,
3040
+ mintRequestNonce,
3008
3041
  deadline: signatureDeadline,
3009
- feeAmount: 0n,
3010
- mintFeeWrapperAddress: resolvedWrapper
3042
+ mintFeeWrapperAddress: resolvedWrapper,
3043
+ // Pass the bundler-estimated `feeAmount` explicitly so the
3044
+ // RelayService skips its legacy `quoteOperatorFeePt` path
3045
+ // (which uses the SDK's old 12_000 bps premium default).
3046
+ // Without this, the response's `feeAmount` (from FeeManager,
3047
+ // 100% premium on top of PAFI's 110% server-side estimate)
3048
+ // would diverge from the actual PT.transfer amount in the
3049
+ // UserOp batch (`quoteOperatorFeePt`'s 120%), and the user
3050
+ // would see one value while the wallet transferred another.
3051
+ feeAmount
3011
3052
  });
3012
3053
  } catch (err) {
3013
3054
  throw new PTClaimError(
3014
3055
  "BUILD_FAILED",
3015
- `prepareMint (fallback) failed: ${err instanceof Error ? err.message : String(err)}`
3056
+ `prepareMint failed: ${err instanceof Error ? err.message : String(err)}`
3016
3057
  );
3017
3058
  }
3059
+ let fallback;
3060
+ if (feeAmount > 0n) {
3061
+ try {
3062
+ fallback = await this.cfg.relayService.prepareMint({
3063
+ userAddress: request.userAddress,
3064
+ aaNonce: request.aaNonce,
3065
+ batchExecutorAddress,
3066
+ pointTokenAddress: request.pointTokenAddress,
3067
+ amount: request.amount,
3068
+ issuerSignerWallet: this.cfg.issuerSignerWallet,
3069
+ domain,
3070
+ mintRequestNonce,
3071
+ deadline: signatureDeadline,
3072
+ feeAmount: 0n,
3073
+ mintFeeWrapperAddress: resolvedWrapper
3074
+ });
3075
+ } catch (err) {
3076
+ throw new PTClaimError(
3077
+ "BUILD_FAILED",
3078
+ `prepareMint (fallback) failed: ${err instanceof Error ? err.message : String(err)}`
3079
+ );
3080
+ }
3081
+ }
3082
+ const calls = decodeBatchExecuteCalls(userOp.callData);
3083
+ const callsFallback = fallback ? decodeBatchExecuteCalls(fallback.callData) : void 0;
3084
+ return {
3085
+ userOp,
3086
+ fallback,
3087
+ lockId,
3088
+ feeAmount,
3089
+ signatureDeadline,
3090
+ expiresInSeconds: Math.floor(this.cfg.lockDurationMs / 1e3),
3091
+ calls,
3092
+ callsFallback
3093
+ };
3094
+ } catch (err) {
3095
+ await this.cfg.ledger.releaseLock(lockId).catch(() => {
3096
+ });
3097
+ throw err;
3018
3098
  }
3019
- const calls = decodeBatchExecuteCalls(userOp.callData);
3020
- const callsFallback = fallback ? decodeBatchExecuteCalls(fallback.callData) : void 0;
3021
- return {
3022
- userOp,
3023
- fallback,
3024
- lockId,
3025
- feeAmount,
3026
- signatureDeadline,
3027
- expiresInSeconds: Math.floor(this.cfg.lockDurationMs / 1e3),
3028
- calls,
3029
- callsFallback
3030
- };
3031
- } catch (err) {
3032
- await this.cfg.ledger.releaseLock(lockId).catch(() => {
3033
- });
3034
- throw err;
3099
+ } finally {
3100
+ userNonces.delete(mintRequestNonce);
3101
+ if (userNonces.size === 0) this.inFlightNonces.delete(nonceKey);
3035
3102
  }
3036
3103
  }
3037
3104
  };
@@ -3370,7 +3437,6 @@ var IssuerApiAdapter = class {
3370
3437
  }
3371
3438
  );
3372
3439
  return {
3373
- mintRequestNonce: result.mintRequestNonce.toString(),
3374
3440
  offChainBalance: result.offChainBalance.toString(),
3375
3441
  onChainBalance: result.onChainBalance.toString(),
3376
3442
  totalBalance: result.totalBalance.toString(),
@@ -3394,8 +3460,7 @@ var IssuerApiAdapter = class {
3394
3460
  amount: input.amount,
3395
3461
  pointTokenAddress,
3396
3462
  chainId: input.chainId,
3397
- aaNonce: input.aaNonce,
3398
- mintRequestNonce: input.mintRequestNonce
3463
+ aaNonce: input.aaNonce
3399
3464
  });
3400
3465
  const sponsorAuth = await this.buildSponsorAuth(
3401
3466
  input.authenticatedAddress,
@@ -3491,8 +3556,7 @@ var IssuerApiAdapter = class {
3491
3556
  amount: input.amount,
3492
3557
  pointTokenAddress,
3493
3558
  chainId: input.chainId,
3494
- aaNonce: input.aaNonce,
3495
- mintRequestNonce: input.mintRequestNonce
3559
+ aaNonce: input.aaNonce
3496
3560
  });
3497
3561
  const prepared = await this.runMobilePrepare(
3498
3562
  input.authenticatedAddress,
@@ -4759,7 +4823,7 @@ async function createIssuerService(config) {
4759
4823
  // src/issuer-state/validator.ts
4760
4824
  import { getAddress as getAddress13 } from "viem";
4761
4825
  import {
4762
- POINT_TOKEN_ABI as POINT_TOKEN_ABI2,
4826
+ POINT_TOKEN_ABI as POINT_TOKEN_ABI3,
4763
4827
  issuerRegistryAbi,
4764
4828
  getContractAddresses as getContractAddresses8
4765
4829
  } from "@pafi-dev/core";
@@ -4808,7 +4872,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
4808
4872
  if (cached) return cached;
4809
4873
  const issuer = await this.provider.readContract({
4810
4874
  address: key,
4811
- abi: POINT_TOKEN_ABI2,
4875
+ abi: POINT_TOKEN_ABI3,
4812
4876
  functionName: "issuer"
4813
4877
  });
4814
4878
  this.pointTokenIssuerCache.set(key, getAddress13(issuer));
@@ -4901,7 +4965,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
4901
4965
  };
4902
4966
  const equitySupply = await this.provider.readContract({
4903
4967
  address: tokenAddr,
4904
- abi: POINT_TOKEN_ABI2,
4968
+ abi: POINT_TOKEN_ABI3,
4905
4969
  functionName: "equitySupply"
4906
4970
  });
4907
4971
  const hardCap = issuer.capitalBase * BigInt(issuer.basisPoints) / 10000n;
@@ -4957,7 +5021,7 @@ var MemoryRedemptionHistoryStore = class {
4957
5021
  };
4958
5022
 
4959
5023
  // src/index.ts
4960
- var PAFI_ISSUER_SDK_VERSION = true ? "0.24.1" : "dev";
5024
+ var PAFI_ISSUER_SDK_VERSION = true ? "0.25.0" : "dev";
4961
5025
  export {
4962
5026
  AdapterMisconfiguredError,
4963
5027
  AuthError,