@pafi-dev/core 0.18.0 → 0.19.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.d.cts CHANGED
@@ -695,6 +695,59 @@ interface BuildPerpDepositViaRelayParams {
695
695
  */
696
696
  declare function buildPerpDepositViaRelay(params: BuildPerpDepositViaRelayParams): PartialUserOperation;
697
697
 
698
+ /**
699
+ * Builder for the `erc20-transfer` sponsored scenario.
700
+ *
701
+ * Produces two UserOps from one request — same nonce, same sender:
702
+ *
703
+ * sponsored (2 calls):
704
+ * [ token.transfer(PAFI_FEE_RECIPIENT, fee), token.transfer(recipient, amount) ]
705
+ *
706
+ * fallback (1 call):
707
+ * [ token.transfer(recipient, amount) ]
708
+ *
709
+ * Both calls use the SAME token contract — the fee currency equals the
710
+ * token being sent (decision documented in
711
+ * `docs/SPONSORED_ERC20_TRANSFER_SPEC.md`). Caller is responsible for
712
+ * validating the token is in the sponsorship allowlist; this function
713
+ * just builds calldata, no policy enforcement.
714
+ *
715
+ * The sponsor-relayer's IntentValidator enforces:
716
+ * - exactly 2 calls
717
+ * - both target the same token address
718
+ * - call[0] = transfer to PAFI_FEE_RECIPIENT, amount >= 95% quoted
719
+ * - call[1] = transfer to recipient (not fee recipient, not 0x0)
720
+ *
721
+ * Fallback variant (1 call, no fee) submits no-paymaster — caller's
722
+ * `sendWithPaymasterFallback` routes there when sponsorship is refused.
723
+ */
724
+ interface BuildErc20TransferParams {
725
+ /** EIP-7702 delegated user EOA (== smart account sender). */
726
+ userAddress: Address;
727
+ /** ERC-4337 nonce from the EntryPoint. */
728
+ aaNonce: bigint;
729
+ /** Whitelisted ERC-20 to transfer. */
730
+ tokenAddress: Address;
731
+ /** Final recipient. Must NOT equal `feeRecipient` or `0x0...0`. */
732
+ recipient: Address;
733
+ /** Amount to send (token-native units; 6-dec for stables, 18-dec for PT). */
734
+ amount: bigint;
735
+ /**
736
+ * Operator fee in the SAME token. Sponsored variant only — pass
737
+ * `undefined` or 0n to skip and build the no-fee variant.
738
+ */
739
+ feeAmount?: bigint;
740
+ /** Required when `feeAmount > 0`. */
741
+ feeRecipient?: Address;
742
+ /** Override gas limits if you have a tighter Pimlico estimate. */
743
+ gasLimits?: {
744
+ callGasLimit?: bigint;
745
+ verificationGasLimit?: bigint;
746
+ preVerificationGas?: bigint;
747
+ };
748
+ }
749
+ declare function buildErc20TransferUserOp(params: BuildErc20TransferParams): PartialUserOperation;
750
+
698
751
  /**
699
752
  * Build an ERC-20 `transfer(to, amount)` operation. Used inside a batch
700
753
  * to move fee tokens from the user to the fee recipient atomically with
@@ -1021,7 +1074,7 @@ interface PaymasterConfig {
1021
1074
  * validates the request's target contracts + function selectors
1022
1075
  * match the expected pattern for the scenario.
1023
1076
  */
1024
- type SponsorshipScenario = "mint" | "burn" | "swap" | "perp-deposit" | "delegate";
1077
+ type SponsorshipScenario = "mint" | "burn" | "swap" | "perp-deposit" | "delegate" | "erc20-transfer";
1025
1078
 
1026
1079
  /**
1027
1080
  * Submission path chosen by `checkEthAndBranch`.
@@ -1576,7 +1629,8 @@ declare function sendWithPaymasterFallback(params: SendWithPaymasterFallbackPara
1576
1629
  *
1577
1630
  * Pass an explicit `gasUnits` to override.
1578
1631
  */
1579
- type FeeScenario = "mint" | "burn" | "swap" | "perp-deposit" | "delegate";
1632
+ type FeeScenario = "mint" | "burn" | "swap" | "perp-deposit" | "delegate" | "erc20-transfer";
1633
+ declare const SCENARIO_GAS_UNITS: Record<FeeScenario, bigint>;
1580
1634
  interface QuoteOperatorFeePtConfig {
1581
1635
  provider: PublicClient;
1582
1636
  chainId: number;
@@ -1689,6 +1743,43 @@ interface QuoteOperatorFeeUsdtConfig {
1689
1743
  */
1690
1744
  declare function quoteOperatorFeeUsdt(config: QuoteOperatorFeeUsdtConfig): Promise<bigint>;
1691
1745
  declare function quoteOperatorFeePt(config: QuoteOperatorFeePtConfig): Promise<bigint>;
1746
+ /**
1747
+ * Router quoter for the `erc20-transfer` sponsored scenario — picks
1748
+ * the correct underlying quoter based on the token being transferred:
1749
+ *
1750
+ * USDC / USDT → `quoteOperatorFeeUsdt` (Chainlink-based, 6-dec)
1751
+ * active PT → `quoteOperatorFeePt` (Chainlink + V3 pool quote)
1752
+ *
1753
+ * Fee is denominated in the SAME token the user is sending — no extra
1754
+ * approval / swap step needed. Caller is responsible for verifying the
1755
+ * token IS in the sponsored allowlist before calling; this function
1756
+ * just routes by address equality.
1757
+ *
1758
+ * Returns the fee in the token's native units (6-dec for USDC/USDT,
1759
+ * 18-dec for PT). The sponsor-relayer reproduces the same quote
1760
+ * server-side with a 5% slack window.
1761
+ *
1762
+ * @example
1763
+ * ```ts
1764
+ * const fee = await quoteOperatorFeeForTransfer({
1765
+ * provider, chainId: 8453,
1766
+ * tokenAddress: USDC_ADDRESS,
1767
+ * });
1768
+ * ```
1769
+ */
1770
+ interface QuoteOperatorFeeForTransferConfig extends Omit<QuoteOperatorFeeUsdtConfig, "scenario"> {
1771
+ /** The ERC-20 the user is transferring. Drives both quote logic + fee currency. */
1772
+ tokenAddress: Address;
1773
+ /**
1774
+ * Subgraph URL override — only consumed when `tokenAddress` resolves
1775
+ * to a PT (USDC/USDT paths don't hit the subgraph).
1776
+ */
1777
+ subgraphUrl?: string;
1778
+ /** PT fallback (only used when `tokenAddress` is a PT and subgraph fails). */
1779
+ fallbackPtPriceUsdt?: number;
1780
+ fetchImpl?: typeof fetch;
1781
+ }
1782
+ declare function quoteOperatorFeeForTransfer(config: QuoteOperatorFeeForTransferConfig): Promise<bigint>;
1692
1783
 
1693
1784
  declare const BATCH_EXECUTOR_ADDRESS_BASE_MAINNET: `0x${string}`;
1694
1785
  declare const BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA: `0x${string}`;
@@ -2141,4 +2232,4 @@ declare class PafiSDK {
2141
2232
  signLoginMessage(message: string): Promise<Hex>;
2142
2233
  }
2143
2234
 
2144
- export { ApiError, BATCH_EXECUTOR_7702_IMPL, BATCH_EXECUTOR_ABI, BATCH_EXECUTOR_ADDRESS_BASE_MAINNET, BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA, BROKER_HASHES, type BuildDelegationUserOpParams, type BuildPartialUserOpParams, type BuildPerpDepositViaRelayParams, type BuildPerpDepositWithGasDeductionParams, COMMON_POOLS, COMMON_TOKENS, CONTRACT_ADDRESSES, ChainConfig, type CheckEthAndBranchParams, ConfigurationError, type ContractAddresses, DUMMY_SIGNATURE_V07, type DelegateDirectParams, type DelegateDirectResult, type DelegateImpl, EIP712Signature, ENTRY_POINT_V07, ENTRY_POINT_V08, type Eip7702AuthorizationJsonRpc, LoginMessageParams, MintRequest, type ModalOpenOptions, ORDERLY_RELAY_ABI, ORDERLY_VAULT_ABI, ORDERLY_VAULT_ADDRESSES, ORDERLY_VAULT_BASE_MAINNET, type Operation, OracleStaleError, type OrderlyRelayDepositRequest, PAFI_SERVICE_URLS, PAFI_SUBGRAPH_URL, PERMIT2_ADDRESS, POINT_TOKEN_FACTORY_ADDRESSES, POINT_TOKEN_IMPL_ADDRESSES, POINT_TOKEN_POOLS, type PackedUserOperationMessage, type PafiErrorType, type PafiProxyTransportParams, PafiSDK, PafiSDKConfig, PafiSdkError, type PafiServiceUrls, type PafiWebModalAdapter, type PafiWebModalHandle, type PartialUserOperation, type PaymasterConfig, type PaymasterFields, PointTokenDomainConfig, PoolKey, QUOTER_V2_ADDRESSES, type QuoteOperatorFeePtConfig, type QuoteOperatorFeeUsdtConfig, SDK_ERROR_HTTP_STATUS_CODE, SIMPLE_7702_IMPL_BASE_MAINNET, SUPPORTED_CHAINS, type SdkErrorHttpStatus, type SendWithPaymasterFallbackParams, type SignAuthorizationFn, type SignatureStruct, SignatureVerification, SignatureVerifyOptions, type SignedAuthorization, SigningError, SimulationError, type SmartAccountSender, type SponsorshipScenario, type SubmissionPath, TOKEN_HASHES, UNIVERSAL_ROUTER_ADDRESSES, type UserOpReceipt, type UserOpTypedData, type UserOperation, V3Path, V3_FACTORY_ADDRESSES, V3_POOL_INIT_CODE_HASH, V3_SWAP_ROUTER_ADDRESSES, ValidationError, type VaultDepositFE, ZERO_VALUE, assembleUserOperation, buildDelegationUserOp, buildEip7702Authorization, buildPartialUserOperation, buildPerpDepositViaRelay, buildPerpDepositWithGasDeduction, buildUserOpTypedData, burnRequestTypes, checkDelegation, checkEthAndBranch, computeAccountId, computeAuthorizationHash, computeUserOpHash, computeV3PoolAddress, createPafiProxyTransport, decodeBatchExecuteCalls, defaultErrorTypeForStatus, delegateDirect, detectDelegateImpl, encodeBatchExecute, encodeV3Path, encodeV3PathReversed, erc20ApproveOp, erc20BurnOp, erc20TransferOp, fetchPafiPools, getAaNonce, getContractAddresses, getDummySignatureFor7702, getPafiServiceUrls, getPafiWebModalAdapter, isDelegatedTo, isDelegatedToTarget, isPaymasterError, mintRequestTypes, openPafiWebModal, openWebPopup, parseEip7702DelegatedAddress, quoteOperatorFeePt, quoteOperatorFeeUsdt, rawCallOp, sendWithPaymasterFallback, serializeUserOpToJsonRpc, setPafiWebModalAdapter, splitAuthorizationSig, webPopupAdapter };
2235
+ export { ApiError, BATCH_EXECUTOR_7702_IMPL, BATCH_EXECUTOR_ABI, BATCH_EXECUTOR_ADDRESS_BASE_MAINNET, BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA, BROKER_HASHES, type BuildDelegationUserOpParams, type BuildErc20TransferParams, type BuildPartialUserOpParams, type BuildPerpDepositViaRelayParams, type BuildPerpDepositWithGasDeductionParams, COMMON_POOLS, COMMON_TOKENS, CONTRACT_ADDRESSES, ChainConfig, type CheckEthAndBranchParams, ConfigurationError, type ContractAddresses, DUMMY_SIGNATURE_V07, type DelegateDirectParams, type DelegateDirectResult, type DelegateImpl, EIP712Signature, ENTRY_POINT_V07, ENTRY_POINT_V08, type Eip7702AuthorizationJsonRpc, type FallbackInfo, type FeeScenario, LoginMessageParams, MintRequest, type ModalOpenOptions, ORDERLY_RELAY_ABI, ORDERLY_VAULT_ABI, ORDERLY_VAULT_ADDRESSES, ORDERLY_VAULT_BASE_MAINNET, type Operation, OracleStaleError, type OrderlyRelayDepositRequest, PAFI_SERVICE_URLS, PAFI_SUBGRAPH_URL, PERMIT2_ADDRESS, POINT_TOKEN_FACTORY_ADDRESSES, POINT_TOKEN_IMPL_ADDRESSES, POINT_TOKEN_POOLS, type PackedUserOperationMessage, type PafiErrorType, type PafiProxyTransportParams, PafiSDK, PafiSDKConfig, PafiSdkError, type PafiServiceUrls, type PafiWebModalAdapter, type PafiWebModalHandle, type PartialUserOperation, type PaymasterConfig, type PaymasterFields, PointTokenDomainConfig, PoolKey, QUOTER_V2_ADDRESSES, type QuoteOperatorFeeForTransferConfig, type QuoteOperatorFeePtConfig, type QuoteOperatorFeeUsdtConfig, SCENARIO_GAS_UNITS, SDK_ERROR_HTTP_STATUS_CODE, SIMPLE_7702_IMPL_BASE_MAINNET, SUPPORTED_CHAINS, type SdkErrorHttpStatus, type SendWithPaymasterFallbackParams, type SignAuthorizationFn, type SignatureStruct, SignatureVerification, SignatureVerifyOptions, type SignedAuthorization, SigningError, SimulationError, type SmartAccountSender, type SponsorshipScenario, type SubmissionPath, TOKEN_HASHES, UNIVERSAL_ROUTER_ADDRESSES, type UserOpReceipt, type UserOpTypedData, type UserOperation, V3Path, V3_FACTORY_ADDRESSES, V3_POOL_INIT_CODE_HASH, V3_SWAP_ROUTER_ADDRESSES, ValidationError, type VaultDepositFE, ZERO_VALUE, assembleUserOperation, buildDelegationUserOp, buildEip7702Authorization, buildErc20TransferUserOp, buildPartialUserOperation, buildPerpDepositViaRelay, buildPerpDepositWithGasDeduction, buildUserOpTypedData, burnRequestTypes, checkDelegation, checkEthAndBranch, computeAccountId, computeAuthorizationHash, computeUserOpHash, computeV3PoolAddress, createPafiProxyTransport, decodeBatchExecuteCalls, defaultErrorTypeForStatus, delegateDirect, detectDelegateImpl, encodeBatchExecute, encodeV3Path, encodeV3PathReversed, erc20ApproveOp, erc20BurnOp, erc20TransferOp, fetchPafiPools, getAaNonce, getContractAddresses, getDummySignatureFor7702, getPafiServiceUrls, getPafiWebModalAdapter, isDelegatedTo, isDelegatedToTarget, isPaymasterError, mintRequestTypes, openPafiWebModal, openWebPopup, parseEip7702DelegatedAddress, quoteOperatorFeeForTransfer, quoteOperatorFeePt, quoteOperatorFeeUsdt, rawCallOp, sendWithPaymasterFallback, serializeUserOpToJsonRpc, setPafiWebModalAdapter, splitAuthorizationSig, webPopupAdapter };
package/dist/index.d.ts CHANGED
@@ -695,6 +695,59 @@ interface BuildPerpDepositViaRelayParams {
695
695
  */
696
696
  declare function buildPerpDepositViaRelay(params: BuildPerpDepositViaRelayParams): PartialUserOperation;
697
697
 
698
+ /**
699
+ * Builder for the `erc20-transfer` sponsored scenario.
700
+ *
701
+ * Produces two UserOps from one request — same nonce, same sender:
702
+ *
703
+ * sponsored (2 calls):
704
+ * [ token.transfer(PAFI_FEE_RECIPIENT, fee), token.transfer(recipient, amount) ]
705
+ *
706
+ * fallback (1 call):
707
+ * [ token.transfer(recipient, amount) ]
708
+ *
709
+ * Both calls use the SAME token contract — the fee currency equals the
710
+ * token being sent (decision documented in
711
+ * `docs/SPONSORED_ERC20_TRANSFER_SPEC.md`). Caller is responsible for
712
+ * validating the token is in the sponsorship allowlist; this function
713
+ * just builds calldata, no policy enforcement.
714
+ *
715
+ * The sponsor-relayer's IntentValidator enforces:
716
+ * - exactly 2 calls
717
+ * - both target the same token address
718
+ * - call[0] = transfer to PAFI_FEE_RECIPIENT, amount >= 95% quoted
719
+ * - call[1] = transfer to recipient (not fee recipient, not 0x0)
720
+ *
721
+ * Fallback variant (1 call, no fee) submits no-paymaster — caller's
722
+ * `sendWithPaymasterFallback` routes there when sponsorship is refused.
723
+ */
724
+ interface BuildErc20TransferParams {
725
+ /** EIP-7702 delegated user EOA (== smart account sender). */
726
+ userAddress: Address;
727
+ /** ERC-4337 nonce from the EntryPoint. */
728
+ aaNonce: bigint;
729
+ /** Whitelisted ERC-20 to transfer. */
730
+ tokenAddress: Address;
731
+ /** Final recipient. Must NOT equal `feeRecipient` or `0x0...0`. */
732
+ recipient: Address;
733
+ /** Amount to send (token-native units; 6-dec for stables, 18-dec for PT). */
734
+ amount: bigint;
735
+ /**
736
+ * Operator fee in the SAME token. Sponsored variant only — pass
737
+ * `undefined` or 0n to skip and build the no-fee variant.
738
+ */
739
+ feeAmount?: bigint;
740
+ /** Required when `feeAmount > 0`. */
741
+ feeRecipient?: Address;
742
+ /** Override gas limits if you have a tighter Pimlico estimate. */
743
+ gasLimits?: {
744
+ callGasLimit?: bigint;
745
+ verificationGasLimit?: bigint;
746
+ preVerificationGas?: bigint;
747
+ };
748
+ }
749
+ declare function buildErc20TransferUserOp(params: BuildErc20TransferParams): PartialUserOperation;
750
+
698
751
  /**
699
752
  * Build an ERC-20 `transfer(to, amount)` operation. Used inside a batch
700
753
  * to move fee tokens from the user to the fee recipient atomically with
@@ -1021,7 +1074,7 @@ interface PaymasterConfig {
1021
1074
  * validates the request's target contracts + function selectors
1022
1075
  * match the expected pattern for the scenario.
1023
1076
  */
1024
- type SponsorshipScenario = "mint" | "burn" | "swap" | "perp-deposit" | "delegate";
1077
+ type SponsorshipScenario = "mint" | "burn" | "swap" | "perp-deposit" | "delegate" | "erc20-transfer";
1025
1078
 
1026
1079
  /**
1027
1080
  * Submission path chosen by `checkEthAndBranch`.
@@ -1576,7 +1629,8 @@ declare function sendWithPaymasterFallback(params: SendWithPaymasterFallbackPara
1576
1629
  *
1577
1630
  * Pass an explicit `gasUnits` to override.
1578
1631
  */
1579
- type FeeScenario = "mint" | "burn" | "swap" | "perp-deposit" | "delegate";
1632
+ type FeeScenario = "mint" | "burn" | "swap" | "perp-deposit" | "delegate" | "erc20-transfer";
1633
+ declare const SCENARIO_GAS_UNITS: Record<FeeScenario, bigint>;
1580
1634
  interface QuoteOperatorFeePtConfig {
1581
1635
  provider: PublicClient;
1582
1636
  chainId: number;
@@ -1689,6 +1743,43 @@ interface QuoteOperatorFeeUsdtConfig {
1689
1743
  */
1690
1744
  declare function quoteOperatorFeeUsdt(config: QuoteOperatorFeeUsdtConfig): Promise<bigint>;
1691
1745
  declare function quoteOperatorFeePt(config: QuoteOperatorFeePtConfig): Promise<bigint>;
1746
+ /**
1747
+ * Router quoter for the `erc20-transfer` sponsored scenario — picks
1748
+ * the correct underlying quoter based on the token being transferred:
1749
+ *
1750
+ * USDC / USDT → `quoteOperatorFeeUsdt` (Chainlink-based, 6-dec)
1751
+ * active PT → `quoteOperatorFeePt` (Chainlink + V3 pool quote)
1752
+ *
1753
+ * Fee is denominated in the SAME token the user is sending — no extra
1754
+ * approval / swap step needed. Caller is responsible for verifying the
1755
+ * token IS in the sponsored allowlist before calling; this function
1756
+ * just routes by address equality.
1757
+ *
1758
+ * Returns the fee in the token's native units (6-dec for USDC/USDT,
1759
+ * 18-dec for PT). The sponsor-relayer reproduces the same quote
1760
+ * server-side with a 5% slack window.
1761
+ *
1762
+ * @example
1763
+ * ```ts
1764
+ * const fee = await quoteOperatorFeeForTransfer({
1765
+ * provider, chainId: 8453,
1766
+ * tokenAddress: USDC_ADDRESS,
1767
+ * });
1768
+ * ```
1769
+ */
1770
+ interface QuoteOperatorFeeForTransferConfig extends Omit<QuoteOperatorFeeUsdtConfig, "scenario"> {
1771
+ /** The ERC-20 the user is transferring. Drives both quote logic + fee currency. */
1772
+ tokenAddress: Address;
1773
+ /**
1774
+ * Subgraph URL override — only consumed when `tokenAddress` resolves
1775
+ * to a PT (USDC/USDT paths don't hit the subgraph).
1776
+ */
1777
+ subgraphUrl?: string;
1778
+ /** PT fallback (only used when `tokenAddress` is a PT and subgraph fails). */
1779
+ fallbackPtPriceUsdt?: number;
1780
+ fetchImpl?: typeof fetch;
1781
+ }
1782
+ declare function quoteOperatorFeeForTransfer(config: QuoteOperatorFeeForTransferConfig): Promise<bigint>;
1692
1783
 
1693
1784
  declare const BATCH_EXECUTOR_ADDRESS_BASE_MAINNET: `0x${string}`;
1694
1785
  declare const BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA: `0x${string}`;
@@ -2141,4 +2232,4 @@ declare class PafiSDK {
2141
2232
  signLoginMessage(message: string): Promise<Hex>;
2142
2233
  }
2143
2234
 
2144
- export { ApiError, BATCH_EXECUTOR_7702_IMPL, BATCH_EXECUTOR_ABI, BATCH_EXECUTOR_ADDRESS_BASE_MAINNET, BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA, BROKER_HASHES, type BuildDelegationUserOpParams, type BuildPartialUserOpParams, type BuildPerpDepositViaRelayParams, type BuildPerpDepositWithGasDeductionParams, COMMON_POOLS, COMMON_TOKENS, CONTRACT_ADDRESSES, ChainConfig, type CheckEthAndBranchParams, ConfigurationError, type ContractAddresses, DUMMY_SIGNATURE_V07, type DelegateDirectParams, type DelegateDirectResult, type DelegateImpl, EIP712Signature, ENTRY_POINT_V07, ENTRY_POINT_V08, type Eip7702AuthorizationJsonRpc, LoginMessageParams, MintRequest, type ModalOpenOptions, ORDERLY_RELAY_ABI, ORDERLY_VAULT_ABI, ORDERLY_VAULT_ADDRESSES, ORDERLY_VAULT_BASE_MAINNET, type Operation, OracleStaleError, type OrderlyRelayDepositRequest, PAFI_SERVICE_URLS, PAFI_SUBGRAPH_URL, PERMIT2_ADDRESS, POINT_TOKEN_FACTORY_ADDRESSES, POINT_TOKEN_IMPL_ADDRESSES, POINT_TOKEN_POOLS, type PackedUserOperationMessage, type PafiErrorType, type PafiProxyTransportParams, PafiSDK, PafiSDKConfig, PafiSdkError, type PafiServiceUrls, type PafiWebModalAdapter, type PafiWebModalHandle, type PartialUserOperation, type PaymasterConfig, type PaymasterFields, PointTokenDomainConfig, PoolKey, QUOTER_V2_ADDRESSES, type QuoteOperatorFeePtConfig, type QuoteOperatorFeeUsdtConfig, SDK_ERROR_HTTP_STATUS_CODE, SIMPLE_7702_IMPL_BASE_MAINNET, SUPPORTED_CHAINS, type SdkErrorHttpStatus, type SendWithPaymasterFallbackParams, type SignAuthorizationFn, type SignatureStruct, SignatureVerification, SignatureVerifyOptions, type SignedAuthorization, SigningError, SimulationError, type SmartAccountSender, type SponsorshipScenario, type SubmissionPath, TOKEN_HASHES, UNIVERSAL_ROUTER_ADDRESSES, type UserOpReceipt, type UserOpTypedData, type UserOperation, V3Path, V3_FACTORY_ADDRESSES, V3_POOL_INIT_CODE_HASH, V3_SWAP_ROUTER_ADDRESSES, ValidationError, type VaultDepositFE, ZERO_VALUE, assembleUserOperation, buildDelegationUserOp, buildEip7702Authorization, buildPartialUserOperation, buildPerpDepositViaRelay, buildPerpDepositWithGasDeduction, buildUserOpTypedData, burnRequestTypes, checkDelegation, checkEthAndBranch, computeAccountId, computeAuthorizationHash, computeUserOpHash, computeV3PoolAddress, createPafiProxyTransport, decodeBatchExecuteCalls, defaultErrorTypeForStatus, delegateDirect, detectDelegateImpl, encodeBatchExecute, encodeV3Path, encodeV3PathReversed, erc20ApproveOp, erc20BurnOp, erc20TransferOp, fetchPafiPools, getAaNonce, getContractAddresses, getDummySignatureFor7702, getPafiServiceUrls, getPafiWebModalAdapter, isDelegatedTo, isDelegatedToTarget, isPaymasterError, mintRequestTypes, openPafiWebModal, openWebPopup, parseEip7702DelegatedAddress, quoteOperatorFeePt, quoteOperatorFeeUsdt, rawCallOp, sendWithPaymasterFallback, serializeUserOpToJsonRpc, setPafiWebModalAdapter, splitAuthorizationSig, webPopupAdapter };
2235
+ export { ApiError, BATCH_EXECUTOR_7702_IMPL, BATCH_EXECUTOR_ABI, BATCH_EXECUTOR_ADDRESS_BASE_MAINNET, BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA, BROKER_HASHES, type BuildDelegationUserOpParams, type BuildErc20TransferParams, type BuildPartialUserOpParams, type BuildPerpDepositViaRelayParams, type BuildPerpDepositWithGasDeductionParams, COMMON_POOLS, COMMON_TOKENS, CONTRACT_ADDRESSES, ChainConfig, type CheckEthAndBranchParams, ConfigurationError, type ContractAddresses, DUMMY_SIGNATURE_V07, type DelegateDirectParams, type DelegateDirectResult, type DelegateImpl, EIP712Signature, ENTRY_POINT_V07, ENTRY_POINT_V08, type Eip7702AuthorizationJsonRpc, type FallbackInfo, type FeeScenario, LoginMessageParams, MintRequest, type ModalOpenOptions, ORDERLY_RELAY_ABI, ORDERLY_VAULT_ABI, ORDERLY_VAULT_ADDRESSES, ORDERLY_VAULT_BASE_MAINNET, type Operation, OracleStaleError, type OrderlyRelayDepositRequest, PAFI_SERVICE_URLS, PAFI_SUBGRAPH_URL, PERMIT2_ADDRESS, POINT_TOKEN_FACTORY_ADDRESSES, POINT_TOKEN_IMPL_ADDRESSES, POINT_TOKEN_POOLS, type PackedUserOperationMessage, type PafiErrorType, type PafiProxyTransportParams, PafiSDK, PafiSDKConfig, PafiSdkError, type PafiServiceUrls, type PafiWebModalAdapter, type PafiWebModalHandle, type PartialUserOperation, type PaymasterConfig, type PaymasterFields, PointTokenDomainConfig, PoolKey, QUOTER_V2_ADDRESSES, type QuoteOperatorFeeForTransferConfig, type QuoteOperatorFeePtConfig, type QuoteOperatorFeeUsdtConfig, SCENARIO_GAS_UNITS, SDK_ERROR_HTTP_STATUS_CODE, SIMPLE_7702_IMPL_BASE_MAINNET, SUPPORTED_CHAINS, type SdkErrorHttpStatus, type SendWithPaymasterFallbackParams, type SignAuthorizationFn, type SignatureStruct, SignatureVerification, SignatureVerifyOptions, type SignedAuthorization, SigningError, SimulationError, type SmartAccountSender, type SponsorshipScenario, type SubmissionPath, TOKEN_HASHES, UNIVERSAL_ROUTER_ADDRESSES, type UserOpReceipt, type UserOpTypedData, type UserOperation, V3Path, V3_FACTORY_ADDRESSES, V3_POOL_INIT_CODE_HASH, V3_SWAP_ROUTER_ADDRESSES, ValidationError, type VaultDepositFE, ZERO_VALUE, assembleUserOperation, buildDelegationUserOp, buildEip7702Authorization, buildErc20TransferUserOp, buildPartialUserOperation, buildPerpDepositViaRelay, buildPerpDepositWithGasDeduction, buildUserOpTypedData, burnRequestTypes, checkDelegation, checkEthAndBranch, computeAccountId, computeAuthorizationHash, computeUserOpHash, computeV3PoolAddress, createPafiProxyTransport, decodeBatchExecuteCalls, defaultErrorTypeForStatus, delegateDirect, detectDelegateImpl, encodeBatchExecute, encodeV3Path, encodeV3PathReversed, erc20ApproveOp, erc20BurnOp, erc20TransferOp, fetchPafiPools, getAaNonce, getContractAddresses, getDummySignatureFor7702, getPafiServiceUrls, getPafiWebModalAdapter, isDelegatedTo, isDelegatedToTarget, isPaymasterError, mintRequestTypes, openPafiWebModal, openWebPopup, parseEip7702DelegatedAddress, quoteOperatorFeeForTransfer, quoteOperatorFeePt, quoteOperatorFeeUsdt, rawCallOp, sendWithPaymasterFallback, serializeUserOpToJsonRpc, setPafiWebModalAdapter, splitAuthorizationSig, webPopupAdapter };
package/dist/index.js CHANGED
@@ -532,6 +532,43 @@ function buildPerpDepositViaRelay(params) {
532
532
  });
533
533
  }
534
534
 
535
+ // src/transfer/buildErc20Transfer.ts
536
+ function buildErc20TransferUserOp(params) {
537
+ if (params.amount <= 0n) {
538
+ throw new Error("buildErc20TransferUserOp: amount must be positive");
539
+ }
540
+ const operations = [];
541
+ if (params.feeAmount && params.feeAmount > 0n) {
542
+ if (!params.feeRecipient) {
543
+ throw new Error(
544
+ "buildErc20TransferUserOp: feeRecipient required when feeAmount > 0"
545
+ );
546
+ }
547
+ operations.push(
548
+ erc20TransferOp(
549
+ params.tokenAddress,
550
+ params.feeRecipient,
551
+ params.feeAmount
552
+ )
553
+ );
554
+ }
555
+ operations.push(
556
+ erc20TransferOp(params.tokenAddress, params.recipient, params.amount)
557
+ );
558
+ return buildPartialUserOperation({
559
+ sender: params.userAddress,
560
+ nonce: params.aaNonce,
561
+ operations,
562
+ gasLimits: {
563
+ // 2 simple ERC-20 transfers + 7702 batch overhead. ~70-90k actual;
564
+ // 200k matches the `delegate` scenario budget and covers premium.
565
+ callGasLimit: params.gasLimits?.callGasLimit ?? 200000n,
566
+ verificationGasLimit: params.gasLimits?.verificationGasLimit ?? 150000n,
567
+ preVerificationGas: params.gasLimits?.preVerificationGas ?? 50000n
568
+ }
569
+ });
570
+ }
571
+
535
572
  // src/userop/types.ts
536
573
  var ZERO_VALUE = 0n;
537
574
 
@@ -1119,7 +1156,11 @@ var SCENARIO_GAS_UNITS = {
1119
1156
  burn: 500000n,
1120
1157
  swap: 700000n,
1121
1158
  "perp-deposit": 800000n,
1122
- delegate: 200000n
1159
+ delegate: 200000n,
1160
+ // 2-call batch: 1 ERC-20 fee transfer + 1 ERC-20 transfer + 7702
1161
+ // delegation overhead. ~70-90k empirical; 200k matches `delegate`
1162
+ // budget and gives headroom for premium variance.
1163
+ "erc20-transfer": 200000n
1123
1164
  };
1124
1165
  var DEFAULT_GAS_UNITS = 500000n;
1125
1166
  var DEFAULT_PREMIUM_BPS = 12e3;
@@ -1184,6 +1225,42 @@ async function quoteOperatorFeePt(config) {
1184
1225
  ]);
1185
1226
  return withPremium * ethPrice8dec * ptPerUsdt18dec / 10n ** 26n;
1186
1227
  }
1228
+ async function quoteOperatorFeeForTransfer(config) {
1229
+ const { provider, chainId, tokenAddress } = config;
1230
+ const { usdc, usdt } = getContractAddresses(chainId);
1231
+ const tokenLower = tokenAddress.toLowerCase();
1232
+ const isStable = usdc && tokenLower === usdc.toLowerCase() || tokenLower === usdt.toLowerCase();
1233
+ if (isStable) {
1234
+ return quoteOperatorFeeUsdt({
1235
+ provider,
1236
+ chainId,
1237
+ scenario: "erc20-transfer",
1238
+ gasUnits: config.gasUnits,
1239
+ premiumBps: config.premiumBps,
1240
+ chainlinkFeedAddress: config.chainlinkFeedAddress,
1241
+ usdtDecimals: config.usdtDecimals,
1242
+ allowStaleFallback: config.allowStaleFallback,
1243
+ fallbackEthPriceUsd: config.fallbackEthPriceUsd,
1244
+ onFallback: config.onFallback
1245
+ });
1246
+ }
1247
+ return quoteOperatorFeePt({
1248
+ provider,
1249
+ chainId,
1250
+ pointTokenAddress: tokenAddress,
1251
+ scenario: "erc20-transfer",
1252
+ gasUnits: config.gasUnits,
1253
+ premiumBps: config.premiumBps,
1254
+ chainlinkFeedAddress: config.chainlinkFeedAddress,
1255
+ subgraphUrl: config.subgraphUrl,
1256
+ usdtDecimals: config.usdtDecimals,
1257
+ allowStaleFallback: config.allowStaleFallback,
1258
+ fallbackEthPriceUsd: config.fallbackEthPriceUsd,
1259
+ fallbackPtPriceUsdt: config.fallbackPtPriceUsdt,
1260
+ onFallback: config.onFallback,
1261
+ fetchImpl: config.fetchImpl
1262
+ });
1263
+ }
1187
1264
  async function getEthPrice8dec(provider, feed, fallback, onFallback) {
1188
1265
  try {
1189
1266
  const result = await provider.readContract({
@@ -1599,6 +1676,7 @@ export {
1599
1676
  PafiSDK,
1600
1677
  PafiSdkError,
1601
1678
  QUOTER_V2_ADDRESSES,
1679
+ SCENARIO_GAS_UNITS,
1602
1680
  SDK_ERROR_HTTP_STATUS_CODE,
1603
1681
  SIMPLE_7702_IMPL_BASE_MAINNET,
1604
1682
  SPONSOR_AUTH_DOMAIN_ANCHOR_BASE_MAINNET,
@@ -1621,6 +1699,7 @@ export {
1621
1699
  buildDelegationUserOp,
1622
1700
  buildDomain,
1623
1701
  buildEip7702Authorization,
1702
+ buildErc20TransferUserOp,
1624
1703
  buildMintRequestTypedData,
1625
1704
  buildPartialUserOperation,
1626
1705
  buildPerpDepositViaRelay,
@@ -1684,6 +1763,7 @@ export {
1684
1763
  permit2Abi,
1685
1764
  pointTokenAbi,
1686
1765
  pointTokenFactoryAbi,
1766
+ quoteOperatorFeeForTransfer,
1687
1767
  quoteOperatorFeePt,
1688
1768
  quoteOperatorFeeUsdt,
1689
1769
  rawCallOp,