@pafi-dev/issuer 0.7.6 → 0.7.8

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
@@ -2317,12 +2317,13 @@ var PerpDepositHandler = class {
2317
2317
 
2318
2318
  // src/api/delegateHandler.ts
2319
2319
  var import_core13 = require("@pafi-dev/core");
2320
+ var import_viem10 = require("viem");
2320
2321
  var DEFAULT_DELEGATE_GAS = {
2321
2322
  callGasLimit: 100000n,
2322
2323
  verificationGasLimit: 150000n,
2323
2324
  preVerificationGas: 50000n
2324
2325
  };
2325
- async function handleDelegateSubmit(params) {
2326
+ async function handleDelegatePrepare(params) {
2326
2327
  const { batchExecutor } = (0, import_core13.getContractAddresses)(params.chainId);
2327
2328
  const partial = (0, import_core13.buildDelegationUserOp)({
2328
2329
  userAddress: params.userAddress,
@@ -2359,39 +2360,76 @@ async function handleDelegateSubmit(params) {
2359
2360
  onWarning: params.onWarning
2360
2361
  });
2361
2362
  const merged = {
2362
- ...userOp,
2363
- ...paymasterFields ?? {}
2363
+ sender: userOp.sender,
2364
+ nonce: userOp.nonce,
2365
+ callData: userOp.callData,
2366
+ callGasLimit: paymasterFields?.callGasLimit ?? userOp.callGasLimit,
2367
+ verificationGasLimit: paymasterFields?.verificationGasLimit ?? userOp.verificationGasLimit,
2368
+ preVerificationGas: paymasterFields?.preVerificationGas ?? userOp.preVerificationGas,
2369
+ maxFeePerGas: paymasterFields?.maxFeePerGas ?? userOp.maxFeePerGas,
2370
+ maxPriorityFeePerGas: paymasterFields?.maxPriorityFeePerGas ?? userOp.maxPriorityFeePerGas,
2371
+ paymaster: paymasterFields?.paymaster,
2372
+ paymasterVerificationGasLimit: paymasterFields?.paymasterVerificationGasLimit,
2373
+ paymasterPostOpGasLimit: paymasterFields?.paymasterPostOpGasLimit,
2374
+ paymasterData: paymasterFields?.paymasterData
2364
2375
  };
2365
- const userOpJson = (0, import_core13.serializeUserOpToJsonRpc)(
2376
+ const userOpHash = (0, import_core13.computeUserOpHash)(merged, params.chainId);
2377
+ const typed = (0, import_core13.buildUserOpTypedData)(merged, params.chainId);
2378
+ await params.store.save(
2379
+ params.lockId,
2366
2380
  {
2367
2381
  sender: merged.sender,
2368
- nonce: merged.nonce,
2382
+ nonce: merged.nonce.toString(10),
2369
2383
  callData: merged.callData,
2370
- callGasLimit: merged.callGasLimit,
2371
- verificationGasLimit: merged.verificationGasLimit,
2372
- preVerificationGas: merged.preVerificationGas,
2373
- maxFeePerGas: merged.maxFeePerGas,
2374
- maxPriorityFeePerGas: merged.maxPriorityFeePerGas,
2375
- paymaster: paymasterFields?.paymaster,
2376
- paymasterVerificationGasLimit: paymasterFields?.paymasterVerificationGasLimit,
2377
- paymasterPostOpGasLimit: paymasterFields?.paymasterPostOpGasLimit,
2378
- paymasterData: paymasterFields?.paymasterData
2384
+ callGasLimit: merged.callGasLimit.toString(10),
2385
+ verificationGasLimit: merged.verificationGasLimit.toString(10),
2386
+ preVerificationGas: merged.preVerificationGas.toString(10),
2387
+ maxFeePerGas: merged.maxFeePerGas.toString(10),
2388
+ maxPriorityFeePerGas: merged.maxPriorityFeePerGas.toString(10),
2389
+ ...merged.paymaster ? { paymaster: merged.paymaster } : {},
2390
+ ...merged.paymasterVerificationGasLimit ? {
2391
+ paymasterVerificationGasLimit: merged.paymasterVerificationGasLimit.toString(10)
2392
+ } : {},
2393
+ ...merged.paymasterPostOpGasLimit ? {
2394
+ paymasterPostOpGasLimit: merged.paymasterPostOpGasLimit.toString(10)
2395
+ } : {},
2396
+ ...merged.paymasterData ? { paymasterData: merged.paymasterData } : {},
2397
+ chainId: params.chainId,
2398
+ userOpHash,
2399
+ eip7702Auth: authorization
2379
2400
  },
2380
- // Delegation UserOp is submitted unsigned — the EIP-7702 authorization
2381
- // is the user's "consent"; no separate AA signature is needed.
2382
- "0x"
2401
+ params.ttlSeconds
2383
2402
  );
2403
+ return {
2404
+ lockId: params.lockId,
2405
+ userOpHash,
2406
+ typedData: serializeUserOpTypedData(typed),
2407
+ expiresInSeconds: params.ttlSeconds,
2408
+ isSponsored: !!paymasterFields
2409
+ };
2410
+ }
2411
+ async function handleDelegateSubmit(params) {
2412
+ const entry = await params.store.get(params.lockId);
2413
+ if (!entry) {
2414
+ throw new PendingUserOpNotFoundError(params.lockId);
2415
+ }
2416
+ if ((0, import_viem10.getAddress)(entry.sender) !== (0, import_viem10.getAddress)(params.authenticatedAddress)) {
2417
+ throw new PendingUserOpForbiddenError(params.lockId);
2418
+ }
2419
+ if (!entry.eip7702Auth) {
2420
+ throw new Error(
2421
+ `delegate entry ${params.lockId} missing eip7702Auth \u2014 prepare step did not run correctly`
2422
+ );
2423
+ }
2424
+ const userOpJson = serializeEntryToJsonRpc(entry, params.userOpSig, "sponsored");
2384
2425
  const result = await relayUserOp({
2385
2426
  client: params.pafiBackendClient,
2386
2427
  userOp: userOpJson,
2387
- entryPoint: import_core13.ENTRY_POINT_V08,
2388
- eip7702Auth: authorization
2428
+ entryPoint: params.entryPoint ?? import_core13.ENTRY_POINT_V08,
2429
+ eip7702Auth: entry.eip7702Auth
2389
2430
  });
2390
- return {
2391
- userOpHash: result.userOpHash,
2392
- isSponsored: !!paymasterFields,
2393
- authorization
2394
- };
2431
+ await params.store.delete(params.lockId);
2432
+ return { userOpHash: result.userOpHash };
2395
2433
  }
2396
2434
 
2397
2435
  // src/api/errorMapper.ts
@@ -2420,7 +2458,8 @@ function createSdkErrorMapper(factories) {
2420
2458
  }
2421
2459
 
2422
2460
  // src/api/issuerApiAdapter.ts
2423
- var import_viem10 = require("viem");
2461
+ var import_node_crypto3 = require("crypto");
2462
+ var import_viem11 = require("viem");
2424
2463
  var import_core14 = require("@pafi-dev/core");
2425
2464
  var AdapterMisconfiguredError = class extends Error {
2426
2465
  code = "ADAPTER_MISCONFIGURED";
@@ -2478,7 +2517,7 @@ var IssuerApiAdapter = class {
2478
2517
  async pools(authenticatedAddress, chainId, pointTokenAddress) {
2479
2518
  const result = await this.cfg.issuerService.api.handlePools(
2480
2519
  authenticatedAddress,
2481
- { chainId, pointTokenAddress: (0, import_viem10.getAddress)(pointTokenAddress) }
2520
+ { chainId, pointTokenAddress: (0, import_viem11.getAddress)(pointTokenAddress) }
2482
2521
  );
2483
2522
  return { pools: result.pools };
2484
2523
  }
@@ -2487,8 +2526,8 @@ var IssuerApiAdapter = class {
2487
2526
  authenticatedAddress,
2488
2527
  {
2489
2528
  chainId,
2490
- userAddress: (0, import_viem10.getAddress)(userAddress),
2491
- pointTokenAddress: (0, import_viem10.getAddress)(pointTokenAddress)
2529
+ userAddress: (0, import_viem11.getAddress)(userAddress),
2530
+ pointTokenAddress: (0, import_viem11.getAddress)(pointTokenAddress)
2492
2531
  }
2493
2532
  );
2494
2533
  return {
@@ -2510,7 +2549,7 @@ var IssuerApiAdapter = class {
2510
2549
  "ptClaimHandler",
2511
2550
  "claim"
2512
2551
  );
2513
- const pointTokenAddress = (0, import_viem10.getAddress)(input.pointTokenAddress);
2552
+ const pointTokenAddress = (0, import_viem11.getAddress)(input.pointTokenAddress);
2514
2553
  const result = await ptClaimHandler.handle({
2515
2554
  authenticatedAddress: input.authenticatedAddress,
2516
2555
  userAddress: input.authenticatedAddress,
@@ -2605,7 +2644,7 @@ var IssuerApiAdapter = class {
2605
2644
  "ptClaimHandler",
2606
2645
  "claimPrepare"
2607
2646
  );
2608
- const pointTokenAddress = (0, import_viem10.getAddress)(input.pointTokenAddress);
2647
+ const pointTokenAddress = (0, import_viem11.getAddress)(input.pointTokenAddress);
2609
2648
  const claimResult = await ptClaimHandler.handle({
2610
2649
  authenticatedAddress: input.authenticatedAddress,
2611
2650
  userAddress: input.authenticatedAddress,
@@ -2651,7 +2690,7 @@ var IssuerApiAdapter = class {
2651
2690
  }
2652
2691
  async redeemPrepare(input) {
2653
2692
  this.assertRedeemHandler();
2654
- const pointTokenAddress = (0, import_viem10.getAddress)(input.pointTokenAddress);
2693
+ const pointTokenAddress = (0, import_viem11.getAddress)(input.pointTokenAddress);
2655
2694
  const redeemResponse = await this.cfg.ptRedeemHandler.handle({
2656
2695
  userAddress: input.authenticatedAddress,
2657
2696
  authenticatedAddress: input.authenticatedAddress,
@@ -2716,45 +2755,73 @@ var IssuerApiAdapter = class {
2716
2755
  // ------------------------------ Delegate endpoints -----------------------
2717
2756
  async delegateStatus(authenticatedAddress, chainId) {
2718
2757
  const { batchExecutor } = (0, import_core14.getContractAddresses)(chainId);
2719
- const code = await this.cfg.provider.getCode({
2720
- address: authenticatedAddress
2721
- });
2722
- return {
2723
- isDelegated: (0, import_core14.parseEip7702DelegatedAddress)(code) !== null,
2724
- batchExecutorAddress: batchExecutor
2725
- };
2726
- }
2727
- async delegatePrepare(authenticatedAddress, chainId) {
2728
- const { batchExecutor } = (0, import_core14.getContractAddresses)(chainId);
2729
- const accountNonce = BigInt(
2730
- await this.cfg.provider.getTransactionCount({
2731
- address: authenticatedAddress
2758
+ const [code, nonce] = await Promise.all([
2759
+ this.cfg.provider.getCode({ address: authenticatedAddress }),
2760
+ this.cfg.provider.getTransactionCount({
2761
+ address: authenticatedAddress,
2762
+ blockTag: "pending"
2732
2763
  })
2733
- );
2734
- const authorizationHash = (0, import_core14.computeAuthorizationHash)(
2735
- chainId,
2736
- batchExecutor,
2737
- accountNonce
2738
- );
2764
+ ]);
2739
2765
  return {
2740
- authorizationHash,
2741
- delegationNonce: accountNonce.toString(),
2766
+ isDelegated: (0, import_core14.parseEip7702DelegatedAddress)(code) !== null,
2742
2767
  batchExecutorAddress: batchExecutor,
2768
+ delegationNonce: nonce.toString(),
2743
2769
  chainId
2744
2770
  };
2745
2771
  }
2746
- async delegateSubmit(input) {
2772
+ /**
2773
+ * Build the delegation-anchor UserOp + obtain paymaster sponsorship
2774
+ * + persist as a pending entry. Mobile must:
2775
+ *
2776
+ * 1. Sign EIP-7702 authorization LOCALLY (Privy `signAuthorization`
2777
+ * with `{contractAddress: batchExecutorAddress, chainId,
2778
+ * nonce: delegationNonce}`) → 65-byte authSig hex.
2779
+ * 2. POST `/delegate/prepare` with `{ chainId, delegationNonce,
2780
+ * authSig }` → this method.
2781
+ * 3. Sign returned `userOpHash` LOCALLY (`signTypedData(typedData)`).
2782
+ * 4. POST `/delegate/submit` with `{ lockId, userOpSig }`.
2783
+ *
2784
+ * v0.7.7 — replaces single-shot delegateSubmit that tried to relay
2785
+ * a UserOp with empty `signature: "0x"` (Simple7702Account's
2786
+ * validateUserOp reverts `ECDSAInvalidSignatureLength` 0xfce698f7).
2787
+ */
2788
+ async delegatePrepare(authenticatedAddress, input) {
2789
+ const { batchExecutor } = (0, import_core14.getContractAddresses)(input.chainId);
2747
2790
  const fees = await this.cfg.provider.estimateFeesPerGas();
2748
- const result = await handleDelegateSubmit({
2749
- userAddress: input.authenticatedAddress,
2791
+ const lockId = (0, import_node_crypto3.randomUUID)();
2792
+ const result = await handleDelegatePrepare({
2793
+ userAddress: authenticatedAddress,
2750
2794
  chainId: input.chainId,
2751
2795
  delegationNonce: input.delegationNonce,
2752
2796
  aaNonce: input.aaNonce,
2753
2797
  authSig: input.authSig,
2754
2798
  fees,
2799
+ lockId,
2800
+ store: this.cfg.pendingUserOpStore,
2801
+ ttlSeconds: 15 * 60,
2802
+ // 15min — match claim/redeem mobile lock duration
2755
2803
  pafiBackendClient: this.cfg.pafiBackendClient,
2756
2804
  onWarning: this.cfg.onWarning
2757
2805
  });
2806
+ return {
2807
+ lockId: result.lockId,
2808
+ userOpHash: result.userOpHash,
2809
+ typedData: result.typedData,
2810
+ expiresInSeconds: result.expiresInSeconds,
2811
+ isSponsored: result.isSponsored,
2812
+ delegationNonce: input.delegationNonce.toString(),
2813
+ batchExecutorAddress: batchExecutor,
2814
+ chainId: input.chainId
2815
+ };
2816
+ }
2817
+ async delegateSubmit(input) {
2818
+ const result = await handleDelegateSubmit({
2819
+ lockId: input.lockId,
2820
+ authenticatedAddress: input.authenticatedAddress,
2821
+ userOpSig: input.userOpSig,
2822
+ store: this.cfg.pendingUserOpStore,
2823
+ pafiBackendClient: this.cfg.pafiBackendClient
2824
+ });
2758
2825
  return { userOpHash: result.userOpHash };
2759
2826
  }
2760
2827
  // ------------------------------ Internal helpers -------------------------
@@ -2813,7 +2880,7 @@ var IssuerApiAdapter = class {
2813
2880
  };
2814
2881
 
2815
2882
  // src/pools/subgraphPoolsProvider.ts
2816
- var import_viem11 = require("viem");
2883
+ var import_viem12 = require("viem");
2817
2884
  var import_core15 = require("@pafi-dev/core");
2818
2885
  var DEFAULT_CACHE_TTL_MS = 3e4;
2819
2886
  var POOL_QUERY = `
@@ -2914,7 +2981,7 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress)
2914
2981
  return [];
2915
2982
  }
2916
2983
  const { pool } = token;
2917
- if (!(0, import_viem11.isAddress)(pool.hooks)) {
2984
+ if (!(0, import_viem12.isAddress)(pool.hooks)) {
2918
2985
  console.error(
2919
2986
  "[PAFI] SubgraphPoolsProvider: invalid hooks address in response:",
2920
2987
  pool.hooks,
@@ -2922,7 +2989,7 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress)
2922
2989
  );
2923
2990
  return [];
2924
2991
  }
2925
- if (!(0, import_viem11.isAddress)(pool.token0.id) || !(0, import_viem11.isAddress)(pool.token1.id)) {
2992
+ if (!(0, import_viem12.isAddress)(pool.token0.id) || !(0, import_viem12.isAddress)(pool.token1.id)) {
2926
2993
  console.error(
2927
2994
  "[PAFI] SubgraphPoolsProvider: invalid token address in response \u2014 skipping pool"
2928
2995
  );
@@ -3072,8 +3139,8 @@ function toUsdtPerNative(priceFloat, usdtDecimals) {
3072
3139
  }
3073
3140
 
3074
3141
  // src/pools/nativePtQuoter.ts
3075
- var import_viem12 = require("viem");
3076
- var CHAINLINK_ABI = (0, import_viem12.parseAbi)([
3142
+ var import_viem13 = require("viem");
3143
+ var CHAINLINK_ABI = (0, import_viem13.parseAbi)([
3077
3144
  "function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)"
3078
3145
  ]);
3079
3146
  var CHAINLINK_MAX_AGE_S = 3600n;
@@ -3395,7 +3462,7 @@ var PafiBackendClient = class {
3395
3462
  };
3396
3463
 
3397
3464
  // src/config.ts
3398
- var import_viem13 = require("viem");
3465
+ var import_viem14 = require("viem");
3399
3466
  var import_core17 = require("@pafi-dev/core");
3400
3467
  function createIssuerService(config) {
3401
3468
  if (!config.provider) {
@@ -3416,7 +3483,7 @@ function createIssuerService(config) {
3416
3483
  "createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
3417
3484
  );
3418
3485
  }
3419
- const tokenAddresses = rawAddresses.map((a) => (0, import_viem13.getAddress)(a));
3486
+ const tokenAddresses = rawAddresses.map((a) => (0, import_viem14.getAddress)(a));
3420
3487
  const ledger = config.ledger;
3421
3488
  const sessionStore = config.sessionStore ?? new MemorySessionStore();
3422
3489
  const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
@@ -3505,7 +3572,7 @@ function createIssuerService(config) {
3505
3572
  }
3506
3573
 
3507
3574
  // src/issuer-state/validator.ts
3508
- var import_viem14 = require("viem");
3575
+ var import_viem15 = require("viem");
3509
3576
  var import_core18 = require("@pafi-dev/core");
3510
3577
  var ISSUER_RECORD_TTL_MS = 3e4;
3511
3578
  var IssuerStateValidator = class _IssuerStateValidator {
@@ -3532,7 +3599,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
3532
3599
  */
3533
3600
  invalidate(pointToken) {
3534
3601
  if (pointToken) {
3535
- const key = (0, import_viem14.getAddress)(pointToken);
3602
+ const key = (0, import_viem15.getAddress)(pointToken);
3536
3603
  this.pointTokenIssuerCache.delete(key);
3537
3604
  this.stateCache.delete(key);
3538
3605
  this.inflight.delete(key);
@@ -3547,7 +3614,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
3547
3614
  * The issuer field is set at `initialize()` and never changes.
3548
3615
  */
3549
3616
  async getIssuerAddressForPointToken(pointToken) {
3550
- const key = (0, import_viem14.getAddress)(pointToken);
3617
+ const key = (0, import_viem15.getAddress)(pointToken);
3551
3618
  const cached = this.pointTokenIssuerCache.get(key);
3552
3619
  if (cached) return cached;
3553
3620
  const issuer = await this.provider.readContract({
@@ -3555,15 +3622,15 @@ var IssuerStateValidator = class _IssuerStateValidator {
3555
3622
  abi: import_core18.POINT_TOKEN_V2_ABI,
3556
3623
  functionName: "issuer"
3557
3624
  });
3558
- this.pointTokenIssuerCache.set(key, (0, import_viem14.getAddress)(issuer));
3559
- return (0, import_viem14.getAddress)(issuer);
3625
+ this.pointTokenIssuerCache.set(key, (0, import_viem15.getAddress)(issuer));
3626
+ return (0, import_viem15.getAddress)(issuer);
3560
3627
  }
3561
3628
  /**
3562
3629
  * Read registry record + totalSupply, with 30s cache and in-flight
3563
3630
  * deduplication. Does NOT throw on inactive/missing — returns raw state.
3564
3631
  */
3565
3632
  async getIssuerState(pointToken) {
3566
- const tokenAddr = (0, import_viem14.getAddress)(pointToken);
3633
+ const tokenAddr = (0, import_viem15.getAddress)(pointToken);
3567
3634
  const now = Date.now();
3568
3635
  const cached = this.stateCache.get(tokenAddr);
3569
3636
  if (cached && cached.expiresAt > now) return cached.value;
@@ -3661,7 +3728,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
3661
3728
  };
3662
3729
 
3663
3730
  // src/index.ts
3664
- var PAFI_ISSUER_SDK_VERSION = true ? "0.7.6" : "dev";
3731
+ var PAFI_ISSUER_SDK_VERSION = true ? "0.7.8" : "dev";
3665
3732
  // Annotate the CommonJS export names for ESM import in node:
3666
3733
  0 && (module.exports = {
3667
3734
  AdapterMisconfiguredError,