@pafi-dev/issuer 0.7.6 → 0.7.7

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,
@@ -2724,37 +2763,59 @@ var IssuerApiAdapter = class {
2724
2763
  batchExecutorAddress: batchExecutor
2725
2764
  };
2726
2765
  }
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
2732
- })
2733
- );
2734
- const authorizationHash = (0, import_core14.computeAuthorizationHash)(
2735
- chainId,
2736
- batchExecutor,
2737
- accountNonce
2738
- );
2739
- return {
2740
- authorizationHash,
2741
- delegationNonce: accountNonce.toString(),
2742
- batchExecutorAddress: batchExecutor,
2743
- chainId
2744
- };
2745
- }
2746
- async delegateSubmit(input) {
2766
+ /**
2767
+ * Build the delegation-anchor UserOp + obtain paymaster sponsorship
2768
+ * + persist as a pending entry. Mobile must:
2769
+ *
2770
+ * 1. Sign EIP-7702 authorization LOCALLY (Privy `signAuthorization`
2771
+ * with `{contractAddress: batchExecutorAddress, chainId,
2772
+ * nonce: delegationNonce}`) → 65-byte authSig hex.
2773
+ * 2. POST `/delegate/prepare` with `{ chainId, delegationNonce,
2774
+ * authSig }` → this method.
2775
+ * 3. Sign returned `userOpHash` LOCALLY (`signTypedData(typedData)`).
2776
+ * 4. POST `/delegate/submit` with `{ lockId, userOpSig }`.
2777
+ *
2778
+ * v0.7.7 — replaces single-shot delegateSubmit that tried to relay
2779
+ * a UserOp with empty `signature: "0x"` (Simple7702Account's
2780
+ * validateUserOp reverts `ECDSAInvalidSignatureLength` 0xfce698f7).
2781
+ */
2782
+ async delegatePrepare(authenticatedAddress, input) {
2783
+ const { batchExecutor } = (0, import_core14.getContractAddresses)(input.chainId);
2747
2784
  const fees = await this.cfg.provider.estimateFeesPerGas();
2748
- const result = await handleDelegateSubmit({
2749
- userAddress: input.authenticatedAddress,
2785
+ const lockId = (0, import_node_crypto3.randomUUID)();
2786
+ const result = await handleDelegatePrepare({
2787
+ userAddress: authenticatedAddress,
2750
2788
  chainId: input.chainId,
2751
2789
  delegationNonce: input.delegationNonce,
2752
2790
  aaNonce: input.aaNonce,
2753
2791
  authSig: input.authSig,
2754
2792
  fees,
2793
+ lockId,
2794
+ store: this.cfg.pendingUserOpStore,
2795
+ ttlSeconds: 15 * 60,
2796
+ // 15min — match claim/redeem mobile lock duration
2755
2797
  pafiBackendClient: this.cfg.pafiBackendClient,
2756
2798
  onWarning: this.cfg.onWarning
2757
2799
  });
2800
+ return {
2801
+ lockId: result.lockId,
2802
+ userOpHash: result.userOpHash,
2803
+ typedData: result.typedData,
2804
+ expiresInSeconds: result.expiresInSeconds,
2805
+ isSponsored: result.isSponsored,
2806
+ delegationNonce: input.delegationNonce.toString(),
2807
+ batchExecutorAddress: batchExecutor,
2808
+ chainId: input.chainId
2809
+ };
2810
+ }
2811
+ async delegateSubmit(input) {
2812
+ const result = await handleDelegateSubmit({
2813
+ lockId: input.lockId,
2814
+ authenticatedAddress: input.authenticatedAddress,
2815
+ userOpSig: input.userOpSig,
2816
+ store: this.cfg.pendingUserOpStore,
2817
+ pafiBackendClient: this.cfg.pafiBackendClient
2818
+ });
2758
2819
  return { userOpHash: result.userOpHash };
2759
2820
  }
2760
2821
  // ------------------------------ Internal helpers -------------------------
@@ -2813,7 +2874,7 @@ var IssuerApiAdapter = class {
2813
2874
  };
2814
2875
 
2815
2876
  // src/pools/subgraphPoolsProvider.ts
2816
- var import_viem11 = require("viem");
2877
+ var import_viem12 = require("viem");
2817
2878
  var import_core15 = require("@pafi-dev/core");
2818
2879
  var DEFAULT_CACHE_TTL_MS = 3e4;
2819
2880
  var POOL_QUERY = `
@@ -2914,7 +2975,7 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress)
2914
2975
  return [];
2915
2976
  }
2916
2977
  const { pool } = token;
2917
- if (!(0, import_viem11.isAddress)(pool.hooks)) {
2978
+ if (!(0, import_viem12.isAddress)(pool.hooks)) {
2918
2979
  console.error(
2919
2980
  "[PAFI] SubgraphPoolsProvider: invalid hooks address in response:",
2920
2981
  pool.hooks,
@@ -2922,7 +2983,7 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress)
2922
2983
  );
2923
2984
  return [];
2924
2985
  }
2925
- if (!(0, import_viem11.isAddress)(pool.token0.id) || !(0, import_viem11.isAddress)(pool.token1.id)) {
2986
+ if (!(0, import_viem12.isAddress)(pool.token0.id) || !(0, import_viem12.isAddress)(pool.token1.id)) {
2926
2987
  console.error(
2927
2988
  "[PAFI] SubgraphPoolsProvider: invalid token address in response \u2014 skipping pool"
2928
2989
  );
@@ -3072,8 +3133,8 @@ function toUsdtPerNative(priceFloat, usdtDecimals) {
3072
3133
  }
3073
3134
 
3074
3135
  // src/pools/nativePtQuoter.ts
3075
- var import_viem12 = require("viem");
3076
- var CHAINLINK_ABI = (0, import_viem12.parseAbi)([
3136
+ var import_viem13 = require("viem");
3137
+ var CHAINLINK_ABI = (0, import_viem13.parseAbi)([
3077
3138
  "function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)"
3078
3139
  ]);
3079
3140
  var CHAINLINK_MAX_AGE_S = 3600n;
@@ -3395,7 +3456,7 @@ var PafiBackendClient = class {
3395
3456
  };
3396
3457
 
3397
3458
  // src/config.ts
3398
- var import_viem13 = require("viem");
3459
+ var import_viem14 = require("viem");
3399
3460
  var import_core17 = require("@pafi-dev/core");
3400
3461
  function createIssuerService(config) {
3401
3462
  if (!config.provider) {
@@ -3416,7 +3477,7 @@ function createIssuerService(config) {
3416
3477
  "createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
3417
3478
  );
3418
3479
  }
3419
- const tokenAddresses = rawAddresses.map((a) => (0, import_viem13.getAddress)(a));
3480
+ const tokenAddresses = rawAddresses.map((a) => (0, import_viem14.getAddress)(a));
3420
3481
  const ledger = config.ledger;
3421
3482
  const sessionStore = config.sessionStore ?? new MemorySessionStore();
3422
3483
  const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
@@ -3505,7 +3566,7 @@ function createIssuerService(config) {
3505
3566
  }
3506
3567
 
3507
3568
  // src/issuer-state/validator.ts
3508
- var import_viem14 = require("viem");
3569
+ var import_viem15 = require("viem");
3509
3570
  var import_core18 = require("@pafi-dev/core");
3510
3571
  var ISSUER_RECORD_TTL_MS = 3e4;
3511
3572
  var IssuerStateValidator = class _IssuerStateValidator {
@@ -3532,7 +3593,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
3532
3593
  */
3533
3594
  invalidate(pointToken) {
3534
3595
  if (pointToken) {
3535
- const key = (0, import_viem14.getAddress)(pointToken);
3596
+ const key = (0, import_viem15.getAddress)(pointToken);
3536
3597
  this.pointTokenIssuerCache.delete(key);
3537
3598
  this.stateCache.delete(key);
3538
3599
  this.inflight.delete(key);
@@ -3547,7 +3608,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
3547
3608
  * The issuer field is set at `initialize()` and never changes.
3548
3609
  */
3549
3610
  async getIssuerAddressForPointToken(pointToken) {
3550
- const key = (0, import_viem14.getAddress)(pointToken);
3611
+ const key = (0, import_viem15.getAddress)(pointToken);
3551
3612
  const cached = this.pointTokenIssuerCache.get(key);
3552
3613
  if (cached) return cached;
3553
3614
  const issuer = await this.provider.readContract({
@@ -3555,15 +3616,15 @@ var IssuerStateValidator = class _IssuerStateValidator {
3555
3616
  abi: import_core18.POINT_TOKEN_V2_ABI,
3556
3617
  functionName: "issuer"
3557
3618
  });
3558
- this.pointTokenIssuerCache.set(key, (0, import_viem14.getAddress)(issuer));
3559
- return (0, import_viem14.getAddress)(issuer);
3619
+ this.pointTokenIssuerCache.set(key, (0, import_viem15.getAddress)(issuer));
3620
+ return (0, import_viem15.getAddress)(issuer);
3560
3621
  }
3561
3622
  /**
3562
3623
  * Read registry record + totalSupply, with 30s cache and in-flight
3563
3624
  * deduplication. Does NOT throw on inactive/missing — returns raw state.
3564
3625
  */
3565
3626
  async getIssuerState(pointToken) {
3566
- const tokenAddr = (0, import_viem14.getAddress)(pointToken);
3627
+ const tokenAddr = (0, import_viem15.getAddress)(pointToken);
3567
3628
  const now = Date.now();
3568
3629
  const cached = this.stateCache.get(tokenAddr);
3569
3630
  if (cached && cached.expiresAt > now) return cached.value;
@@ -3661,7 +3722,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
3661
3722
  };
3662
3723
 
3663
3724
  // src/index.ts
3664
- var PAFI_ISSUER_SDK_VERSION = true ? "0.7.6" : "dev";
3725
+ var PAFI_ISSUER_SDK_VERSION = true ? "0.7.7" : "dev";
3665
3726
  // Annotate the CommonJS export names for ESM import in node:
3666
3727
  0 && (module.exports = {
3667
3728
  AdapterMisconfiguredError,