Copy https://agg-api.nep.finance/v1/swell/quote
Copy https://agg-api.nep.finance/v1/swell/swap
Generates the transaction data needed to execute the swap through the router contract
Copy import {ethers} from 'ethers'; // ^6.13.4
import type {TransactionRequest} from 'ethers';
const routerApiUrl = 'router-API';
const rpcUrl = 'network-RPC'; // Replace with your Network RPC
const privateKey = 'your-private-key-here'; // Replace with your private key
const wallet = new ethers.Wallet(privateKey);
// Connect to a provider (e.g., Infura or any Ethereum node)
const provider = new ethers.JsonRpcProvider(rpcUrl);
// Utility
async function signAndSendTransaction(tx: TransactionRequest) {
try {
const signer = wallet.connect(provider);
if (!tx.gasLimit) {
// Estimate the transaction gas
const estimatedGas = await signer.estimateGas(tx);
tx.gasLimit = estimatedGas * BigInt(120) / BigInt(100);
}
// Sign the transaction
const signedTx = await wallet.signTransaction(tx);
console.log('Signed Transaction:', signedTx);
// Send the signed transaction to the network
const txResponse = await signer.sendTransaction(tx);
console.log('Transaction Hash:', txResponse.hash);
// Wait for the transaction to be mined (optional)
const receipt = await txResponse.wait();
console.log('Transaction Mined:', receipt);
return receipt;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
type Address = `0x${string}`
export const EtherAddress = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
const erc20Abi = [
{
"constant": true,
"inputs": [{"name": "_owner", "type": "address"}, {"name": "_spender", "type": "address"}],
"name": "allowance",
"outputs": [{"name": "remaining", "type": "uint256"}],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{"name": "_spender", "type": "address"}, {"name": "_value", "type": "uint256"}],
"name": "approve",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
]
async function approve(token: Address, spender: Address, amount: string | bigint) {
const contract = new ethers.Contract(token, erc20Abi, provider);
const allowance = await contract.allowance(wallet.address, spender);
if (allowance < BigInt(amount)) {
const data = contract.interface.encodeFunctionData('approve', [spender, amount]);
return signAndSendTransaction({to: token, data})
}
return Promise.resolve(true);
}
function serializeParameters(params: Record<string, any>) {
const searchParams = new URLSearchParams(
Object.fromEntries(Object.entries(params).filter(([_, v]) => !!v))
);
return searchParams.toString();
}
interface Swap {
amountIn: string;
amountOut: string;
data: string;
exchange: string;
pool: Address;
tokenIn: Address;
tokenOut: Address;
type: string;
}
interface Split {
amountIn: string;
amountOut: string;
swaps: Swap[];
}
interface QuoteResponse {
amountIn: string;
amountInUsd: number;
amountOut: string;
amountOutUsd: number;
minAmountOut: string;
splits: Split[];
tokenIn: Address;
tokenOut: Address;
}
interface Transaction {
data: string;
router: Address;
}
interface SwapResponse {
quote: QuoteResponse;
tx: Transaction;
}
interface QuoteParameters {
tokenIn: Address;
tokenOut: Address;
amountIn: string | bigint;
exchanges?: string[];
}
// Retrieves the optimal trading route and price quote between two tokens
export async function quote(args: QuoteParameters): Promise<QuoteResponse> {
const params = {
...args,
amountIn: args.amountIn.toString(),
exchanges: args.exchanges?.join(','),
};
const quoteResponse = await fetch(`${routerApiUrl}/quote?${serializeParameters(params)}`);
return quoteResponse.json();
}
interface SwapParameters extends QuoteParameters {
slippage?: number;
receiver?: Address;
}
// Generates the transaction data needed to execute the swap through the router contract
export async function swap(args: SwapParameters) {
const params = {
...args,
amountIn: args.amountIn.toString(),
exchanges: args.exchanges?.join(','),
slippage: args?.slippage?.toString(),
receiver: args.receiver || wallet.address,
};
// get encoded transaction data
const encodingResponse = await fetch(`${routerApiUrl}/swap?${serializeParameters(params)}`);
const encodingResult: SwapResponse = await encodingResponse.json();
const tokenInIsNative = args.tokenIn.toLowerCase() === EtherAddress.toLowerCase();
if (!tokenInIsNative) {
// approve ERC20
await approve(args.tokenIn, encodingResult.tx.router, args.amountIn);
}
return await signAndSendTransaction({
to: encodingResult.tx.router,
value: tokenInIsNative ? args.amountIn : undefined,
data: encodingResult.tx.data,
});
}