@pafi-dev/issuer 0.5.9 → 0.5.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -28,6 +28,8 @@ __export(index_exports, {
28
28
  FeeManager: () => FeeManager,
29
29
  InMemoryCursorStore: () => InMemoryCursorStore,
30
30
  IssuerApiHandlers: () => IssuerApiHandlers,
31
+ IssuerStateError: () => IssuerStateError,
32
+ IssuerStateValidator: () => IssuerStateValidator,
31
33
  MemorySessionStore: () => MemorySessionStore,
32
34
  NonceManager: () => NonceManager,
33
35
  PAFI_ISSUER_SDK_VERSION: () => PAFI_ISSUER_SDK_VERSION,
@@ -44,7 +46,8 @@ __export(index_exports, {
44
46
  authenticateRequest: () => authenticateRequest,
45
47
  createIssuerService: () => createIssuerService,
46
48
  createSubgraphNativeUsdtQuoter: () => createSubgraphNativeUsdtQuoter,
47
- createSubgraphPoolsProvider: () => createSubgraphPoolsProvider
49
+ createSubgraphPoolsProvider: () => createSubgraphPoolsProvider,
50
+ serializeEntryToJsonRpc: () => serializeEntryToJsonRpc
48
51
  });
49
52
  module.exports = __toCommonJS(index_exports);
50
53
 
@@ -2093,6 +2096,198 @@ function createIssuerService(config) {
2093
2096
  };
2094
2097
  }
2095
2098
 
2099
+ // src/userop-store/serialize.ts
2100
+ var import_core9 = require("@pafi-dev/core");
2101
+ function serializeEntryToJsonRpc(entry, signature) {
2102
+ return (0, import_core9.serializeUserOpToJsonRpc)(
2103
+ {
2104
+ sender: entry.sender,
2105
+ nonce: BigInt(entry.nonce),
2106
+ callData: entry.callData,
2107
+ callGasLimit: BigInt(entry.callGasLimit),
2108
+ verificationGasLimit: BigInt(entry.verificationGasLimit),
2109
+ preVerificationGas: BigInt(entry.preVerificationGas),
2110
+ maxFeePerGas: BigInt(entry.maxFeePerGas),
2111
+ maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas),
2112
+ paymaster: entry.paymaster,
2113
+ paymasterVerificationGasLimit: entry.paymasterVerificationGasLimit != null ? BigInt(entry.paymasterVerificationGasLimit) : void 0,
2114
+ paymasterPostOpGasLimit: entry.paymasterPostOpGasLimit != null ? BigInt(entry.paymasterPostOpGasLimit) : void 0,
2115
+ paymasterData: entry.paymasterData
2116
+ },
2117
+ signature
2118
+ );
2119
+ }
2120
+
2121
+ // src/issuer-state/validator.ts
2122
+ var import_viem11 = require("viem");
2123
+ var import_core10 = require("@pafi-dev/core");
2124
+
2125
+ // src/issuer-state/types.ts
2126
+ var IssuerStateError = class extends Error {
2127
+ constructor(code, message, details) {
2128
+ super(message);
2129
+ this.code = code;
2130
+ this.details = details;
2131
+ this.name = "IssuerStateError";
2132
+ }
2133
+ code;
2134
+ details;
2135
+ };
2136
+
2137
+ // src/issuer-state/validator.ts
2138
+ var ISSUER_RECORD_TTL_MS = 3e4;
2139
+ var IssuerStateValidator = class _IssuerStateValidator {
2140
+ constructor(provider, registryAddress) {
2141
+ this.provider = provider;
2142
+ this.registryAddress = registryAddress;
2143
+ }
2144
+ provider;
2145
+ registryAddress;
2146
+ pointTokenIssuerCache = /* @__PURE__ */ new Map();
2147
+ stateCache = /* @__PURE__ */ new Map();
2148
+ inflight = /* @__PURE__ */ new Map();
2149
+ /**
2150
+ * Convenience factory — reads `registryAddress` from the SDK
2151
+ * `CONTRACT_ADDRESSES` map for the given chain.
2152
+ */
2153
+ static forChain(provider, chainId) {
2154
+ const { issuerRegistry } = (0, import_core10.getContractAddresses)(chainId);
2155
+ return new _IssuerStateValidator(provider, issuerRegistry);
2156
+ }
2157
+ /**
2158
+ * Invalidate cached state for one PointToken, or everything if omitted.
2159
+ * Call after admin txs that change registry or cap settings.
2160
+ */
2161
+ invalidate(pointToken) {
2162
+ if (pointToken) {
2163
+ const key = (0, import_viem11.getAddress)(pointToken);
2164
+ this.pointTokenIssuerCache.delete(key);
2165
+ this.stateCache.delete(key);
2166
+ this.inflight.delete(key);
2167
+ } else {
2168
+ this.pointTokenIssuerCache.clear();
2169
+ this.stateCache.clear();
2170
+ this.inflight.clear();
2171
+ }
2172
+ }
2173
+ /**
2174
+ * Resolve `PointToken.issuer()` once per token and memoize.
2175
+ * The issuer field is set at `initialize()` and never changes.
2176
+ */
2177
+ async getIssuerAddressForPointToken(pointToken) {
2178
+ const key = (0, import_viem11.getAddress)(pointToken);
2179
+ const cached = this.pointTokenIssuerCache.get(key);
2180
+ if (cached) return cached;
2181
+ const issuer = await this.provider.readContract({
2182
+ address: key,
2183
+ abi: import_core10.POINT_TOKEN_V2_ABI,
2184
+ functionName: "issuer"
2185
+ });
2186
+ this.pointTokenIssuerCache.set(key, (0, import_viem11.getAddress)(issuer));
2187
+ return (0, import_viem11.getAddress)(issuer);
2188
+ }
2189
+ /**
2190
+ * Read registry record + totalSupply, with 30s cache and in-flight
2191
+ * deduplication. Does NOT throw on inactive/missing — returns raw state.
2192
+ */
2193
+ async getIssuerState(pointToken) {
2194
+ const tokenAddr = (0, import_viem11.getAddress)(pointToken);
2195
+ const now = Date.now();
2196
+ const cached = this.stateCache.get(tokenAddr);
2197
+ if (cached && cached.expiresAt > now) return cached.value;
2198
+ const existing = this.inflight.get(tokenAddr);
2199
+ if (existing) return existing;
2200
+ const promise = this.fetchIssuerState(tokenAddr).then((state) => {
2201
+ this.stateCache.set(tokenAddr, {
2202
+ value: state,
2203
+ expiresAt: Date.now() + ISSUER_RECORD_TTL_MS
2204
+ });
2205
+ return state;
2206
+ }).finally(() => {
2207
+ this.inflight.delete(tokenAddr);
2208
+ });
2209
+ this.inflight.set(tokenAddr, promise);
2210
+ return promise;
2211
+ }
2212
+ /**
2213
+ * Validate that `amount` PT can be minted on `pointToken` right now.
2214
+ *
2215
+ * Throws `IssuerStateError` with:
2216
+ * - `ISSUER_NOT_REGISTERED` — registry has no record for this issuer
2217
+ * - `ISSUER_INACTIVE` — issuer.active is false
2218
+ * - `MINT_CAP_EXCEEDED` — totalSupply + amount would exceed hardCap
2219
+ *
2220
+ * Returns the fetched state on success so callers can log without a
2221
+ * second RPC round-trip.
2222
+ */
2223
+ async preValidateMint(pointToken, amount) {
2224
+ let state;
2225
+ try {
2226
+ state = await this.getIssuerState(pointToken);
2227
+ } catch (err) {
2228
+ if (err.message.includes("IssuerNotFound")) {
2229
+ throw new IssuerStateError(
2230
+ "ISSUER_NOT_REGISTERED",
2231
+ `IssuerRegistry has no record for PointToken ${pointToken}`,
2232
+ { pointToken }
2233
+ );
2234
+ }
2235
+ throw err;
2236
+ }
2237
+ const { issuer, totalSupply, hardCap, remaining } = state;
2238
+ if (!issuer.active) {
2239
+ throw new IssuerStateError(
2240
+ "ISSUER_INACTIVE",
2241
+ `Issuer ${issuer.issuerAddress} is deactivated on IssuerRegistry`,
2242
+ { issuer: issuer.issuerAddress, pointToken: issuer.pointToken }
2243
+ );
2244
+ }
2245
+ if (totalSupply + amount > hardCap) {
2246
+ throw new IssuerStateError(
2247
+ "MINT_CAP_EXCEEDED",
2248
+ `Requested ${amount} PT would exceed mint cap. Cap=${hardCap}, minted=${totalSupply}, remaining=${remaining}`,
2249
+ {
2250
+ requested: amount.toString(),
2251
+ cap: hardCap.toString(),
2252
+ minted: totalSupply.toString(),
2253
+ remaining: remaining.toString()
2254
+ }
2255
+ );
2256
+ }
2257
+ return state;
2258
+ }
2259
+ async fetchIssuerState(tokenAddr) {
2260
+ const issuerAddr = await this.getIssuerAddressForPointToken(tokenAddr);
2261
+ const [tuple, totalSupply] = await Promise.all([
2262
+ this.provider.readContract({
2263
+ address: this.registryAddress,
2264
+ abi: import_core10.issuerRegistryAbi,
2265
+ functionName: "getIssuer",
2266
+ args: [issuerAddr]
2267
+ }),
2268
+ this.provider.readContract({
2269
+ address: tokenAddr,
2270
+ abi: import_core10.POINT_TOKEN_V2_ABI,
2271
+ functionName: "totalSupply"
2272
+ })
2273
+ ]);
2274
+ const issuer = {
2275
+ issuerAddress: tuple[0],
2276
+ signerAddress: tuple[1],
2277
+ name: tuple[2],
2278
+ symbol: tuple[3],
2279
+ declaredTotalSupply: tuple[4],
2280
+ capBasisPoints: tuple[5],
2281
+ active: tuple[6],
2282
+ pointToken: tuple[7],
2283
+ mintingOracle: tuple[8]
2284
+ };
2285
+ const hardCap = issuer.declaredTotalSupply * BigInt(issuer.capBasisPoints) / 10000n;
2286
+ const remaining = hardCap > totalSupply ? hardCap - totalSupply : 0n;
2287
+ return { issuer, totalSupply, hardCap, remaining };
2288
+ }
2289
+ };
2290
+
2096
2291
  // src/index.ts
2097
2292
  var PAFI_ISSUER_SDK_VERSION = "0.4.0";
2098
2293
  // Annotate the CommonJS export names for ESM import in node:
@@ -2105,6 +2300,8 @@ var PAFI_ISSUER_SDK_VERSION = "0.4.0";
2105
2300
  FeeManager,
2106
2301
  InMemoryCursorStore,
2107
2302
  IssuerApiHandlers,
2303
+ IssuerStateError,
2304
+ IssuerStateValidator,
2108
2305
  MemorySessionStore,
2109
2306
  NonceManager,
2110
2307
  PAFI_ISSUER_SDK_VERSION,
@@ -2121,6 +2318,7 @@ var PAFI_ISSUER_SDK_VERSION = "0.4.0";
2121
2318
  authenticateRequest,
2122
2319
  createIssuerService,
2123
2320
  createSubgraphNativeUsdtQuoter,
2124
- createSubgraphPoolsProvider
2321
+ createSubgraphPoolsProvider,
2322
+ serializeEntryToJsonRpc
2125
2323
  });
2126
2324
  //# sourceMappingURL=index.cjs.map