Для работы с Universal Router в среде JavaScript (ES6) требуется установка официальных пакетов экосистемы Uniswap. Базовый набор включает:
@uniswap/universal-routerethers или viem (в зависимости от
выбранного стека)Установка через пакетный менеджер:
npm install @uniswap/universal-router ethers
или
yarn add @uniswap/universal-router ethers
Современные JavaScript-проекты используют модульную систему ES6
(import/export). Для корректной работы необходимо:
"type": "module" в
package.json.mjsПример package.json:
{
"type": "module"
}
Universal Router не предоставляет «высокоуровневого клиента», а работает через ABI и вызовы смарт-контракта. Основные элементы импортируются следующим образом:
import { ethers } from 'ethers'
import { UNIVERSAL_ROUTER_ADDRESS } from '@uniswap/universal-router'
import UniversalRouterABI from '@uniswap/universal-router/artifacts/contracts/UniversalRouter.sol/UniversalRouter.json' assert { type: 'json' }
Ключевые моменты:
ethers используется для взаимодействия с
блокчейномUNIVERSAL_ROUTER_ADDRESS — адрес контракта (может
отличаться в зависимости от сети)Провайдер — это точка входа для взаимодействия с сетью Ethereum.
const provider = new ethers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_API_KEY')
Возможные альтернативы:
Для подписания транзакций используется Signer:
const wallet = new ethers.Wallet(PRIVATE_KEY, provider)
Важно:
.env)После инициализации провайдера и кошелька создаётся контракт:
const router = new ethers.Contract(
UNIVERSAL_ROUTER_ADDRESS,
UniversalRouterABI.abi,
wallet
)
Объект router становится основным интерфейсом для
взаимодействия с Universal Router.
Universal Router развёрнут в нескольких сетях. Наиболее используемые:
| Сеть | Адрес |
|---|---|
| Ethereum Mainnet | фиксированный |
| Arbitrum | отдельный адрес |
| Optimism | отдельный адрес |
Пример переключения сети:
const provider = new ethers.JsonRpcProvider('https://arb1.arbitrum.io/rpc')
Адрес роутера должен соответствовать выбранной сети.
Для ES6-проектов рекомендуется использовать dotenv:
npm install dotenv
Подключение:
import dotenv from 'dotenv'
dotenv.config()
const PRIVATE_KEY = process.env.PRIVATE_KEY
const RPC_URL = process.env.RPC_URL
Файл .env:
PRIVATE_KEY=your_private_key
RPC_URL=https://mainnet.infura.io/v3/your_key
Базовая проверка корректности инициализации:
async function checkConnection() {
const balance = await provider.getBalance(wallet.address)
console.log(`Balance: ${ethers.formatEther(balance)} ETH`)
}
checkConnection()
Если баланс успешно получен:
Universal Router использует концепцию команд (commands) и входных данных (inputs).
Перед использованием требуется:
Импорт вспомогательных инструментов:
import { AbiCoder } from 'ethers'
Создание кодировщика:
const abiCoder = new AbiCoder()
Все операции выполняются через функцию execute:
await router.execute(commands, inputs, deadline)
Где:
commands — байтовая последовательность инструкцийinputs — массив закодированных параметровdeadline — timestamp, ограничивающий выполнениеТипичные проблемы:
1. Неверный RPC URL
Error: could not detect network
2. Неверный приватный ключ
Error: invalid private key
3. Несоответствие сети и адреса контракта
execution reverted
Рекомендуется добавлять обработку:
try {
// операции
} catch (error) {
console.error('Connection error:', error)
}
Все взаимодействия с блокчейном — асинхронные. Используется
async/await:
async function init() {
const network = await provider.getNetwork()
console.log(network)
}
init()
Типичная структура проекта:
/src
/config
provider.js
/contracts
router.js
/utils
encoding.js
index.js
Пример provider.js:
import { ethers } from 'ethers'
import dotenv from 'dotenv'
dotenv.config()
export const provider = new ethers.JsonRpcProvider(process.env.RPC_URL)
Пример router.js:
import { ethers } from 'ethers'
import { provider } from '../config/provider.js'
import UniversalRouterABI from '@uniswap/universal-router/artifacts/contracts/UniversalRouter.sol/UniversalRouter.json' assert { type: 'json' }
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
export const router = new ethers.Contract(
'UNIVERSAL_ROUTER_ADDRESS',
UniversalRouterABI.abi,
wallet
)
Для уменьшения количества подключений:
ContractПример:
let routerInstance = null
export function getRouter() {
if (!routerInstance) {
routerInstance = new ethers.Contract(
UNIVERSAL_ROUTER_ADDRESS,
UniversalRouterABI.abi,
wallet
)
}
return routerInstance
}
При использовании в браузере:
ethers.BrowserProviderconst provider = new ethers.BrowserProvider(window.ethereum)
const signer = await provider.getSigner()
Проверка существования контракта:
const code = await provider.getCode(UNIVERSAL_ROUTER_ADDRESS)
if (code === '0x') {
throw new Error('Contract not deployed')
}
ES6-версия ethers использует BigInt:
const amount = 1000000000000000000n
или:
const amount = ethers.parseEther('1')
Для отслеживания выполнения:
console.log({
address: wallet.address,
network: await provider.getNetwork(),
})
Дополнительно:
debug логированиеПосле выполнения всех шагов:
Среда готова для выполнения сложных сценариев: