@pulsadev/permit2
v0.1.0
Published
EIP-2612 Permit + Uniswap Permit2 — gasless approve signatures, typed data building, nonce queries. Zero dependencies, pure RPC.
Readme
@pulsadev/permit2
EIP-2612 Permit + Uniswap Permit2 — gasless approve signatures, typed data building, nonce queries. Zero dependencies, pure RPC.
Build EIP-712 typed data for both EIP-2612 and Permit2, query on-chain state, no ethers/viem required.
Features
- EIP-2612 Permit — build typed data for gasless token approvals
- Permit2 PermitSingle — single token allowance via signature
- Permit2 PermitBatch — batch token allowances in one signature
- Permit2 PermitTransferFrom — signature-based token transfers
- Permit2 BatchTransferFrom — batch signature transfers
- On-chain queries — nonce, domain separator, Permit2 allowance
- Token domain auto-detection — reads name, version from contract
- EIP-712 typed data output — ready for
eth_signTypedData_v4 - Zero dependencies — ~10 KB bundled, ESM + CJS, pure TypeScript
Install
npm install @pulsadev/permit2Quick Start
EIP-2612 Permit (gasless approve)
import { buildPermitData } from '@pulsadev/permit2'
const permitData = await buildPermitData(
'https://ethereum-rpc.publicnode.com',
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
'0xOwner...', // token owner
'0xSpender...', // approved spender
1000000n, // amount (1 USDC)
BigInt(Math.floor(Date.now() / 1000) + 3600), // 1 hour deadline
)
// Sign with wallet
const signature = await wallet.signTypedData(permitData.typedData)Permit2 PermitSingle
import { createPermitSingle, buildPermitSingleTypedData } from '@pulsadev/permit2'
const permit = createPermitSingle(
'0xUSDC...', // token
1000000n, // amount
BigInt(Math.floor(Date.now() / 1000) + 86400), // 24h expiration
0n, // nonce
'0xSpender...', // spender
BigInt(Math.floor(Date.now() / 1000) + 3600), // 1h sig deadline
)
const typedData = buildPermitSingleTypedData(permit, 1) // chainId = 1
const signature = await wallet.signTypedData(typedData)Permit2 TransferFrom
import { createPermitTransferFrom, buildPermitTransferFromTypedData } from '@pulsadev/permit2'
const permit = createPermitTransferFrom(
'0xUSDC...', 1000000n, '0xSpender...', 0n,
BigInt(Math.floor(Date.now() / 1000) + 3600),
)
const typedData = buildPermitTransferFromTypedData(permit, 1)Query on-chain state
import { getPermitNonce, getDomainSeparator, getPermit2Allowance } from '@pulsadev/permit2'
const nonce = await getPermitNonce(rpcUrl, tokenAddress, ownerAddress)
const domainSep = await getDomainSeparator(rpcUrl, tokenAddress)
const allowance = await getPermit2Allowance(rpcUrl, owner, token, spender)
// { amount, expiration, nonce }API
EIP-2612
| Function | Description |
|----------|-------------|
| buildPermitData(rpcUrl, token, owner, spender, value, deadline, chainId?) | Build complete permit typed data |
| getPermitNonce(rpcUrl, token, owner) | Get current permit nonce |
| getDomainSeparator(rpcUrl, token) | Get DOMAIN_SEPARATOR |
| getTokenDomain(rpcUrl, token, chainId?) | Get full EIP-712 domain |
Permit2
| Function | Description |
|----------|-------------|
| buildPermitSingleTypedData(permit, chainId) | Build PermitSingle EIP-712 data |
| buildPermitBatchTypedData(permit, chainId) | Build PermitBatch EIP-712 data |
| buildPermitTransferFromTypedData(permit, chainId) | Build PermitTransferFrom EIP-712 data |
| buildPermitBatchTransferFromTypedData(permit, chainId) | Build BatchTransferFrom EIP-712 data |
| getPermit2Allowance(rpcUrl, owner, token, spender) | Query Permit2 allowance |
| createPermitSingle(token, amount, expiration, nonce, spender, sigDeadline) | Helper to create PermitSingle |
| createPermitTransferFrom(token, amount, spender, nonce, deadline) | Helper to create PermitTransferFrom |
Why not @uniswap/permit2-sdk?
| | @uniswap/permit2-sdk | @1inch/permit-utils | @pulsadev/permit2 | |--|---------------------|---------------------|-------------------| | EIP-2612 | No | Yes | Yes | | Permit2 | Yes | No | Yes | | Dependencies | ethers v5 | ethers v6 | None | | On-chain queries | No | Yes | Yes | | Domain auto-detect | No | Yes | Yes | | Bundle size | Heavy | Medium | ~10 KB |
License
MIT © Yuto Nakamura
