Permit2
Here’s the guideline of using Permit2 in OpenOcean Swap API
About Permit2
OpenOcean Swap API supports Uniswap’s Permit2 SignatureTransfer contract, which standardizes token approvals across applications and improves both UX and security.
Permit2 is a universal token approval contract from Uniswap. Instead of requiring users to first send an approve transaction and then a swap, Permit2 allows approvals to be handled through a single EIP-712 signature. This removes the “double transaction” flow and gives developers more control over allowance scope (amounts, deadlines, nonces).
For simpler integration, you may also consider using AllowanceHolder contract, which requires a one-time approval without additional signatures.
Using Permit2 with OpenOcean Swap API
To integrate Permit2 (SignatureTransfer) into your swap flow, follow these steps:
Check the current allowance
(Optional) Approve Permit2 if needed
Generate the Permit2 signature and data
Build the transaction body
Send the transaction with the Permit2 signature
1. Check the current allowance for permit2
Verify whether the target token has granted Permit2 sufficient spending allowance.
import { ethers } from 'ethers';
async function allowance() {
const rpcUrl = 'https://base.llamarpc.com';
const token = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
const account = "";
const permit2Address = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
const provider = new ethers.JsonRpcProvider(rpcUrl);
const contract = new ethers.Contract(token, ERC20_ABI, provider);
const allowance = await contract.allowance(account, permit2Address);
console.log(`allowance: ${allowance.toString()}`)
}2. Approve Permit2 if needed (Optional)
If the allowance is insufficient, call the token’s approve() method once to authorize Permit2 with the required amount.
import { ethers, Contract } from 'ethers';
async function approve() {
const rpcUrl = 'https://base.llamarpc.com';
const inTokenAddress = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913';
const privateKey = '';
const permit2Address = '0x000000000022D473030F116dDEE9F6B43aC78BA3';
let provider = new ethers.JsonRpcProvider(rpcUrl);
const wallet = new ethers.Wallet(privateKey, provider);
const contract = await new Contract(inTokenAddress, ERC20_ABI, wallet);
try {
await contract.approve(permit2Address, new BigNumber('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff').toFixed(0, 1));
} catch (error) {
return error;
}
return true;
}3. Generate the Permit2 signature and data
Create the authorization signature and encoded data using the Permit2 standard for later use in the transaction.
import { PERMIT2_ADDRESS, PermitTransferFrom, SignatureTransfer } from '@uniswap/permit2-sdk';
import { ethers } from 'ethers';
async function signAndBuildData() {
const privateKey = "";
const token = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"; // in token address
const amount = "1000000000"; // in amount
const spender = "0x6352a56caadC4F1E25CD6c75970Fa768A3304e64"; // openocean contract
const nonce = 0;
const chainId = 8453;
const deadline = 1761877730;
const wallet = new ethers.Wallet(privateKey);
const permit: PermitTransferFrom = { permitted: { token, amount }, spender, nonce, deadline };
const { domain, types, values } = SignatureTransfer.getPermitData(permit, PERMIT2_ADDRESS, chainId, undefined);
const signature = await wallet._signTypedData(domain, types, values);
console.log(`signature: ${signature}`)
const iface = new ethers.utils.Interface(PERMIT2_ABI);
const permitTransferFromData = [[[token, amount], nonce, deadline], [spender, amount], wallet.address, signature];
const data = iface.encodeFunctionData('permitTransferFrom', permitTransferFromData);
console.log(`data: ${data}`)
}4. Build the transaction body
Use the OpenOcean Swap API response to construct the final on-chain transaction calldata.
async function swap() {
const params = {
inTokenAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
outTokenAddress: '0x4200000000000000000000000000000000000006',
slippage: 1, // 1 means 1%
amount: 1000, // without decimals
gasPrice: 1, // without decimals, get from gasPrice api
account: '0xB3cbe...', // wallet address
permit: '0x30f28b7a000...' // build from step 3 data
}
const { data } = await axios({
url: `https://open-api.openocean.finance/v4/8453/swap`,
method: 'GET',
params
})
return data;
}**5. Send the transaction with the Permit2 signature **
Submit the transaction on-chain, including the Permit2 signature to complete the token swap process.
async function send_transaction() {
const rpcUrl = 'https://base.llamarpc.com';
const privateKey = ''; // wallet privateKey
const provider = new ethers.JsonRpcProvider(rpcUrl);
// get from swap
const params: any = {
from: '', // wallet address, get from swap
to: '', // contract address, get from swap
gasPrice: '', // wei, get from swap
data: '', // input data, get from swap
value: '', // native token amount, get from swap
gasLimit: '' // get from swap
}
const gasLimit = await provider.estimateGas(params);
params.gasLimit = gasLimit;
const wallet = new ethers.Wallet(privateKey, provider);
const { hash } = await wallet.sendTransaction(params);
return hash;
}Supported Chains
Ethereum
1
0x000000000022D473030F116dDEE9F6B43aC78BA3
BNB Chain
56
0x000000000022D473030F116dDEE9F6B43aC78BA3
Polygon
137
0x000000000022D473030F116dDEE9F6B43aC78BA3
Arbitrum
42161
0x000000000022D473030F116dDEE9F6B43aC78BA3
Base
8453
0x000000000022D473030F116dDEE9F6B43aC78BA3
Linea
59144
0x000000000022D473030F116dDEE9F6B43aC78BA3
Optimism
10
0x000000000022D473030F116dDEE9F6B43aC78BA3
Avalanche
43114
0x000000000022D473030F116dDEE9F6B43aC78BA3
Sei
1329
0x000000000022D473030F116dDEE9F6B43aC78BA3
zkSync
324
0x0000000000225e31D15943971F47aD3022F714Fa
Scroll
534352
0x000000000022D473030F116dDEE9F6B43aC78BA3
Celo
42220
0x000000000022D473030F116dDEE9F6B43aC78BA3
Gnosis
100
0x000000000022D473030F116dDEE9F6B43aC78BA3
Sonic
146
0x000000000022D473030F116dDEE9F6B43aC78BA3
Berachain
80094
0x000000000022D473030F116dDEE9F6B43aC78BA3
Unichain
130
0x000000000022D473030F116dDEE9F6B43aC78BA3
Swell
130
0x000000000022D473030F116dDEE9F6B43aC78BA3
HyperEVM
999
0x000000000022D473030F116dDEE9F6B43aC78BA3
Plume
98866
0x000000000022D473030F116dDEE9F6B43aC78BA3
Tac
239
0x000000000022D473030F116dDEE9F6B43aC78BA3
Plasma
9745
0x000000000022D473030F116dDEE9F6B43aC78BA3
Last updated