@pafi-dev/issuer 0.20.0 → 0.22.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/README.md +48 -7
- package/dist/index.cjs +188 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +195 -19
- package/dist/index.d.ts +195 -19
- package/dist/index.js +182 -54
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
package/dist/index.cjs
CHANGED
|
@@ -57,6 +57,7 @@ __export(index_exports, {
|
|
|
57
57
|
PerpDepositError: () => PerpDepositError,
|
|
58
58
|
PerpDepositHandler: () => PerpDepositHandler,
|
|
59
59
|
PointIndexer: () => PointIndexer,
|
|
60
|
+
PointTokenDomainResolver: () => PointTokenDomainResolver,
|
|
60
61
|
PolicyProvider: () => PolicyProvider,
|
|
61
62
|
REDEMPTION_HISTORY_WINDOW_SEC: () => REDEMPTION_HISTORY_WINDOW_SEC,
|
|
62
63
|
RedemptionService: () => RedemptionService,
|
|
@@ -83,6 +84,7 @@ __export(index_exports, {
|
|
|
83
84
|
handleMobilePrepare: () => handleMobilePrepare,
|
|
84
85
|
handleMobileSubmit: () => handleMobileSubmit,
|
|
85
86
|
handleRedeemStatus: () => handleRedeemStatus,
|
|
87
|
+
makePostgresSingletonLock: () => makePostgresSingletonLock,
|
|
86
88
|
mergePaymasterFields: () => mergePaymasterFields,
|
|
87
89
|
payloadFromGenericError: () => payloadFromGenericError,
|
|
88
90
|
payloadFromHttpException: () => payloadFromHttpException,
|
|
@@ -1624,6 +1626,10 @@ var DEFAULT_BATCH_SIZE2 = 2000n;
|
|
|
1624
1626
|
var DEFAULT_POLL_INTERVAL_MS2 = 5e3;
|
|
1625
1627
|
var BurnIndexer = class {
|
|
1626
1628
|
provider;
|
|
1629
|
+
/**
|
|
1630
|
+
* The PointToken this indexer watches. Exposed so callers can key
|
|
1631
|
+
* leader-election locks / cursor stores by token (audit H-04 fix).
|
|
1632
|
+
*/
|
|
1627
1633
|
pointTokenAddress;
|
|
1628
1634
|
ledger;
|
|
1629
1635
|
cursorStore;
|
|
@@ -1783,6 +1789,45 @@ var BurnIndexer = class {
|
|
|
1783
1789
|
}
|
|
1784
1790
|
};
|
|
1785
1791
|
|
|
1792
|
+
// src/indexer/postgresSingletonLock.ts
|
|
1793
|
+
function makePostgresSingletonLock(runner) {
|
|
1794
|
+
return {
|
|
1795
|
+
async acquire(key) {
|
|
1796
|
+
const lockId = hashKeyToInt64(key);
|
|
1797
|
+
const rows = await runner.query(
|
|
1798
|
+
"SELECT pg_try_advisory_lock($1::bigint) AS got",
|
|
1799
|
+
[lockId]
|
|
1800
|
+
);
|
|
1801
|
+
const got = rows[0]?.got === true;
|
|
1802
|
+
if (!got) return null;
|
|
1803
|
+
return {
|
|
1804
|
+
async release() {
|
|
1805
|
+
try {
|
|
1806
|
+
await runner.query("SELECT pg_advisory_unlock($1::bigint)", [
|
|
1807
|
+
lockId
|
|
1808
|
+
]);
|
|
1809
|
+
} catch {
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1816
|
+
function hashKeyToInt64(key) {
|
|
1817
|
+
const FNV_OFFSET = 0xcbf29ce484222325n;
|
|
1818
|
+
const FNV_PRIME = 0x100000001b3n;
|
|
1819
|
+
const MASK_64 = (1n << 64n) - 1n;
|
|
1820
|
+
let hash = FNV_OFFSET;
|
|
1821
|
+
for (let i = 0; i < key.length; i++) {
|
|
1822
|
+
hash ^= BigInt(key.charCodeAt(i));
|
|
1823
|
+
hash = hash * FNV_PRIME & MASK_64;
|
|
1824
|
+
}
|
|
1825
|
+
const SIGNED_MAX = (1n << 63n) - 1n;
|
|
1826
|
+
const TWO64 = 1n << 64n;
|
|
1827
|
+
const signed = hash > SIGNED_MAX ? hash - TWO64 : hash;
|
|
1828
|
+
return signed.toString();
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1786
1831
|
// src/api/handlers.ts
|
|
1787
1832
|
var import_viem6 = require("viem");
|
|
1788
1833
|
var import_core6 = require("@pafi-dev/core");
|
|
@@ -2143,8 +2188,59 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
|
|
|
2143
2188
|
}
|
|
2144
2189
|
};
|
|
2145
2190
|
|
|
2146
|
-
// src/api/
|
|
2191
|
+
// src/api/pointTokenDomainResolver.ts
|
|
2147
2192
|
var import_viem7 = require("viem");
|
|
2193
|
+
var NAME_ABI = [
|
|
2194
|
+
{
|
|
2195
|
+
type: "function",
|
|
2196
|
+
name: "name",
|
|
2197
|
+
stateMutability: "view",
|
|
2198
|
+
inputs: [],
|
|
2199
|
+
outputs: [{ type: "string" }]
|
|
2200
|
+
}
|
|
2201
|
+
];
|
|
2202
|
+
var PointTokenDomainResolver = class {
|
|
2203
|
+
provider;
|
|
2204
|
+
overrides;
|
|
2205
|
+
cache = /* @__PURE__ */ new Map();
|
|
2206
|
+
constructor(config) {
|
|
2207
|
+
this.provider = config.provider;
|
|
2208
|
+
this.overrides = /* @__PURE__ */ new Map();
|
|
2209
|
+
if (config.overrides) {
|
|
2210
|
+
for (const [addr, name] of Object.entries(config.overrides)) {
|
|
2211
|
+
this.overrides.set((0, import_viem7.getAddress)(addr).toLowerCase(), name);
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
async resolve(pointTokenAddress) {
|
|
2216
|
+
const key = (0, import_viem7.getAddress)(pointTokenAddress).toLowerCase();
|
|
2217
|
+
const cached = this.cache.get(key);
|
|
2218
|
+
if (cached !== void 0) return cached;
|
|
2219
|
+
const override = this.overrides.get(key);
|
|
2220
|
+
if (override !== void 0) {
|
|
2221
|
+
this.cache.set(key, override);
|
|
2222
|
+
return override;
|
|
2223
|
+
}
|
|
2224
|
+
const name = await this.provider.readContract({
|
|
2225
|
+
address: pointTokenAddress,
|
|
2226
|
+
abi: NAME_ABI,
|
|
2227
|
+
functionName: "name"
|
|
2228
|
+
});
|
|
2229
|
+
this.cache.set(key, name);
|
|
2230
|
+
return name;
|
|
2231
|
+
}
|
|
2232
|
+
/** Invalidate one address (after deploy / proxy upgrade) or all. */
|
|
2233
|
+
invalidate(pointTokenAddress) {
|
|
2234
|
+
if (pointTokenAddress) {
|
|
2235
|
+
this.cache.delete((0, import_viem7.getAddress)(pointTokenAddress).toLowerCase());
|
|
2236
|
+
} else {
|
|
2237
|
+
this.cache.clear();
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
};
|
|
2241
|
+
|
|
2242
|
+
// src/api/handlers/ptRedeemHandler.ts
|
|
2243
|
+
var import_viem8 = require("viem");
|
|
2148
2244
|
var import_core7 = require("@pafi-dev/core");
|
|
2149
2245
|
var DEFAULT_REDEEM_LOCK_MS = 15 * 60 * 1e3;
|
|
2150
2246
|
var DEFAULT_SIG_DEADLINE_SEC = 15 * 60;
|
|
@@ -2165,10 +2261,9 @@ var PTRedeemHandler = class {
|
|
|
2165
2261
|
relayService;
|
|
2166
2262
|
provider;
|
|
2167
2263
|
feeService;
|
|
2168
|
-
pointTokenAddress;
|
|
2169
2264
|
batchExecutorAddress;
|
|
2170
2265
|
chainId;
|
|
2171
|
-
|
|
2266
|
+
domainResolver;
|
|
2172
2267
|
burnerSignerWallet;
|
|
2173
2268
|
redeemLockDurationMs;
|
|
2174
2269
|
signatureDeadlineSeconds;
|
|
@@ -2205,10 +2300,9 @@ var PTRedeemHandler = class {
|
|
|
2205
2300
|
this.relayService = config.relayService;
|
|
2206
2301
|
this.provider = config.provider;
|
|
2207
2302
|
this.feeService = config.feeService;
|
|
2208
|
-
this.
|
|
2209
|
-
this.batchExecutorAddress = (0, import_viem7.getAddress)(config.batchExecutorAddress);
|
|
2303
|
+
this.batchExecutorAddress = (0, import_viem8.getAddress)(config.batchExecutorAddress);
|
|
2210
2304
|
this.chainId = config.chainId;
|
|
2211
|
-
this.
|
|
2305
|
+
this.domainResolver = config.domainResolver;
|
|
2212
2306
|
this.burnerSignerWallet = config.burnerSignerWallet;
|
|
2213
2307
|
if (this.burnerSignerWallet?.account?.type === "local") {
|
|
2214
2308
|
console.warn("[PAFI] PTRedeemHandler: burnerSignerWallet uses a local (private key) account. Use a KMS-backed signer in production.");
|
|
@@ -2221,7 +2315,7 @@ var PTRedeemHandler = class {
|
|
|
2221
2315
|
}
|
|
2222
2316
|
}
|
|
2223
2317
|
async handle(request) {
|
|
2224
|
-
if ((0,
|
|
2318
|
+
if ((0, import_viem8.getAddress)(request.authenticatedAddress) !== (0, import_viem8.getAddress)(request.userAddress)) {
|
|
2225
2319
|
throw new PTRedeemError(
|
|
2226
2320
|
"UNAUTHORIZED",
|
|
2227
2321
|
`userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`
|
|
@@ -2230,11 +2324,12 @@ var PTRedeemHandler = class {
|
|
|
2230
2324
|
if (request.amount <= 0n) {
|
|
2231
2325
|
throw new PTRedeemError("INVALID_AMOUNT", "redeem amount must be positive");
|
|
2232
2326
|
}
|
|
2327
|
+
const pointTokenAddress = (0, import_viem8.getAddress)(request.pointTokenAddress);
|
|
2233
2328
|
if (this.redemptionService) {
|
|
2234
2329
|
const decision = await this.redemptionService.evaluate(
|
|
2235
2330
|
request.userAddress,
|
|
2236
2331
|
request.amount,
|
|
2237
|
-
|
|
2332
|
+
pointTokenAddress
|
|
2238
2333
|
);
|
|
2239
2334
|
if (!decision.allowed) {
|
|
2240
2335
|
const denial = decision.denial;
|
|
@@ -2248,7 +2343,7 @@ var PTRedeemHandler = class {
|
|
|
2248
2343
|
let burnNonce;
|
|
2249
2344
|
try {
|
|
2250
2345
|
burnNonce = await this.provider.readContract({
|
|
2251
|
-
address:
|
|
2346
|
+
address: pointTokenAddress,
|
|
2252
2347
|
abi: import_core7.POINT_TOKEN_ABI,
|
|
2253
2348
|
functionName: "burnRequestNonces",
|
|
2254
2349
|
args: [request.userAddress]
|
|
@@ -2259,27 +2354,27 @@ var PTRedeemHandler = class {
|
|
|
2259
2354
|
`failed to read burnRequestNonces(${request.userAddress}): ${err instanceof Error ? err.message : String(err)}`
|
|
2260
2355
|
);
|
|
2261
2356
|
}
|
|
2262
|
-
const
|
|
2263
|
-
let userNonces = this.inFlightNonces.get(
|
|
2357
|
+
const nonceKey = `${(0, import_viem8.getAddress)(request.userAddress).toLowerCase()}:${pointTokenAddress.toLowerCase()}`;
|
|
2358
|
+
let userNonces = this.inFlightNonces.get(nonceKey);
|
|
2264
2359
|
if (!userNonces) {
|
|
2265
2360
|
userNonces = /* @__PURE__ */ new Set();
|
|
2266
|
-
this.inFlightNonces.set(
|
|
2361
|
+
this.inFlightNonces.set(nonceKey, userNonces);
|
|
2267
2362
|
}
|
|
2268
2363
|
if (userNonces.has(burnNonce)) {
|
|
2269
2364
|
throw new PTRedeemError(
|
|
2270
2365
|
"NONCE_IN_FLIGHT",
|
|
2271
|
-
`A burn request for nonce ${burnNonce} is already in progress for ${request.userAddress}. Retry after the current request completes.`
|
|
2366
|
+
`A burn request for nonce ${burnNonce} is already in progress for ${request.userAddress} on ${pointTokenAddress}. Retry after the current request completes.`
|
|
2272
2367
|
);
|
|
2273
2368
|
}
|
|
2274
2369
|
userNonces.add(burnNonce);
|
|
2275
2370
|
try {
|
|
2276
|
-
return await this._handleAfterNonceLock(request, burnNonce);
|
|
2371
|
+
return await this._handleAfterNonceLock(request, burnNonce, pointTokenAddress);
|
|
2277
2372
|
} finally {
|
|
2278
2373
|
userNonces.delete(burnNonce);
|
|
2279
|
-
if (userNonces.size === 0) this.inFlightNonces.delete(
|
|
2374
|
+
if (userNonces.size === 0) this.inFlightNonces.delete(nonceKey);
|
|
2280
2375
|
}
|
|
2281
2376
|
}
|
|
2282
|
-
async _handleAfterNonceLock(request, burnNonce) {
|
|
2377
|
+
async _handleAfterNonceLock(request, burnNonce, pointTokenAddress) {
|
|
2283
2378
|
const previewDeadline = BigInt(
|
|
2284
2379
|
Math.floor(this.now() / 1e3) + this.signatureDeadlineSeconds
|
|
2285
2380
|
);
|
|
@@ -2290,13 +2385,13 @@ var PTRedeemHandler = class {
|
|
|
2290
2385
|
const previewUserOp = this.relayService.previewBurnUserOp({
|
|
2291
2386
|
userAddress: request.userAddress,
|
|
2292
2387
|
aaNonce: burnNonce,
|
|
2293
|
-
pointTokenAddress
|
|
2388
|
+
pointTokenAddress,
|
|
2294
2389
|
amount: request.amount,
|
|
2295
2390
|
deadline: previewDeadline
|
|
2296
2391
|
});
|
|
2297
2392
|
fee = await this.feeService.estimateGasFee({
|
|
2298
2393
|
scenario: "burn",
|
|
2299
|
-
contractAddress:
|
|
2394
|
+
contractAddress: pointTokenAddress,
|
|
2300
2395
|
partialUserOp: {
|
|
2301
2396
|
sender: previewUserOp.sender,
|
|
2302
2397
|
nonce: previewUserOp.nonce,
|
|
@@ -2315,7 +2410,7 @@ var PTRedeemHandler = class {
|
|
|
2315
2410
|
}
|
|
2316
2411
|
const onChainBalance = await (0, import_core7.getPointTokenBalance)(
|
|
2317
2412
|
this.provider,
|
|
2318
|
-
|
|
2413
|
+
pointTokenAddress,
|
|
2319
2414
|
request.userAddress
|
|
2320
2415
|
);
|
|
2321
2416
|
if (onChainBalance < request.amount) {
|
|
@@ -2325,10 +2420,11 @@ var PTRedeemHandler = class {
|
|
|
2325
2420
|
);
|
|
2326
2421
|
}
|
|
2327
2422
|
const deadline = previewDeadline;
|
|
2423
|
+
const domainName = await this.domainResolver.resolve(pointTokenAddress);
|
|
2328
2424
|
const domain = {
|
|
2329
|
-
name:
|
|
2425
|
+
name: domainName,
|
|
2330
2426
|
chainId: this.chainId,
|
|
2331
|
-
verifyingContract:
|
|
2427
|
+
verifyingContract: pointTokenAddress
|
|
2332
2428
|
};
|
|
2333
2429
|
const sponsoredBurnAmount = request.amount - fee;
|
|
2334
2430
|
const sponsoredBurnRequest = {
|
|
@@ -2350,14 +2446,14 @@ var PTRedeemHandler = class {
|
|
|
2350
2446
|
request.userAddress,
|
|
2351
2447
|
sponsoredBurnAmount,
|
|
2352
2448
|
this.redeemLockDurationMs,
|
|
2353
|
-
|
|
2449
|
+
pointTokenAddress
|
|
2354
2450
|
);
|
|
2355
2451
|
try {
|
|
2356
2452
|
const sponsoredUserOp = await this.relayService.prepareBurn({
|
|
2357
2453
|
mode: "burnWithSig",
|
|
2358
2454
|
userAddress: request.userAddress,
|
|
2359
2455
|
aaNonce: request.aaNonce,
|
|
2360
|
-
pointTokenAddress
|
|
2456
|
+
pointTokenAddress,
|
|
2361
2457
|
batchExecutorAddress: this.batchExecutorAddress,
|
|
2362
2458
|
burnRequest: sponsoredBurnRequest,
|
|
2363
2459
|
burnerSignature: sponsoredSig,
|
|
@@ -2385,7 +2481,7 @@ var PTRedeemHandler = class {
|
|
|
2385
2481
|
request.userAddress,
|
|
2386
2482
|
request.amount,
|
|
2387
2483
|
this.redeemLockDurationMs,
|
|
2388
|
-
|
|
2484
|
+
pointTokenAddress
|
|
2389
2485
|
);
|
|
2390
2486
|
let fallbackUserOp;
|
|
2391
2487
|
try {
|
|
@@ -2393,7 +2489,7 @@ var PTRedeemHandler = class {
|
|
|
2393
2489
|
mode: "burnWithSig",
|
|
2394
2490
|
userAddress: request.userAddress,
|
|
2395
2491
|
aaNonce: request.aaNonce,
|
|
2396
|
-
pointTokenAddress
|
|
2492
|
+
pointTokenAddress,
|
|
2397
2493
|
batchExecutorAddress: this.batchExecutorAddress,
|
|
2398
2494
|
burnRequest: fallbackBurnRequest,
|
|
2399
2495
|
burnerSignature: fallbackSig,
|
|
@@ -2418,7 +2514,7 @@ var PTRedeemHandler = class {
|
|
|
2418
2514
|
await this.redemptionService.recordSuccessfulInitiate({
|
|
2419
2515
|
user: request.userAddress,
|
|
2420
2516
|
amountPt: request.amount,
|
|
2421
|
-
pointTokenAddress
|
|
2517
|
+
pointTokenAddress,
|
|
2422
2518
|
reservationId: sponsoredLockId
|
|
2423
2519
|
}).catch(() => {
|
|
2424
2520
|
});
|
|
@@ -2541,7 +2637,7 @@ async function handleRedeemStatus(params) {
|
|
|
2541
2637
|
}
|
|
2542
2638
|
|
|
2543
2639
|
// src/api/mobileHandlers.ts
|
|
2544
|
-
var
|
|
2640
|
+
var import_viem9 = require("viem");
|
|
2545
2641
|
var import_core10 = require("@pafi-dev/core");
|
|
2546
2642
|
|
|
2547
2643
|
// src/userop-store/serialize.ts
|
|
@@ -2887,7 +2983,7 @@ async function handleMobileSubmit(params) {
|
|
|
2887
2983
|
if (!entry) {
|
|
2888
2984
|
throw new PendingUserOpNotFoundError(params.lockId);
|
|
2889
2985
|
}
|
|
2890
|
-
if ((0,
|
|
2986
|
+
if ((0, import_viem9.getAddress)(entry.sender) !== (0, import_viem9.getAddress)(params.authenticatedAddress)) {
|
|
2891
2987
|
throw new PendingUserOpForbiddenError(params.lockId);
|
|
2892
2988
|
}
|
|
2893
2989
|
const variant = params.variant ?? "sponsored";
|
|
@@ -2903,7 +2999,7 @@ async function handleMobileSubmit(params) {
|
|
|
2903
2999
|
}
|
|
2904
3000
|
|
|
2905
3001
|
// src/api/handlers/ptClaimHandler.ts
|
|
2906
|
-
var
|
|
3002
|
+
var import_viem10 = require("viem");
|
|
2907
3003
|
var import_core11 = require("@pafi-dev/core");
|
|
2908
3004
|
|
|
2909
3005
|
// src/issuer-state/types.ts
|
|
@@ -2949,7 +3045,7 @@ var PTClaimHandler = class {
|
|
|
2949
3045
|
};
|
|
2950
3046
|
}
|
|
2951
3047
|
async handle(request) {
|
|
2952
|
-
if ((0,
|
|
3048
|
+
if ((0, import_viem10.getAddress)(request.authenticatedAddress) !== (0, import_viem10.getAddress)(request.userAddress)) {
|
|
2953
3049
|
throw new PTClaimError(
|
|
2954
3050
|
"VALIDATION_FAILED",
|
|
2955
3051
|
`userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`
|
|
@@ -3004,8 +3100,11 @@ var PTClaimHandler = class {
|
|
|
3004
3100
|
callData: previewUserOp.callData
|
|
3005
3101
|
}
|
|
3006
3102
|
}) : 0n;
|
|
3103
|
+
const domainName = await this.cfg.domainResolver.resolve(
|
|
3104
|
+
request.pointTokenAddress
|
|
3105
|
+
);
|
|
3007
3106
|
const domain = {
|
|
3008
|
-
name:
|
|
3107
|
+
name: domainName,
|
|
3009
3108
|
chainId: request.chainId,
|
|
3010
3109
|
verifyingContract: request.pointTokenAddress
|
|
3011
3110
|
};
|
|
@@ -3021,8 +3120,16 @@ var PTClaimHandler = class {
|
|
|
3021
3120
|
domain,
|
|
3022
3121
|
mintRequestNonce: request.mintRequestNonce,
|
|
3023
3122
|
deadline: signatureDeadline,
|
|
3024
|
-
mintFeeWrapperAddress: resolvedWrapper
|
|
3025
|
-
//
|
|
3123
|
+
mintFeeWrapperAddress: resolvedWrapper,
|
|
3124
|
+
// Pass the bundler-estimated `feeAmount` explicitly so the
|
|
3125
|
+
// RelayService skips its legacy `quoteOperatorFeePt` path
|
|
3126
|
+
// (which uses the SDK's old 12_000 bps premium default).
|
|
3127
|
+
// Without this, the response's `feeAmount` (from FeeManager,
|
|
3128
|
+
// 100% premium on top of PAFI's 110% server-side estimate)
|
|
3129
|
+
// would diverge from the actual PT.transfer amount in the
|
|
3130
|
+
// UserOp batch (`quoteOperatorFeePt`'s 120%), and the user
|
|
3131
|
+
// would see one value while the wallet transferred another.
|
|
3132
|
+
feeAmount
|
|
3026
3133
|
});
|
|
3027
3134
|
} catch (err) {
|
|
3028
3135
|
throw new PTClaimError(
|
|
@@ -3203,7 +3310,7 @@ var PerpDepositHandler = class {
|
|
|
3203
3310
|
|
|
3204
3311
|
// src/api/delegateHandler.ts
|
|
3205
3312
|
var import_core13 = require("@pafi-dev/core");
|
|
3206
|
-
var
|
|
3313
|
+
var import_viem11 = require("viem");
|
|
3207
3314
|
var DEFAULT_DELEGATE_GAS = {
|
|
3208
3315
|
callGasLimit: 100000n,
|
|
3209
3316
|
verificationGasLimit: 150000n,
|
|
@@ -3290,7 +3397,7 @@ async function handleDelegateSubmit(params) {
|
|
|
3290
3397
|
if (!entry) {
|
|
3291
3398
|
throw new PendingUserOpNotFoundError(params.lockId);
|
|
3292
3399
|
}
|
|
3293
|
-
if ((0,
|
|
3400
|
+
if ((0, import_viem11.getAddress)(entry.sender) !== (0, import_viem11.getAddress)(params.authenticatedAddress)) {
|
|
3294
3401
|
throw new PendingUserOpForbiddenError(params.lockId);
|
|
3295
3402
|
}
|
|
3296
3403
|
if (!entry.eip7702Auth) {
|
|
@@ -3311,7 +3418,7 @@ async function handleDelegateSubmit(params) {
|
|
|
3311
3418
|
|
|
3312
3419
|
// src/api/issuerApiAdapter.ts
|
|
3313
3420
|
var import_node_crypto3 = require("crypto");
|
|
3314
|
-
var
|
|
3421
|
+
var import_viem12 = require("viem");
|
|
3315
3422
|
var import_core14 = require("@pafi-dev/core");
|
|
3316
3423
|
var AdapterMisconfiguredError = class extends Error {
|
|
3317
3424
|
code = "ADAPTER_MISCONFIGURED";
|
|
@@ -3369,7 +3476,7 @@ var IssuerApiAdapter = class {
|
|
|
3369
3476
|
async pools(authenticatedAddress, chainId, pointTokenAddress) {
|
|
3370
3477
|
const result = await this.cfg.issuerService.api.handlePools(
|
|
3371
3478
|
authenticatedAddress,
|
|
3372
|
-
{ chainId, pointTokenAddress: (0,
|
|
3479
|
+
{ chainId, pointTokenAddress: (0, import_viem12.getAddress)(pointTokenAddress) }
|
|
3373
3480
|
);
|
|
3374
3481
|
return { pools: result.pools };
|
|
3375
3482
|
}
|
|
@@ -3378,8 +3485,8 @@ var IssuerApiAdapter = class {
|
|
|
3378
3485
|
authenticatedAddress,
|
|
3379
3486
|
{
|
|
3380
3487
|
chainId,
|
|
3381
|
-
userAddress: (0,
|
|
3382
|
-
pointTokenAddress: (0,
|
|
3488
|
+
userAddress: (0, import_viem12.getAddress)(userAddress),
|
|
3489
|
+
pointTokenAddress: (0, import_viem12.getAddress)(pointTokenAddress)
|
|
3383
3490
|
}
|
|
3384
3491
|
);
|
|
3385
3492
|
return {
|
|
@@ -3400,7 +3507,7 @@ var IssuerApiAdapter = class {
|
|
|
3400
3507
|
"ptClaimHandler",
|
|
3401
3508
|
"claim"
|
|
3402
3509
|
);
|
|
3403
|
-
const pointTokenAddress = (0,
|
|
3510
|
+
const pointTokenAddress = (0, import_viem12.getAddress)(input.pointTokenAddress);
|
|
3404
3511
|
const result = await ptClaimHandler.handle({
|
|
3405
3512
|
authenticatedAddress: input.authenticatedAddress,
|
|
3406
3513
|
userAddress: input.authenticatedAddress,
|
|
@@ -3427,9 +3534,11 @@ var IssuerApiAdapter = class {
|
|
|
3427
3534
|
}
|
|
3428
3535
|
async redeem(input) {
|
|
3429
3536
|
this.assertRedeemHandler();
|
|
3537
|
+
const pointTokenAddress = (0, import_viem12.getAddress)(input.pointTokenAddress);
|
|
3430
3538
|
const response = await this.cfg.ptRedeemHandler.handle({
|
|
3431
3539
|
userAddress: input.authenticatedAddress,
|
|
3432
3540
|
authenticatedAddress: input.authenticatedAddress,
|
|
3541
|
+
pointTokenAddress,
|
|
3433
3542
|
amount: input.amount,
|
|
3434
3543
|
aaNonce: input.aaNonce,
|
|
3435
3544
|
chainId: input.chainId
|
|
@@ -3495,7 +3604,7 @@ var IssuerApiAdapter = class {
|
|
|
3495
3604
|
"ptClaimHandler",
|
|
3496
3605
|
"claimPrepare"
|
|
3497
3606
|
);
|
|
3498
|
-
const pointTokenAddress = (0,
|
|
3607
|
+
const pointTokenAddress = (0, import_viem12.getAddress)(input.pointTokenAddress);
|
|
3499
3608
|
const claimResult = await ptClaimHandler.handle({
|
|
3500
3609
|
authenticatedAddress: input.authenticatedAddress,
|
|
3501
3610
|
userAddress: input.authenticatedAddress,
|
|
@@ -3541,10 +3650,11 @@ var IssuerApiAdapter = class {
|
|
|
3541
3650
|
}
|
|
3542
3651
|
async redeemPrepare(input) {
|
|
3543
3652
|
this.assertRedeemHandler();
|
|
3544
|
-
const pointTokenAddress = (0,
|
|
3653
|
+
const pointTokenAddress = (0, import_viem12.getAddress)(input.pointTokenAddress);
|
|
3545
3654
|
const redeemResponse = await this.cfg.ptRedeemHandler.handle({
|
|
3546
3655
|
userAddress: input.authenticatedAddress,
|
|
3547
3656
|
authenticatedAddress: input.authenticatedAddress,
|
|
3657
|
+
pointTokenAddress,
|
|
3548
3658
|
amount: input.amount,
|
|
3549
3659
|
aaNonce: input.aaNonce,
|
|
3550
3660
|
chainId: input.chainId
|
|
@@ -3731,7 +3841,7 @@ var IssuerApiAdapter = class {
|
|
|
3731
3841
|
};
|
|
3732
3842
|
|
|
3733
3843
|
// src/pools/subgraphPoolsProvider.ts
|
|
3734
|
-
var
|
|
3844
|
+
var import_viem13 = require("viem");
|
|
3735
3845
|
var import_core15 = require("@pafi-dev/core");
|
|
3736
3846
|
var DEFAULT_CACHE_TTL_MS = 3e4;
|
|
3737
3847
|
var MAX_REASONABLE_FEE_TIER = 1e6;
|
|
@@ -3854,7 +3964,7 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress,
|
|
|
3854
3964
|
return [];
|
|
3855
3965
|
}
|
|
3856
3966
|
const { pool } = token;
|
|
3857
|
-
if (!(0,
|
|
3967
|
+
if (!(0, import_viem13.isAddress)(pool.token0.id) || !(0, import_viem13.isAddress)(pool.token1.id)) {
|
|
3858
3968
|
const error = new Error(
|
|
3859
3969
|
"[PAFI] SubgraphPoolsProvider: invalid token address in response"
|
|
3860
3970
|
);
|
|
@@ -4007,8 +4117,8 @@ function toUsdtPerNative(priceFloat, usdtDecimals) {
|
|
|
4007
4117
|
}
|
|
4008
4118
|
|
|
4009
4119
|
// src/pools/nativePtQuoter.ts
|
|
4010
|
-
var
|
|
4011
|
-
var CHAINLINK_ABI = (0,
|
|
4120
|
+
var import_viem14 = require("viem");
|
|
4121
|
+
var CHAINLINK_ABI = (0, import_viem14.parseAbi)([
|
|
4012
4122
|
"function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)"
|
|
4013
4123
|
]);
|
|
4014
4124
|
var CHAINLINK_MAX_AGE_S = 3600n;
|
|
@@ -4292,7 +4402,7 @@ var PafiBackendClient = class {
|
|
|
4292
4402
|
};
|
|
4293
4403
|
|
|
4294
4404
|
// src/config.ts
|
|
4295
|
-
var
|
|
4405
|
+
var import_viem15 = require("viem");
|
|
4296
4406
|
var import_core18 = require("@pafi-dev/core");
|
|
4297
4407
|
|
|
4298
4408
|
// src/redemption/evaluator.ts
|
|
@@ -4600,7 +4710,7 @@ var RedemptionService = class {
|
|
|
4600
4710
|
};
|
|
4601
4711
|
|
|
4602
4712
|
// src/config.ts
|
|
4603
|
-
function createIssuerService(config) {
|
|
4713
|
+
async function createIssuerService(config) {
|
|
4604
4714
|
if (!config.provider) {
|
|
4605
4715
|
throw new Error("createIssuerService: provider is required");
|
|
4606
4716
|
}
|
|
@@ -4619,7 +4729,7 @@ function createIssuerService(config) {
|
|
|
4619
4729
|
"createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
|
|
4620
4730
|
);
|
|
4621
4731
|
}
|
|
4622
|
-
const tokenAddresses = rawAddresses.map((a) => (0,
|
|
4732
|
+
const tokenAddresses = rawAddresses.map((a) => (0, import_viem15.getAddress)(a));
|
|
4623
4733
|
const ledger = config.ledger;
|
|
4624
4734
|
const sessionStore = config.sessionStore ?? new MemorySessionStore();
|
|
4625
4735
|
const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
|
|
@@ -4719,9 +4829,26 @@ function createIssuerService(config) {
|
|
|
4719
4829
|
handlersConfig.mintFeeWrapperAddress = resolvedWrapperAddress;
|
|
4720
4830
|
}
|
|
4721
4831
|
const handlers = new IssuerApiHandlers(handlersConfig);
|
|
4832
|
+
const indexerLeaderLocks = [];
|
|
4722
4833
|
if (config.indexer?.autoStart) {
|
|
4723
|
-
|
|
4724
|
-
|
|
4834
|
+
const lock = config.indexer.singletonLock;
|
|
4835
|
+
if (!lock) {
|
|
4836
|
+
console.warn(
|
|
4837
|
+
"[@pafi-dev/issuer] indexer.autoStart=true without singletonLock \u2014 this is UNSAFE in multi-replica deployments (audit finding H-04). 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."
|
|
4838
|
+
);
|
|
4839
|
+
for (const idx of indexers.values()) {
|
|
4840
|
+
idx.start();
|
|
4841
|
+
}
|
|
4842
|
+
} else {
|
|
4843
|
+
for (const [tokenAddr, idx] of indexers.entries()) {
|
|
4844
|
+
const key = `pafi-issuer:point-indexer:${tokenAddr.toLowerCase()}`;
|
|
4845
|
+
const handle = await lock.acquire(key);
|
|
4846
|
+
if (!handle) {
|
|
4847
|
+
continue;
|
|
4848
|
+
}
|
|
4849
|
+
idx.start();
|
|
4850
|
+
indexerLeaderLocks.push(handle);
|
|
4851
|
+
}
|
|
4725
4852
|
}
|
|
4726
4853
|
}
|
|
4727
4854
|
return {
|
|
@@ -4732,13 +4859,14 @@ function createIssuerService(config) {
|
|
|
4732
4859
|
relay: relayService,
|
|
4733
4860
|
fee: feeManager,
|
|
4734
4861
|
indexers,
|
|
4862
|
+
indexerLeaderLocks,
|
|
4735
4863
|
api: handlers,
|
|
4736
4864
|
redemption
|
|
4737
4865
|
};
|
|
4738
4866
|
}
|
|
4739
4867
|
|
|
4740
4868
|
// src/issuer-state/validator.ts
|
|
4741
|
-
var
|
|
4869
|
+
var import_viem16 = require("viem");
|
|
4742
4870
|
var import_core19 = require("@pafi-dev/core");
|
|
4743
4871
|
var ISSUER_RECORD_TTL_MS = 3e4;
|
|
4744
4872
|
var IssuerStateValidator = class _IssuerStateValidator {
|
|
@@ -4765,7 +4893,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
4765
4893
|
*/
|
|
4766
4894
|
invalidate(pointToken) {
|
|
4767
4895
|
if (pointToken) {
|
|
4768
|
-
const key = (0,
|
|
4896
|
+
const key = (0, import_viem16.getAddress)(pointToken);
|
|
4769
4897
|
this.pointTokenIssuerCache.delete(key);
|
|
4770
4898
|
this.stateCache.delete(key);
|
|
4771
4899
|
this.inflight.delete(key);
|
|
@@ -4780,7 +4908,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
4780
4908
|
* The issuer field is set at `initialize()` and never changes.
|
|
4781
4909
|
*/
|
|
4782
4910
|
async getIssuerAddressForPointToken(pointToken) {
|
|
4783
|
-
const key = (0,
|
|
4911
|
+
const key = (0, import_viem16.getAddress)(pointToken);
|
|
4784
4912
|
const cached = this.pointTokenIssuerCache.get(key);
|
|
4785
4913
|
if (cached) return cached;
|
|
4786
4914
|
const issuer = await this.provider.readContract({
|
|
@@ -4788,15 +4916,15 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
4788
4916
|
abi: import_core19.POINT_TOKEN_ABI,
|
|
4789
4917
|
functionName: "issuer"
|
|
4790
4918
|
});
|
|
4791
|
-
this.pointTokenIssuerCache.set(key, (0,
|
|
4792
|
-
return (0,
|
|
4919
|
+
this.pointTokenIssuerCache.set(key, (0, import_viem16.getAddress)(issuer));
|
|
4920
|
+
return (0, import_viem16.getAddress)(issuer);
|
|
4793
4921
|
}
|
|
4794
4922
|
/**
|
|
4795
4923
|
* Read registry record + totalSupply, with 30s cache and in-flight
|
|
4796
4924
|
* deduplication. Does NOT throw on inactive/missing — returns raw state.
|
|
4797
4925
|
*/
|
|
4798
4926
|
async getIssuerState(pointToken) {
|
|
4799
|
-
const tokenAddr = (0,
|
|
4927
|
+
const tokenAddr = (0, import_viem16.getAddress)(pointToken);
|
|
4800
4928
|
const now = Date.now();
|
|
4801
4929
|
const cached = this.stateCache.get(tokenAddr);
|
|
4802
4930
|
if (cached && cached.expiresAt > now) return cached.value;
|
|
@@ -4939,7 +5067,7 @@ var MemoryRedemptionHistoryStore = class {
|
|
|
4939
5067
|
};
|
|
4940
5068
|
|
|
4941
5069
|
// src/index.ts
|
|
4942
|
-
var PAFI_ISSUER_SDK_VERSION = true ? "0.
|
|
5070
|
+
var PAFI_ISSUER_SDK_VERSION = true ? "0.22.0" : "dev";
|
|
4943
5071
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4944
5072
|
0 && (module.exports = {
|
|
4945
5073
|
AdapterMisconfiguredError,
|
|
@@ -4979,6 +5107,7 @@ var PAFI_ISSUER_SDK_VERSION = true ? "0.20.0" : "dev";
|
|
|
4979
5107
|
PerpDepositError,
|
|
4980
5108
|
PerpDepositHandler,
|
|
4981
5109
|
PointIndexer,
|
|
5110
|
+
PointTokenDomainResolver,
|
|
4982
5111
|
PolicyProvider,
|
|
4983
5112
|
REDEMPTION_HISTORY_WINDOW_SEC,
|
|
4984
5113
|
RedemptionService,
|
|
@@ -5005,6 +5134,7 @@ var PAFI_ISSUER_SDK_VERSION = true ? "0.20.0" : "dev";
|
|
|
5005
5134
|
handleMobilePrepare,
|
|
5006
5135
|
handleMobileSubmit,
|
|
5007
5136
|
handleRedeemStatus,
|
|
5137
|
+
makePostgresSingletonLock,
|
|
5008
5138
|
mergePaymasterFields,
|
|
5009
5139
|
payloadFromGenericError,
|
|
5010
5140
|
payloadFromHttpException,
|