@pafi-dev/issuer 0.23.0 → 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.cjs +244 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -25
- package/dist/index.d.ts +78 -25
- package/dist/index.js +252 -134
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -579,12 +579,14 @@ import {
|
|
|
579
579
|
erc20Abi
|
|
580
580
|
} from "viem";
|
|
581
581
|
import {
|
|
582
|
-
|
|
582
|
+
POINT_TOKEN_MINT_SIG_ABI,
|
|
583
|
+
POINT_TOKEN_BURN_SIG_ABI,
|
|
583
584
|
mintFeeWrapperAbi,
|
|
584
585
|
buildPartialUserOperation,
|
|
585
586
|
signMintRequest,
|
|
586
587
|
getContractAddresses,
|
|
587
|
-
quoteOperatorFeePt
|
|
588
|
+
quoteOperatorFeePt,
|
|
589
|
+
Source
|
|
588
590
|
} from "@pafi-dev/core";
|
|
589
591
|
var RelayService = class {
|
|
590
592
|
provider;
|
|
@@ -673,6 +675,7 @@ var RelayService = class {
|
|
|
673
675
|
"prepareMint: deadline exceeds maximum allowed window (1 hour)"
|
|
674
676
|
);
|
|
675
677
|
}
|
|
678
|
+
const MINT_SOURCE = Source.EQUITY;
|
|
676
679
|
const useWrapper = params.mintFeeWrapperAddress !== void 0;
|
|
677
680
|
const receiverForSig = useWrapper ? params.mintFeeWrapperAddress : params.userAddress;
|
|
678
681
|
let minterSig;
|
|
@@ -684,6 +687,7 @@ var RelayService = class {
|
|
|
684
687
|
user: params.userAddress,
|
|
685
688
|
receiver: receiverForSig,
|
|
686
689
|
amount: params.amount,
|
|
690
|
+
source: MINT_SOURCE,
|
|
687
691
|
nonce: params.mintRequestNonce,
|
|
688
692
|
deadline: params.deadline
|
|
689
693
|
}
|
|
@@ -714,9 +718,15 @@ var RelayService = class {
|
|
|
714
718
|
mintTarget = params.mintFeeWrapperAddress;
|
|
715
719
|
} else {
|
|
716
720
|
mintCallData = encodeFunctionData({
|
|
717
|
-
abi:
|
|
721
|
+
abi: POINT_TOKEN_MINT_SIG_ABI,
|
|
718
722
|
functionName: "mint",
|
|
719
|
-
args: [
|
|
723
|
+
args: [
|
|
724
|
+
params.userAddress,
|
|
725
|
+
params.amount,
|
|
726
|
+
MINT_SOURCE,
|
|
727
|
+
params.deadline,
|
|
728
|
+
minterSig
|
|
729
|
+
]
|
|
720
730
|
});
|
|
721
731
|
mintTarget = params.pointTokenAddress;
|
|
722
732
|
}
|
|
@@ -801,11 +811,12 @@ var RelayService = class {
|
|
|
801
811
|
let burnCallData;
|
|
802
812
|
try {
|
|
803
813
|
burnCallData = encodeFunctionData({
|
|
804
|
-
abi:
|
|
814
|
+
abi: POINT_TOKEN_BURN_SIG_ABI,
|
|
805
815
|
functionName: "burn",
|
|
806
816
|
args: [
|
|
807
817
|
params.burnRequest.from,
|
|
808
818
|
params.burnRequest.amount,
|
|
819
|
+
params.burnRequest.source,
|
|
809
820
|
params.burnRequest.deadline,
|
|
810
821
|
params.burnerSignature
|
|
811
822
|
]
|
|
@@ -900,11 +911,12 @@ var RelayService = class {
|
|
|
900
911
|
mintTarget = params.mintFeeWrapperAddress;
|
|
901
912
|
} else {
|
|
902
913
|
mintCallData = encodeFunctionData({
|
|
903
|
-
abi:
|
|
914
|
+
abi: POINT_TOKEN_MINT_SIG_ABI,
|
|
904
915
|
functionName: "mint",
|
|
905
916
|
args: [
|
|
906
917
|
params.userAddress,
|
|
907
918
|
params.amount,
|
|
919
|
+
Source.EQUITY,
|
|
908
920
|
params.deadline,
|
|
909
921
|
PLACEHOLDER_SIG_65
|
|
910
922
|
]
|
|
@@ -926,11 +938,12 @@ var RelayService = class {
|
|
|
926
938
|
/** Burn-side mirror of `previewMintUserOp`. */
|
|
927
939
|
previewBurnUserOp(params) {
|
|
928
940
|
const burnCallData = encodeFunctionData({
|
|
929
|
-
abi:
|
|
941
|
+
abi: POINT_TOKEN_BURN_SIG_ABI,
|
|
930
942
|
functionName: "burn",
|
|
931
943
|
args: [
|
|
932
944
|
params.userAddress,
|
|
933
945
|
params.amount,
|
|
946
|
+
Source.EQUITY,
|
|
934
947
|
params.deadline,
|
|
935
948
|
PLACEHOLDER_SIG_65
|
|
936
949
|
]
|
|
@@ -1148,6 +1161,16 @@ var InMemoryCursorStore = class _InMemoryCursorStore {
|
|
|
1148
1161
|
|
|
1149
1162
|
// src/indexer/pointIndexer.ts
|
|
1150
1163
|
import { getAddress as getAddress3, parseAbiItem } from "viem";
|
|
1164
|
+
var PointIndexerFinalizeError = class extends Error {
|
|
1165
|
+
constructor(message, context, cause) {
|
|
1166
|
+
super(message);
|
|
1167
|
+
this.context = context;
|
|
1168
|
+
this.cause = cause;
|
|
1169
|
+
this.name = "PointIndexerFinalizeError";
|
|
1170
|
+
}
|
|
1171
|
+
context;
|
|
1172
|
+
cause;
|
|
1173
|
+
};
|
|
1151
1174
|
var TRANSFER_EVENT = parseAbiItem(
|
|
1152
1175
|
"event Transfer(address indexed from, address indexed to, uint256 value)"
|
|
1153
1176
|
);
|
|
@@ -1373,8 +1396,18 @@ var PointIndexer = class {
|
|
|
1373
1396
|
evt.txHash,
|
|
1374
1397
|
this.pointTokenAddress
|
|
1375
1398
|
);
|
|
1376
|
-
} catch {
|
|
1377
|
-
|
|
1399
|
+
} catch (err) {
|
|
1400
|
+
throw new PointIndexerFinalizeError(
|
|
1401
|
+
`PointIndexer.deductBalance failed for tx ${evt.txHash} (to=${evt.to}, amount=${evt.amount}, block=${evt.blockNumber}); cursor will NOT advance, next tick retries.`,
|
|
1402
|
+
{
|
|
1403
|
+
pointToken: this.pointTokenAddress,
|
|
1404
|
+
to: evt.to,
|
|
1405
|
+
amount: evt.amount,
|
|
1406
|
+
txHash: evt.txHash,
|
|
1407
|
+
blockNumber: evt.blockNumber
|
|
1408
|
+
},
|
|
1409
|
+
err
|
|
1410
|
+
);
|
|
1378
1411
|
}
|
|
1379
1412
|
try {
|
|
1380
1413
|
await this.ledger.updateMintStatus(match.lockId, "MINTED", evt.txHash);
|
|
@@ -1396,6 +1429,16 @@ function pickMatchingLock(locks, amount) {
|
|
|
1396
1429
|
|
|
1397
1430
|
// src/indexer/burnIndexer.ts
|
|
1398
1431
|
import { getAddress as getAddress4, parseAbiItem as parseAbiItem2 } from "viem";
|
|
1432
|
+
var BurnIndexerFinalizeError = class extends Error {
|
|
1433
|
+
constructor(message, context, cause) {
|
|
1434
|
+
super(message);
|
|
1435
|
+
this.context = context;
|
|
1436
|
+
this.cause = cause;
|
|
1437
|
+
this.name = "BurnIndexerFinalizeError";
|
|
1438
|
+
}
|
|
1439
|
+
context;
|
|
1440
|
+
cause;
|
|
1441
|
+
};
|
|
1399
1442
|
var TRANSFER_EVENT2 = parseAbiItem2(
|
|
1400
1443
|
"event Transfer(address indexed from, address indexed to, uint256 value)"
|
|
1401
1444
|
);
|
|
@@ -1563,7 +1606,18 @@ var BurnIndexer = class {
|
|
|
1563
1606
|
try {
|
|
1564
1607
|
await this.ledger.resolveCreditByBurnTx(lockId, evt.txHash);
|
|
1565
1608
|
} catch (err) {
|
|
1566
|
-
|
|
1609
|
+
throw new BurnIndexerFinalizeError(
|
|
1610
|
+
`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.`,
|
|
1611
|
+
{
|
|
1612
|
+
pointToken: this.pointTokenAddress,
|
|
1613
|
+
from: evt.from,
|
|
1614
|
+
amount: evt.amount,
|
|
1615
|
+
txHash: evt.txHash,
|
|
1616
|
+
blockNumber: evt.blockNumber,
|
|
1617
|
+
lockId
|
|
1618
|
+
},
|
|
1619
|
+
err
|
|
1620
|
+
);
|
|
1567
1621
|
}
|
|
1568
1622
|
}
|
|
1569
1623
|
};
|
|
@@ -1611,7 +1665,6 @@ function hashKeyToInt64(key) {
|
|
|
1611
1665
|
import { getAddress as getAddress5 } from "viem";
|
|
1612
1666
|
import {
|
|
1613
1667
|
getMintFeeBps,
|
|
1614
|
-
getMintRequestNonce,
|
|
1615
1668
|
getPointTokenBalance,
|
|
1616
1669
|
isMinter
|
|
1617
1670
|
} from "@pafi-dev/core";
|
|
@@ -1883,14 +1936,12 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
|
|
|
1883
1936
|
{ requested: pointToken }
|
|
1884
1937
|
);
|
|
1885
1938
|
}
|
|
1886
|
-
const [
|
|
1887
|
-
getMintRequestNonce(this.provider, pointToken, normalizedAuthed),
|
|
1939
|
+
const [offChainBalance, onChainBalance, minter] = await Promise.all([
|
|
1888
1940
|
this.ledger.getBalance(normalizedAuthed, pointToken),
|
|
1889
1941
|
getPointTokenBalance(this.provider, pointToken, normalizedAuthed),
|
|
1890
1942
|
isMinter(this.provider, pointToken, normalizedAuthed)
|
|
1891
1943
|
]);
|
|
1892
1944
|
return {
|
|
1893
|
-
mintRequestNonce,
|
|
1894
1945
|
offChainBalance,
|
|
1895
1946
|
onChainBalance,
|
|
1896
1947
|
totalBalance: offChainBalance + onChainBalance,
|
|
@@ -2027,12 +2078,14 @@ var PointTokenDomainResolver = class {
|
|
|
2027
2078
|
import { getAddress as getAddress7 } from "viem";
|
|
2028
2079
|
import {
|
|
2029
2080
|
signBurnRequest,
|
|
2030
|
-
POINT_TOKEN_ABI
|
|
2081
|
+
POINT_TOKEN_ABI,
|
|
2031
2082
|
getPointTokenBalance as getPointTokenBalance2,
|
|
2032
|
-
getContractAddresses as getContractAddresses2
|
|
2083
|
+
getContractAddresses as getContractAddresses2,
|
|
2084
|
+
Source as Source2
|
|
2033
2085
|
} from "@pafi-dev/core";
|
|
2034
2086
|
var DEFAULT_REDEEM_LOCK_MS = 15 * 60 * 1e3;
|
|
2035
|
-
var
|
|
2087
|
+
var M11_SAFETY_MARGIN_MS = 30 * 1e3;
|
|
2088
|
+
var DEFAULT_SIG_DEADLINE_SEC = (DEFAULT_REDEEM_LOCK_MS - M11_SAFETY_MARGIN_MS) / 1e3;
|
|
2036
2089
|
var PTRedeemError = class extends PafiSdkError {
|
|
2037
2090
|
httpStatus = "unprocessable";
|
|
2038
2091
|
code;
|
|
@@ -2099,6 +2152,13 @@ var PTRedeemHandler = class {
|
|
|
2099
2152
|
this.redeemLockDurationMs = config.redeemLockDurationMs ?? DEFAULT_REDEEM_LOCK_MS;
|
|
2100
2153
|
this.signatureDeadlineSeconds = config.signatureDeadlineSeconds ?? DEFAULT_SIG_DEADLINE_SEC;
|
|
2101
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
|
+
}
|
|
2102
2162
|
if (config.redemptionService) {
|
|
2103
2163
|
this.redemptionService = config.redemptionService;
|
|
2104
2164
|
}
|
|
@@ -2133,7 +2193,7 @@ var PTRedeemHandler = class {
|
|
|
2133
2193
|
try {
|
|
2134
2194
|
burnNonce = await this.provider.readContract({
|
|
2135
2195
|
address: pointTokenAddress,
|
|
2136
|
-
abi:
|
|
2196
|
+
abi: POINT_TOKEN_ABI,
|
|
2137
2197
|
functionName: "burnRequestNonces",
|
|
2138
2198
|
args: [request.userAddress]
|
|
2139
2199
|
});
|
|
@@ -2164,8 +2224,14 @@ var PTRedeemHandler = class {
|
|
|
2164
2224
|
}
|
|
2165
2225
|
}
|
|
2166
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
|
+
);
|
|
2167
2233
|
const previewDeadline = BigInt(
|
|
2168
|
-
Math.
|
|
2234
|
+
Math.min(requestedDeadlineSec, lockBoundedDeadlineSec)
|
|
2169
2235
|
);
|
|
2170
2236
|
let fee;
|
|
2171
2237
|
if (request.feeAmount !== void 0) {
|
|
@@ -2173,7 +2239,7 @@ var PTRedeemHandler = class {
|
|
|
2173
2239
|
} else if (this.feeService) {
|
|
2174
2240
|
const previewUserOp = this.relayService.previewBurnUserOp({
|
|
2175
2241
|
userAddress: request.userAddress,
|
|
2176
|
-
aaNonce:
|
|
2242
|
+
aaNonce: request.aaNonce,
|
|
2177
2243
|
pointTokenAddress,
|
|
2178
2244
|
amount: request.amount,
|
|
2179
2245
|
deadline: previewDeadline
|
|
@@ -2215,10 +2281,12 @@ var PTRedeemHandler = class {
|
|
|
2215
2281
|
chainId: this.chainId,
|
|
2216
2282
|
verifyingContract: pointTokenAddress
|
|
2217
2283
|
};
|
|
2284
|
+
const BURN_SOURCE = Source2.EQUITY;
|
|
2218
2285
|
const sponsoredBurnAmount = request.amount - fee;
|
|
2219
2286
|
const sponsoredBurnRequest = {
|
|
2220
2287
|
from: request.userAddress,
|
|
2221
2288
|
amount: sponsoredBurnAmount,
|
|
2289
|
+
source: BURN_SOURCE,
|
|
2222
2290
|
nonce: burnNonce,
|
|
2223
2291
|
deadline
|
|
2224
2292
|
};
|
|
@@ -2254,6 +2322,7 @@ var PTRedeemHandler = class {
|
|
|
2254
2322
|
const fallbackBurnRequest = {
|
|
2255
2323
|
from: request.userAddress,
|
|
2256
2324
|
amount: request.amount,
|
|
2325
|
+
source: BURN_SOURCE,
|
|
2257
2326
|
nonce: burnNonce,
|
|
2258
2327
|
deadline
|
|
2259
2328
|
};
|
|
@@ -2796,6 +2865,7 @@ async function handleMobileSubmit(params) {
|
|
|
2796
2865
|
// src/api/handlers/ptClaimHandler.ts
|
|
2797
2866
|
import { getAddress as getAddress9 } from "viem";
|
|
2798
2867
|
import {
|
|
2868
|
+
POINT_TOKEN_ABI as POINT_TOKEN_ABI2,
|
|
2799
2869
|
decodeBatchExecuteCalls,
|
|
2800
2870
|
getContractAddresses as getContractAddresses3
|
|
2801
2871
|
} from "@pafi-dev/core";
|
|
@@ -2831,14 +2901,30 @@ function isNoWrapper2(address) {
|
|
|
2831
2901
|
return lower === "0x0000000000000000000000000000000000000000" || lower === "0x000000000000000000000000000000000000dead";
|
|
2832
2902
|
}
|
|
2833
2903
|
var DEFAULT_LOCK_MS = 15 * 60 * 1e3;
|
|
2834
|
-
var
|
|
2904
|
+
var M11_SAFETY_MARGIN_MS2 = 30 * 1e3;
|
|
2905
|
+
var DEFAULT_SIG_DEADLINE_SEC2 = (DEFAULT_LOCK_MS - M11_SAFETY_MARGIN_MS2) / 1e3;
|
|
2835
2906
|
var PTClaimHandler = class {
|
|
2836
2907
|
cfg;
|
|
2908
|
+
inFlightNonces = /* @__PURE__ */ new Map();
|
|
2837
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
|
+
}
|
|
2838
2924
|
this.cfg = {
|
|
2839
2925
|
...config,
|
|
2840
|
-
lockDurationMs
|
|
2841
|
-
signatureDeadlineSeconds
|
|
2926
|
+
lockDurationMs,
|
|
2927
|
+
signatureDeadlineSeconds,
|
|
2842
2928
|
now: config.now ?? (() => Date.now())
|
|
2843
2929
|
};
|
|
2844
2930
|
}
|
|
@@ -2868,77 +2954,82 @@ var PTClaimHandler = class {
|
|
|
2868
2954
|
}
|
|
2869
2955
|
const chainAddresses = getContractAddresses3(request.chainId);
|
|
2870
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);
|
|
2871
2985
|
const wrapperOverride = this.cfg.mintFeeWrapperAddress;
|
|
2872
2986
|
const wrapperFromSdk = chainAddresses.mintFeeWrapper;
|
|
2873
2987
|
const resolvedWrapper = wrapperOverride !== void 0 ? isNoWrapper2(wrapperOverride) ? void 0 : wrapperOverride : isNoWrapper2(wrapperFromSdk) ? void 0 : wrapperFromSdk;
|
|
2874
|
-
const lockId = await this.cfg.ledger.lockForMinting(
|
|
2875
|
-
request.userAddress,
|
|
2876
|
-
request.amount,
|
|
2877
|
-
this.cfg.lockDurationMs,
|
|
2878
|
-
request.pointTokenAddress
|
|
2879
|
-
);
|
|
2880
2988
|
try {
|
|
2881
|
-
const
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
pointTokenAddress: request.pointTokenAddress,
|
|
2888
|
-
amount: request.amount,
|
|
2889
|
-
deadline: signatureDeadline,
|
|
2890
|
-
mintFeeWrapperAddress: resolvedWrapper
|
|
2891
|
-
});
|
|
2892
|
-
const feeAmount = this.cfg.feeService ? await this.cfg.feeService.estimateGasFee({
|
|
2893
|
-
scenario: resolvedWrapper ? "mint-wrapped" : "mint",
|
|
2894
|
-
contractAddress: request.pointTokenAddress,
|
|
2895
|
-
partialUserOp: {
|
|
2896
|
-
sender: previewUserOp.sender,
|
|
2897
|
-
nonce: previewUserOp.nonce,
|
|
2898
|
-
callData: previewUserOp.callData
|
|
2899
|
-
}
|
|
2900
|
-
}) : 0n;
|
|
2901
|
-
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,
|
|
2902
2995
|
request.pointTokenAddress
|
|
2903
2996
|
);
|
|
2904
|
-
const domain = {
|
|
2905
|
-
name: domainName,
|
|
2906
|
-
chainId: request.chainId,
|
|
2907
|
-
verifyingContract: request.pointTokenAddress
|
|
2908
|
-
};
|
|
2909
|
-
let userOp;
|
|
2910
2997
|
try {
|
|
2911
|
-
|
|
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({
|
|
2912
3006
|
userAddress: request.userAddress,
|
|
2913
3007
|
aaNonce: request.aaNonce,
|
|
2914
|
-
batchExecutorAddress,
|
|
2915
3008
|
pointTokenAddress: request.pointTokenAddress,
|
|
2916
3009
|
amount: request.amount,
|
|
2917
|
-
issuerSignerWallet: this.cfg.issuerSignerWallet,
|
|
2918
|
-
domain,
|
|
2919
|
-
mintRequestNonce: request.mintRequestNonce,
|
|
2920
3010
|
deadline: signatureDeadline,
|
|
2921
|
-
mintFeeWrapperAddress: resolvedWrapper
|
|
2922
|
-
// Pass the bundler-estimated `feeAmount` explicitly so the
|
|
2923
|
-
// RelayService skips its legacy `quoteOperatorFeePt` path
|
|
2924
|
-
// (which uses the SDK's old 12_000 bps premium default).
|
|
2925
|
-
// Without this, the response's `feeAmount` (from FeeManager,
|
|
2926
|
-
// 100% premium on top of PAFI's 110% server-side estimate)
|
|
2927
|
-
// would diverge from the actual PT.transfer amount in the
|
|
2928
|
-
// UserOp batch (`quoteOperatorFeePt`'s 120%), and the user
|
|
2929
|
-
// would see one value while the wallet transferred another.
|
|
2930
|
-
feeAmount
|
|
3011
|
+
mintFeeWrapperAddress: resolvedWrapper
|
|
2931
3012
|
});
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
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
|
|
2936
3024
|
);
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
3025
|
+
const domain = {
|
|
3026
|
+
name: domainName,
|
|
3027
|
+
chainId: request.chainId,
|
|
3028
|
+
verifyingContract: request.pointTokenAddress
|
|
3029
|
+
};
|
|
3030
|
+
let userOp;
|
|
2940
3031
|
try {
|
|
2941
|
-
|
|
3032
|
+
userOp = await this.cfg.relayService.prepareMint({
|
|
2942
3033
|
userAddress: request.userAddress,
|
|
2943
3034
|
aaNonce: request.aaNonce,
|
|
2944
3035
|
batchExecutorAddress,
|
|
@@ -2946,34 +3037,68 @@ var PTClaimHandler = class {
|
|
|
2946
3037
|
amount: request.amount,
|
|
2947
3038
|
issuerSignerWallet: this.cfg.issuerSignerWallet,
|
|
2948
3039
|
domain,
|
|
2949
|
-
mintRequestNonce
|
|
3040
|
+
mintRequestNonce,
|
|
2950
3041
|
deadline: signatureDeadline,
|
|
2951
|
-
|
|
2952
|
-
|
|
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
|
|
2953
3052
|
});
|
|
2954
3053
|
} catch (err) {
|
|
2955
3054
|
throw new PTClaimError(
|
|
2956
3055
|
"BUILD_FAILED",
|
|
2957
|
-
`prepareMint
|
|
3056
|
+
`prepareMint failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2958
3057
|
);
|
|
2959
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;
|
|
2960
3098
|
}
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
userOp,
|
|
2965
|
-
fallback,
|
|
2966
|
-
lockId,
|
|
2967
|
-
feeAmount,
|
|
2968
|
-
signatureDeadline,
|
|
2969
|
-
expiresInSeconds: Math.floor(this.cfg.lockDurationMs / 1e3),
|
|
2970
|
-
calls,
|
|
2971
|
-
callsFallback
|
|
2972
|
-
};
|
|
2973
|
-
} catch (err) {
|
|
2974
|
-
await this.cfg.ledger.releaseLock(lockId).catch(() => {
|
|
2975
|
-
});
|
|
2976
|
-
throw err;
|
|
3099
|
+
} finally {
|
|
3100
|
+
userNonces.delete(mintRequestNonce);
|
|
3101
|
+
if (userNonces.size === 0) this.inFlightNonces.delete(nonceKey);
|
|
2977
3102
|
}
|
|
2978
3103
|
}
|
|
2979
3104
|
};
|
|
@@ -3312,7 +3437,6 @@ var IssuerApiAdapter = class {
|
|
|
3312
3437
|
}
|
|
3313
3438
|
);
|
|
3314
3439
|
return {
|
|
3315
|
-
mintRequestNonce: result.mintRequestNonce.toString(),
|
|
3316
3440
|
offChainBalance: result.offChainBalance.toString(),
|
|
3317
3441
|
onChainBalance: result.onChainBalance.toString(),
|
|
3318
3442
|
totalBalance: result.totalBalance.toString(),
|
|
@@ -3336,8 +3460,7 @@ var IssuerApiAdapter = class {
|
|
|
3336
3460
|
amount: input.amount,
|
|
3337
3461
|
pointTokenAddress,
|
|
3338
3462
|
chainId: input.chainId,
|
|
3339
|
-
aaNonce: input.aaNonce
|
|
3340
|
-
mintRequestNonce: input.mintRequestNonce
|
|
3463
|
+
aaNonce: input.aaNonce
|
|
3341
3464
|
});
|
|
3342
3465
|
const sponsorAuth = await this.buildSponsorAuth(
|
|
3343
3466
|
input.authenticatedAddress,
|
|
@@ -3433,8 +3556,7 @@ var IssuerApiAdapter = class {
|
|
|
3433
3556
|
amount: input.amount,
|
|
3434
3557
|
pointTokenAddress,
|
|
3435
3558
|
chainId: input.chainId,
|
|
3436
|
-
aaNonce: input.aaNonce
|
|
3437
|
-
mintRequestNonce: input.mintRequestNonce
|
|
3559
|
+
aaNonce: input.aaNonce
|
|
3438
3560
|
});
|
|
3439
3561
|
const prepared = await this.runMobilePrepare(
|
|
3440
3562
|
input.authenticatedAddress,
|
|
@@ -4703,8 +4825,7 @@ import { getAddress as getAddress13 } from "viem";
|
|
|
4703
4825
|
import {
|
|
4704
4826
|
POINT_TOKEN_ABI as POINT_TOKEN_ABI3,
|
|
4705
4827
|
issuerRegistryAbi,
|
|
4706
|
-
getContractAddresses as getContractAddresses8
|
|
4707
|
-
getTokenCap
|
|
4828
|
+
getContractAddresses as getContractAddresses8
|
|
4708
4829
|
} from "@pafi-dev/core";
|
|
4709
4830
|
var ISSUER_RECORD_TTL_MS = 3e4;
|
|
4710
4831
|
var IssuerStateValidator = class _IssuerStateValidator {
|
|
@@ -4805,22 +4926,22 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
4805
4926
|
}
|
|
4806
4927
|
throw err;
|
|
4807
4928
|
}
|
|
4808
|
-
const { issuer,
|
|
4929
|
+
const { issuer, equityCap, equitySupply, remaining } = state;
|
|
4809
4930
|
if (!issuer.active) {
|
|
4810
4931
|
throw new IssuerStateError(
|
|
4811
4932
|
"ISSUER_INACTIVE",
|
|
4812
|
-
`Issuer ${issuer.
|
|
4813
|
-
{
|
|
4933
|
+
`Issuer "${issuer.name}" is deactivated on IssuerRegistry`,
|
|
4934
|
+
{ pointToken }
|
|
4814
4935
|
);
|
|
4815
4936
|
}
|
|
4816
|
-
if (
|
|
4937
|
+
if (equitySupply + amount > equityCap.hardCap) {
|
|
4817
4938
|
throw new IssuerStateError(
|
|
4818
4939
|
"MINT_CAP_EXCEEDED",
|
|
4819
|
-
`Requested ${amount} PT would exceed mint cap. Cap=${hardCap},
|
|
4940
|
+
`Requested ${amount} PT would exceed EQUITY mint cap. Cap=${equityCap.hardCap}, equityMinted=${equitySupply}, remaining=${remaining}`,
|
|
4820
4941
|
{
|
|
4821
4942
|
requested: amount.toString(),
|
|
4822
|
-
cap: hardCap.toString(),
|
|
4823
|
-
|
|
4943
|
+
cap: equityCap.hardCap.toString(),
|
|
4944
|
+
equityMinted: equitySupply.toString(),
|
|
4824
4945
|
remaining: remaining.toString()
|
|
4825
4946
|
}
|
|
4826
4947
|
);
|
|
@@ -4836,33 +4957,28 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
4836
4957
|
args: [issuerAddr]
|
|
4837
4958
|
});
|
|
4838
4959
|
const issuer = {
|
|
4839
|
-
issuerAddress: issuerStruct.issuerAddress,
|
|
4840
4960
|
signerAddress: issuerStruct.signerAddress,
|
|
4841
4961
|
name: issuerStruct.name,
|
|
4842
|
-
symbol: issuerStruct.symbol,
|
|
4843
4962
|
active: issuerStruct.active,
|
|
4844
|
-
|
|
4845
|
-
|
|
4963
|
+
capitalBase: issuerStruct.capitalBase,
|
|
4964
|
+
basisPoints: Number(issuerStruct.basisPoints)
|
|
4846
4965
|
};
|
|
4847
|
-
const
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
capBasisPoints: tokenCap.capBasisPoints
|
|
4966
|
+
const equitySupply = await this.provider.readContract({
|
|
4967
|
+
address: tokenAddr,
|
|
4968
|
+
abi: POINT_TOKEN_ABI3,
|
|
4969
|
+
functionName: "equitySupply"
|
|
4970
|
+
});
|
|
4971
|
+
const hardCap = issuer.capitalBase * BigInt(issuer.basisPoints) / 10000n;
|
|
4972
|
+
const equityCap = {
|
|
4973
|
+
capitalBase: issuer.capitalBase,
|
|
4974
|
+
basisPoints: issuer.basisPoints,
|
|
4975
|
+
hardCap
|
|
4858
4976
|
};
|
|
4859
|
-
const
|
|
4860
|
-
const remaining = hardCap > totalSupply ? hardCap - totalSupply : 0n;
|
|
4977
|
+
const remaining = hardCap > equitySupply ? hardCap - equitySupply : 0n;
|
|
4861
4978
|
return {
|
|
4862
4979
|
issuer,
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
hardCap,
|
|
4980
|
+
equityCap,
|
|
4981
|
+
equitySupply,
|
|
4866
4982
|
remaining
|
|
4867
4983
|
};
|
|
4868
4984
|
}
|
|
@@ -4905,7 +5021,7 @@ var MemoryRedemptionHistoryStore = class {
|
|
|
4905
5021
|
};
|
|
4906
5022
|
|
|
4907
5023
|
// src/index.ts
|
|
4908
|
-
var PAFI_ISSUER_SDK_VERSION = true ? "0.
|
|
5024
|
+
var PAFI_ISSUER_SDK_VERSION = true ? "0.25.0" : "dev";
|
|
4909
5025
|
export {
|
|
4910
5026
|
AdapterMisconfiguredError,
|
|
4911
5027
|
AuthError,
|
|
@@ -4913,6 +5029,7 @@ export {
|
|
|
4913
5029
|
BundlerNotConfiguredError,
|
|
4914
5030
|
BundlerRejectedError,
|
|
4915
5031
|
BurnIndexer,
|
|
5032
|
+
BurnIndexerFinalizeError,
|
|
4916
5033
|
ConfigurationError,
|
|
4917
5034
|
DEFAULT_REDEMPTION_POLICY,
|
|
4918
5035
|
DefaultPolicyEngine,
|
|
@@ -4944,6 +5061,7 @@ export {
|
|
|
4944
5061
|
PerpDepositError,
|
|
4945
5062
|
PerpDepositHandler,
|
|
4946
5063
|
PointIndexer,
|
|
5064
|
+
PointIndexerFinalizeError,
|
|
4947
5065
|
PointTokenDomainResolver,
|
|
4948
5066
|
PolicyProvider,
|
|
4949
5067
|
REDEMPTION_HISTORY_WINDOW_SEC,
|