@pafi-dev/issuer 0.20.0 → 0.21.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.js CHANGED
@@ -1915,8 +1915,59 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
1915
1915
  }
1916
1916
  };
1917
1917
 
1918
- // src/api/handlers/ptRedeemHandler.ts
1918
+ // src/api/pointTokenDomainResolver.ts
1919
1919
  import { getAddress as getAddress6 } from "viem";
1920
+ var NAME_ABI = [
1921
+ {
1922
+ type: "function",
1923
+ name: "name",
1924
+ stateMutability: "view",
1925
+ inputs: [],
1926
+ outputs: [{ type: "string" }]
1927
+ }
1928
+ ];
1929
+ var PointTokenDomainResolver = class {
1930
+ provider;
1931
+ overrides;
1932
+ cache = /* @__PURE__ */ new Map();
1933
+ constructor(config) {
1934
+ this.provider = config.provider;
1935
+ this.overrides = /* @__PURE__ */ new Map();
1936
+ if (config.overrides) {
1937
+ for (const [addr, name] of Object.entries(config.overrides)) {
1938
+ this.overrides.set(getAddress6(addr).toLowerCase(), name);
1939
+ }
1940
+ }
1941
+ }
1942
+ async resolve(pointTokenAddress) {
1943
+ const key = getAddress6(pointTokenAddress).toLowerCase();
1944
+ const cached = this.cache.get(key);
1945
+ if (cached !== void 0) return cached;
1946
+ const override = this.overrides.get(key);
1947
+ if (override !== void 0) {
1948
+ this.cache.set(key, override);
1949
+ return override;
1950
+ }
1951
+ const name = await this.provider.readContract({
1952
+ address: pointTokenAddress,
1953
+ abi: NAME_ABI,
1954
+ functionName: "name"
1955
+ });
1956
+ this.cache.set(key, name);
1957
+ return name;
1958
+ }
1959
+ /** Invalidate one address (after deploy / proxy upgrade) or all. */
1960
+ invalidate(pointTokenAddress) {
1961
+ if (pointTokenAddress) {
1962
+ this.cache.delete(getAddress6(pointTokenAddress).toLowerCase());
1963
+ } else {
1964
+ this.cache.clear();
1965
+ }
1966
+ }
1967
+ };
1968
+
1969
+ // src/api/handlers/ptRedeemHandler.ts
1970
+ import { getAddress as getAddress7 } from "viem";
1920
1971
  import {
1921
1972
  signBurnRequest,
1922
1973
  POINT_TOKEN_ABI as POINT_TOKEN_ABI2,
@@ -1942,10 +1993,9 @@ var PTRedeemHandler = class {
1942
1993
  relayService;
1943
1994
  provider;
1944
1995
  feeService;
1945
- pointTokenAddress;
1946
1996
  batchExecutorAddress;
1947
1997
  chainId;
1948
- domain;
1998
+ domainResolver;
1949
1999
  burnerSignerWallet;
1950
2000
  redeemLockDurationMs;
1951
2001
  signatureDeadlineSeconds;
@@ -1982,10 +2032,9 @@ var PTRedeemHandler = class {
1982
2032
  this.relayService = config.relayService;
1983
2033
  this.provider = config.provider;
1984
2034
  this.feeService = config.feeService;
1985
- this.pointTokenAddress = getAddress6(config.pointTokenAddress);
1986
- this.batchExecutorAddress = getAddress6(config.batchExecutorAddress);
2035
+ this.batchExecutorAddress = getAddress7(config.batchExecutorAddress);
1987
2036
  this.chainId = config.chainId;
1988
- this.domain = config.domain;
2037
+ this.domainResolver = config.domainResolver;
1989
2038
  this.burnerSignerWallet = config.burnerSignerWallet;
1990
2039
  if (this.burnerSignerWallet?.account?.type === "local") {
1991
2040
  console.warn("[PAFI] PTRedeemHandler: burnerSignerWallet uses a local (private key) account. Use a KMS-backed signer in production.");
@@ -1998,7 +2047,7 @@ var PTRedeemHandler = class {
1998
2047
  }
1999
2048
  }
2000
2049
  async handle(request) {
2001
- if (getAddress6(request.authenticatedAddress) !== getAddress6(request.userAddress)) {
2050
+ if (getAddress7(request.authenticatedAddress) !== getAddress7(request.userAddress)) {
2002
2051
  throw new PTRedeemError(
2003
2052
  "UNAUTHORIZED",
2004
2053
  `userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`
@@ -2007,11 +2056,12 @@ var PTRedeemHandler = class {
2007
2056
  if (request.amount <= 0n) {
2008
2057
  throw new PTRedeemError("INVALID_AMOUNT", "redeem amount must be positive");
2009
2058
  }
2059
+ const pointTokenAddress = getAddress7(request.pointTokenAddress);
2010
2060
  if (this.redemptionService) {
2011
2061
  const decision = await this.redemptionService.evaluate(
2012
2062
  request.userAddress,
2013
2063
  request.amount,
2014
- this.pointTokenAddress
2064
+ pointTokenAddress
2015
2065
  );
2016
2066
  if (!decision.allowed) {
2017
2067
  const denial = decision.denial;
@@ -2025,7 +2075,7 @@ var PTRedeemHandler = class {
2025
2075
  let burnNonce;
2026
2076
  try {
2027
2077
  burnNonce = await this.provider.readContract({
2028
- address: this.pointTokenAddress,
2078
+ address: pointTokenAddress,
2029
2079
  abi: POINT_TOKEN_ABI2,
2030
2080
  functionName: "burnRequestNonces",
2031
2081
  args: [request.userAddress]
@@ -2036,27 +2086,27 @@ var PTRedeemHandler = class {
2036
2086
  `failed to read burnRequestNonces(${request.userAddress}): ${err instanceof Error ? err.message : String(err)}`
2037
2087
  );
2038
2088
  }
2039
- const userKey = getAddress6(request.userAddress).toLowerCase();
2040
- let userNonces = this.inFlightNonces.get(userKey);
2089
+ const nonceKey = `${getAddress7(request.userAddress).toLowerCase()}:${pointTokenAddress.toLowerCase()}`;
2090
+ let userNonces = this.inFlightNonces.get(nonceKey);
2041
2091
  if (!userNonces) {
2042
2092
  userNonces = /* @__PURE__ */ new Set();
2043
- this.inFlightNonces.set(userKey, userNonces);
2093
+ this.inFlightNonces.set(nonceKey, userNonces);
2044
2094
  }
2045
2095
  if (userNonces.has(burnNonce)) {
2046
2096
  throw new PTRedeemError(
2047
2097
  "NONCE_IN_FLIGHT",
2048
- `A burn request for nonce ${burnNonce} is already in progress for ${request.userAddress}. Retry after the current request completes.`
2098
+ `A burn request for nonce ${burnNonce} is already in progress for ${request.userAddress} on ${pointTokenAddress}. Retry after the current request completes.`
2049
2099
  );
2050
2100
  }
2051
2101
  userNonces.add(burnNonce);
2052
2102
  try {
2053
- return await this._handleAfterNonceLock(request, burnNonce);
2103
+ return await this._handleAfterNonceLock(request, burnNonce, pointTokenAddress);
2054
2104
  } finally {
2055
2105
  userNonces.delete(burnNonce);
2056
- if (userNonces.size === 0) this.inFlightNonces.delete(userKey);
2106
+ if (userNonces.size === 0) this.inFlightNonces.delete(nonceKey);
2057
2107
  }
2058
2108
  }
2059
- async _handleAfterNonceLock(request, burnNonce) {
2109
+ async _handleAfterNonceLock(request, burnNonce, pointTokenAddress) {
2060
2110
  const previewDeadline = BigInt(
2061
2111
  Math.floor(this.now() / 1e3) + this.signatureDeadlineSeconds
2062
2112
  );
@@ -2067,13 +2117,13 @@ var PTRedeemHandler = class {
2067
2117
  const previewUserOp = this.relayService.previewBurnUserOp({
2068
2118
  userAddress: request.userAddress,
2069
2119
  aaNonce: burnNonce,
2070
- pointTokenAddress: this.pointTokenAddress,
2120
+ pointTokenAddress,
2071
2121
  amount: request.amount,
2072
2122
  deadline: previewDeadline
2073
2123
  });
2074
2124
  fee = await this.feeService.estimateGasFee({
2075
2125
  scenario: "burn",
2076
- contractAddress: this.pointTokenAddress,
2126
+ contractAddress: pointTokenAddress,
2077
2127
  partialUserOp: {
2078
2128
  sender: previewUserOp.sender,
2079
2129
  nonce: previewUserOp.nonce,
@@ -2092,7 +2142,7 @@ var PTRedeemHandler = class {
2092
2142
  }
2093
2143
  const onChainBalance = await getPointTokenBalance2(
2094
2144
  this.provider,
2095
- this.pointTokenAddress,
2145
+ pointTokenAddress,
2096
2146
  request.userAddress
2097
2147
  );
2098
2148
  if (onChainBalance < request.amount) {
@@ -2102,10 +2152,11 @@ var PTRedeemHandler = class {
2102
2152
  );
2103
2153
  }
2104
2154
  const deadline = previewDeadline;
2155
+ const domainName = await this.domainResolver.resolve(pointTokenAddress);
2105
2156
  const domain = {
2106
- name: this.domain.name,
2157
+ name: domainName,
2107
2158
  chainId: this.chainId,
2108
- verifyingContract: this.domain.verifyingContract ?? this.pointTokenAddress
2159
+ verifyingContract: pointTokenAddress
2109
2160
  };
2110
2161
  const sponsoredBurnAmount = request.amount - fee;
2111
2162
  const sponsoredBurnRequest = {
@@ -2127,14 +2178,14 @@ var PTRedeemHandler = class {
2127
2178
  request.userAddress,
2128
2179
  sponsoredBurnAmount,
2129
2180
  this.redeemLockDurationMs,
2130
- this.pointTokenAddress
2181
+ pointTokenAddress
2131
2182
  );
2132
2183
  try {
2133
2184
  const sponsoredUserOp = await this.relayService.prepareBurn({
2134
2185
  mode: "burnWithSig",
2135
2186
  userAddress: request.userAddress,
2136
2187
  aaNonce: request.aaNonce,
2137
- pointTokenAddress: this.pointTokenAddress,
2188
+ pointTokenAddress,
2138
2189
  batchExecutorAddress: this.batchExecutorAddress,
2139
2190
  burnRequest: sponsoredBurnRequest,
2140
2191
  burnerSignature: sponsoredSig,
@@ -2162,7 +2213,7 @@ var PTRedeemHandler = class {
2162
2213
  request.userAddress,
2163
2214
  request.amount,
2164
2215
  this.redeemLockDurationMs,
2165
- this.pointTokenAddress
2216
+ pointTokenAddress
2166
2217
  );
2167
2218
  let fallbackUserOp;
2168
2219
  try {
@@ -2170,7 +2221,7 @@ var PTRedeemHandler = class {
2170
2221
  mode: "burnWithSig",
2171
2222
  userAddress: request.userAddress,
2172
2223
  aaNonce: request.aaNonce,
2173
- pointTokenAddress: this.pointTokenAddress,
2224
+ pointTokenAddress,
2174
2225
  batchExecutorAddress: this.batchExecutorAddress,
2175
2226
  burnRequest: fallbackBurnRequest,
2176
2227
  burnerSignature: fallbackSig,
@@ -2195,7 +2246,7 @@ var PTRedeemHandler = class {
2195
2246
  await this.redemptionService.recordSuccessfulInitiate({
2196
2247
  user: request.userAddress,
2197
2248
  amountPt: request.amount,
2198
- pointTokenAddress: this.pointTokenAddress,
2249
+ pointTokenAddress,
2199
2250
  reservationId: sponsoredLockId
2200
2251
  }).catch(() => {
2201
2252
  });
@@ -2318,7 +2369,7 @@ async function handleRedeemStatus(params) {
2318
2369
  }
2319
2370
 
2320
2371
  // src/api/mobileHandlers.ts
2321
- import { getAddress as getAddress7 } from "viem";
2372
+ import { getAddress as getAddress8 } from "viem";
2322
2373
  import {
2323
2374
  ENTRY_POINT_V08,
2324
2375
  parseEip7702DelegatedAddress
@@ -2670,7 +2721,7 @@ async function handleMobileSubmit(params) {
2670
2721
  if (!entry) {
2671
2722
  throw new PendingUserOpNotFoundError(params.lockId);
2672
2723
  }
2673
- if (getAddress7(entry.sender) !== getAddress7(params.authenticatedAddress)) {
2724
+ if (getAddress8(entry.sender) !== getAddress8(params.authenticatedAddress)) {
2674
2725
  throw new PendingUserOpForbiddenError(params.lockId);
2675
2726
  }
2676
2727
  const variant = params.variant ?? "sponsored";
@@ -2686,7 +2737,7 @@ async function handleMobileSubmit(params) {
2686
2737
  }
2687
2738
 
2688
2739
  // src/api/handlers/ptClaimHandler.ts
2689
- import { getAddress as getAddress8 } from "viem";
2740
+ import { getAddress as getAddress9 } from "viem";
2690
2741
  import {
2691
2742
  decodeBatchExecuteCalls,
2692
2743
  getContractAddresses as getContractAddresses3
@@ -2735,7 +2786,7 @@ var PTClaimHandler = class {
2735
2786
  };
2736
2787
  }
2737
2788
  async handle(request) {
2738
- if (getAddress8(request.authenticatedAddress) !== getAddress8(request.userAddress)) {
2789
+ if (getAddress9(request.authenticatedAddress) !== getAddress9(request.userAddress)) {
2739
2790
  throw new PTClaimError(
2740
2791
  "VALIDATION_FAILED",
2741
2792
  `userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`
@@ -2790,8 +2841,11 @@ var PTClaimHandler = class {
2790
2841
  callData: previewUserOp.callData
2791
2842
  }
2792
2843
  }) : 0n;
2844
+ const domainName = await this.cfg.domainResolver.resolve(
2845
+ request.pointTokenAddress
2846
+ );
2793
2847
  const domain = {
2794
- name: this.cfg.pointTokenDomainName,
2848
+ name: domainName,
2795
2849
  chainId: request.chainId,
2796
2850
  verifyingContract: request.pointTokenAddress
2797
2851
  };
@@ -3006,7 +3060,7 @@ import {
3006
3060
  getContractAddresses as getContractAddresses5,
3007
3061
  serializeUserOpToJsonRpc as serializeUserOpToJsonRpc2
3008
3062
  } from "@pafi-dev/core";
3009
- import { getAddress as getAddress9 } from "viem";
3063
+ import { getAddress as getAddress10 } from "viem";
3010
3064
  var DEFAULT_DELEGATE_GAS = {
3011
3065
  callGasLimit: 100000n,
3012
3066
  verificationGasLimit: 150000n,
@@ -3093,7 +3147,7 @@ async function handleDelegateSubmit(params) {
3093
3147
  if (!entry) {
3094
3148
  throw new PendingUserOpNotFoundError(params.lockId);
3095
3149
  }
3096
- if (getAddress9(entry.sender) !== getAddress9(params.authenticatedAddress)) {
3150
+ if (getAddress10(entry.sender) !== getAddress10(params.authenticatedAddress)) {
3097
3151
  throw new PendingUserOpForbiddenError(params.lockId);
3098
3152
  }
3099
3153
  if (!entry.eip7702Auth) {
@@ -3114,7 +3168,7 @@ async function handleDelegateSubmit(params) {
3114
3168
 
3115
3169
  // src/api/issuerApiAdapter.ts
3116
3170
  import { randomUUID } from "crypto";
3117
- import { getAddress as getAddress10 } from "viem";
3171
+ import { getAddress as getAddress11 } from "viem";
3118
3172
  import {
3119
3173
  buildAndSignSponsorAuth,
3120
3174
  decodeBatchExecuteCalls as decodeBatchExecuteCalls3,
@@ -3179,7 +3233,7 @@ var IssuerApiAdapter = class {
3179
3233
  async pools(authenticatedAddress, chainId, pointTokenAddress) {
3180
3234
  const result = await this.cfg.issuerService.api.handlePools(
3181
3235
  authenticatedAddress,
3182
- { chainId, pointTokenAddress: getAddress10(pointTokenAddress) }
3236
+ { chainId, pointTokenAddress: getAddress11(pointTokenAddress) }
3183
3237
  );
3184
3238
  return { pools: result.pools };
3185
3239
  }
@@ -3188,8 +3242,8 @@ var IssuerApiAdapter = class {
3188
3242
  authenticatedAddress,
3189
3243
  {
3190
3244
  chainId,
3191
- userAddress: getAddress10(userAddress),
3192
- pointTokenAddress: getAddress10(pointTokenAddress)
3245
+ userAddress: getAddress11(userAddress),
3246
+ pointTokenAddress: getAddress11(pointTokenAddress)
3193
3247
  }
3194
3248
  );
3195
3249
  return {
@@ -3210,7 +3264,7 @@ var IssuerApiAdapter = class {
3210
3264
  "ptClaimHandler",
3211
3265
  "claim"
3212
3266
  );
3213
- const pointTokenAddress = getAddress10(input.pointTokenAddress);
3267
+ const pointTokenAddress = getAddress11(input.pointTokenAddress);
3214
3268
  const result = await ptClaimHandler.handle({
3215
3269
  authenticatedAddress: input.authenticatedAddress,
3216
3270
  userAddress: input.authenticatedAddress,
@@ -3237,9 +3291,11 @@ var IssuerApiAdapter = class {
3237
3291
  }
3238
3292
  async redeem(input) {
3239
3293
  this.assertRedeemHandler();
3294
+ const pointTokenAddress = getAddress11(input.pointTokenAddress);
3240
3295
  const response = await this.cfg.ptRedeemHandler.handle({
3241
3296
  userAddress: input.authenticatedAddress,
3242
3297
  authenticatedAddress: input.authenticatedAddress,
3298
+ pointTokenAddress,
3243
3299
  amount: input.amount,
3244
3300
  aaNonce: input.aaNonce,
3245
3301
  chainId: input.chainId
@@ -3305,7 +3361,7 @@ var IssuerApiAdapter = class {
3305
3361
  "ptClaimHandler",
3306
3362
  "claimPrepare"
3307
3363
  );
3308
- const pointTokenAddress = getAddress10(input.pointTokenAddress);
3364
+ const pointTokenAddress = getAddress11(input.pointTokenAddress);
3309
3365
  const claimResult = await ptClaimHandler.handle({
3310
3366
  authenticatedAddress: input.authenticatedAddress,
3311
3367
  userAddress: input.authenticatedAddress,
@@ -3351,10 +3407,11 @@ var IssuerApiAdapter = class {
3351
3407
  }
3352
3408
  async redeemPrepare(input) {
3353
3409
  this.assertRedeemHandler();
3354
- const pointTokenAddress = getAddress10(input.pointTokenAddress);
3410
+ const pointTokenAddress = getAddress11(input.pointTokenAddress);
3355
3411
  const redeemResponse = await this.cfg.ptRedeemHandler.handle({
3356
3412
  userAddress: input.authenticatedAddress,
3357
3413
  authenticatedAddress: input.authenticatedAddress,
3414
+ pointTokenAddress,
3358
3415
  amount: input.amount,
3359
3416
  aaNonce: input.aaNonce,
3360
3417
  chainId: input.chainId
@@ -4102,7 +4159,7 @@ var PafiBackendClient = class {
4102
4159
  };
4103
4160
 
4104
4161
  // src/config.ts
4105
- import { getAddress as getAddress11 } from "viem";
4162
+ import { getAddress as getAddress12 } from "viem";
4106
4163
  import { getContractAddresses as getContractAddresses7 } from "@pafi-dev/core";
4107
4164
 
4108
4165
  // src/redemption/evaluator.ts
@@ -4431,7 +4488,7 @@ function createIssuerService(config) {
4431
4488
  "createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
4432
4489
  );
4433
4490
  }
4434
- const tokenAddresses = rawAddresses.map((a) => getAddress11(a));
4491
+ const tokenAddresses = rawAddresses.map((a) => getAddress12(a));
4435
4492
  const ledger = config.ledger;
4436
4493
  const sessionStore = config.sessionStore ?? new MemorySessionStore();
4437
4494
  const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
@@ -4550,7 +4607,7 @@ function createIssuerService(config) {
4550
4607
  }
4551
4608
 
4552
4609
  // src/issuer-state/validator.ts
4553
- import { getAddress as getAddress12 } from "viem";
4610
+ import { getAddress as getAddress13 } from "viem";
4554
4611
  import {
4555
4612
  POINT_TOKEN_ABI as POINT_TOKEN_ABI3,
4556
4613
  issuerRegistryAbi,
@@ -4582,7 +4639,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
4582
4639
  */
4583
4640
  invalidate(pointToken) {
4584
4641
  if (pointToken) {
4585
- const key = getAddress12(pointToken);
4642
+ const key = getAddress13(pointToken);
4586
4643
  this.pointTokenIssuerCache.delete(key);
4587
4644
  this.stateCache.delete(key);
4588
4645
  this.inflight.delete(key);
@@ -4597,7 +4654,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
4597
4654
  * The issuer field is set at `initialize()` and never changes.
4598
4655
  */
4599
4656
  async getIssuerAddressForPointToken(pointToken) {
4600
- const key = getAddress12(pointToken);
4657
+ const key = getAddress13(pointToken);
4601
4658
  const cached = this.pointTokenIssuerCache.get(key);
4602
4659
  if (cached) return cached;
4603
4660
  const issuer = await this.provider.readContract({
@@ -4605,15 +4662,15 @@ var IssuerStateValidator = class _IssuerStateValidator {
4605
4662
  abi: POINT_TOKEN_ABI3,
4606
4663
  functionName: "issuer"
4607
4664
  });
4608
- this.pointTokenIssuerCache.set(key, getAddress12(issuer));
4609
- return getAddress12(issuer);
4665
+ this.pointTokenIssuerCache.set(key, getAddress13(issuer));
4666
+ return getAddress13(issuer);
4610
4667
  }
4611
4668
  /**
4612
4669
  * Read registry record + totalSupply, with 30s cache and in-flight
4613
4670
  * deduplication. Does NOT throw on inactive/missing — returns raw state.
4614
4671
  */
4615
4672
  async getIssuerState(pointToken) {
4616
- const tokenAddr = getAddress12(pointToken);
4673
+ const tokenAddr = getAddress13(pointToken);
4617
4674
  const now = Date.now();
4618
4675
  const cached = this.stateCache.get(tokenAddr);
4619
4676
  if (cached && cached.expiresAt > now) return cached.value;
@@ -4756,7 +4813,7 @@ var MemoryRedemptionHistoryStore = class {
4756
4813
  };
4757
4814
 
4758
4815
  // src/index.ts
4759
- var PAFI_ISSUER_SDK_VERSION = true ? "0.20.0" : "dev";
4816
+ var PAFI_ISSUER_SDK_VERSION = true ? "0.21.0" : "dev";
4760
4817
  export {
4761
4818
  AdapterMisconfiguredError,
4762
4819
  AuthError,
@@ -4795,6 +4852,7 @@ export {
4795
4852
  PerpDepositError,
4796
4853
  PerpDepositHandler,
4797
4854
  PointIndexer,
4855
+ PointTokenDomainResolver,
4798
4856
  PolicyProvider,
4799
4857
  REDEMPTION_HISTORY_WINDOW_SEC,
4800
4858
  RedemptionService,