@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.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { PafiSdkError, SdkErrorHttpStatus, PointTokenDomainConfig, PartialUserOperation, BurnRequest, PoolKey, UserOpTypedData, decodeBatchExecuteCalls, BROKER_HASHES, Eip7702AuthorizationJsonRpc, BuiltSponsorAuth, ENTRY_POINT_V08 } from '@pafi-dev/core';
1
+ import { PafiSdkError, SdkErrorHttpStatus, PointTokenDomainConfig, PartialUserOperation, BurnRequest, PoolKey, UserOpTypedData, decodeBatchExecuteCalls, BROKER_HASHES, BuiltSponsorAuth, ENTRY_POINT_V08 } from '@pafi-dev/core';
2
2
  export { PAFI_SUBGRAPH_URL, PafiSdkError, SdkErrorHttpStatus, ValidationError } from '@pafi-dev/core';
3
3
  import { Address, Hex, PublicClient, WalletClient } from 'viem';
4
4
 
@@ -1481,6 +1481,25 @@ interface PendingUserOpEntry {
1481
1481
  preVerificationGas: string;
1482
1482
  userOpHash: Hex;
1483
1483
  };
1484
+ /**
1485
+ * EIP-7702 authorization tuple — present only on the `delegate`
1486
+ * scenario where the UserOp anchors the EOA's one-time delegation
1487
+ * to a 7702 implementation. Embedded into the eth_sendUserOperation
1488
+ * payload at submit time so Pimlico bundler applies the bytecode
1489
+ * atomically with the UserOp execution. Pre-computed at prepare
1490
+ * time from the user's `signAuthorization` signature so submit
1491
+ * doesn't need to re-derive it.
1492
+ *
1493
+ * v0.7.7 — added per delegate-flow refactor (mobile prepare/submit).
1494
+ */
1495
+ eip7702Auth?: {
1496
+ chainId: string;
1497
+ address: string;
1498
+ nonce: string;
1499
+ r: string;
1500
+ s: string;
1501
+ yParity: string;
1502
+ };
1484
1503
  }
1485
1504
  /**
1486
1505
  * Storage backend for pending UserOps in the mobile prepare/submit pattern.
@@ -1969,55 +1988,30 @@ declare class PerpDepositHandler {
1969
1988
  handle(request: PerpDepositRequest): Promise<PerpDepositResponse>;
1970
1989
  }
1971
1990
 
1972
- /**
1973
- * Pure mechanics for the EIP-7702 delegation submit flow. Builds the
1974
- * delegation-anchor UserOp via `buildDelegationUserOp` (self-call EOA
1975
- * with empty calldata), attaches paymaster sponsorship, splits the
1976
- * user's authorization signature into the JSON-RPC tuple, and relays
1977
- * via the PAFI sponsor-relayer.
1978
- *
1979
- * The UserOp itself is a no-op — a self-call to the user's EOA with
1980
- * `data: "0x"`. The work is in the `eip7702Auth` object: the bundler
1981
- * picks it up, runs the EIP-7702 path, and installs the delegation on
1982
- * the user's EOA atomically with the (no-op) UserOp.
1983
- *
1984
- * v0.7.1 — switched from `encodeBatchExecute([])` (which throws
1985
- * "operations array must not be empty") to `buildDelegationUserOp`
1986
- * (self-call pattern). See SDK_CORE_TRADING_AUDIT.md C1.
1987
- *
1988
- * Throws the same `BundlerNotConfiguredError` / `BundlerRejectedError`
1989
- * as other relay paths so issuer controllers can use one error mapper.
1990
- */
1991
1991
  interface HandleDelegateSubmitParams {
1992
- userAddress: Address;
1993
- chainId: number;
1994
- /** Account nonce read at `delegate/prepare` time and signed by the user. */
1995
- delegationNonce: bigint;
1996
- /** ERC-4337 account nonce. Caller fetches via EntryPoint.getNonce. */
1997
- aaNonce: bigint;
1998
- /** 65-byte secp256k1 signature over the EIP-7702 authorization hash. */
1999
- authSig: Hex | string;
2000
- /** EIP-1559 fees from `provider.estimateFeesPerGas()` (or RPC equivalent). */
2001
- fees: {
2002
- maxFeePerGas?: bigint;
2003
- maxPriorityFeePerGas?: bigint;
2004
- };
1992
+ lockId: string;
1993
+ /** Authenticated user EOA — must match the entry's `sender`. */
1994
+ authenticatedAddress: Address;
1995
+ /** User signature over the persisted userOpHash. */
1996
+ userOpSig: Hex;
1997
+ store: IPendingUserOpStore;
2005
1998
  pafiBackendClient?: PafiBackendClient | null;
2006
- onWarning?: (msg: string) => void;
2007
- /** Override gas limits for the empty-batch UserOp. */
2008
- gasLimits?: {
2009
- callGasLimit?: bigint;
2010
- verificationGasLimit?: bigint;
2011
- preVerificationGas?: bigint;
2012
- };
1999
+ /** Defaults to `ENTRY_POINT_V08`. */
2000
+ entryPoint?: string;
2013
2001
  }
2014
2002
  interface HandleDelegateSubmitResult {
2015
2003
  userOpHash: Hex;
2016
- /** True when paymaster sponsorship was applied (gas is free). */
2017
- isSponsored: boolean;
2018
- /** The authorization tuple actually sent to the bundler. */
2019
- authorization: Eip7702AuthorizationJsonRpc;
2020
2004
  }
2005
+ /**
2006
+ * Retrieve the persisted delegate UserOp, embed the user's signature,
2007
+ * and submit to the bundler with the cached `eip7702Auth` field.
2008
+ *
2009
+ * Throws:
2010
+ * - `PendingUserOpNotFoundError` — entry expired or already submitted (404)
2011
+ * - `PendingUserOpForbiddenError` — sender mismatch (403)
2012
+ * - `BundlerNotConfiguredError` — `pafiBackendClient` missing (503)
2013
+ * - `BundlerRejectedError` — bundler rejected the UserOp (422)
2014
+ */
2021
2015
  declare function handleDelegateSubmit(params: HandleDelegateSubmitParams): Promise<HandleDelegateSubmitResult>;
2022
2016
 
2023
2017
  /**
@@ -2310,9 +2304,35 @@ interface MobileSubmitDto {
2310
2304
  interface DelegateStatusDto {
2311
2305
  isDelegated: boolean;
2312
2306
  batchExecutorAddress: Address;
2307
+ /**
2308
+ * EOA tx count fetched on-chain via `getTransactionCount(blockTag: 'pending')`.
2309
+ * Mobile passes this VERBATIM into Privy `signAuthorization({ ..., nonce })` —
2310
+ * MUST NOT hardcode `0` or fetch independently. For a fresh embedded wallet
2311
+ * it will be `"0"`, but re-delegation or post-activity wallets will be > 0.
2312
+ * Returned as decimal string (preserves bigint precision over JSON).
2313
+ */
2314
+ delegationNonce: string;
2315
+ chainId: number;
2313
2316
  }
2314
2317
  interface DelegatePrepareDto {
2315
- authorizationHash: Hex;
2318
+ /**
2319
+ * v0.7.7 — refactored to mobile prepare/submit pattern. Mobile signs
2320
+ * the EIP-7702 authorization LOCALLY (Privy `signAuthorization`),
2321
+ * then signs `userOpHash` (or `typedData`) BEFORE submit. See
2322
+ * `handleDelegatePrepare` for rationale.
2323
+ *
2324
+ * Pre-v0.7.7 callers expected `{ authorizationHash, delegationNonce,
2325
+ * batchExecutorAddress, chainId }` — `delegationNonce` +
2326
+ * `batchExecutorAddress` retained for back-compat so mobile can
2327
+ * compute the authorization hash if needed; `authorizationHash`
2328
+ * removed (mobile's Privy hook computes it locally).
2329
+ */
2330
+ lockId: string;
2331
+ userOpHash: Hex;
2332
+ typedData: SerializedUserOpTypedData;
2333
+ expiresInSeconds: number;
2334
+ isSponsored: boolean;
2335
+ /** Echoed for mobile to recompute the authorization hash if desired. */
2316
2336
  delegationNonce: string;
2317
2337
  batchExecutorAddress: Address;
2318
2338
  chainId: number;
@@ -2379,13 +2399,32 @@ declare class IssuerApiAdapter {
2379
2399
  claimStatus(authenticatedAddress: Address, lockId: string): Promise<MintStatusResponse>;
2380
2400
  redeemStatus(authenticatedAddress: Address, lockId: string): Promise<BurnStatusResponse>;
2381
2401
  delegateStatus(authenticatedAddress: Address, chainId: number): Promise<DelegateStatusDto>;
2382
- delegatePrepare(authenticatedAddress: Address, chainId: number): Promise<DelegatePrepareDto>;
2383
- delegateSubmit(input: {
2384
- authenticatedAddress: Address;
2402
+ /**
2403
+ * Build the delegation-anchor UserOp + obtain paymaster sponsorship
2404
+ * + persist as a pending entry. Mobile must:
2405
+ *
2406
+ * 1. Sign EIP-7702 authorization LOCALLY (Privy `signAuthorization`
2407
+ * with `{contractAddress: batchExecutorAddress, chainId,
2408
+ * nonce: delegationNonce}`) → 65-byte authSig hex.
2409
+ * 2. POST `/delegate/prepare` with `{ chainId, delegationNonce,
2410
+ * authSig }` → this method.
2411
+ * 3. Sign returned `userOpHash` LOCALLY (`signTypedData(typedData)`).
2412
+ * 4. POST `/delegate/submit` with `{ lockId, userOpSig }`.
2413
+ *
2414
+ * v0.7.7 — replaces single-shot delegateSubmit that tried to relay
2415
+ * a UserOp with empty `signature: "0x"` (Simple7702Account's
2416
+ * validateUserOp reverts `ECDSAInvalidSignatureLength` 0xfce698f7).
2417
+ */
2418
+ delegatePrepare(authenticatedAddress: Address, input: {
2385
2419
  chainId: number;
2386
2420
  delegationNonce: bigint;
2387
- aaNonce: bigint;
2388
2421
  authSig: Hex | string;
2422
+ aaNonce: bigint;
2423
+ }): Promise<DelegatePrepareDto>;
2424
+ delegateSubmit(input: {
2425
+ authenticatedAddress: Address;
2426
+ lockId: string;
2427
+ userOpSig: Hex;
2389
2428
  }): Promise<MobileSubmitDto>;
2390
2429
  /**
2391
2430
  * Build + sign a SponsorAuth payload. Returns `undefined` when no
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { PafiSdkError, SdkErrorHttpStatus, PointTokenDomainConfig, PartialUserOperation, BurnRequest, PoolKey, UserOpTypedData, decodeBatchExecuteCalls, BROKER_HASHES, Eip7702AuthorizationJsonRpc, BuiltSponsorAuth, ENTRY_POINT_V08 } from '@pafi-dev/core';
1
+ import { PafiSdkError, SdkErrorHttpStatus, PointTokenDomainConfig, PartialUserOperation, BurnRequest, PoolKey, UserOpTypedData, decodeBatchExecuteCalls, BROKER_HASHES, BuiltSponsorAuth, ENTRY_POINT_V08 } from '@pafi-dev/core';
2
2
  export { PAFI_SUBGRAPH_URL, PafiSdkError, SdkErrorHttpStatus, ValidationError } from '@pafi-dev/core';
3
3
  import { Address, Hex, PublicClient, WalletClient } from 'viem';
4
4
 
@@ -1481,6 +1481,25 @@ interface PendingUserOpEntry {
1481
1481
  preVerificationGas: string;
1482
1482
  userOpHash: Hex;
1483
1483
  };
1484
+ /**
1485
+ * EIP-7702 authorization tuple — present only on the `delegate`
1486
+ * scenario where the UserOp anchors the EOA's one-time delegation
1487
+ * to a 7702 implementation. Embedded into the eth_sendUserOperation
1488
+ * payload at submit time so Pimlico bundler applies the bytecode
1489
+ * atomically with the UserOp execution. Pre-computed at prepare
1490
+ * time from the user's `signAuthorization` signature so submit
1491
+ * doesn't need to re-derive it.
1492
+ *
1493
+ * v0.7.7 — added per delegate-flow refactor (mobile prepare/submit).
1494
+ */
1495
+ eip7702Auth?: {
1496
+ chainId: string;
1497
+ address: string;
1498
+ nonce: string;
1499
+ r: string;
1500
+ s: string;
1501
+ yParity: string;
1502
+ };
1484
1503
  }
1485
1504
  /**
1486
1505
  * Storage backend for pending UserOps in the mobile prepare/submit pattern.
@@ -1969,55 +1988,30 @@ declare class PerpDepositHandler {
1969
1988
  handle(request: PerpDepositRequest): Promise<PerpDepositResponse>;
1970
1989
  }
1971
1990
 
1972
- /**
1973
- * Pure mechanics for the EIP-7702 delegation submit flow. Builds the
1974
- * delegation-anchor UserOp via `buildDelegationUserOp` (self-call EOA
1975
- * with empty calldata), attaches paymaster sponsorship, splits the
1976
- * user's authorization signature into the JSON-RPC tuple, and relays
1977
- * via the PAFI sponsor-relayer.
1978
- *
1979
- * The UserOp itself is a no-op — a self-call to the user's EOA with
1980
- * `data: "0x"`. The work is in the `eip7702Auth` object: the bundler
1981
- * picks it up, runs the EIP-7702 path, and installs the delegation on
1982
- * the user's EOA atomically with the (no-op) UserOp.
1983
- *
1984
- * v0.7.1 — switched from `encodeBatchExecute([])` (which throws
1985
- * "operations array must not be empty") to `buildDelegationUserOp`
1986
- * (self-call pattern). See SDK_CORE_TRADING_AUDIT.md C1.
1987
- *
1988
- * Throws the same `BundlerNotConfiguredError` / `BundlerRejectedError`
1989
- * as other relay paths so issuer controllers can use one error mapper.
1990
- */
1991
1991
  interface HandleDelegateSubmitParams {
1992
- userAddress: Address;
1993
- chainId: number;
1994
- /** Account nonce read at `delegate/prepare` time and signed by the user. */
1995
- delegationNonce: bigint;
1996
- /** ERC-4337 account nonce. Caller fetches via EntryPoint.getNonce. */
1997
- aaNonce: bigint;
1998
- /** 65-byte secp256k1 signature over the EIP-7702 authorization hash. */
1999
- authSig: Hex | string;
2000
- /** EIP-1559 fees from `provider.estimateFeesPerGas()` (or RPC equivalent). */
2001
- fees: {
2002
- maxFeePerGas?: bigint;
2003
- maxPriorityFeePerGas?: bigint;
2004
- };
1992
+ lockId: string;
1993
+ /** Authenticated user EOA — must match the entry's `sender`. */
1994
+ authenticatedAddress: Address;
1995
+ /** User signature over the persisted userOpHash. */
1996
+ userOpSig: Hex;
1997
+ store: IPendingUserOpStore;
2005
1998
  pafiBackendClient?: PafiBackendClient | null;
2006
- onWarning?: (msg: string) => void;
2007
- /** Override gas limits for the empty-batch UserOp. */
2008
- gasLimits?: {
2009
- callGasLimit?: bigint;
2010
- verificationGasLimit?: bigint;
2011
- preVerificationGas?: bigint;
2012
- };
1999
+ /** Defaults to `ENTRY_POINT_V08`. */
2000
+ entryPoint?: string;
2013
2001
  }
2014
2002
  interface HandleDelegateSubmitResult {
2015
2003
  userOpHash: Hex;
2016
- /** True when paymaster sponsorship was applied (gas is free). */
2017
- isSponsored: boolean;
2018
- /** The authorization tuple actually sent to the bundler. */
2019
- authorization: Eip7702AuthorizationJsonRpc;
2020
2004
  }
2005
+ /**
2006
+ * Retrieve the persisted delegate UserOp, embed the user's signature,
2007
+ * and submit to the bundler with the cached `eip7702Auth` field.
2008
+ *
2009
+ * Throws:
2010
+ * - `PendingUserOpNotFoundError` — entry expired or already submitted (404)
2011
+ * - `PendingUserOpForbiddenError` — sender mismatch (403)
2012
+ * - `BundlerNotConfiguredError` — `pafiBackendClient` missing (503)
2013
+ * - `BundlerRejectedError` — bundler rejected the UserOp (422)
2014
+ */
2021
2015
  declare function handleDelegateSubmit(params: HandleDelegateSubmitParams): Promise<HandleDelegateSubmitResult>;
2022
2016
 
2023
2017
  /**
@@ -2310,9 +2304,35 @@ interface MobileSubmitDto {
2310
2304
  interface DelegateStatusDto {
2311
2305
  isDelegated: boolean;
2312
2306
  batchExecutorAddress: Address;
2307
+ /**
2308
+ * EOA tx count fetched on-chain via `getTransactionCount(blockTag: 'pending')`.
2309
+ * Mobile passes this VERBATIM into Privy `signAuthorization({ ..., nonce })` —
2310
+ * MUST NOT hardcode `0` or fetch independently. For a fresh embedded wallet
2311
+ * it will be `"0"`, but re-delegation or post-activity wallets will be > 0.
2312
+ * Returned as decimal string (preserves bigint precision over JSON).
2313
+ */
2314
+ delegationNonce: string;
2315
+ chainId: number;
2313
2316
  }
2314
2317
  interface DelegatePrepareDto {
2315
- authorizationHash: Hex;
2318
+ /**
2319
+ * v0.7.7 — refactored to mobile prepare/submit pattern. Mobile signs
2320
+ * the EIP-7702 authorization LOCALLY (Privy `signAuthorization`),
2321
+ * then signs `userOpHash` (or `typedData`) BEFORE submit. See
2322
+ * `handleDelegatePrepare` for rationale.
2323
+ *
2324
+ * Pre-v0.7.7 callers expected `{ authorizationHash, delegationNonce,
2325
+ * batchExecutorAddress, chainId }` — `delegationNonce` +
2326
+ * `batchExecutorAddress` retained for back-compat so mobile can
2327
+ * compute the authorization hash if needed; `authorizationHash`
2328
+ * removed (mobile's Privy hook computes it locally).
2329
+ */
2330
+ lockId: string;
2331
+ userOpHash: Hex;
2332
+ typedData: SerializedUserOpTypedData;
2333
+ expiresInSeconds: number;
2334
+ isSponsored: boolean;
2335
+ /** Echoed for mobile to recompute the authorization hash if desired. */
2316
2336
  delegationNonce: string;
2317
2337
  batchExecutorAddress: Address;
2318
2338
  chainId: number;
@@ -2379,13 +2399,32 @@ declare class IssuerApiAdapter {
2379
2399
  claimStatus(authenticatedAddress: Address, lockId: string): Promise<MintStatusResponse>;
2380
2400
  redeemStatus(authenticatedAddress: Address, lockId: string): Promise<BurnStatusResponse>;
2381
2401
  delegateStatus(authenticatedAddress: Address, chainId: number): Promise<DelegateStatusDto>;
2382
- delegatePrepare(authenticatedAddress: Address, chainId: number): Promise<DelegatePrepareDto>;
2383
- delegateSubmit(input: {
2384
- authenticatedAddress: Address;
2402
+ /**
2403
+ * Build the delegation-anchor UserOp + obtain paymaster sponsorship
2404
+ * + persist as a pending entry. Mobile must:
2405
+ *
2406
+ * 1. Sign EIP-7702 authorization LOCALLY (Privy `signAuthorization`
2407
+ * with `{contractAddress: batchExecutorAddress, chainId,
2408
+ * nonce: delegationNonce}`) → 65-byte authSig hex.
2409
+ * 2. POST `/delegate/prepare` with `{ chainId, delegationNonce,
2410
+ * authSig }` → this method.
2411
+ * 3. Sign returned `userOpHash` LOCALLY (`signTypedData(typedData)`).
2412
+ * 4. POST `/delegate/submit` with `{ lockId, userOpSig }`.
2413
+ *
2414
+ * v0.7.7 — replaces single-shot delegateSubmit that tried to relay
2415
+ * a UserOp with empty `signature: "0x"` (Simple7702Account's
2416
+ * validateUserOp reverts `ECDSAInvalidSignatureLength` 0xfce698f7).
2417
+ */
2418
+ delegatePrepare(authenticatedAddress: Address, input: {
2385
2419
  chainId: number;
2386
2420
  delegationNonce: bigint;
2387
- aaNonce: bigint;
2388
2421
  authSig: Hex | string;
2422
+ aaNonce: bigint;
2423
+ }): Promise<DelegatePrepareDto>;
2424
+ delegateSubmit(input: {
2425
+ authenticatedAddress: Address;
2426
+ lockId: string;
2427
+ userOpSig: Hex;
2389
2428
  }): Promise<MobileSubmitDto>;
2390
2429
  /**
2391
2430
  * Build + sign a SponsorAuth payload. Returns `undefined` when no