{"_id":"@0xkey-io/gas-station","_rev":"4-58f7fc4b4e0d7d6f7acd35fded491934","name":"@0xkey-io/gas-station","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"@0xkey-io/gas-station","version":"0.1.0","keywords":["0xkey","gas-station","eip-7702","delegated-execution","paymaster","ethereum","viem"],"author":{"url":"https://0xkey.com/","name":"0xkey"},"license":"Apache-2.0","_id":"@0xkey-io/gas-station@0.1.0","maintainers":[{"name":"0xkey-developer","email":"developer@0xkey.io"}],"homepage":"https://github.com/0xkey-io/sdk-js/tree/main/packages/gas-station","bugs":{"url":"https://github.com/0xkey-io/sdk-js/issues"},"dist":{"shasum":"bb30dd32d1e1885d667c200289667f9f0728e994","tarball":"https://registry.npmjs.org/@0xkey-io/gas-station/-/gas-station-0.1.0.tgz","fileCount":51,"integrity":"sha512-xAaopiEqqfTBPWXA1UHsR9l2fxly/fP+gkr5vRflzCn0c3POUCLYEZb4bkugOSauvTqJT3w5Ry6cvnkNTVfwhg==","signatures":[{"sig":"MEYCIQCGZJ7671p6ouY9e42AkQ5fN5XWDIfCRJ/HfXLPSDL1MwIhAJZLgq30K74LviQFuee29dqt/aUV372ZyCi9eBRT5H7s","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":735480},"main":"dist/index.js","_from":"file:0xkey-io-gas-station-0.1.0.tgz","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"build":"rollup -c ../../rollup.config.base.mjs","clean":"rimraf ./dist ./.cache","typecheck":"tsc --noEmit"},"_npmUser":{"name":"0xkey-developer","email":"developer@0xkey.io"},"_resolved":"/private/var/folders/lf/b69416ms3zvccf0ght6bq02r0000gn/T/5263785c7dd63091e2e899d7872cb599/0xkey-io-gas-station-0.1.0.tgz","_integrity":"sha512-xAaopiEqqfTBPWXA1UHsR9l2fxly/fP+gkr5vRflzCn0c3POUCLYEZb4bkugOSauvTqJT3w5Ry6cvnkNTVfwhg==","repository":{"url":"git+https://github.com/0xkey-io/sdk-js.git","type":"git","directory":"packages/gas-station"},"_npmVersion":"11.4.2","description":"0xkey Gas Station SDK for EIP-7702 delegated execution","directories":{},"_nodeVersion":"24.3.0","dependencies":{"viem":"^2.34.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.0","@types/node":"^24.6.2","@0xkey-io/sdk-server":"0.1.0"},"peerDependencies":{"viem":"^2.24.0","@0xkey-io/sdk-server":"0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/gas-station_0.1.0_1779443580977_0.5618118731067465","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@0xkey-io/gas-station","version":"0.1.1","keywords":["0xkey","gas-station","eip-7702","delegated-execution","paymaster","ethereum","viem"],"author":{"url":"https://0xkey.com/","name":"0xkey"},"license":"Apache-2.0","_id":"@0xkey-io/gas-station@0.1.1","maintainers":[{"name":"0xkey-developer","email":"developer@0xkey.io"}],"homepage":"https://github.com/0xkey-io/sdk-js/tree/main/packages/gas-station","bugs":{"url":"https://github.com/0xkey-io/sdk-js/issues"},"dist":{"shasum":"4d58eb7d3692d035814a7bb3dbd98423535da50f","tarball":"https://registry.npmjs.org/@0xkey-io/gas-station/-/gas-station-0.1.1.tgz","fileCount":51,"integrity":"sha512-9mrIIFtKfJBfYn8xd2oxycDa9WcgW8k8wECxEAmoqCdIYVqFvP54NrI+sjhStinaIXZ7tnnH8W/CbCQlTQ8Q7Q==","signatures":[{"sig":"MEUCIQD83l5mB1AdNR3UK4xvX/69RL3lC11RbQAoCo/PG8wrzwIgZXSIrB66O6JjyJuQe8DgFS1npomZb7ZvY4xUURFC/gM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":735480},"main":"dist/index.js","_from":"file:0xkey-io-gas-station-0.1.1.tgz","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"build":"rollup -c ../../rollup.config.base.mjs","clean":"rimraf ./dist ./.cache","typecheck":"tsc --noEmit"},"_npmUser":{"name":"0xkey-developer","email":"developer@0xkey.io"},"_resolved":"/private/var/folders/lf/b69416ms3zvccf0ght6bq02r0000gn/T/97ba144cd3ca31add75c9109f2f19746/0xkey-io-gas-station-0.1.1.tgz","_integrity":"sha512-9mrIIFtKfJBfYn8xd2oxycDa9WcgW8k8wECxEAmoqCdIYVqFvP54NrI+sjhStinaIXZ7tnnH8W/CbCQlTQ8Q7Q==","repository":{"url":"git+https://github.com/0xkey-io/sdk-js.git","type":"git","directory":"packages/gas-station"},"_npmVersion":"11.4.2","description":"0xkey Gas Station SDK for EIP-7702 delegated execution","directories":{},"_nodeVersion":"24.3.0","dependencies":{"viem":"^2.34.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.0","@types/node":"^24.6.2","@0xkey-io/sdk-server":"0.1.1"},"peerDependencies":{"viem":"^2.24.0","@0xkey-io/sdk-server":"0.1.1"},"_npmOperationalInternal":{"tmp":"tmp/gas-station_0.1.1_1779452039842_0.5797783141652151","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@0xkey-io/gas-station","version":"0.1.2","keywords":["0xkey","gas-station","eip-7702","delegated-execution","paymaster","ethereum","viem"],"author":{"url":"https://0xkey.com/","name":"0xkey"},"license":"Apache-2.0","_id":"@0xkey-io/gas-station@0.1.2","maintainers":[{"name":"0xkey-developer","email":"developer@0xkey.io"}],"homepage":"https://github.com/0xkey-io/sdk-js/tree/main/packages/gas-station","bugs":{"url":"https://github.com/0xkey-io/sdk-js/issues"},"dist":{"shasum":"12eb24e78c22ad476a5b11929fa3dd122ed84cba","tarball":"https://registry.npmjs.org/@0xkey-io/gas-station/-/gas-station-0.1.2.tgz","fileCount":51,"integrity":"sha512-tZ9efyArNp+vTbMJCn1adOCKxWzOfnfVk178+27NHhPD59A+DyUMMKuRWx0Z13rAICsRUVDZX0pN0IkQaO2EmQ==","signatures":[{"sig":"MEQCIDQMEG9zjslgz3JrItioN17etsSCfuDwFfGoqWXOvCVwAiBeAtAAElF1wduZunHPeajmqxwMyskEUm1QWGR5Obalrg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":735480},"main":"dist/index.js","_from":"file:0xkey-io-gas-station-0.1.2.tgz","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"build":"rollup -c ../../rollup.config.base.mjs","clean":"rimraf ./dist ./.cache","typecheck":"tsc --noEmit"},"_npmUser":{"name":"0xkey-developer","email":"developer@0xkey.io"},"_resolved":"/tmp/0af48ac12603ae260fe16e46b562f234/0xkey-io-gas-station-0.1.2.tgz","_integrity":"sha512-tZ9efyArNp+vTbMJCn1adOCKxWzOfnfVk178+27NHhPD59A+DyUMMKuRWx0Z13rAICsRUVDZX0pN0IkQaO2EmQ==","repository":{"url":"git+https://github.com/0xkey-io/sdk-js.git","type":"git","directory":"packages/gas-station"},"_npmVersion":"11.5.1","description":"0xkey Gas Station SDK for EIP-7702 delegated execution","directories":{},"_nodeVersion":"20.17.0","dependencies":{"viem":"^2.34.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.0","@types/node":"^24.6.2","@0xkey-io/sdk-server":"0.1.2"},"peerDependencies":{"viem":"^2.24.0","@0xkey-io/sdk-server":"0.1.2"},"_npmOperationalInternal":{"tmp":"tmp/gas-station_0.1.2_1782244192944_0.48002880741472365","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@0xkey-io/gas-station","version":"0.1.3","description":"0xkey Gas Station SDK for EIP-7702 delegated execution","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.mjs","require":"./dist/index.js","types":"./dist/index.d.ts"}},"author":{"name":"0xkey","url":"https://0xkey.com/"},"homepage":"https://github.com/0xkey-io/sdk-js/tree/main/packages/gas-station","bugs":{"url":"https://github.com/0xkey-io/sdk-js/issues"},"repository":{"type":"git","url":"git+https://github.com/0xkey-io/sdk-js.git","directory":"packages/gas-station"},"keywords":["0xkey","gas-station","eip-7702","delegated-execution","paymaster","ethereum","viem"],"dependencies":{"viem":"^2.34.0"},"devDependencies":{"@types/node":"^24.6.2","typescript":"^5.3.0","@0xkey-io/sdk-server":"0.1.3"},"peerDependencies":{"viem":"^2.24.0","@0xkey-io/sdk-server":"0.1.3"},"license":"Apache-2.0","publishConfig":{"access":"public"},"scripts":{"build":"rollup -c ../../rollup.config.base.mjs","typecheck":"tsc --noEmit","clean":"rimraf ./dist ./.cache"},"_id":"@0xkey-io/gas-station@0.1.3","_integrity":"sha512-Ckb/A/zq98hqVcK04m5M+7yAFgs3FX/g2Ui7txaLriHYajb6r8fIDgZzMMReuTK9raX2H0zFd47pVNgshSRs9A==","_resolved":"/tmp/9925beab471b0e245ab3dad59a1e87e3/0xkey-io-gas-station-0.1.3.tgz","_from":"file:0xkey-io-gas-station-0.1.3.tgz","_nodeVersion":"20.17.0","_npmVersion":"11.5.1","dist":{"integrity":"sha512-Ckb/A/zq98hqVcK04m5M+7yAFgs3FX/g2Ui7txaLriHYajb6r8fIDgZzMMReuTK9raX2H0zFd47pVNgshSRs9A==","shasum":"11702cd39f97b084dc08462d9fd14fae059b8e77","tarball":"https://registry.npmjs.org/@0xkey-io/gas-station/-/gas-station-0.1.3.tgz","fileCount":51,"unpackedSize":735480,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDFoliHFt69kCdVQo0QzYu5P9j/DzNLgYb3+bI83Us2YwIhAOMnk/6j2BqM9TTlCtjVrCe9IqZyqHHQqAMUjj7K/RZQ"}]},"_npmUser":{"name":"0xkey-developer","email":"developer@0xkey.io"},"directories":{},"maintainers":[{"name":"0xkey-developer","email":"developer@0xkey.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/gas-station_0.1.3_1783079733214_0.024304997795455474"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-22T09:53:00.834Z","modified":"2026-07-03T11:55:33.604Z","0.1.0":"2026-05-22T09:53:01.110Z","0.1.1":"2026-05-22T12:14:00.038Z","0.1.2":"2026-06-23T19:49:53.081Z","0.1.3":"2026-07-03T11:55:33.445Z"},"bugs":{"url":"https://github.com/0xkey-io/sdk-js/issues"},"author":{"name":"0xkey","url":"https://0xkey.com/"},"license":"Apache-2.0","homepage":"https://github.com/0xkey-io/sdk-js/tree/main/packages/gas-station","keywords":["0xkey","gas-station","eip-7702","delegated-execution","paymaster","ethereum","viem"],"repository":{"type":"git","url":"git+https://github.com/0xkey-io/sdk-js.git","directory":"packages/gas-station"},"description":"0xkey Gas Station SDK for EIP-7702 delegated execution","maintainers":[{"name":"0xkey-developer","email":"developer@0xkey.io"}],"readme":"# ZeroXKey Gas Station SDK\n\nA reusable SDK for implementing gasless transactions using EIP-7702, ZeroXKey wallet management, and your own paymaster. This package provides clean abstractions and utility methods to quickly integrate with ZeroXKey's contracts for sponsored transaction execution.\n\n## What is This?\n\nThis SDK enables you to:\n\n- **Bring your own paymaster** to sponsor user transactions\n- **Use ZeroXKey** for secure wallet management and transaction signing\n- **Execute gasless transactions** via EIP-7702 delegation and EIP-712 signed intents\n- **Support any on-chain action** through generic execution parameters\n\nPerfect for building dApps where users don't need ETH for gas, enabling seamless onboarding and better UX.\n\n## How It Works\n\n1. **EIP-7702 Authorization**: One-time setup where an EOA authorizes a gas station contract\n2. **EIP-712 Signed Intents**: User signs off-chain intents for what they want to execute\n3. **Paymaster Execution**: Your paymaster submits the transaction and pays for gas\n4. **ZeroXKey Integration**: All signatures handled securely through ZeroXKey\n\n## Quick Start\n\n### 1. Install Dependencies\n\n```bash\npnpm install @0xkey-io/gas-station @0xkey-io/sdk-server @0xkey-io/viem viem\n```\n\n### 2. Set Up Environment\n\nCreate `.env.local`:\n\n```bash\n# ZeroXKey Configuration\nBASE_URL=https://api.0xkey.com\nAPI_PRIVATE_KEY=your_0xkey_api_private_key\nAPI_PUBLIC_KEY=your_0xkey_api_public_key\nORGANIZATION_ID=your_0xkey_organization_id\n\n# Wallet Addresses\nEOA_ADDRESS=0x...                            # User's wallet address\nPAYMASTER_ADDRESS=0x...                      # Your paymaster address\n\n# RPC Configuration\nBASE_RPC_URL=https://mainnet.base.org\nETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/...\n\n# Gas Station Contracts (Optional - defaults to deterministic addresses)\nDELEGATE_CONTRACT=0x...    # EIP-7702 delegate contract\nEXECUTION_CONTRACT=0x...   # Gas Sponsorship entrypoint contract which calls the delegate.\n```\n\n**Note**: The gas station contracts are currently deployed at deterministic addresses on the following chains:\n\n- **Ethereum Mainnet**\n- **Base Mainnet**\n\nThese addresses are built into the SDK, so you don't need to specify them unless you are using custom deployments.\n\n### 3. Initialize and Use\n\n```typescript\nimport { GasStationClient } from \"@0xkey-io/gas-station\";\nimport { ZeroXKey } from \"@0xkey-io/sdk-server\";\nimport { createAccount } from \"@0xkey-io/viem\";\nimport { parseEther, parseUnits, createWalletClient, http } from \"viem\";\nimport { base } from \"viem/chains\";\n\n// Initialize ZeroXKey\nconst zeroXKeyClient = new ZeroXKey({\n  apiBaseUrl: process.env.BASE_URL!,\n  apiPrivateKey: process.env.API_PRIVATE_KEY!,\n  apiPublicKey: process.env.API_PUBLIC_KEY!,\n  defaultOrganizationId: process.env.ORGANIZATION_ID!,\n});\n\n// Create ZeroXKey accounts\nconst userAccount = await createAccount({\n  client: zeroXKeyClient.apiClient(),\n  organizationId: process.env.ORGANIZATION_ID!,\n  signWith: process.env.EOA_ADDRESS as `0x${string}`,\n});\n\nconst paymasterAccount = await createAccount({\n  client: zeroXKeyClient.apiClient(),\n  organizationId: process.env.ORGANIZATION_ID!,\n  signWith: process.env.PAYMASTER_ADDRESS as `0x${string}`,\n});\n\n// Create viem wallet clients\nconst userWalletClient = createWalletClient({\n  account: userAccount,\n  chain: base,\n  transport: http(process.env.BASE_RPC_URL!),\n});\n\nconst paymasterWalletClient = createWalletClient({\n  account: paymasterAccount,\n  chain: base,\n  transport: http(process.env.BASE_RPC_URL!),\n});\n\n// Create Gas Station clients\nconst userClient = new GasStationClient({\n  walletClient: userWalletClient,\n});\n\nconst paymasterClient = new GasStationClient({\n  walletClient: paymasterWalletClient,\n});\n\n// One-time: Authorize the EOA to use gas station\nconst authorization = await userClient.signAuthorization();\nawait paymasterClient.submitAuthorizations([authorization]);\n\n// Execute a gasless ETH transfer\nlet nonce = await userClient.getNonce();\nconst ethIntent = await userClient\n  .createIntent()\n  .transferETH(\"0xRecipient...\", parseEther(\"0.1\"))\n  .sign(nonce);\nawait paymasterClient.execute(ethIntent);\n\n// Execute a gasless token transfer\nnonce = await userClient.getNonce();\nconst usdcIntent = await userClient\n  .createIntent()\n  .transferToken(\n    \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\", // USDC on Base\n    \"0xRecipient...\",\n    parseUnits(\"10\", 6),\n  )\n  .sign(nonce);\nawait paymasterClient.execute(usdcIntent);\n```\n\n## Core API\n\n### GasStationClient\n\nMain client for gas station operations. Each client instance wraps a viem wallet client.\n\n#### Constructor\n\n```typescript\nnew GasStationClient({\n  walletClient: WalletClient,          // Viem wallet client (e.g., with ZeroXKey account)\n  delegateContract?: `0x${string}`,    // Optional: defaults to deterministic address\n  executionContract?: `0x${string}`,   // Optional: defaults to deterministic address\n})\n```\n\n#### Methods\n\n**End User Methods** (call with user client):\n\n**`signAuthorization(): Promise<SignedAuthorization>`**\n\n- Sign an EIP-7702 authorization for the gas station contract\n- Returns authorization that can be submitted by paymaster\n\n**`createIntent(): IntentBuilder`**\n\n- Create a builder for composing transactions\n- Intent must be signed before execution\n\n**`getNonce(address?: Address): Promise<bigint>`**\n\n- Get current nonce from gas station contract\n- Defaults to the signer's address if not specified\n\n**Paymaster Methods** (call with paymaster client):\n\n**`submitAuthorizations(authorizations: SignedAuthorization[]): Promise<{ txHash, blockNumber }>`**\n\n- Submit signed EIP-7702 authorization transaction(s)\n- Supports authorizing multiple EOAs in a single transaction\n- Paymaster pays for gas\n\n**`execute(intent: ExecutionIntent): Promise<{ txHash, blockNumber, gasUsed }>`**\n\n- Execute a signed intent through the gas station\n- Paymaster pays for gas\n\n### IntentBuilder\n\nComposable builder for complex multi-step transactions.\n\n```typescript\nconst nonce = await userClient.getNonce();\nconst builder = userClient.createIntent();\n\nconst intent = await builder\n  .transferToken(usdcAddress, recipient, amount)\n  .sign(nonce);\n\nawait paymasterClient.execute(intent);\n```\n\n## Common Use Cases\n\n### Simple Payment\n\n```typescript\n// Gasless USDC payment\nconst nonce = await userClient.getNonce();\nconst intent = await userClient\n  .createIntent()\n  .transferToken(usdcAddress, recipientAddress, parseUnits(\"50\", 6))\n  .sign(nonce);\n\nconst result = await paymasterClient.execute(intent);\nconsole.log(`Payment sent: ${result.txHash}`);\n```\n\n### Token Approval + DEX Swap\n\n```typescript\n// Step 1: Approve DEX to spend tokens\nlet nonce = await userClient.getNonce();\nconst approvalIntent = await userClient\n  .createIntent()\n  .approveToken(usdcAddress, dexAddress, parseUnits(\"100\", 6))\n  .sign(nonce);\nawait paymasterClient.execute(approvalIntent);\n\n// Step 2: Execute swap\nnonce = await userClient.getNonce();\nconst swapIntent = await userClient\n  .createIntent()\n  .callContract({\n    contract: dexAddress,\n    abi: DEX_ABI,\n    functionName: \"swapExactTokensForTokens\",\n    args: [amountIn, amountOutMin, path, recipient, deadline],\n  })\n  .sign(nonce);\nawait paymasterClient.execute(swapIntent);\n```\n\n### User Onboarding\n\n```typescript\nasync function onboardUser(userAddress: string) {\n  // Create viem wallet client for user\n  const userAccount = await createAccount({\n    client: zeroXKeyClient.apiClient(),\n    organizationId: ORGANIZATION_ID,\n    signWith: userAddress as `0x${string}`,\n  });\n\n  const userWalletClient = createWalletClient({\n    account: userAccount,\n    chain: base,\n    transport: http(BASE_RPC_URL),\n  });\n\n  // Create Gas Station clients\n  const userClient = new GasStationClient({\n    walletClient: userWalletClient,\n  });\n\n  // Authorize user (paymaster pays)\n  const authorization = await userClient.signAuthorization();\n  await paymasterClient.submitAuthorizations([authorization]);\n\n  // User can now execute transactions without ETH\n  console.log(\"✅ User ready for gasless transactions!\");\n}\n```\n\n## Architecture\n\n### Gas Station Pattern\n\n1. **Delegate Contract**: Authorized to EOA via EIP-7702\n2. **Execution Contract**: Contains execution logic and nonce management\n3. **EOA**: Signs EIP-712 intents off-chain\n4. **Paymaster**: Submits transactions and pays gas\n\n### Transaction Flow\n\n```\nUser (EOA)\n  ↓ Signs EIP-712 intent off-chain\n  ↓\nSDK (GasStationClient)\n  ↓ Builds transaction\n  ↓\nPaymaster\n  ↓ Submits transaction, pays gas\n  ↓\nGas Station Contract\n  ↓ Validates signature & nonce\n  ↓ Executes on behalf of EOA\n  ↓\nTarget Contract (USDC, NFT, DEX, etc.)\n```\n\n## Chain Support\n\nAvailable presets for quick setup:\n\n- **BASE_MAINNET** - Base mainnet (includes USDC address)\n- **ETHEREUM_MAINNET** - Ethereum mainnet (includes USDC address)\n\n```typescript\n// Chain presets are available for quick configuration\nimport { CHAIN_PRESETS, GasStationClient } from \"@0xkey-io/gas-station\";\nimport { createWalletClient, http } from \"viem\";\n\nconst basePreset = CHAIN_PRESETS.BASE_MAINNET;\nconst userWalletClient = createWalletClient({\n  account: userAccount,\n  chain: basePreset.chain,\n  transport: http(basePreset.rpcUrl),\n});\n\nconst userClient = new GasStationClient({\n  walletClient: userWalletClient,\n});\n```\n\n## Security\n\n- **EIP-712 Signed Intents**: All executions require valid typed signatures\n- **EIP-7702 Scoping**: Authorization is per-EOA and can be revoked\n- **Deadline Enforcement**: Each transaction includes a deadline (Unix timestamp) to prevent replay attacks; signatures expire after this time\n- **ZeroXKey Integration**: Private keys never leave ZeroXKey's secure infrastructure\n\n### Security Policies\n\nZeroXKey policies provide additional security layers by restricting what transactions can be signed and executed. The Gas Station SDK includes helpers for creating these policies.\n\n#### EOA Intent Signing Policies\n\nRestrict what EIP-712 intents the EOA can sign:\n\n```typescript\nimport { buildIntentSigningPolicy } from \"@0xkey-io/gas-station\";\n\n// USDC-only policy\nconst eoaPolicy = buildIntentSigningPolicy({\n  organizationId: \"a5b89e4f-1234-5678-9abc-def012345678\",\n  eoaUserId: \"3c7d6e8a-4b5c-6d7e-8f9a-0b1c2d3e4f5a\",\n  restrictions: {\n    allowedContracts: [\"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\"], // USDC on Base\n    disallowEthTransfer: true, // Disallow ETH transfers\n  },\n  policyName: \"USDC Only Policy\",\n});\n\n// Resulting policy restricts signing to USDC transfers only:\n// {\n//   organizationId: \"a5b89e4f-1234-5678-9abc-def012345678\",\n//   policyName: \"USDC Only Policy\",\n//   effect: \"EFFECT_ALLOW\",\n//   consensus: \"approvers.any(user, user.id == '3c7d6e8a-4b5c-6d7e-8f9a-0b1c2d3e4f5a')\",\n//   condition: \"activity.resource == 'PRIVATE_KEY' && \" +\n//              \"activity.action == 'SIGN' && \" +\n//              \"eth.eip_712.primary_type == 'Execution' && \" +\n//              \"(eth.eip_712.message['to'] == '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913') && \" +\n//              \"eth.eip_712.message['value'] == '0'\",\n//   notes: \"Restricts which EIP-712 intents the EOA can sign for gas station execution\"\n// }\n```\n\n#### Paymaster Execution Policies\n\nRestrict what on-chain transactions the paymaster can submit:\n\n```typescript\nimport {\n  buildPaymasterExecutionPolicy,\n  DEFAULT_EXECUTION_CONTRACT,\n  ensureGasStationInterface,\n} from \"@0xkey-io/gas-station\";\nimport { parseGwei, parseEther } from \"viem\";\n\n// First, ensure the Gas Station ABI is uploaded (enables ABI-based policies)\nawait ensureGasStationInterface(\n  zeroXKeyClient.apiClient(),\n  \"your-org-id\",\n  DEFAULT_EXECUTION_CONTRACT,\n  undefined,\n  \"Base Mainnet\",\n);\n\n// Paymaster protection policy with ETH amount limit\nconst paymasterPolicy = buildPaymasterExecutionPolicy({\n  organizationId: \"f8c3a5e7-9876-5432-1abc-def098765432\",\n  paymasterUserId: \"8f2a1b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c\",\n  executionContractAddress: DEFAULT_EXECUTION_CONTRACT,\n  restrictions: {\n    allowedEOAs: [\"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb\"],\n    allowedContracts: [\"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\"],\n    maxEthAmount: parseEther(\"0.1\"), // Max 0.1 ETH per EOA transaction\n    maxGasPrice: parseGwei(\"50\"), // Max 50 gwei gas price\n    maxGasLimit: 500000n, // Max 500k gas limit\n  },\n  policyName: \"Paymaster Protection\",\n});\n\n// Resulting policy uses ABI parsing for direct argument access:\n// {\n//   organizationId: \"f8c3a5e7-9876-5432-1abc-def098765432\",\n//   policyName: \"Paymaster Protection\",\n//   effect: \"EFFECT_ALLOW\",\n//   consensus: \"approvers.any(user, user.id == '8f2a1b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c')\",\n//   condition: \"activity.resource == 'PRIVATE_KEY' && \" +\n//              \"activity.action == 'SIGN' && \" +\n//              \"eth.tx.to == '0x00000000008c57a1ce37836a5e9d36759d070d8c' && \" +\n//              \"(eth.tx.contract_call_args['_to'] == '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913') && \" +\n//              \"(eth.tx.contract_call_args['_target'] == '0x742d35cc6634c0532925a3b844bc9e7595f0beb') && \" +\n//              \"eth.tx.contract_call_args['_ethAmount'] <= 100000000000000000 && \" +\n//              \"eth.tx.gasPrice <= 50000000000 && \" +\n//              \"eth.tx.gas <= 500000\",\n//   notes: \"Restricts which transactions the paymaster can execute on the gas station\"\n// }\n```\n\n**Note:** The `ensureGasStationInterface()` function uploads the Gas Station ABI to ZeroXKey's Smart Contract Interface feature. This enables ZeroXKey's policy engine to parse the ABI-encoded transaction data and directly compare the `_ethAmount` parameter as a uint256 value, rather than raw bytes. The function checks if the ABI already exists before uploading to avoid duplicates.\n\n#### Defense in Depth\n\nCombine both policy types for maximum security:\n\n```typescript\nimport {\n  buildIntentSigningPolicy,\n  buildPaymasterExecutionPolicy,\n  DEFAULT_EXECUTION_CONTRACT,\n} from \"@0xkey-io/gas-station\";\nimport { parseGwei } from \"viem\";\n\n// Layer 1: EOA can only sign USDC intents\nconst eoaPolicy = buildIntentSigningPolicy({\n  organizationId: \"a5b89e4f-1234-5678-9abc-def012345678\",\n  eoaUserId: \"3c7d6e8a-4b5c-6d7e-8f9a-0b1c2d3e4f5a\",\n  restrictions: {\n    allowedContracts: [\"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\"],\n    disallowEthTransfer: true, // No ETH transfers\n  },\n});\n\n// Layer 2: Paymaster can only execute for specific users with gas limits\nconst paymasterPolicy = buildPaymasterExecutionPolicy({\n  organizationId: \"f8c3a5e7-9876-5432-1abc-def098765432\",\n  paymasterUserId: \"8f2a1b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c\",\n  executionContractAddress: DEFAULT_EXECUTION_CONTRACT,\n  restrictions: {\n    allowedEOAs: [\"0xUserAddress...\"],\n    allowedContracts: [\"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\"],\n    maxGasPrice: parseGwei(\"50\"),\n    maxGasLimit: 500000n,\n  },\n});\n```\n\n### Advanced: Writing Custom Paymaster Policies\n\nWhen using `buildPaymasterExecutionPolicy`, the SDK creates ZeroXKey policies that parse the transaction calldata to enforce restrictions. Understanding the transaction structure allows you to write custom policies for advanced use cases.\n\n#### Transaction Data Structure\n\nWhen the paymaster signs an execution transaction calling `execute(address _target, address _to, uint256 _ethAmount, bytes _data)`, the transaction data (`eth.tx.data`) has the following structure:\n\n| Position in eth.tx.data | Length    | Content                | Example                                           |\n| ----------------------- | --------- | ---------------------- | ------------------------------------------------- |\n| `[2..10]`               | 8 chars   | Function selector      | `6c5c2ed9` (execute)                              |\n| `[10..74]`              | 64 chars  | \\_target (EOA, padded) | `0000...742d35cc6634c0532925a3b844bc9e7595f0beb`  |\n| `[74..138]`             | 64 chars  | \\_to (output contract) | `0000...833589fcd6edb6e08f4c7c32d4f71b54bda02913` |\n| `[138..202]`            | 64 chars  | \\_ethAmount (uint256)  | `0000...0000` (0 ETH) or amount in wei            |\n| `[202..266]`            | 64 chars  | Offset to \\_data bytes | `0000...0080` (128 bytes)                         |\n| `[266..330]`            | 64 chars  | Packed data length     | `0000...0055` (85 bytes: 65+16+4)                 |\n| `[330..460]`            | 130 chars | Signature (65 bytes)   | EIP-712 signature from EOA                        |\n| `[460..492]`            | 32 chars  | Nonce (16 bytes)       | `00000000000000000000000000000000`                |\n| `[492..500]`            | 8 chars   | Deadline (4 bytes)     | `6ac7d340` (Unix timestamp)                       |\n| `[500+]`                | Variable  | Call data              | Encoded function call for target contract         |\n\n**Important:** ZeroXKey's `eth.tx.data` includes the `0x` prefix, so positions start at index 2 (after `0x`).\n\n**Note:** The deadline is a Unix timestamp that prevents replay attacks by expiring signatures after a specified time. The SDK defaults to 1 hour, customizable with `withDeadline()`.\n\n#### Policy Conditions Reference\n\n**Check execution contract address:**\n\n```typescript\neth.tx.to == \"0x00000000008c57a1ce37836a5e9d36759d070d8c\";\n```\n\n**Check which EOA is executing:**\n\n```typescript\neth.tx.data[10..74] == '0000000000000000000000742d35cc6634c0532925a3b844bc9e7595f0beb'\n```\n\n**Check target contract (output contract):**\n\n```typescript\neth.tx.data[74..138] == '0000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913'\n```\n\n**Check ETH amount:**\n\n```typescript\neth.tx.data[138..202].hex_to_uint() <= 100000000000000000; // Max 0.1 ETH in wei\n```\n\n**Check gas price:**\n\n```typescript\neth.tx.gasPrice <= 50000000000; // 50 gwei in wei\n```\n\n**Check gas limit:**\n\n```typescript\neth.tx.gas <= 500000;\n```\n\n#### Example: Custom Multi-Contract Policy\n\nAllow paymaster to execute for USDC or DAI only:\n\n```typescript\nconst policy = {\n  organizationId: \"f8c3a5e7-9876-5432-1abc-def098765432\",\n  policyName: \"Stablecoin Execution Policy\",\n  effect: \"EFFECT_ALLOW\",\n  consensus: `approvers.any(user, user.id == '${paymasterUserId}')`,\n  condition: [\n    \"activity.resource == 'PRIVATE_KEY'\",\n    \"activity.action == 'SIGN'\",\n    \"eth.tx.to == '0x00000000008c57a1ce37836a5e9d36759d070d8c'\",\n    // Allow USDC or DAI\n    \"(eth.tx.data[74..138] == '0000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913' || eth.tx.data[74..138] == '00000000000000000000006b175474e89094c44da98b954eedeac495271d0f')\",\n    // Gas limits\n    \"eth.tx.gasPrice <= 100000000000\",\n    \"eth.tx.gas <= 500000\",\n  ].join(\" && \"),\n  notes: \"Allow USDC and DAI execution with gas limits\",\n};\n\nawait zeroXKeyClient.apiClient().createPolicy(policy);\n```\n\n#### Example: Whitelist Specific EOAs\n\nOnly allow execution for approved user wallets:\n\n```typescript\nconst approvedEOAs = [\n  \"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb\",\n  \"0x1234567890123456789012345678901234567890\",\n];\n\nconst eoaConditions = approvedEOAs\n  .map((addr) => {\n    const padded = addr.slice(2).toLowerCase().padStart(64, \"0\");\n    return `eth.tx.data[10..74] == '${padded}'`;\n  })\n  .join(\" || \");\n\nconst policy = {\n  organizationId: \"f8c3a5e7-9876-5432-1abc-def098765432\",\n  policyName: \"Approved Users Only\",\n  effect: \"EFFECT_ALLOW\",\n  consensus: `approvers.any(user, user.id == '${paymasterUserId}')`,\n  condition: [\n    \"activity.resource == 'PRIVATE_KEY'\",\n    \"activity.action == 'SIGN'\",\n    \"eth.tx.to == '0x00000000008c57a1ce37836a5e9d36759d070d8c'\",\n    `(${eoaConditions})`,\n  ].join(\" && \"),\n};\n\nawait zeroXKeyClient.apiClient().createPolicy(policy);\n```\n\n#### Using the Helper Functions\n\nFor most cases, use the built-in helpers which handle the byte positions correctly:\n\n```typescript\nimport {\n  buildPaymasterExecutionPolicy,\n  DEFAULT_EXECUTION_CONTRACT,\n} from \"@0xkey-io/gas-station\";\nimport { parseGwei } from \"viem\";\n\nconst policy = buildPaymasterExecutionPolicy({\n  organizationId: subOrgId,\n  paymasterUserId: paymasterUserId,\n  executionContractAddress: DEFAULT_EXECUTION_CONTRACT,\n  restrictions: {\n    allowedContracts: [\n      \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\", // USDC\n      \"0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb\", // DAI\n    ],\n    allowedEOAs: [\"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb\"],\n    maxGasPrice: parseGwei(\"100\"),\n    maxGasLimit: 500000n,\n  },\n  policyName: \"Production Paymaster Policy\",\n});\n\nawait zeroXKeyClient.apiClient().createPolicy(policy);\n```\n\nThe helper functions automatically:\n\n- Convert addresses to lowercase\n- Add proper padding for EOA addresses\n- Calculate correct byte positions (accounting for `0x` prefix)\n- Generate proper OR conditions for multiple allowed values\n\n## Troubleshooting\n\n### Authorization Failed\n\n- Ensure paymaster has ETH for gas\n- Verify delegate contract address is correct\n\n### Execution Failed\n\n- Confirm EOA is authorized (check with `isAuthorized()`)\n- Verify execution contract address matches deployment\n- Check nonce hasn't been reused\n- Ensure target contract call is valid\n\n### Insufficient Funds\n\n- EOA must have sufficient token balance for transfers\n- Paymaster must have ETH for gas\n\n### Invalid Signature\n\n- Verify EOA address is correct\n- Ensure chain ID matches the network\n- Check intent was signed with correct nonce\n\n## Best Practices\n\n1. **Client Separation**: Create separate client instances for users and paymasters\n2. **Authorization**: Only call `authorize()` once per EOA\n3. **Nonce Management**: Always fetch fresh nonce before creating intents\n4. **Rate Limiting**: Implement paymaster rate limits to prevent abuse\n\n## License\n\nSee the main SDK repository for license information.\n","readmeFilename":"README.md"}