@pafi-dev/issuer 0.24.1 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +155 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -7
- package/dist/index.d.ts +2 -7
- package/dist/index.js +159 -95
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
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 [
|
|
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
|
|
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.
|
|
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:
|
|
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
|
|
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
|
|
2899
|
-
signatureDeadlineSeconds
|
|
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
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
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
|
-
|
|
2997
|
-
|
|
3025
|
+
const domain = {
|
|
3026
|
+
name: domainName,
|
|
3027
|
+
chainId: request.chainId,
|
|
3028
|
+
verifyingContract: request.pointTokenAddress
|
|
3029
|
+
};
|
|
3030
|
+
let userOp;
|
|
2998
3031
|
try {
|
|
2999
|
-
|
|
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
|
|
3040
|
+
mintRequestNonce,
|
|
3008
3041
|
deadline: signatureDeadline,
|
|
3009
|
-
|
|
3010
|
-
|
|
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
|
|
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
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
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
|
|
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:
|
|
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:
|
|
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.
|
|
5024
|
+
var PAFI_ISSUER_SDK_VERSION = true ? "0.26.0" : "dev";
|
|
4961
5025
|
export {
|
|
4962
5026
|
AdapterMisconfiguredError,
|
|
4963
5027
|
AuthError,
|