mirror of
https://github.com/0xbow-io/privacy-pools-core.git
synced 2026-01-09 01:17:58 -05:00
Multi-hop swaps, leaner fees, better quoting, validation bugfixes (#94)
Co-authored-by: casiojapi <casiopilled@gmail.com>
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
FROM node:23
|
||||
ARG GIT_SHA="0000000"
|
||||
ARG BUILD_DATE=
|
||||
|
||||
WORKDIR /build
|
||||
RUN yarn global add typescript
|
||||
@@ -9,6 +11,8 @@ RUN yarn install
|
||||
|
||||
COPY src/ ./src/
|
||||
RUN yarn build
|
||||
ENV GIT_SHA=$GIT_SHA
|
||||
ENV BUILD_DATE=$BUILD_DATE
|
||||
|
||||
EXPOSE 3000
|
||||
CMD ["node", "dist/src/index.js"]
|
||||
CMD ["node", "dist/index.js"]
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"license": "Apache-2.0",
|
||||
"author": "Wonderland",
|
||||
"type": "module",
|
||||
"main": "./dist/src/index.js",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"directories": {
|
||||
"src": "src"
|
||||
},
|
||||
@@ -18,7 +18,8 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.build.json",
|
||||
"start": "node ./dist/src/index.js",
|
||||
"build:clean": "rm -r ./tsconfig.build.tsbuildinfo ./dist && tsc -p tsconfig.build.json",
|
||||
"start": "node ./dist/index.js",
|
||||
"build:start": "yarn build && yarn start",
|
||||
"start:ts": "node --no-warnings=ExperimentalWarning --loader ts-node/esm src/index.ts",
|
||||
"check-types": "tsc --noEmit -p ./tsconfig.json",
|
||||
@@ -34,7 +35,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xbow/privacy-pools-core-sdk": "0.1.17",
|
||||
"@uniswap/v3-sdk": "^3.25.2",
|
||||
"@ethersproject/bignumber": "5.8.0",
|
||||
"@ethersproject/bytes": "5.8.0",
|
||||
"@uniswap/sdk-core": "7.7.2",
|
||||
"@uniswap/universal-router-sdk": "4.19.5",
|
||||
"@uniswap/v3-sdk": "3.25.2",
|
||||
"ajv": "8.17.1",
|
||||
"body-parser": "1.20.3",
|
||||
"cors": "^2.8.5",
|
||||
@@ -45,7 +50,10 @@
|
||||
"zod": "3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/body-parser": "^1.19.6",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "5.0.0"
|
||||
"@types/express": "5.0.0",
|
||||
"@vitest/coverage-v8": "^3.2.4",
|
||||
"vitest": "^3.2.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
notFoundMiddleware,
|
||||
} from "./middlewares/index.js";
|
||||
import { relayerRouter } from "./routes/index.js";
|
||||
import { CONFIG } from "./config/index.js";
|
||||
import { CORS_ALLOW_ALL, ALLOWED_DOMAINS } from "./config/index.js";
|
||||
|
||||
// Initialize the express app
|
||||
const app = express();
|
||||
@@ -15,16 +15,25 @@ const app = express();
|
||||
// Middleware functions
|
||||
const parseJsonMiddleware = bodyParser.json();
|
||||
|
||||
// CORS config
|
||||
// CORS config - allow all origins by default for development and testnet
|
||||
const isTestnetRelayer = process.env.NODE_ENV === 'production' &&
|
||||
(process.env.RELAYER_HOST === 'testnet-relayer.privacypools.com' ||
|
||||
process.env.HOST === 'testnet-relayer.privacypools.com');
|
||||
|
||||
const shouldAllowAll = CORS_ALLOW_ALL || isTestnetRelayer;
|
||||
|
||||
const corsOptions = {
|
||||
origin: CONFIG.cors_allow_all ? '*' : function (origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) {
|
||||
if (!origin || CONFIG.allowed_domains.indexOf(origin) !== -1) {
|
||||
origin: shouldAllowAll ? '*' : function (origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) {
|
||||
// Allow requests without origin (like mobile apps) or from allowed domains
|
||||
if (!origin || ALLOWED_DOMAINS.indexOf(origin) !== -1) {
|
||||
callback(null, true);
|
||||
} else {
|
||||
console.log(`Request blocked by CORS middleware: ${origin}. Allowed domains: ${CONFIG.allowed_domains}`);
|
||||
console.log(`Request blocked by CORS middleware: ${origin}. Allowed domains: ${ALLOWED_DOMAINS}`);
|
||||
callback(new Error("Not allowed by CORS"));
|
||||
}
|
||||
},
|
||||
credentials: true,
|
||||
optionsSuccessStatus: 200
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { ConfigError } from "../exceptions/base.exception.js";
|
||||
import { ConfigError, RelayerError } from "../exceptions/base.exception.js";
|
||||
import { zConfig } from "./schemas.js";
|
||||
import { ChainConfig, AssetConfig } from "./types.js";
|
||||
import { AssetConfig, ChainConfig } from "./types.js";
|
||||
|
||||
/**
|
||||
* Reads the configuration file from the path specified in the CONFIG_PATH environment variable
|
||||
@@ -110,18 +110,26 @@ export function getEntrypointAddress(chainId: number): string {
|
||||
*
|
||||
* @param {number} chainId - The chain ID
|
||||
* @param {string} assetAddress - The asset address
|
||||
* @returns {AssetConfig | undefined} The asset configuration, or undefined if not found
|
||||
* @returns {AssetConfig} The asset configuration, or undefined if not found
|
||||
*/
|
||||
export function getAssetConfig(chainId: number, assetAddress: string): AssetConfig | undefined {
|
||||
export function getAssetConfig(chainId: number, assetAddress: string): AssetConfig {
|
||||
const chainConfig = getChainConfig(chainId);
|
||||
|
||||
if (!chainConfig.supported_assets) {
|
||||
return undefined;
|
||||
throw RelayerError.assetNotSupported();
|
||||
}
|
||||
|
||||
return chainConfig.supported_assets.find(
|
||||
const assetConfig = chainConfig.supported_assets.find(
|
||||
asset => asset.asset_address.toLowerCase() === assetAddress.toLowerCase()
|
||||
);
|
||||
|
||||
if (!assetConfig) {
|
||||
throw RelayerError.assetNotSupported();
|
||||
}
|
||||
|
||||
return assetConfig
|
||||
|
||||
}
|
||||
|
||||
// Re-export types
|
||||
export * from "./types.js";
|
||||
export * from "./types.js";
|
||||
|
||||
@@ -64,8 +64,8 @@ export const zChainConfig = z.object({
|
||||
// Common configuration schema
|
||||
export const zCommonConfig = z.object({
|
||||
sqlite_db_path: z.string().transform((p) => path.resolve(p)),
|
||||
cors_allow_all: z.boolean().default(false),
|
||||
allowed_domains: z.array(z.string().url()),
|
||||
cors_allow_all: z.boolean().default(true),
|
||||
allowed_domains: z.array(z.string().url()).default(["https://testnet.privacypools.com, https://prod-privacy-pool-ui.vercel.app, https://staging-privacy-pool-ui.vercel.app, https://dev-privacy-pool-ui.vercel.app, http://localhost:3000"]),
|
||||
});
|
||||
|
||||
// Default configuration schema
|
||||
|
||||
@@ -82,6 +82,12 @@ export class RelayerError extends Error {
|
||||
public static unknown(message?: string): RelayerError {
|
||||
return new RelayerError(message || "", ErrorCode.UNKNOWN);
|
||||
}
|
||||
|
||||
public static assetNotSupported(
|
||||
details?: Record<string, unknown> | string) {
|
||||
return new RelayerError("Asset is not supported", ErrorCode.ASSET_NOT_SUPPORTED, details);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class ValidationError extends RelayerError {
|
||||
@@ -246,7 +252,7 @@ export class WithdrawalValidationError extends RelayerError {
|
||||
);
|
||||
}
|
||||
|
||||
public static assetNotSupported(details: string) {
|
||||
public static override assetNotSupported(details: string) {
|
||||
return new WithdrawalValidationError(
|
||||
"Asset not supported on this chain",
|
||||
ErrorCode.ASSET_NOT_SUPPORTED,
|
||||
@@ -285,7 +291,7 @@ export class QuoterError extends RelayerError {
|
||||
this.name = this.constructor.name;
|
||||
}
|
||||
|
||||
public static assetNotSupported(
|
||||
public static override assetNotSupported(
|
||||
details?: Record<string, unknown> | string) {
|
||||
return new QuoterError("Asset is not supported", ErrorCode.ASSET_NOT_SUPPORTED, details);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { getAddress } from "viem";
|
||||
import { getAssetConfig, getFeeReceiverAddress } from "../../config/index.js";
|
||||
import { getAssetConfig, getFeeReceiverAddress, getSignerPrivateKey } from "../../config/index.js";
|
||||
import { QuoterError } from "../../exceptions/base.exception.js";
|
||||
import { web3Provider } from "../../providers/index.js";
|
||||
import { quoteService } from "../../services/index.js";
|
||||
import { QuoteMarshall } from "../../types.js";
|
||||
import { encodeWithdrawalData } from "../../utils.js";
|
||||
import { encodeWithdrawalData, isFeeReceiverSameAsSigner, isNative } from "../../utils.js";
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
import { QuoteFee } from "../../services/quote.service.js";
|
||||
|
||||
const TIME_20_SECS = 20 * 1000;
|
||||
// const TIME_20_SECS = 20 * 1000;
|
||||
const TIME_60_SECS = 60 * 1000;
|
||||
|
||||
const EXPIRATION_TIME = TIME_60_SECS;
|
||||
|
||||
export async function relayQuoteHandler(
|
||||
req: Request,
|
||||
@@ -17,34 +22,63 @@ export async function relayQuoteHandler(
|
||||
|
||||
const chainId = Number(req.body.chainId!);
|
||||
const amountIn = BigInt(req.body.amount!.toString());
|
||||
const assetAddress = getAddress(req.body.asset!.toString())
|
||||
const asset = getAddress(req.body.asset!.toString());
|
||||
let extraGas = Boolean(req.body.extraGas);
|
||||
|
||||
const config = getAssetConfig(chainId, assetAddress);
|
||||
const config = getAssetConfig(chainId, asset);
|
||||
if (config === undefined)
|
||||
return next(QuoterError.assetNotSupported(`Asset ${assetAddress} for chain ${chainId} is not supported`));
|
||||
return next(QuoterError.assetNotSupported(`Asset ${asset} for chain ${chainId} is not supported`));
|
||||
|
||||
const feeBPS = await quoteService.quoteFeeBPSNative({
|
||||
chainId, amountIn, assetAddress, baseFeeBPS: config.fee_bps, value: 0n
|
||||
});
|
||||
if (isNative(asset)) {
|
||||
extraGas = false;
|
||||
}
|
||||
|
||||
const recipient = req.body.recipient ? getAddress(req.body.recipient.toString()) : undefined
|
||||
let quote: QuoteFee;
|
||||
try {
|
||||
quote = await quoteService.quoteFeeBPSNative({
|
||||
chainId, amountIn, assetAddress: asset, baseFeeBPS: config.fee_bps, extraGas: extraGas
|
||||
});
|
||||
} catch (e) {
|
||||
return next(e);
|
||||
}
|
||||
|
||||
const { feeBPS, gasPrice, extraGasFundAmount, relayTxCost, extraGasTxCost } = quote;
|
||||
const recipient = req.body.recipient ? getAddress(req.body.recipient.toString()) : undefined;
|
||||
const detail = {
|
||||
relayTxCost: { gas: relayTxCost, eth: relayTxCost * gasPrice },
|
||||
extraGasFundAmount: extraGasFundAmount ? { gas: extraGasFundAmount, eth: extraGasFundAmount * gasPrice } : undefined,
|
||||
extraGasTxCost: extraGasTxCost ? { gas: extraGasTxCost, eth: extraGasTxCost * gasPrice } : undefined,
|
||||
};
|
||||
|
||||
const quoteResponse = new QuoteMarshall({
|
||||
baseFeeBPS: config.fee_bps,
|
||||
feeBPS,
|
||||
gasPrice,
|
||||
detail,
|
||||
});
|
||||
|
||||
if (recipient) {
|
||||
const feeReceiverAddress = getFeeReceiverAddress(chainId);
|
||||
let feeReceiverAddress: `0x${string}`;
|
||||
const finalFeeReceiverAddress = getAddress(getFeeReceiverAddress(chainId));
|
||||
if (extraGas) {
|
||||
const signer = privateKeyToAccount(getSignerPrivateKey(chainId) as `0x${string}`);
|
||||
if (isFeeReceiverSameAsSigner(chainId)) {
|
||||
feeReceiverAddress = finalFeeReceiverAddress;
|
||||
} else {
|
||||
feeReceiverAddress = signer.address;
|
||||
}
|
||||
} else {
|
||||
feeReceiverAddress = finalFeeReceiverAddress;
|
||||
}
|
||||
const withdrawalData = encodeWithdrawalData({
|
||||
feeRecipient: getAddress(feeReceiverAddress),
|
||||
recipient,
|
||||
relayFeeBPS: feeBPS
|
||||
})
|
||||
const expiration = Number(new Date()) + TIME_20_SECS
|
||||
const relayerCommitment = { withdrawalData, expiration };
|
||||
});
|
||||
const expiration = Number(new Date()) + EXPIRATION_TIME;
|
||||
const relayerCommitment = { withdrawalData, expiration, asset, amount: amountIn, extraGas };
|
||||
const signedRelayerCommitment = await web3Provider.signRelayerCommitment(chainId, relayerCommitment);
|
||||
quoteResponse.addFeeCommitment({ expiration, withdrawalData, signedRelayerCommitment })
|
||||
quoteResponse.addFeeCommitment({ expiration, asset, withdrawalData, signedRelayerCommitment, extraGas, amount: amountIn });
|
||||
}
|
||||
|
||||
res
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { getAddress } from "viem";
|
||||
import { CONFIG, getChainConfig } from "../../config/index.js";
|
||||
import { ConfigError, ValidationError } from "../../exceptions/base.exception.js";
|
||||
import {
|
||||
RelayerResponse,
|
||||
RelayRequestBody,
|
||||
WithdrawalPayload,
|
||||
} from "../../interfaces/relayer/request.js";
|
||||
import { validateRelayRequestBody } from "../../schemes/relayer/request.scheme.js";
|
||||
import { web3Provider } from "../../providers/index.js";
|
||||
import { zRelayRequest } from "../../schemes/relayer/request.scheme.js";
|
||||
import { privacyPoolRelayer } from "../../services/index.js";
|
||||
import { RequestMashall } from "../../types.js";
|
||||
import { CONFIG, getChainConfig } from "../../config/index.js";
|
||||
import { web3Provider } from "../../providers/index.js";
|
||||
|
||||
/**
|
||||
* Converts a RelayRequestBody into a WithdrawalPayload.
|
||||
@@ -19,25 +17,19 @@ import { web3Provider } from "../../providers/index.js";
|
||||
* @returns {WithdrawalPayload} - The formatted withdrawal payload.
|
||||
*/
|
||||
function relayRequestBodyToWithdrawalPayload(
|
||||
body: RelayRequestBody,
|
||||
body: ReturnType<typeof zRelayRequest['parse']>,
|
||||
): WithdrawalPayload {
|
||||
const proof = { ...body.proof, protocol: "groth16", curve: "bn128" };
|
||||
const publicSignals = body.publicSignals;
|
||||
const scope = BigInt(body.scope);
|
||||
const withdrawal = {
|
||||
processooor: getAddress(body.withdrawal.processooor),
|
||||
data: body.withdrawal.data as `0x{string}`,
|
||||
};
|
||||
const wp = {
|
||||
return {
|
||||
...body,
|
||||
proof: {
|
||||
proof,
|
||||
publicSignals,
|
||||
proof: {
|
||||
...body.proof,
|
||||
protocol: "groth16",
|
||||
curve: "bn128"
|
||||
},
|
||||
publicSignals: body.publicSignals,
|
||||
},
|
||||
withdrawal,
|
||||
scope,
|
||||
feeCommitment: body.feeCommitment
|
||||
};
|
||||
return wp;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,36 +50,23 @@ function isChainSupported(chainId: number): boolean {
|
||||
* @throws {ValidationError} - If the input data is invalid.
|
||||
* @throws {ConfigError} - If the chain is not supported.
|
||||
*/
|
||||
function parseWithdrawal(body: Request["body"]): { payload: WithdrawalPayload, chainId: number } {
|
||||
if (validateRelayRequestBody(body)) {
|
||||
try {
|
||||
const payload = relayRequestBodyToWithdrawalPayload(body);
|
||||
const chainId = typeof body.chainId === 'string' ? parseInt(body.chainId, 10) : body.chainId;
|
||||
function parseWithdrawal(body: Request["body"]): { payload: WithdrawalPayload, chainId: number; } {
|
||||
|
||||
if (isNaN(chainId)) {
|
||||
throw ValidationError.invalidInput({ message: "Invalid chain ID format" });
|
||||
}
|
||||
const { data, error, success } = zRelayRequest.safeParse(body);
|
||||
|
||||
// Check if the chain is supported early
|
||||
if (!isChainSupported(chainId)) {
|
||||
throw ValidationError.invalidInput({ message: `Chain with ID ${chainId} not supported.` });
|
||||
}
|
||||
|
||||
return { payload, chainId };
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
// Re-throw ConfigError as is
|
||||
if (error instanceof ConfigError) {
|
||||
throw error;
|
||||
}
|
||||
// TODO: extend this catch to return more details about the issue (viem error, node error, etc)
|
||||
throw ValidationError.invalidInput({
|
||||
message: "Can't parse payload into SDK structure",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
throw ValidationError.invalidInput({ message: "Payload format error" });
|
||||
if (!success) {
|
||||
throw ValidationError.invalidInput({ error, message: "Error parsing payload" });
|
||||
}
|
||||
|
||||
const payload = relayRequestBodyToWithdrawalPayload(data);
|
||||
|
||||
// Check if the chain is supported early
|
||||
if (!isChainSupported(data.chainId)) {
|
||||
throw ValidationError.invalidInput({ message: `Chain with ID ${data.chainId} not supported.` });
|
||||
}
|
||||
|
||||
return { payload, chainId: data.chainId };
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,10 +83,12 @@ export async function relayRequestHandler(
|
||||
) {
|
||||
try {
|
||||
const { payload: withdrawalPayload, chainId } = parseWithdrawal(req.body);
|
||||
|
||||
const maxGasPrice = getChainConfig(chainId)?.max_gas_price;
|
||||
const currentGasPrice = await web3Provider.getGasPrice(chainId);
|
||||
|
||||
if (maxGasPrice !== undefined && currentGasPrice > maxGasPrice) {
|
||||
throw ConfigError.maxGasPrice(`Current gas price ${currentGasPrice} is higher than max price ${maxGasPrice}`)
|
||||
throw ConfigError.maxGasPrice(`Current gas price ${currentGasPrice} is higher than max price ${maxGasPrice}`);
|
||||
}
|
||||
|
||||
const requestResponse: RelayerResponse =
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
* Represents the relayer commitment for a pre-built withdrawal.
|
||||
*/
|
||||
export interface FeeCommitment {
|
||||
expiration: number,
|
||||
withdrawalData: `0x${string}`,
|
||||
asset: `0x${string}`,
|
||||
expiration: number,
|
||||
amount: bigint,
|
||||
extraGas: boolean,
|
||||
signedRelayerCommitment: `0x${string}`,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { FeeCommitment } from "./common.js";
|
||||
|
||||
export interface QuotetBody {
|
||||
/** Chain ID to process the request on */
|
||||
chainId: string | number;
|
||||
@@ -9,10 +7,20 @@ export interface QuotetBody {
|
||||
asset: string;
|
||||
/** Asset address */
|
||||
recipient?: string;
|
||||
/** Extra gas flag */
|
||||
extraGas: boolean;
|
||||
}
|
||||
|
||||
export interface QuoteResponse {
|
||||
baseFeeBPS: bigint,
|
||||
feeBPS: bigint,
|
||||
feeCommitment?: FeeCommitment
|
||||
gasPrice: bigint,
|
||||
detail: { [key: string]: { gas: bigint, eth: bigint; } | undefined; };
|
||||
feeCommitment?: {
|
||||
expiration: number,
|
||||
withdrawalData: `0x${string}`,
|
||||
amount: string,
|
||||
extraGas: boolean,
|
||||
signedRelayerCommitment: `0x${string}`,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -75,6 +75,8 @@ export interface RelayerResponse {
|
||||
requestId: string;
|
||||
/** Optional transaction hash */
|
||||
txHash?: string;
|
||||
/** Optional transaction swap hash */
|
||||
txSwap?: string;
|
||||
/** Optional error message */
|
||||
error?: string;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { ValidationError } from "../../exceptions/base.exception.js";
|
||||
import { validateDetailsQuerystring } from "../../schemes/relayer/details.scheme.js";
|
||||
import { validateRelayRequestBody } from "../../schemes/relayer/request.scheme.js";
|
||||
import { zRelayRequest } from "../../schemes/relayer/request.scheme.js";
|
||||
import { validateQuoteBody } from "../../schemes/relayer/quote.scheme.js";
|
||||
|
||||
// Middleware to validate the details querying
|
||||
@@ -26,11 +26,9 @@ export function validateRelayRequestMiddleware(
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
const isValid = validateRelayRequestBody(req.body);
|
||||
if (!isValid) {
|
||||
const messages: string[] = [];
|
||||
validateRelayRequestBody.errors?.forEach(e => e?.message ? messages.push(e.message) : undefined);
|
||||
next(ValidationError.invalidInput({ message: messages.join("\n") }));
|
||||
const { success, error } = zRelayRequest.safeParse(req.body);
|
||||
if (!success) {
|
||||
next(ValidationError.invalidInput({ message: error.errors.map(i => `${i.path.join('.')}: ${i.message}`).join("\n") }));
|
||||
return;
|
||||
}
|
||||
next();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Web3Provider } from "./web3.provider.js";
|
||||
import { UniswapProvider } from "./uniswap.provider.js"
|
||||
import { UniswapProvider } from "./uniswap/uniswap.provider.js"
|
||||
import { QuoteProvider } from "./quote.provider.js";
|
||||
|
||||
export { db } from "./db.provider.js";
|
||||
export { SdkProvider } from "./sdk.provider.js";
|
||||
export { SqliteDatabase } from "./sqlite.provider.js";
|
||||
export { UniswapProvider } from "./uniswap.provider.js"
|
||||
export { UniswapProvider } from "./uniswap/uniswap.provider.js"
|
||||
|
||||
export const web3Provider = new Web3Provider();
|
||||
export const uniswapProvider = new UniswapProvider();
|
||||
|
||||
@@ -6,9 +6,9 @@ export class QuoteProvider {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
async quoteNativeTokenInERC20(chainId: number, addressIn: Address, amountIn: bigint): Promise<{ num: bigint, den: bigint }> {
|
||||
const { in: in_, out } = (await uniswapProvider.quoteNativeToken(chainId, addressIn, amountIn))!;
|
||||
return { num: out.amount, den: in_.amount };
|
||||
async quoteNativeTokenInERC20(chainId: number, addressIn: Address, amountIn: bigint): Promise<{ num: bigint, den: bigint, path: (string|number)[] }> {
|
||||
const { in: in_, out, path } = (await uniswapProvider.quoteNativeToken(chainId, addressIn, amountIn))!;
|
||||
return { num: out.amount, den: in_.amount, path };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
import { Token } from '@uniswap/sdk-core'
|
||||
import { FeeAmount } from '@uniswap/v3-sdk'
|
||||
import { Address, getContract } from 'viem'
|
||||
|
||||
import { web3Provider } from '../providers/index.js'
|
||||
import { BlockchainError, RelayerError } from '../exceptions/base.exception.js'
|
||||
import { isViemError } from '../utils.js'
|
||||
import { QUOTER_CONTRACT_ADDRESS, WRAPPED_NATIVE_TOKEN_ADDRESS } from './uniswap/constants.js'
|
||||
import { IERC20MinimalABI } from './uniswap/erc20.abi.js'
|
||||
import { QuoterV2ABI } from './uniswap/quoterV2.abi.js'
|
||||
|
||||
export type UniswapQuote = {
|
||||
chainId: number;
|
||||
addressIn: string;
|
||||
addressOut: string;
|
||||
amountIn: bigint;
|
||||
};
|
||||
|
||||
type QuoteToken = { amount: bigint, decimals: number }
|
||||
export type Quote = {
|
||||
in: QuoteToken
|
||||
out: QuoteToken
|
||||
};
|
||||
|
||||
export class UniswapProvider {
|
||||
|
||||
async getTokenInfo(chainId: number, address: Address): Promise<Token> {
|
||||
const contract = getContract({
|
||||
address,
|
||||
abi: IERC20MinimalABI.abi,
|
||||
client: web3Provider.client(chainId)
|
||||
});
|
||||
const [decimals, symbol] = await Promise.all([
|
||||
contract.read.decimals(),
|
||||
contract.read.symbol(),
|
||||
])
|
||||
return new Token(chainId, address, Number(decimals), symbol);
|
||||
}
|
||||
|
||||
async quoteNativeToken(chainId: number, addressIn: Address, amountIn: bigint): Promise<Quote> {
|
||||
const addressOut = WRAPPED_NATIVE_TOKEN_ADDRESS[chainId.toString()]!
|
||||
return this.quote({
|
||||
chainId,
|
||||
amountIn,
|
||||
addressOut,
|
||||
addressIn
|
||||
});
|
||||
}
|
||||
|
||||
async quote({ chainId, addressIn, addressOut, amountIn }: UniswapQuote) {
|
||||
const tokenIn = await this.getTokenInfo(chainId, addressIn as Address);
|
||||
const tokenOut = await this.getTokenInfo(chainId, addressOut as Address);
|
||||
const quoterContract = getContract({
|
||||
address: QUOTER_CONTRACT_ADDRESS[chainId.toString()]!,
|
||||
abi: QuoterV2ABI.abi,
|
||||
client: web3Provider.client(chainId)
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
const quotedAmountOut = await quoterContract.simulate.quoteExactInputSingle([{
|
||||
tokenIn: tokenIn.address as Address,
|
||||
tokenOut: tokenOut.address as Address,
|
||||
fee: FeeAmount.MEDIUM,
|
||||
amountIn,
|
||||
sqrtPriceLimitX96: 0n,
|
||||
}])
|
||||
|
||||
// amount, sqrtPriceX96After, tickAfter, gasEstimate
|
||||
const [amount, , , ] = quotedAmountOut.result;
|
||||
return {
|
||||
in: {
|
||||
amount: amountIn, decimals: tokenIn.decimals
|
||||
},
|
||||
out: {
|
||||
amount, decimals: tokenOut.decimals
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof Error && isViemError(error)) {
|
||||
const { metaMessages, shortMessage } = error;
|
||||
throw BlockchainError.txError((metaMessages ? metaMessages[0] : undefined) || shortMessage)
|
||||
} else {
|
||||
throw RelayerError.unknown("Something went wrong while quoting")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
200
packages/relayer/src/providers/uniswap/abis/erc20.abi.ts
Normal file
200
packages/relayer/src/providers/uniswap/abis/erc20.abi.ts
Normal file
@@ -0,0 +1,200 @@
|
||||
export const IERC20MinimalABI = [
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
] as const;
|
||||
15
packages/relayer/src/providers/uniswap/abis/factoryV3.abi.ts
Normal file
15
packages/relayer/src/providers/uniswap/abis/factoryV3.abi.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export const FactoryV3ABI = [
|
||||
{
|
||||
type: 'function',
|
||||
name: 'getPool',
|
||||
stateMutability: 'view',
|
||||
inputs: [
|
||||
{ name: 'tokenA', type: 'address' },
|
||||
{ name: 'tokenB', type: 'address' },
|
||||
{ name: 'fee', type: 'uint24' }
|
||||
],
|
||||
outputs: [
|
||||
{ name: 'pool', type: 'address' }
|
||||
]
|
||||
}
|
||||
] as const;
|
||||
901
packages/relayer/src/providers/uniswap/abis/permit2.abi.ts
Normal file
901
packages/relayer/src/providers/uniswap/abis/permit2.abi.ts
Normal file
@@ -0,0 +1,901 @@
|
||||
export const Permit2ABI = [
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "deadline",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "AllowanceExpired",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "ExcessiveInvalidation",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "InsufficientAllowance",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "maxAmount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "InvalidAmount",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InvalidContractSignature",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InvalidNonce",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InvalidSignature",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InvalidSignatureLength",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InvalidSigner",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "LengthMismatch",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "signatureDeadline",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "SignatureExpired",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint160",
|
||||
"name": "amount",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint48",
|
||||
"name": "expiration",
|
||||
"type": "uint48"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "Lockdown",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint48",
|
||||
"name": "newNonce",
|
||||
"type": "uint48"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint48",
|
||||
"name": "oldNonce",
|
||||
"type": "uint48"
|
||||
}
|
||||
],
|
||||
"name": "NonceInvalidation",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint160",
|
||||
"name": "amount",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint48",
|
||||
"name": "expiration",
|
||||
"type": "uint48"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint48",
|
||||
"name": "nonce",
|
||||
"type": "uint48"
|
||||
}
|
||||
],
|
||||
"name": "Permit",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "word",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "mask",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "UnorderedNonceInvalidation",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "DOMAIN_SEPARATOR",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "amount",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "uint48",
|
||||
"name": "expiration",
|
||||
"type": "uint48"
|
||||
},
|
||||
{
|
||||
"internalType": "uint48",
|
||||
"name": "nonce",
|
||||
"type": "uint48"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "amount",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "uint48",
|
||||
"name": "expiration",
|
||||
"type": "uint48"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint48",
|
||||
"name": "newNonce",
|
||||
"type": "uint48"
|
||||
}
|
||||
],
|
||||
"name": "invalidateNonces",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "wordPos",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "mask",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "invalidateUnorderedNonces",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IAllowanceTransfer.TokenSpenderPair[]",
|
||||
"name": "approvals",
|
||||
"type": "tuple[]"
|
||||
}
|
||||
],
|
||||
"name": "lockdown",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "nonceBitmap",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "amount",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "uint48",
|
||||
"name": "expiration",
|
||||
"type": "uint48"
|
||||
},
|
||||
{
|
||||
"internalType": "uint48",
|
||||
"name": "nonce",
|
||||
"type": "uint48"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IAllowanceTransfer.PermitDetails[]",
|
||||
"name": "details",
|
||||
"type": "tuple[]"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "sigDeadline",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IAllowanceTransfer.PermitBatch",
|
||||
"name": "permitBatch",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "permit",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "amount",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "uint48",
|
||||
"name": "expiration",
|
||||
"type": "uint48"
|
||||
},
|
||||
{
|
||||
"internalType": "uint48",
|
||||
"name": "nonce",
|
||||
"type": "uint48"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IAllowanceTransfer.PermitDetails",
|
||||
"name": "details",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "sigDeadline",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IAllowanceTransfer.PermitSingle",
|
||||
"name": "permitSingle",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "permit",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.TokenPermissions",
|
||||
"name": "permitted",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "nonce",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "deadline",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.PermitTransferFrom",
|
||||
"name": "permit",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "requestedAmount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.SignatureTransferDetails",
|
||||
"name": "transferDetails",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "permitTransferFrom",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.TokenPermissions[]",
|
||||
"name": "permitted",
|
||||
"type": "tuple[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "nonce",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "deadline",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.PermitBatchTransferFrom",
|
||||
"name": "permit",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "requestedAmount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.SignatureTransferDetails[]",
|
||||
"name": "transferDetails",
|
||||
"type": "tuple[]"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "permitTransferFrom",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.TokenPermissions",
|
||||
"name": "permitted",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "nonce",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "deadline",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.PermitTransferFrom",
|
||||
"name": "permit",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "requestedAmount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.SignatureTransferDetails",
|
||||
"name": "transferDetails",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "witness",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "string",
|
||||
"name": "witnessTypeString",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "permitWitnessTransferFrom",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.TokenPermissions[]",
|
||||
"name": "permitted",
|
||||
"type": "tuple[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "nonce",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "deadline",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.PermitBatchTransferFrom",
|
||||
"name": "permit",
|
||||
"type": "tuple"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "requestedAmount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct ISignatureTransfer.SignatureTransferDetails[]",
|
||||
"name": "transferDetails",
|
||||
"type": "tuple[]"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "witness",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "string",
|
||||
"name": "witnessTypeString",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "permitWitnessTransferFrom",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "amount",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IAllowanceTransfer.AllowanceTransferDetails[]",
|
||||
"name": "transferDetails",
|
||||
"type": "tuple[]"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "amount",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
] as const;
|
||||
267
packages/relayer/src/providers/uniswap/abis/quoterV2.abi.ts
Normal file
267
packages/relayer/src/providers/uniswap/abis/quoterV2.abi.ts
Normal file
@@ -0,0 +1,267 @@
|
||||
export const QuoterV2ABI = [
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_factory",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_WETH9",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "WETH9",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "factory",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "path",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountIn",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "quoteExactInput",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountOut",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160[]",
|
||||
"name": "sqrtPriceX96AfterList",
|
||||
"type": "uint160[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32[]",
|
||||
"name": "initializedTicksCrossedList",
|
||||
"type": "uint32[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "gasEstimate",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "tokenIn",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "tokenOut",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountIn",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint24",
|
||||
"name": "fee",
|
||||
"type": "uint24"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceLimitX96",
|
||||
"type": "uint160"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IQuoterV2.QuoteExactInputSingleParams",
|
||||
"name": "params",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"name": "quoteExactInputSingle",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountOut",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceX96After",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "initializedTicksCrossed",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "gasEstimate",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "path",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountOut",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "quoteExactOutput",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountIn",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160[]",
|
||||
"name": "sqrtPriceX96AfterList",
|
||||
"type": "uint160[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32[]",
|
||||
"name": "initializedTicksCrossedList",
|
||||
"type": "uint32[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "gasEstimate",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "tokenIn",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "tokenOut",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint24",
|
||||
"name": "fee",
|
||||
"type": "uint24"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceLimitX96",
|
||||
"type": "uint160"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IQuoterV2.QuoteExactOutputSingleParams",
|
||||
"name": "params",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"name": "quoteExactOutputSingle",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountIn",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceX96After",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "initializedTicksCrossed",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "gasEstimate",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "int256",
|
||||
"name": "amount0Delta",
|
||||
"type": "int256"
|
||||
},
|
||||
{
|
||||
"internalType": "int256",
|
||||
"name": "amount1Delta",
|
||||
"type": "int256"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "path",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "uniswapV3SwapCallback",
|
||||
"outputs": [],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
] as const;
|
||||
@@ -0,0 +1,443 @@
|
||||
export const UniversalRouterABI = [
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "permit2",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "weth9",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "v2Factory",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "v3Factory",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "pairInitCodeHash",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "poolInitCodeHash",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "v4PoolManager",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "v3NFTPositionManager",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "v4PositionManager",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"internalType": "struct RouterParameters",
|
||||
"name": "params",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "BalanceTooLow",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "ContractLocked",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "Currency",
|
||||
"name": "currency",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "DeltaNotNegative",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "Currency",
|
||||
"name": "currency",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "DeltaNotPositive",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "ETHNotAccepted",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "commandIndex",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "message",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "ExecutionFailed",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "FromAddressIsNotOwner",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InputLengthMismatch",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InsufficientBalance",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InsufficientETH",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InsufficientToken",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes4",
|
||||
"name": "action",
|
||||
"type": "bytes4"
|
||||
}
|
||||
],
|
||||
"name": "InvalidAction",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InvalidBips",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "commandType",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "InvalidCommandType",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InvalidEthSender",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InvalidPath",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InvalidReserves",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "LengthMismatch",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "tokenId",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "NotAuthorizedForToken",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "NotPoolManager",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "OnlyMintAllowed",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "SliceOutOfBounds",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "TransactionDeadlinePassed",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "UnsafeCast",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "action",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "UnsupportedAction",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "V2InvalidPath",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "V2TooLittleReceived",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "V2TooMuchRequested",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "V3InvalidAmountOut",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "V3InvalidCaller",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "V3InvalidSwap",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "V3TooLittleReceived",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "V3TooMuchRequested",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "minAmountOutReceived",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountReceived",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "V4TooLittleReceived",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "maxAmountInRequested",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountRequested",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "V4TooMuchRequested",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "V3_POSITION_MANAGER",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract INonfungiblePositionManager",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "V4_POSITION_MANAGER",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IPositionManager",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "commands",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes[]",
|
||||
"name": "inputs",
|
||||
"type": "bytes[]"
|
||||
}
|
||||
],
|
||||
"name": "execute",
|
||||
"outputs": [],
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "commands",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes[]",
|
||||
"name": "inputs",
|
||||
"type": "bytes[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "deadline",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "execute",
|
||||
"outputs": [],
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "msgSender",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "poolManager",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IPoolManager",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "int256",
|
||||
"name": "amount0Delta",
|
||||
"type": "int256"
|
||||
},
|
||||
{
|
||||
"internalType": "int256",
|
||||
"name": "amount1Delta",
|
||||
"type": "int256"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "data",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "uniswapV3SwapCallback",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "data",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "unlockCallback",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"stateMutability": "payable",
|
||||
"type": "receive"
|
||||
}
|
||||
] as const;
|
||||
983
packages/relayer/src/providers/uniswap/abis/v3pool.abi.ts
Normal file
983
packages/relayer/src/providers/uniswap/abis/v3pool.abi.ts
Normal file
@@ -0,0 +1,983 @@
|
||||
export const v3PoolABI = [
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickLower",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickUpper",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount1",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Burn",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickLower",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickUpper",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount0",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount1",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "Collect",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount0",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount1",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "CollectProtocol",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount1",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "paid0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "paid1",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Flash",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint16",
|
||||
"name": "observationCardinalityNextOld",
|
||||
"type": "uint16"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint16",
|
||||
"name": "observationCardinalityNextNew",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"name": "IncreaseObservationCardinalityNext",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceX96",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "int24",
|
||||
"name": "tick",
|
||||
"type": "int24"
|
||||
}
|
||||
],
|
||||
"name": "Initialize",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickLower",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickUpper",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount1",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Mint",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint8",
|
||||
"name": "feeProtocol0Old",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint8",
|
||||
"name": "feeProtocol1Old",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint8",
|
||||
"name": "feeProtocol0New",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint8",
|
||||
"name": "feeProtocol1New",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"name": "SetFeeProtocol",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "int256",
|
||||
"name": "amount0",
|
||||
"type": "int256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "int256",
|
||||
"name": "amount1",
|
||||
"type": "int256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceX96",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "liquidity",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "int24",
|
||||
"name": "tick",
|
||||
"type": "int24"
|
||||
}
|
||||
],
|
||||
"name": "Swap",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "tickLower",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "tickUpper",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "burn",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount1",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "tickLower",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "tickUpper",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount0Requested",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount1Requested",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "collect",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount0",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount1",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount0Requested",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount1Requested",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "collectProtocol",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount0",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount1",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "factory",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "fee",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint24",
|
||||
"name": "",
|
||||
"type": "uint24"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "feeGrowthGlobal0X128",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "feeGrowthGlobal1X128",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount1",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "data",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "flash",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "observationCardinalityNext",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"name": "increaseObservationCardinalityNext",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceX96",
|
||||
"type": "uint160"
|
||||
}
|
||||
],
|
||||
"name": "initialize",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "liquidity",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "maxLiquidityPerTick",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "tickLower",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "tickUpper",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "data",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "mint",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount1",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "index",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "observations",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "blockTimestamp",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"internalType": "int56",
|
||||
"name": "tickCumulative",
|
||||
"type": "int56"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "secondsPerLiquidityCumulativeX128",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "initialized",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint32[]",
|
||||
"name": "secondsAgos",
|
||||
"type": "uint32[]"
|
||||
}
|
||||
],
|
||||
"name": "observe",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "int56[]",
|
||||
"name": "tickCumulatives",
|
||||
"type": "int56[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160[]",
|
||||
"name": "secondsPerLiquidityCumulativeX128s",
|
||||
"type": "uint160[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "key",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "positions",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "_liquidity",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "feeGrowthInside0LastX128",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "feeGrowthInside1LastX128",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "tokensOwed0",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "tokensOwed1",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "protocolFees",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "token0",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "token1",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint8",
|
||||
"name": "feeProtocol0",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"internalType": "uint8",
|
||||
"name": "feeProtocol1",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"name": "setFeeProtocol",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "slot0",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceX96",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "tick",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "observationIndex",
|
||||
"type": "uint16"
|
||||
},
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "observationCardinality",
|
||||
"type": "uint16"
|
||||
},
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "observationCardinalityNext",
|
||||
"type": "uint16"
|
||||
},
|
||||
{
|
||||
"internalType": "uint8",
|
||||
"name": "feeProtocol",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "unlocked",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "tickLower",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "tickUpper",
|
||||
"type": "int24"
|
||||
}
|
||||
],
|
||||
"name": "snapshotCumulativesInside",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "int56",
|
||||
"name": "tickCumulativeInside",
|
||||
"type": "int56"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "secondsPerLiquidityInsideX128",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "secondsInside",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "zeroForOne",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"internalType": "int256",
|
||||
"name": "amountSpecified",
|
||||
"type": "int256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceLimitX96",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "data",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "swap",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "int256",
|
||||
"name": "amount0",
|
||||
"type": "int256"
|
||||
},
|
||||
{
|
||||
"internalType": "int256",
|
||||
"name": "amount1",
|
||||
"type": "int256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "int16",
|
||||
"name": "wordPosition",
|
||||
"type": "int16"
|
||||
}
|
||||
],
|
||||
"name": "tickBitmap",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "tickSpacing",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "",
|
||||
"type": "int24"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "int24",
|
||||
"name": "tick",
|
||||
"type": "int24"
|
||||
}
|
||||
],
|
||||
"name": "ticks",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "liquidityGross",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "int128",
|
||||
"name": "liquidityNet",
|
||||
"type": "int128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "feeGrowthOutside0X128",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "feeGrowthOutside1X128",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "int56",
|
||||
"name": "tickCumulativeOutside",
|
||||
"type": "int56"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "secondsPerLiquidityOutsideX128",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "secondsOutside",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "initialized",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "token0",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "token1",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
] as const;
|
||||
198
packages/relayer/src/providers/uniswap/commands.ts
Normal file
198
packages/relayer/src/providers/uniswap/commands.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
import { encodeAbiParameters, getAddress } from "viem";
|
||||
|
||||
const V3_SWAP_EXACT_IN = 0x00;
|
||||
const UNWRAP_WETH = 0x0c;
|
||||
const PERMIT2_TRANSFER_FROM = 0x02;
|
||||
const SWEEP = 0x04;
|
||||
const TRANSFER = 0x05;
|
||||
const PERMIT2_PERMIT = 0x0a;
|
||||
|
||||
export type CommandPair = [number, `0x${string}`];
|
||||
|
||||
export interface IPermitSingle {
|
||||
details: {
|
||||
token: `0x${string}`;
|
||||
amount: bigint;
|
||||
expiration: number;
|
||||
nonce: number;
|
||||
};
|
||||
spender: `0x${string}`;
|
||||
sigDeadline: bigint;
|
||||
}
|
||||
|
||||
export interface Permit2Params {
|
||||
permit: IPermitSingle;
|
||||
signature: string;
|
||||
}
|
||||
|
||||
export function permit2({ permit, signature }: Permit2Params): CommandPair {
|
||||
const encodedInput = encodeAbiParameters(
|
||||
[
|
||||
{
|
||||
name: 'PermitSingle', type: 'tuple',
|
||||
components: [
|
||||
{
|
||||
name: "details", type: "tuple", components: [
|
||||
{ name: "token", type: "address" },
|
||||
{ name: "amount", type: "uint160" },
|
||||
{ name: "expiration", type: "uint48" },
|
||||
{ name: "nonce", type: "uint48" },
|
||||
]
|
||||
},
|
||||
{ name: "spender", type: "address" },
|
||||
{ name: "sigDeadline", type: "uint256" }
|
||||
]
|
||||
},
|
||||
{ name: 'signature', type: 'bytes' },
|
||||
],
|
||||
[
|
||||
permit,
|
||||
signature as `0x${string}`
|
||||
]
|
||||
);
|
||||
return [PERMIT2_PERMIT, encodedInput];
|
||||
}
|
||||
|
||||
interface TransferParams {
|
||||
token: string;
|
||||
recipient: `0x${string}`;
|
||||
amount: bigint;
|
||||
}
|
||||
|
||||
export function transferWithPermit({ token, recipient, amount }: TransferParams): CommandPair {
|
||||
const encodedInput = encodeAbiParameters(
|
||||
[
|
||||
{ name: 'token', type: 'address' },
|
||||
{ name: 'recipient', type: 'address' },
|
||||
{ name: 'amount', type: 'uint256' },
|
||||
],
|
||||
[
|
||||
getAddress(token), getAddress(recipient), amount
|
||||
]
|
||||
);
|
||||
return [PERMIT2_TRANSFER_FROM, encodedInput];
|
||||
}
|
||||
|
||||
export function transfer({ token, recipient, amount }: TransferParams): CommandPair {
|
||||
const encodedInput = encodeAbiParameters(
|
||||
[
|
||||
{ name: 'token', type: 'address' },
|
||||
{ name: 'recipient', type: 'address' },
|
||||
{ name: 'amount', type: 'uint256' },
|
||||
],
|
||||
[
|
||||
getAddress(token), getAddress(recipient), amount
|
||||
]
|
||||
);
|
||||
return [TRANSFER, encodedInput];
|
||||
}
|
||||
|
||||
interface V3SwapExactInParams {
|
||||
recipient: string;
|
||||
amountIn: bigint;
|
||||
minAmountOut: bigint;
|
||||
path: `0x${string}`;
|
||||
payerIsUser: boolean;
|
||||
}
|
||||
|
||||
export function swapV3ExactIn({
|
||||
recipient,
|
||||
amountIn,
|
||||
minAmountOut,
|
||||
path,
|
||||
payerIsUser
|
||||
}: V3SwapExactInParams): CommandPair {
|
||||
const encodedInput = encodeAbiParameters(
|
||||
[
|
||||
{ name: 'recipient', type: 'address' },
|
||||
{ name: 'amountIn', type: 'uint256' },
|
||||
{ name: 'minAmountOut', type: 'uint256' },
|
||||
{ name: 'path', type: 'bytes' },
|
||||
{ name: 'payerIsUser', type: 'bool' },
|
||||
],
|
||||
[
|
||||
getAddress(recipient), amountIn, minAmountOut, path, payerIsUser
|
||||
]
|
||||
);
|
||||
return [V3_SWAP_EXACT_IN, encodedInput];
|
||||
}
|
||||
|
||||
interface UnwrapWethParams {
|
||||
recipient: string;
|
||||
minAmountOut: bigint;
|
||||
}
|
||||
|
||||
export function unwrapWeth({ recipient, minAmountOut }: UnwrapWethParams): CommandPair {
|
||||
const encodedInput = encodeAbiParameters(
|
||||
[
|
||||
{ name: 'recipient', type: 'address' },
|
||||
{ name: 'minAmountOut', type: 'uint256' },
|
||||
],
|
||||
[
|
||||
getAddress(recipient), minAmountOut
|
||||
]
|
||||
);
|
||||
return [UNWRAP_WETH, encodedInput];
|
||||
}
|
||||
|
||||
interface SweepParams {
|
||||
token: string;
|
||||
recipient: string;
|
||||
minAmountOut: bigint;
|
||||
}
|
||||
|
||||
export function sweep({ token, recipient, minAmountOut }: SweepParams): CommandPair {
|
||||
const encodedInput = encodeAbiParameters(
|
||||
[
|
||||
{ name: 'token', type: 'address' },
|
||||
{ name: 'recipient', type: 'address' },
|
||||
{ name: 'minAmountOut', type: 'uint256' },
|
||||
],
|
||||
[
|
||||
getAddress(token), getAddress(recipient), minAmountOut
|
||||
]
|
||||
);
|
||||
return [SWEEP, encodedInput];
|
||||
}
|
||||
|
||||
export const enum Command {
|
||||
permit2 = "permit2",
|
||||
transfer = "transfer",
|
||||
transferWithPermit = "transferWithPermit",
|
||||
swapV3ExactIn = "swapV3ExactIn",
|
||||
unrwapWeth = "unrwapWeth",
|
||||
sweep = "sweep",
|
||||
};
|
||||
|
||||
interface CommandParams {
|
||||
[Command.permit2]: Permit2Params;
|
||||
[Command.transfer]: TransferParams;
|
||||
[Command.transferWithPermit]: TransferParams;
|
||||
[Command.swapV3ExactIn]: V3SwapExactInParams;
|
||||
[Command.unrwapWeth]: UnwrapWethParams;
|
||||
[Command.sweep]: SweepParams;
|
||||
};
|
||||
|
||||
type CommandFnMap = {
|
||||
[K in keyof CommandParams]: (params: CommandParams[K]) => CommandPair;
|
||||
};
|
||||
|
||||
export type Instruction = {
|
||||
[K in keyof CommandParams]: {
|
||||
command: K;
|
||||
params: CommandParams[K];
|
||||
}
|
||||
}[keyof CommandParams];
|
||||
|
||||
export const commandFnMap: CommandFnMap = {
|
||||
[Command.permit2]: permit2,
|
||||
[Command.transfer]: transfer,
|
||||
[Command.transferWithPermit]: transferWithPermit,
|
||||
[Command.sweep]: sweep,
|
||||
[Command.swapV3ExactIn]: swapV3ExactIn,
|
||||
[Command.unrwapWeth]: unwrapWeth,
|
||||
};
|
||||
|
||||
export function encodeInstruction<K extends Command>(ins: { command: K, params: CommandParams[K]; }): CommandPair {
|
||||
return commandFnMap[ins.command](ins.params);
|
||||
}
|
||||
@@ -1,16 +1,33 @@
|
||||
import { Address } from "viem";
|
||||
import { QUOTER_ADDRESSES, V3_CORE_FACTORY_ADDRESSES } from "@uniswap/sdk-core";
|
||||
import { UNIVERSAL_ROUTER_ADDRESS, UniversalRouterVersion } from "@uniswap/universal-router-sdk";
|
||||
import { FeeAmount } from "@uniswap/v3-sdk";
|
||||
import { Address, getAddress } from "viem";
|
||||
|
||||
export { WETH9 as WRAPPED_NATIVE_TOKEN_ADDRESS } from "@uniswap/sdk-core";
|
||||
|
||||
export const PERMIT2_ADDRESS = '0x000000000022D473030F116dDEE9F6B43aC78BA3'
|
||||
|
||||
export function permit2Address(chainId?: number): `0x${string}` {
|
||||
switch (chainId) {
|
||||
case 324:
|
||||
return '0x0000000000225e31D15943971F47aD3022F714Fa'
|
||||
default:
|
||||
return PERMIT2_ADDRESS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mainnet, Polygon, Optimism, Arbitrum, Testnets Address
|
||||
* Mainnet (1), Polygon (137), Optimism (10), Arbitrum (42161), Testnets Address (11155111)
|
||||
* source: https://github.com/Uniswap/v3-periphery/blob/main/deploys.md
|
||||
*/
|
||||
export const QUOTER_CONTRACT_ADDRESS: Record<string, Address> = {
|
||||
"1": "0x61fFE014bA17989E743c5F6cB21bF9697530B21e", // Ethereum
|
||||
"137": "0x61fFE014bA17989E743c5F6cB21bF9697530B21e", // polygon
|
||||
"10": "0x61fFE014bA17989E743c5F6cB21bF9697530B21e", // Optimism
|
||||
"42161": "0x61fFE014bA17989E743c5F6cB21bF9697530B21e", // Arbitrum
|
||||
"11155111": "0xEd1f6473345F45b75F8179591dd5bA1888cf2FB3", // Sepolia
|
||||
};
|
||||
|
||||
// export const QUOTER_CONTRACT_ADDRESS: Record<string, Address> = {
|
||||
// "1": "0x61fFE014bA17989E743c5F6cB21bF9697530B21e", // Ethereum
|
||||
// "137": "0x61fFE014bA17989E743c5F6cB21bF9697530B21e", // polygon
|
||||
// "10": "0x61fFE014bA17989E743c5F6cB21bF9697530B21e", // Optimism
|
||||
// "42161": "0x61fFE014bA17989E743c5F6cB21bF9697530B21e", // Arbitrum
|
||||
// "11155111": "0xEd1f6473345F45b75F8179591dd5bA1888cf2FB3", // Sepolia
|
||||
// };
|
||||
|
||||
export const FACTORY_CONTRACT_ADDRESS: Record<string, Address> = {
|
||||
"1": "0x1F98431c8aD98523631AE4a59f267346ea31F984", // Ethereum
|
||||
@@ -18,13 +35,45 @@ export const FACTORY_CONTRACT_ADDRESS: Record<string, Address> = {
|
||||
"10": "0x1F98431c8aD98523631AE4a59f267346ea31F984", // Optimism
|
||||
"42161": "0x1F98431c8aD98523631AE4a59f267346ea31F984", // Arbitrum
|
||||
"11155111": "0x0227628f3f023bb0b980b67d528571c95c6dac1c", // Sepolia
|
||||
};
|
||||
|
||||
// Common intermediate tokens for multi-hop routing
|
||||
export const INTERMEDIATE_TOKENS: Record<string, Address[]> = {
|
||||
'1': [ // Mainnet
|
||||
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
|
||||
'0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
|
||||
'0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
|
||||
'0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', // WBTC
|
||||
],
|
||||
'11155111': [ // Sepolia
|
||||
'0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', // USDC
|
||||
'0x7169D38820dfd117C3FA1f22a697dBA58d90BA06', // USDT
|
||||
],
|
||||
};
|
||||
|
||||
export function getRouterAddress(chainId: number) {
|
||||
return getAddress(UNIVERSAL_ROUTER_ADDRESS(UniversalRouterVersion.V2_0, chainId));
|
||||
}
|
||||
|
||||
export const WRAPPED_NATIVE_TOKEN_ADDRESS: Record<string, Address> = {
|
||||
"1": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // mainnet (WETH)
|
||||
"137": "0x0000000000000000000000000000000000001010", // polygon (POL)
|
||||
// "137": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", // (WPOL) TODO: compare which token to use
|
||||
"10": "0x4200000000000000000000000000000000000006", // Optimism (WETH)
|
||||
"42161": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", // Arbitrum (WETH)
|
||||
"11155111": "0xfff9976782d46cc05630d1f6ebab18b2324d6b14", // sepolia (WETH)
|
||||
export function getPermit2Address(chainId: number) {
|
||||
return getAddress(permit2Address(chainId));
|
||||
}
|
||||
|
||||
export function getV3Factory(chainId: number) {
|
||||
return getAddress(V3_CORE_FACTORY_ADDRESSES[chainId]!)
|
||||
}
|
||||
|
||||
export function getQuoterAddress(chainId: number) {
|
||||
const mainnetQuoter = "0x61fFE014bA17989E743c5F6cB21bF9697530B21e";
|
||||
return getAddress(chainId !== 1 ? QUOTER_ADDRESSES[chainId]! : mainnetQuoter)
|
||||
}
|
||||
|
||||
export const FeeTiers: FeeAmount[] = [
|
||||
FeeAmount.LOWEST,
|
||||
FeeAmount.LOW_200,
|
||||
FeeAmount.LOW_300,
|
||||
FeeAmount.LOW_400,
|
||||
FeeAmount.LOW,
|
||||
FeeAmount.MEDIUM,
|
||||
FeeAmount.HIGH,
|
||||
];
|
||||
|
||||
58
packages/relayer/src/providers/uniswap/createPermit.ts
Normal file
58
packages/relayer/src/providers/uniswap/createPermit.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { Address, CustomSource, getContract } from "viem";
|
||||
|
||||
import { web3Provider } from "../index.js";
|
||||
import { Permit2ABI } from "./abis/permit2.abi.js";
|
||||
import { createPermitSingleData, PermitSingle } from "./permit2.js";
|
||||
|
||||
export async function createPermit2<Signer extends CustomSource>({
|
||||
signer,
|
||||
chainId,
|
||||
permit2Address,
|
||||
routerAddress,
|
||||
assetAddress,
|
||||
allowanceAmount,
|
||||
}: {
|
||||
signer: Signer,
|
||||
chainId: number,
|
||||
permit2Address: Address,
|
||||
routerAddress: Address,
|
||||
assetAddress: Address,
|
||||
allowanceAmount: bigint,
|
||||
}): Promise<[PermitSingle, `0x${string}`]> {
|
||||
|
||||
const deadline = Math.floor(3600 + Number(new Date()) / 1000); // one hour
|
||||
|
||||
const permitContract = getContract({
|
||||
abi: Permit2ABI,
|
||||
address: permit2Address,
|
||||
client: web3Provider.client(chainId)
|
||||
});
|
||||
|
||||
const allowance = await permitContract.read.allowance([
|
||||
signer.address,
|
||||
assetAddress,
|
||||
routerAddress
|
||||
]);
|
||||
const [, , nonce] = allowance;
|
||||
|
||||
const permitSingle = {
|
||||
spender: routerAddress,
|
||||
details: {
|
||||
token: assetAddress,
|
||||
amount: allowanceAmount,
|
||||
expiration: deadline,
|
||||
nonce
|
||||
},
|
||||
sigDeadline: BigInt(deadline)
|
||||
};
|
||||
const permitData = createPermitSingleData(permitSingle, permit2Address, chainId);
|
||||
|
||||
const signature = await signer.signTypedData({
|
||||
domain: permitData.domain,
|
||||
types: permitData.types,
|
||||
message: permitSingle,
|
||||
primaryType: "PermitSingle"
|
||||
});
|
||||
|
||||
return [permitSingle, signature];
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
export const IERC20MinimalABI = {
|
||||
"abi": [
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
} as const;
|
||||
17
packages/relayer/src/providers/uniswap/factory.abi.ts
Normal file
17
packages/relayer/src/providers/uniswap/factory.abi.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export const FactoryABI = {
|
||||
abi: [
|
||||
{
|
||||
type: 'function',
|
||||
name: 'getPool',
|
||||
stateMutability: 'view',
|
||||
inputs: [
|
||||
{ name: 'tokenA', type: 'address' },
|
||||
{ name: 'tokenB', type: 'address' },
|
||||
{ name: 'fee', type: 'uint24' }
|
||||
],
|
||||
outputs: [
|
||||
{ name: 'pool', type: 'address' }
|
||||
]
|
||||
}
|
||||
]
|
||||
} as const;
|
||||
60
packages/relayer/src/providers/uniswap/permit2.ts
Normal file
60
packages/relayer/src/providers/uniswap/permit2.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
const PERMIT2_DOMAIN_NAME = 'Permit2';
|
||||
|
||||
export function permit2Domain(permit2Address: `0x${string}`, chainId: number) {
|
||||
return {
|
||||
name: PERMIT2_DOMAIN_NAME,
|
||||
chainId,
|
||||
verifyingContract: permit2Address,
|
||||
};
|
||||
}
|
||||
|
||||
export const PERMIT_DETAILS = [
|
||||
{ name: 'token', type: 'address' },
|
||||
{ name: 'amount', type: 'uint160' },
|
||||
{ name: 'expiration', type: 'uint48' },
|
||||
{ name: 'nonce', type: 'uint48' },
|
||||
];
|
||||
|
||||
export const PERMIT_TYPES = {
|
||||
PermitSingle: [
|
||||
{ name: 'details', type: 'PermitDetails' },
|
||||
{ name: 'spender', type: 'address' },
|
||||
{ name: 'sigDeadline', type: 'uint256' },
|
||||
],
|
||||
PermitDetails: PERMIT_DETAILS,
|
||||
};
|
||||
|
||||
export interface PermitDetails {
|
||||
token: `0x${string}`,
|
||||
amount: bigint,
|
||||
expiration: number,
|
||||
nonce: number;
|
||||
}
|
||||
|
||||
export interface PermitSingle {
|
||||
details: PermitDetails;
|
||||
spender: `0x${string}`;
|
||||
sigDeadline: bigint;
|
||||
}
|
||||
|
||||
const MaxUint48 = BigInt('0xffffffffffff');
|
||||
const MaxUint160 = BigInt('0xffffffffffffffffffffffffffffffffffffffff');
|
||||
const MaxAllowanceTransferAmount = MaxUint160;
|
||||
const MaxAllowanceExpiration = MaxUint48;
|
||||
const MaxOrderedNonce = MaxUint48;
|
||||
|
||||
export function validatePermitDetails(details: PermitDetails) {
|
||||
if (MaxOrderedNonce <= details.nonce) throw new Error('NONCE_OUT_OF_RANGE');
|
||||
if (MaxAllowanceTransferAmount <= details.amount) throw new Error('AMOUNT_OUT_OF_RANGE');
|
||||
if (MaxAllowanceExpiration <= details.expiration) throw new Error('EXPIRATION_OUT_OF_RANGE');
|
||||
}
|
||||
|
||||
export function createPermitSingleData(permit: PermitSingle, permit2Address: `0x${string}`, chainId: number) {
|
||||
const domain = permit2Domain(permit2Address, chainId);
|
||||
validatePermitDetails(permit.details);
|
||||
return {
|
||||
domain,
|
||||
types: PERMIT_TYPES,
|
||||
values: permit,
|
||||
};
|
||||
}
|
||||
76
packages/relayer/src/providers/uniswap/pools.ts
Normal file
76
packages/relayer/src/providers/uniswap/pools.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { Token, WETH9 } from "@uniswap/sdk-core";
|
||||
import { encodeRouteToPath, FeeAmount, Pool, Route as V3Route } from '@uniswap/v3-sdk';
|
||||
import { getAddress, getContract, toHex } from "viem";
|
||||
|
||||
import { getV3Factory } from "./constants.js";
|
||||
import { web3Provider } from "../index.js";
|
||||
import { v3PoolABI } from "./abis/v3pool.abi.js";
|
||||
|
||||
|
||||
function sortTokens(tokenA: Token, tokenB: Token): [Token, Token] {
|
||||
return tokenA.address.toLowerCase() < tokenB.address.toLowerCase()
|
||||
? [tokenA, tokenB]
|
||||
: [tokenB, tokenA];
|
||||
}
|
||||
|
||||
export async function getPool(chainId: number, tokenA: Token, tokenB: Token, fee: FeeAmount) {
|
||||
|
||||
const V3_FACTORY = getV3Factory(chainId);
|
||||
|
||||
const [token0, token1] = sortTokens(tokenA, tokenB);
|
||||
const poolAddress = Pool.getAddress(token0, token1, fee, undefined, V3_FACTORY);
|
||||
|
||||
const poolContract = getContract({
|
||||
abi: v3PoolABI,
|
||||
address: getAddress(poolAddress),
|
||||
client: web3Provider.client(chainId),
|
||||
});
|
||||
|
||||
const [liquidity, slot0] = await Promise.all([
|
||||
poolContract.read.liquidity(),
|
||||
poolContract.read.slot0(),
|
||||
]);
|
||||
|
||||
const [sqrtPriceX96, tick, , , , ,] = slot0;
|
||||
|
||||
const pool = new Pool(token0, token1, fee, toHex(sqrtPriceX96), toHex(liquidity), tick);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
export async function getPoolPath(tokenIn: `0x${string}`, chainId: number) {
|
||||
const weth = WETH9[chainId]!;
|
||||
const TokenIn = new Token(chainId, tokenIn, 1);
|
||||
const pool = await getPool(chainId, TokenIn, weth, FeeAmount.LOW); // 0.05% fee tier
|
||||
const route = new V3Route([pool], TokenIn, weth);
|
||||
const pathParams = encodeRouteToPath(route, false) as `0x${string}`;
|
||||
return pathParams;
|
||||
}
|
||||
|
||||
export function hopsFromAddressRoute(route: `0x${string}`[]) {
|
||||
const hops: [`0x${string}`, `0x${string}`][] = [];
|
||||
for (let i = 1; i <= route.length - 1; i++) {
|
||||
hops.push([route[i - 1]!, route[i]!]);
|
||||
}
|
||||
return hops;
|
||||
}
|
||||
|
||||
function isAddress(p: `0x${string}` | FeeAmount): p is `0x${string}` {
|
||||
return (p as `0x${string}`).length !== undefined;
|
||||
}
|
||||
|
||||
export function encodePath(path: (`0x${string}` | FeeAmount)[]): `0x${string}` {
|
||||
// Encode the path for quoteExactInput
|
||||
// Path encoding: token0 (20 bytes) + fee0 (3 bytes) + token1 (20 bytes) + fee1 (3 bytes) + token2 (20 bytes)...
|
||||
let encodedPath: `0x${string}` = '0x';
|
||||
path.forEach(p => {
|
||||
// is address
|
||||
if (isAddress(p)) {
|
||||
encodedPath += p.replace(/^0x/, ""); // Remove '0x' prefix
|
||||
// is number
|
||||
} else {
|
||||
encodedPath += p.toString(16).padStart(6, '0');
|
||||
}
|
||||
});
|
||||
return encodedPath
|
||||
}
|
||||
@@ -1,269 +0,0 @@
|
||||
export const QuoterV2ABI = {
|
||||
"abi": [
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_factory",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_WETH9",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "WETH9",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "factory",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "path",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountIn",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "quoteExactInput",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountOut",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160[]",
|
||||
"name": "sqrtPriceX96AfterList",
|
||||
"type": "uint160[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32[]",
|
||||
"name": "initializedTicksCrossedList",
|
||||
"type": "uint32[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "gasEstimate",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "tokenIn",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "tokenOut",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountIn",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint24",
|
||||
"name": "fee",
|
||||
"type": "uint24"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceLimitX96",
|
||||
"type": "uint160"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IQuoterV2.QuoteExactInputSingleParams",
|
||||
"name": "params",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"name": "quoteExactInputSingle",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountOut",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceX96After",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "initializedTicksCrossed",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "gasEstimate",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "path",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountOut",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "quoteExactOutput",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountIn",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160[]",
|
||||
"name": "sqrtPriceX96AfterList",
|
||||
"type": "uint160[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32[]",
|
||||
"name": "initializedTicksCrossedList",
|
||||
"type": "uint32[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "gasEstimate",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "tokenIn",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "tokenOut",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint24",
|
||||
"name": "fee",
|
||||
"type": "uint24"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceLimitX96",
|
||||
"type": "uint160"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IQuoterV2.QuoteExactOutputSingleParams",
|
||||
"name": "params",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"name": "quoteExactOutputSingle",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountIn",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceX96After",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "initializedTicksCrossed",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "gasEstimate",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "int256",
|
||||
"name": "amount0Delta",
|
||||
"type": "int256"
|
||||
},
|
||||
{
|
||||
"internalType": "int256",
|
||||
"name": "amount1Delta",
|
||||
"type": "int256"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "path",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "uniswapV3SwapCallback",
|
||||
"outputs": [],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
} as const;
|
||||
564
packages/relayer/src/providers/uniswap/uniswap.provider.ts
Normal file
564
packages/relayer/src/providers/uniswap/uniswap.provider.ts
Normal file
@@ -0,0 +1,564 @@
|
||||
import { Token } from '@uniswap/sdk-core';
|
||||
import { FeeAmount } from '@uniswap/v3-sdk';
|
||||
import { Account, Address, getAddress, getContract, GetContractReturnType, PublicClient, WriteContractParameters } from 'viem';
|
||||
import { privateKeyToAccount } from 'viem/accounts';
|
||||
|
||||
import { getSignerPrivateKey } from "../../config/index.js";
|
||||
import { BlockchainError, RelayerError } from '../../exceptions/base.exception.js';
|
||||
import { web3Provider } from '../../providers/index.js';
|
||||
import { isFeeReceiverSameAsSigner, isViemError } from '../../utils.js';
|
||||
import { IERC20MinimalABI } from './abis/erc20.abi.js';
|
||||
import { FactoryV3ABI } from './abis/factoryV3.abi.js';
|
||||
import { QuoterV2ABI } from './abis/quoterV2.abi.js';
|
||||
import { UniversalRouterABI } from './abis/universalRouter.abi.js';
|
||||
import { v3PoolABI } from './abis/v3pool.abi.js';
|
||||
import { Command, CommandPair, encodeInstruction, Instruction, Permit2Params } from './commands.js';
|
||||
import { FeeTiers, getPermit2Address, getQuoterAddress, getRouterAddress, getV3Factory, INTERMEDIATE_TOKENS, WRAPPED_NATIVE_TOKEN_ADDRESS } from './constants.js';
|
||||
import { createPermit2 } from './createPermit.js';
|
||||
import { encodePath, hopsFromAddressRoute } from './pools.js';
|
||||
|
||||
export type UniswapQuote = {
|
||||
chainId: number;
|
||||
addressIn: string;
|
||||
addressOut: string;
|
||||
amountIn: bigint;
|
||||
};
|
||||
|
||||
type QuoteToken = { amount: bigint, decimals: number; };
|
||||
|
||||
export type Quote = {
|
||||
path: (string | FeeAmount)[];
|
||||
in: QuoteToken;
|
||||
out: QuoteToken;
|
||||
};
|
||||
|
||||
interface SwapWithRefundParams {
|
||||
feeReceiver: `0x${string}`;
|
||||
nativeRecipient: `0x${string}`;
|
||||
tokenIn: `0x${string}`;
|
||||
feeGross: bigint;
|
||||
refundAmount: bigint;
|
||||
chainId: number;
|
||||
feeBase: bigint;
|
||||
}
|
||||
|
||||
interface CreateInstructionsFeeReceiveerIsRelayer {
|
||||
router: { address: Address; };
|
||||
relayer: Account;
|
||||
nativeRecipient: Address;
|
||||
amountToSwap: bigint;
|
||||
minAmountOut: bigint;
|
||||
permitParmas: Permit2Params;
|
||||
pathParams: `0x${string}`;
|
||||
refundAmount: bigint;
|
||||
}
|
||||
|
||||
interface CreateInstructionsFeeReceiveerIsNotRelayer extends CreateInstructionsFeeReceiveerIsRelayer {
|
||||
tokenIn: Address;
|
||||
feeReceiver: Address;
|
||||
feeBase: bigint;
|
||||
}
|
||||
|
||||
const ZERO_ADDRESS = getAddress("0x0000000000000000000000000000000000000000");
|
||||
function isNullAddress(a: string) {
|
||||
return getAddress(a) === ZERO_ADDRESS;
|
||||
}
|
||||
|
||||
export class UniswapProvider {
|
||||
|
||||
static readonly ZERO_ADDRESS = ZERO_ADDRESS;
|
||||
|
||||
async getTokenInfo(chainId: number, address: Address): Promise<Token> {
|
||||
const contract = getContract({
|
||||
address,
|
||||
abi: IERC20MinimalABI,
|
||||
client: web3Provider.client(chainId)
|
||||
});
|
||||
const [decimals, symbol] = await Promise.all([
|
||||
contract.read.decimals(),
|
||||
contract.read.symbol(),
|
||||
]);
|
||||
return new Token(chainId, address, Number(decimals), symbol);
|
||||
}
|
||||
|
||||
getFactory(chainId: number) {
|
||||
const factoryAddress = getV3Factory(chainId);
|
||||
if (!factoryAddress) {
|
||||
throw RelayerError.unknown(`No Uniswap V3 factory address configured for chain ${chainId}`);
|
||||
}
|
||||
return getContract({
|
||||
address: factoryAddress,
|
||||
abi: FactoryV3ABI,
|
||||
client: web3Provider.client(chainId)
|
||||
});
|
||||
}
|
||||
|
||||
getQuoter(chainId: number) {
|
||||
return getContract({
|
||||
address: getQuoterAddress(chainId),
|
||||
abi: QuoterV2ABI,
|
||||
client: web3Provider.client(chainId)
|
||||
});
|
||||
}
|
||||
|
||||
getPool(chainId: number, poolAddress: `0x${string}`): GetContractReturnType<typeof v3PoolABI, PublicClient> {
|
||||
return getContract({
|
||||
abi: v3PoolABI,
|
||||
address: getAddress(poolAddress),
|
||||
client: web3Provider.client(chainId),
|
||||
});
|
||||
}
|
||||
|
||||
async quoteNativeToken(chainId: number, addressIn: Address, amountIn: bigint): Promise<Quote> {
|
||||
const weth = WRAPPED_NATIVE_TOKEN_ADDRESS[chainId]!;
|
||||
// First try direct quote
|
||||
try {
|
||||
return await this.quote({
|
||||
chainId,
|
||||
amountIn,
|
||||
addressOut: weth.address,
|
||||
addressIn
|
||||
});
|
||||
} catch (directError) {
|
||||
|
||||
// If direct quote fails, try multi-hop routing
|
||||
const intermediateTokens = INTERMEDIATE_TOKENS[chainId.toString()] || [];
|
||||
for (const intermediateToken of intermediateTokens) {
|
||||
|
||||
// Skip if intermediate token is same as input or output
|
||||
if (intermediateToken.toLowerCase() === addressIn.toLowerCase() ||
|
||||
intermediateToken.toLowerCase() === weth.address.toLowerCase()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
return await this.quoteMultiHop({
|
||||
chainId,
|
||||
amountIn,
|
||||
path: [addressIn as Address, intermediateToken, weth.address as Address]
|
||||
});
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
throw directError;
|
||||
}
|
||||
}
|
||||
|
||||
private async poolHasLiquidity(chainId: number, poolAddress: `0x${string}`) {
|
||||
const pool = this.getPool(chainId, poolAddress);
|
||||
const [liq, slot0] = await Promise.all([
|
||||
pool.read.liquidity(),
|
||||
pool.read.slot0()
|
||||
]);
|
||||
if (liq === 0n)
|
||||
return false;
|
||||
// sqrtPriceX96, tick, observationIndex, observationCardinality, observationCardinalityNext, feeProtocol, unlocked
|
||||
const tick = slot0[1];
|
||||
const unlocked = slot0[6];
|
||||
if (!unlocked || tick === 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async findLowestFeePoolForPair(chainId: number, addressIn: string, addressOut: string): Promise<FeeAmount> {
|
||||
const factory = this.getFactory(chainId);
|
||||
let fee: FeeAmount | undefined;
|
||||
for (const candidateFee of FeeTiers) {
|
||||
const pool = await factory.read.getPool([
|
||||
addressIn as Address,
|
||||
addressOut as Address,
|
||||
candidateFee,
|
||||
]);
|
||||
|
||||
// we found one!
|
||||
if (!isNullAddress(pool) && await this.poolHasLiquidity(chainId, pool)) {
|
||||
fee = candidateFee;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fee === undefined) {
|
||||
throw RelayerError.unknown(
|
||||
`No usable Uniswap V3 pool found for pair ${addressIn}/${addressOut} on any known fee tier`
|
||||
);
|
||||
}
|
||||
return fee;
|
||||
}
|
||||
|
||||
async quote({ chainId, addressIn, addressOut, amountIn }: UniswapQuote) {
|
||||
const tokenIn = await this.getTokenInfo(chainId, addressIn as Address);
|
||||
const tokenOut = await this.getTokenInfo(chainId, addressOut as Address);
|
||||
const quoterContract = this.getQuoter(chainId);
|
||||
|
||||
const fee = await this.findLowestFeePoolForPair(chainId, addressIn, addressOut);
|
||||
try {
|
||||
|
||||
const quotedAmountOut = await quoterContract.simulate.quoteExactInputSingle([{
|
||||
tokenIn: tokenIn.address as Address,
|
||||
tokenOut: tokenOut.address as Address,
|
||||
fee,
|
||||
amountIn,
|
||||
sqrtPriceLimitX96: 0n,
|
||||
}]);
|
||||
|
||||
// amount, sqrtPriceX96After, tickAfter, gasEstimate
|
||||
const [amount, , ,] = quotedAmountOut.result;
|
||||
return {
|
||||
path: [tokenIn.address, fee, tokenOut.address],
|
||||
in: {
|
||||
amount: amountIn, decimals: tokenIn.decimals
|
||||
},
|
||||
out: {
|
||||
amount, decimals: tokenOut.decimals
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof Error && isViemError(error)) {
|
||||
const { metaMessages, shortMessage } = error;
|
||||
throw BlockchainError.txError((metaMessages ? metaMessages[0] : undefined) || shortMessage);
|
||||
} else {
|
||||
throw RelayerError.unknown("Something went wrong while quoting");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async quoteMultiHop({ chainId, amountIn, path }: { chainId: number, amountIn: bigint, path: Address[]; }): Promise<Quote> {
|
||||
if (path.length < 2) {
|
||||
throw RelayerError.unknown('Path must contain at least 2 addresses');
|
||||
}
|
||||
|
||||
const quoterContract = this.getQuoter(chainId);
|
||||
|
||||
// Get token info for input and output
|
||||
const [tokenIn, tokenOut] = await Promise.all([
|
||||
this.getTokenInfo(chainId, path[0]!),
|
||||
this.getTokenInfo(chainId, path[path.length - 1]!)
|
||||
]);
|
||||
|
||||
// For each hop, we need to find a valid pool and fee tier
|
||||
const pathWithFees: { token: Address, fee: FeeAmount; }[] = [];
|
||||
const hops: [`0x${string}`, `0x${string}`][] = [];
|
||||
for (let i = 1; i <= path.length - 1; i++) {
|
||||
hops.push([path[i - 1]!, path[i]!]);
|
||||
}
|
||||
|
||||
for (const hop of hops) {
|
||||
const [tokenA, tokenB] = hop;
|
||||
try {
|
||||
const fee = await this.findLowestFeePoolForPair(chainId, tokenA, tokenB);
|
||||
const feePath = { token: tokenA, fee };
|
||||
pathWithFees.push(feePath);
|
||||
} catch {
|
||||
throw RelayerError.unknown(
|
||||
`No pool found for hop: ${tokenA} -> ${tokenB}`
|
||||
);
|
||||
}
|
||||
}
|
||||
pathWithFees.push({ token: path[path.length - 1] as Address, fee: FeeAmount.MEDIUM }); // fee doesn't matter for last token
|
||||
|
||||
// Encode the path for quoteExactInput
|
||||
// Path encoding: token0 (20 bytes) + fee0 (3 bytes) + token1 (20 bytes) + fee1 (3 bytes) + token2 (20 bytes)...
|
||||
let encodedPath = '0x';
|
||||
const plainPath: (string | FeeAmount)[] = [];
|
||||
pathWithFees.forEach((p, i) => {
|
||||
const { token, fee } = p;
|
||||
encodedPath += token.replace(/^0x/, ""); // Remove '0x' prefix
|
||||
plainPath.push(token);
|
||||
if (i < pathWithFees.length - 1) {
|
||||
// Add fee as 3 bytes (24 bits)
|
||||
encodedPath += fee.toString(16).padStart(6, '0');
|
||||
plainPath.push(fee);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
const quotedAmount = await quoterContract.simulate.quoteExactInput([
|
||||
encodedPath as `0x${string}`,
|
||||
amountIn
|
||||
]);
|
||||
|
||||
const [amountOut] = quotedAmount.result;
|
||||
|
||||
return {
|
||||
path: plainPath,
|
||||
in: {
|
||||
amount: amountIn,
|
||||
decimals: tokenIn.decimals
|
||||
},
|
||||
out: {
|
||||
amount: amountOut,
|
||||
decimals: tokenOut.decimals
|
||||
}
|
||||
};
|
||||
} catch {
|
||||
throw RelayerError.unknown(
|
||||
`Failed to get multi-hop quote for path: ${path.join(' -> ')}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async approvePermit2forERC20(tokenIn: `0x${string}`, chainId: number) {
|
||||
// 0) - (this is done only once) - Approve Permit2 to move Relayer's ERC20
|
||||
const relayer = privateKeyToAccount(getSignerPrivateKey(chainId) as `0x${string}`);
|
||||
const PERMIT2_ADDRESS = getPermit2Address(chainId);
|
||||
const client = web3Provider.client(chainId);
|
||||
const erc20 = getContract({
|
||||
abi: IERC20MinimalABI,
|
||||
address: tokenIn,
|
||||
client,
|
||||
});
|
||||
const allowance = await erc20.read.allowance([relayer.address, PERMIT2_ADDRESS]);
|
||||
if (allowance < 2n ** 128n) {
|
||||
const hash = await erc20.write.approve(
|
||||
[PERMIT2_ADDRESS, 2n ** 256n - 1n],
|
||||
{ chain: client.chain, account: relayer }
|
||||
);
|
||||
await client.waitForTransactionReceipt({ hash });
|
||||
}
|
||||
}
|
||||
|
||||
static createInstructionsIfFeeReceiverIsNotRelayer({
|
||||
permitParmas, router, pathParams, relayer,
|
||||
tokenIn, feeReceiver, feeBase,
|
||||
refundAmount, amountToSwap, minAmountOut, nativeRecipient
|
||||
}: CreateInstructionsFeeReceiveerIsNotRelayer): Instruction[] {
|
||||
// OPERATIONS:
|
||||
// 1) Send permit for Router to move Gross Fees in Token from Relayer
|
||||
// 2) AllowanceTransfer from Relayer to feeReceiver for Base Fees
|
||||
// 3) Swap ERC20 for WETH consuming (Gross-Base) Fees, destination Router, setting the payerIsUser=true flag, meaning to use permit2 (Relayer has the tokens)
|
||||
// 4) Unwrap WETH to Router
|
||||
// 5) Transfer native Refund value to Relayer
|
||||
// 6) Sweep whatever is left to Recipient
|
||||
return [
|
||||
// This is used to authorize the router to move our tokens
|
||||
{ command: Command.permit2, params: permitParmas },
|
||||
// We send relaying fees to feeReceiver
|
||||
{ command: Command.transferWithPermit, params: { token: tokenIn, recipient: feeReceiver, amount: feeBase } },
|
||||
|
||||
// Swap consuming all
|
||||
{
|
||||
command: Command.swapV3ExactIn, params: {
|
||||
// we're going to unwrap weth from here
|
||||
recipient: router.address,
|
||||
amountIn: amountToSwap,
|
||||
minAmountOut,
|
||||
// USDC-WETH
|
||||
path: pathParams,
|
||||
// The relayer is the tx initiator
|
||||
payerIsUser: true,
|
||||
}
|
||||
},
|
||||
// the router will hold the value for further splitting
|
||||
{ command: Command.unrwapWeth, params: { recipient: router.address, minAmountOut } },
|
||||
// gas refund to relayer
|
||||
// 0 address means moving native
|
||||
{ command: Command.transfer, params: { token: this.ZERO_ADDRESS, recipient: relayer.address, amount: refundAmount } },
|
||||
// 0 address means moving native
|
||||
// sweep reminder to the withdrawal address
|
||||
{ command: Command.sweep, params: { token: this.ZERO_ADDRESS, recipient: nativeRecipient, minAmountOut: 0n } }
|
||||
];
|
||||
}
|
||||
|
||||
static createInstructionsIfFeeReceiverIsRelayer({
|
||||
permitParmas, router, pathParams, relayer,
|
||||
refundAmount, amountToSwap, minAmountOut, nativeRecipient
|
||||
}: CreateInstructionsFeeReceiveerIsRelayer): Instruction[] {
|
||||
// OPERATIONS:
|
||||
// 1) Send permit for Router to move Gross Fees in Token from Relayer
|
||||
// 2) Swap ERC20 for WETH, destination Router, setting the payerIsUser=true flag
|
||||
// 3) Unwrap WETH to Router
|
||||
// 4) Transfer native Refund value to Relayer
|
||||
// 5) Sweep whatever is left to Recipient
|
||||
return [
|
||||
// This is used to authorize the router to move our tokens
|
||||
{ command: Command.permit2, params: permitParmas },
|
||||
// Swap consuming all
|
||||
{
|
||||
command: Command.swapV3ExactIn, params: {
|
||||
// we're going to unwrap weth from here
|
||||
recipient: router.address,
|
||||
amountIn: amountToSwap,
|
||||
minAmountOut,
|
||||
// USDC-WETH
|
||||
path: pathParams,
|
||||
// The relayer is the tx initiator
|
||||
payerIsUser: true,
|
||||
}
|
||||
},
|
||||
// the router will hold the value for further splitting
|
||||
{ command: Command.unrwapWeth, params: { recipient: router.address, minAmountOut } },
|
||||
// gas refund to relayer
|
||||
// 0 address means moving native
|
||||
{ command: Command.transfer, params: { token: this.ZERO_ADDRESS, recipient: relayer.address, amount: refundAmount } },
|
||||
// 0 address means moving native
|
||||
// sweep reminder to the withdrawal address
|
||||
{ command: Command.sweep, params: { token: this.ZERO_ADDRESS, recipient: nativeRecipient, minAmountOut: 0n } }
|
||||
];
|
||||
}
|
||||
|
||||
async simulateSwapExactInputForWeth({
|
||||
nativeRecipient,
|
||||
feeReceiver,
|
||||
feeBase,
|
||||
feeGross,
|
||||
tokenIn,
|
||||
encodedPath,
|
||||
refundAmount,
|
||||
chainId
|
||||
}: SwapWithRefundParams & { encodedPath: `0x${string}`; }): Promise<WriteContractParameters> {
|
||||
|
||||
await this.approvePermit2forERC20(tokenIn, chainId);
|
||||
|
||||
const minAmountOut = refundAmount;
|
||||
const ROUTER_ADDRESS = getRouterAddress(chainId);
|
||||
const PERMIT2_ADDRESS = getPermit2Address(chainId);
|
||||
const relayer = privateKeyToAccount(getSignerPrivateKey(chainId) as `0x${string}`);
|
||||
const client = web3Provider.client(chainId);
|
||||
|
||||
const router = getContract({
|
||||
abi: UniversalRouterABI,
|
||||
address: ROUTER_ADDRESS,
|
||||
client
|
||||
});
|
||||
|
||||
const amountToSwap = feeGross - feeBase;
|
||||
|
||||
const [permit, signature] = await createPermit2({
|
||||
signer: relayer,
|
||||
chainId,
|
||||
allowanceAmount: feeGross,
|
||||
permit2Address: PERMIT2_ADDRESS,
|
||||
routerAddress: ROUTER_ADDRESS,
|
||||
assetAddress: tokenIn
|
||||
});
|
||||
|
||||
let instructions;
|
||||
if (isFeeReceiverSameAsSigner(chainId)) {
|
||||
// If feeReceiver is the same as signer, moving coins around is easier
|
||||
instructions = UniswapProvider.createInstructionsIfFeeReceiverIsRelayer({
|
||||
relayer,
|
||||
router,
|
||||
amountToSwap,
|
||||
permitParmas: { permit, signature },
|
||||
refundAmount,
|
||||
minAmountOut,
|
||||
pathParams: encodedPath,
|
||||
nativeRecipient
|
||||
});
|
||||
|
||||
} else {
|
||||
instructions = UniswapProvider.createInstructionsIfFeeReceiverIsNotRelayer({
|
||||
relayer,
|
||||
router,
|
||||
amountToSwap,
|
||||
permitParmas: { permit, signature },
|
||||
refundAmount,
|
||||
minAmountOut,
|
||||
pathParams: encodedPath,
|
||||
nativeRecipient,
|
||||
// we need to know receiver and how much to take
|
||||
feeReceiver,
|
||||
feeBase,
|
||||
tokenIn
|
||||
});
|
||||
}
|
||||
|
||||
const commandPairs: CommandPair[] = [];
|
||||
instructions.forEach((ins) => commandPairs.push(encodeInstruction(ins)));
|
||||
|
||||
const commands = "0x" + commandPairs.map(x => x[0].toString(16).padStart(2, "0")).join("") as `0x${string}`;
|
||||
const params = commandPairs.map(x => x[1]);
|
||||
|
||||
try {
|
||||
const { request: simulation } = await router.simulate.execute([commands, params], { account: relayer });
|
||||
const estimateGas = await client.estimateContractGas(simulation);
|
||||
|
||||
const {
|
||||
address,
|
||||
abi,
|
||||
functionName,
|
||||
args,
|
||||
chain,
|
||||
nonce,
|
||||
} = simulation;
|
||||
|
||||
return {
|
||||
functionName,
|
||||
account: relayer,
|
||||
address,
|
||||
abi,
|
||||
args,
|
||||
chain,
|
||||
nonce,
|
||||
gas: estimateGas * 11n / 10n
|
||||
};
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async findSingleOrMultiHopPath(chainId: number, tokenIn: `0x${string}`) {
|
||||
const weth = WRAPPED_NATIVE_TOKEN_ADDRESS[chainId]!;
|
||||
|
||||
let path: (`0x${string}` | number)[] = [];
|
||||
try {
|
||||
const fee = await this.findLowestFeePoolForPair(chainId, tokenIn, weth.address);
|
||||
path = [tokenIn, fee, getAddress(weth.address)];
|
||||
} catch (error) {
|
||||
if (!(error instanceof RelayerError)) {
|
||||
throw error;
|
||||
}
|
||||
// we try multi-hop
|
||||
const intermediateTokens = INTERMEDIATE_TOKENS[chainId.toString()] || [];
|
||||
for (const auxToken of intermediateTokens) {
|
||||
try {
|
||||
const hops = hopsFromAddressRoute([tokenIn, auxToken, getAddress(weth.address)]);
|
||||
const feeHops = await Promise.all(hops.map(async hop => {
|
||||
const [tokenIn, tokenOut] = hop;
|
||||
return {
|
||||
token: tokenIn,
|
||||
fee: await this.findLowestFeePoolForPair(chainId, tokenIn, tokenOut)
|
||||
};
|
||||
}));
|
||||
feeHops.push({ token: getAddress(weth.address), fee: FeeAmount.LOWEST }); // the last fee is not encoded
|
||||
const _path: (`0x${string}` | number)[] = [];
|
||||
feeHops.forEach((h, i) => {
|
||||
const { token, fee } = h;
|
||||
_path.push(token);
|
||||
if (i < feeHops.length - 1) {
|
||||
_path.push(fee);
|
||||
}
|
||||
});
|
||||
path = _path;
|
||||
break;
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (path.length === 0) {
|
||||
throw RelayerError.unknown(
|
||||
`Couldn't find any Uniswap V3 route for pair ${tokenIn}/weth on any known fee tier`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
async swapExactInputForWeth(params: SwapWithRefundParams) {
|
||||
const { chainId, tokenIn } = params;
|
||||
const path = await this.findSingleOrMultiHopPath(chainId, tokenIn);
|
||||
const encodedPath = encodePath(path);
|
||||
const writeContractParams = await this.simulateSwapExactInputForWeth({ ...params, encodedPath });
|
||||
const relayer = web3Provider.signer(chainId);
|
||||
const txHash = await relayer.writeContract(writeContractParams);
|
||||
return txHash;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Chain, createPublicClient, Hex, http, PublicClient, verifyTypedData } from "viem";
|
||||
import { Chain, createPublicClient, createWalletClient, Hex, http, PublicClient, verifyTypedData, WalletClient } from "viem";
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
import {
|
||||
CONFIG,
|
||||
getSignerPrivateKey
|
||||
} from "../config/index.js";
|
||||
import { createChainObject } from "../utils.js";
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
import { FeeCommitment } from "../interfaces/relayer/common.js";
|
||||
import { createChainObject } from "../utils.js";
|
||||
|
||||
interface IWeb3Provider {
|
||||
client(chainId: number): PublicClient;
|
||||
@@ -16,12 +16,15 @@ const domain = (chainId: number) => ({
|
||||
name: "Privacy Pools Relayer",
|
||||
version: "1",
|
||||
chainId,
|
||||
} as const)
|
||||
} as const);
|
||||
|
||||
const RelayerCommitmentTypes = {
|
||||
RelayerCommitment: [
|
||||
{ name: "withdrawalData", type: "bytes" },
|
||||
{ name: "asset", type: "address" },
|
||||
{ name: "expiration", type: "uint256" },
|
||||
{ name: "amount", type: "uint256" },
|
||||
{ name: "extraGas", type: "bool" },
|
||||
]
|
||||
} as const;
|
||||
|
||||
@@ -29,8 +32,9 @@ const RelayerCommitmentTypes = {
|
||||
* Class representing the provider for interacting with several chains
|
||||
*/
|
||||
export class Web3Provider implements IWeb3Provider {
|
||||
chains: { [key: number]: Chain };
|
||||
clients: { [key: number]: PublicClient };
|
||||
chains: { [key: number]: Chain; };
|
||||
clients: { [key: number]: PublicClient; };
|
||||
signers: { [key: number]: WalletClient; };
|
||||
|
||||
constructor() {
|
||||
this.chains = Object.fromEntries(CONFIG.chains.map(chainConfig => {
|
||||
@@ -43,38 +47,60 @@ export class Web3Provider implements IWeb3Provider {
|
||||
chain,
|
||||
transport: http(chain.rpcUrls.default.http[0])
|
||||
})];
|
||||
}))
|
||||
}));
|
||||
this.signers = Object.fromEntries(Object.entries(this.chains).map(([chainId, chain]) => {
|
||||
const account = privateKeyToAccount(getSignerPrivateKey(Number(chainId)) as `0x${string}`);
|
||||
return [
|
||||
Number(chainId),
|
||||
createWalletClient({
|
||||
account,
|
||||
chain,
|
||||
transport: http(chain.rpcUrls.default.http[0])
|
||||
})];
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
client(chainId: number): PublicClient {
|
||||
const client = this.clients[chainId];
|
||||
if (client === undefined) {
|
||||
throw Error(`Web3ProviderError::UnsupportedChainId(${chainId})`)
|
||||
throw Error(`Web3ProviderError::UnsupportedChainId(${chainId})`);
|
||||
}
|
||||
else return client
|
||||
else return client;
|
||||
}
|
||||
|
||||
signer(chainId: number): WalletClient {
|
||||
const signer = this.signers[chainId];
|
||||
if (signer === undefined) {
|
||||
throw Error(`Web3ProviderError::UnsupportedChainId(${chainId})`);
|
||||
}
|
||||
else return signer;
|
||||
}
|
||||
|
||||
async getGasPrice(chainId: number): Promise<bigint> {
|
||||
return await this.client(chainId).getGasPrice()
|
||||
return await this.client(chainId).getGasPrice();
|
||||
}
|
||||
|
||||
async signRelayerCommitment(chainId: number, commitment: Omit<FeeCommitment, 'signedRelayerCommitment'>) {
|
||||
const signer = privateKeyToAccount(getSignerPrivateKey(chainId) as Hex);
|
||||
const { withdrawalData, expiration } = commitment;
|
||||
const { withdrawalData, expiration, extraGas, amount, asset } = commitment;
|
||||
return signer.signTypedData({
|
||||
domain: domain(chainId),
|
||||
types: RelayerCommitmentTypes,
|
||||
primaryType: 'RelayerCommitment',
|
||||
message: {
|
||||
withdrawalData,
|
||||
asset,
|
||||
amount,
|
||||
extraGas,
|
||||
expiration: BigInt(expiration)
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
async verifyRelayerCommitment(chainId: number, commitment: FeeCommitment): Promise<boolean> {
|
||||
const signer = privateKeyToAccount(getSignerPrivateKey(chainId) as Hex);
|
||||
const { withdrawalData, expiration, signedRelayerCommitment } = commitment;
|
||||
const { withdrawalData, asset, expiration, amount, extraGas, signedRelayerCommitment } = commitment;
|
||||
return verifyTypedData({
|
||||
address: signer.address,
|
||||
domain: domain(chainId),
|
||||
@@ -82,10 +108,13 @@ export class Web3Provider implements IWeb3Provider {
|
||||
primaryType: 'RelayerCommitment',
|
||||
message: {
|
||||
withdrawalData,
|
||||
asset,
|
||||
amount,
|
||||
extraGas,
|
||||
expiration: BigInt(expiration)
|
||||
},
|
||||
signature: signedRelayerCommitment
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ const quoteSchema: JSONSchemaType<QuotetBody> = {
|
||||
amount: { type: ["string"] },
|
||||
asset: { type: ["string"] },
|
||||
recipient: { type: ["string"], nullable: true },
|
||||
extraGas: { type: "boolean" }
|
||||
},
|
||||
required: ["chainId", "amount", "asset"],
|
||||
} as const;
|
||||
|
||||
@@ -1,59 +1,56 @@
|
||||
import { Ajv, JSONSchemaType } from "ajv";
|
||||
import { RelayRequestBody } from "../../interfaces/relayer/request.js";
|
||||
import { getAddress } from "viem";
|
||||
import { z } from "zod";
|
||||
|
||||
// AJV schema for validation
|
||||
const ajv = new Ajv();
|
||||
const zNonNegativeBigInt = z
|
||||
.string()
|
||||
.or(z.number())
|
||||
.pipe(z.coerce.bigint().nonnegative());
|
||||
|
||||
const relayRequestSchema: JSONSchemaType<RelayRequestBody> = {
|
||||
type: "object",
|
||||
properties: {
|
||||
withdrawal: {
|
||||
type: "object",
|
||||
properties: {
|
||||
processooor: { type: "string" },
|
||||
data: { type: "string", pattern: "0x[0-9a-fA-F]+" },
|
||||
},
|
||||
required: ["processooor", "data"],
|
||||
},
|
||||
publicSignals: {
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
minItems: 8,
|
||||
maxItems: 8,
|
||||
},
|
||||
proof: {
|
||||
type: "object",
|
||||
properties: {
|
||||
protocol: { type: "string" },
|
||||
curve: { type: "string" },
|
||||
pi_a: { type: "array", items: { type: "string" }, minItems: 1 },
|
||||
pi_b: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
minItems: 1,
|
||||
},
|
||||
minItems: 1,
|
||||
},
|
||||
pi_c: { type: "array", items: { type: "string" }, minItems: 1 },
|
||||
},
|
||||
required: ["pi_a", "pi_b", "pi_c"],
|
||||
},
|
||||
scope: { type: "string" },
|
||||
chainId: { type: ["string", "number"] },
|
||||
feeCommitment: {
|
||||
type: "object",
|
||||
properties: {
|
||||
expiration: { type: "number" },
|
||||
withdrawalData: { type: "string", pattern: "0x[0-9a-fA-F]+" },
|
||||
signedRelayerCommitment: { type: "string", pattern: "0x[0-9a-fA-F]+" }
|
||||
},
|
||||
nullable: true,
|
||||
required: ["expiration", "signedRelayerCommitment"]
|
||||
}
|
||||
},
|
||||
required: ["withdrawal", "proof", "publicSignals", "scope", "chainId"],
|
||||
} as const;
|
||||
// Address validation schema
|
||||
export const zAddress = z
|
||||
.string()
|
||||
.regex(/^0x[0-9a-fA-F]+/)
|
||||
.length(42)
|
||||
.transform((v) => getAddress(v));
|
||||
|
||||
export const validateRelayRequestBody = ajv.compile(relayRequestSchema);
|
||||
export const zHex = z
|
||||
.string()
|
||||
.regex(/^0x[0-9a-fA-F]+/)
|
||||
.transform(x => x as `0x${string}`);
|
||||
|
||||
export const zWithdrawal = z.object({
|
||||
processooor: zAddress,
|
||||
data: zHex
|
||||
});
|
||||
|
||||
export const zProof = z.object({
|
||||
protocol: z.string().optional(),
|
||||
curve: z.string().optional(),
|
||||
pi_a: z.tuple([z.string(), z.string(), z.string()]),
|
||||
pi_b: z.tuple([
|
||||
z.tuple([z.string(), z.string()]),
|
||||
z.tuple([z.string(), z.string()]),
|
||||
z.tuple([z.string(), z.string()]),
|
||||
]),
|
||||
pi_c: z.tuple([z.string(), z.string(), z.string()]),
|
||||
});
|
||||
|
||||
export const zFeeCommitment = z.object({
|
||||
expiration: z.number().nonnegative().int(),
|
||||
withdrawalData: zHex,
|
||||
asset: zAddress,
|
||||
signedRelayerCommitment: zHex,
|
||||
extraGas: z.boolean(),
|
||||
amount: zNonNegativeBigInt
|
||||
});
|
||||
|
||||
export const zRelayRequest = z.object({
|
||||
withdrawal: zWithdrawal,
|
||||
publicSignals: z.array(z.string()).length(8),
|
||||
proof: zProof,
|
||||
scope: zNonNegativeBigInt,
|
||||
chainId: z.string().or(z.number()).pipe(z.coerce.number().positive()),
|
||||
feeCommitment: zFeeCommitment.optional()
|
||||
})
|
||||
.strict()
|
||||
.readonly();
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Handles withdrawal requests within the Privacy Pool relayer.
|
||||
*/
|
||||
import { getAddress } from "viem";
|
||||
import { Address, getAddress } from "viem";
|
||||
import {
|
||||
getAssetConfig,
|
||||
getEntrypointAddress,
|
||||
getFeeReceiverAddress
|
||||
getFeeReceiverAddress,
|
||||
getSignerPrivateKey
|
||||
} from "../config/index.js";
|
||||
import {
|
||||
BlockchainError,
|
||||
@@ -17,13 +18,17 @@ import {
|
||||
RelayerResponse,
|
||||
WithdrawalPayload,
|
||||
} from "../interfaces/relayer/request.js";
|
||||
import { db, SdkProvider, web3Provider } from "../providers/index.js";
|
||||
import { db, SdkProvider, UniswapProvider, web3Provider } from "../providers/index.js";
|
||||
import { RelayerDatabase } from "../types/db.types.js";
|
||||
import { SdkProviderInterface } from "../types/sdk.types.js";
|
||||
import { decodeWithdrawalData, isViemError, parseSignals } from "../utils.js";
|
||||
import { decodeWithdrawalData, isFeeReceiverSameAsSigner, isNative, isViemError, parseSignals } from "../utils.js";
|
||||
import { quoteService } from "./index.js";
|
||||
import { Web3Provider } from "../providers/web3.provider.js";
|
||||
import { FeeCommitment } from "../interfaces/relayer/common.js";
|
||||
import { uniswapProvider } from "../providers/index.js";
|
||||
import { WRAPPED_NATIVE_TOKEN_ADDRESS } from "../providers/uniswap/constants.js";
|
||||
import { Withdrawal, WithdrawalProof } from "@0xbow/privacy-pools-core-sdk";
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
|
||||
/**
|
||||
* Class representing the Privacy Pool Relayer, responsible for processing withdrawal requests.
|
||||
@@ -35,6 +40,7 @@ export class PrivacyPoolRelayer {
|
||||
protected sdkProvider: SdkProviderInterface;
|
||||
/** Web3 provider for handling blockchain interactions. */
|
||||
protected web3Provider: Web3Provider;
|
||||
protected uniswapProvider: UniswapProvider;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the Privacy Pool Relayer.
|
||||
@@ -43,6 +49,7 @@ export class PrivacyPoolRelayer {
|
||||
this.db = db;
|
||||
this.sdkProvider = new SdkProvider();
|
||||
this.web3Provider = web3Provider;
|
||||
this.uniswapProvider = uniswapProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,17 +67,33 @@ export class PrivacyPoolRelayer {
|
||||
await this.db.createNewRequest(requestId, timestamp, req);
|
||||
await this.validateWithdrawal(req, chainId);
|
||||
|
||||
const extraGas = req.feeCommitment?.extraGas ?? false;
|
||||
|
||||
const isValidWithdrawalProof = await this.verifyProof(req.proof);
|
||||
if (!isValidWithdrawalProof) {
|
||||
throw ZkError.invalidProof();
|
||||
}
|
||||
|
||||
// We do early check, before relaying
|
||||
if (extraGas) {
|
||||
if (!WRAPPED_NATIVE_TOKEN_ADDRESS[chainId])
|
||||
throw RelayerError.unknown(`Missing wrapped native token for chain ${chainId}`);
|
||||
}
|
||||
|
||||
const response = await this.broadcastWithdrawal(req, chainId);
|
||||
// const response = { hash: "0x" }
|
||||
|
||||
let txSwap;
|
||||
if (extraGas) {
|
||||
txSwap = await this.swapForNativeAndFund(req.scope, req.withdrawal, req.proof, chainId, response.hash);
|
||||
}
|
||||
|
||||
await this.db.updateBroadcastedRequest(requestId, response.hash);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
txHash: response.hash,
|
||||
txSwap,
|
||||
timestamp,
|
||||
requestId,
|
||||
};
|
||||
@@ -116,6 +139,42 @@ export class PrivacyPoolRelayer {
|
||||
}
|
||||
}
|
||||
|
||||
async swapForNativeAndFund(scope: bigint, withdrawal: Withdrawal, proof: WithdrawalProof, chainId: number, relayTx: string) {
|
||||
|
||||
const { assetAddress } = await this.sdkProvider.scopeData(scope, chainId);
|
||||
if (isNative(assetAddress)) {
|
||||
// we shouldn't be here
|
||||
return;
|
||||
}
|
||||
|
||||
const relayReceipt = await web3Provider.client(chainId).waitForTransactionReceipt({ hash: relayTx as `0x${string}` });
|
||||
const { gasUsed: relayGasUsed, effectiveGasPrice: relayGasPrice } = relayReceipt;
|
||||
|
||||
const assetConfig = getAssetConfig(chainId, assetAddress);
|
||||
const feeReceiver = getFeeReceiverAddress(chainId) as Address;
|
||||
const { recipient, relayFeeBPS } = decodeWithdrawalData(withdrawal.data);
|
||||
const withdrawnValue = parseSignals(proof.publicSignals).withdrawnValue;
|
||||
const gasPrice = await web3Provider.getGasPrice(chainId);
|
||||
|
||||
const feeGross = withdrawnValue * relayFeeBPS / 10_000n;
|
||||
const feeBase = withdrawnValue * assetConfig.fee_bps / 10_000n;
|
||||
|
||||
const relayerGasRefundValue = gasPrice * quoteService.extraGasTxCost + relayGasPrice * relayGasUsed;
|
||||
|
||||
const txHash = await this.uniswapProvider.swapExactInputForWeth({
|
||||
chainId,
|
||||
feeGross,
|
||||
feeBase,
|
||||
refundAmount: relayerGasRefundValue,
|
||||
tokenIn: assetAddress,
|
||||
nativeRecipient: recipient,
|
||||
feeReceiver
|
||||
});
|
||||
|
||||
return txHash;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a withdrawal proof.
|
||||
*
|
||||
@@ -138,15 +197,15 @@ export class PrivacyPoolRelayer {
|
||||
protected async broadcastWithdrawal(
|
||||
withdrawal: WithdrawalPayload,
|
||||
chainId: number,
|
||||
): Promise<{ hash: string }> {
|
||||
): Promise<{ hash: string; }> {
|
||||
try {
|
||||
return await this.sdkProvider.broadcastWithdrawal(withdrawal, chainId);
|
||||
} catch (error) {
|
||||
if (isViemError(error)) {
|
||||
const { metaMessages, shortMessage } = error;
|
||||
throw BlockchainError.txError((metaMessages ? metaMessages[0] : undefined) || shortMessage)
|
||||
throw BlockchainError.txError((metaMessages ? metaMessages[0] : undefined) || shortMessage);
|
||||
} else {
|
||||
throw RelayerError.unknown("Something went wrong while broadcasting Tx")
|
||||
throw RelayerError.unknown("Something went wrong while broadcasting Tx");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,26 +221,49 @@ export class PrivacyPoolRelayer {
|
||||
protected async validateWithdrawal(wp: WithdrawalPayload, chainId: number) {
|
||||
const entrypointAddress = getEntrypointAddress(chainId);
|
||||
const feeReceiverAddress = getFeeReceiverAddress(chainId);
|
||||
const signerAddress = privateKeyToAccount(getSignerPrivateKey(chainId) as `0x${string}`).address;
|
||||
|
||||
const { feeRecipient, relayFeeBPS } = decodeWithdrawalData(
|
||||
wp.withdrawal.data,
|
||||
);
|
||||
const extraGas = wp.feeCommitment?.extraGas ?? false;
|
||||
|
||||
// If there's a fee commitment, then we use it's withdrawalData as source of truth to check against the proof.
|
||||
const withdrawalData = wp.feeCommitment ? wp.feeCommitment.withdrawalData : wp.withdrawal.data;
|
||||
if ((wp.feeCommitment !== undefined) && (wp.feeCommitment.withdrawalData !== wp.withdrawal.data)) {
|
||||
throw WithdrawalValidationError.relayerCommitmentRejected(
|
||||
`Signed commitment does not match withdrawal data, exiting early: commitment data ${wp.feeCommitment.withdrawalData}, request data ${wp.withdrawal.data}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { feeRecipient, relayFeeBPS } = decodeWithdrawalData(withdrawalData);
|
||||
const proofSignals = parseSignals(wp.proof.publicSignals);
|
||||
|
||||
if ((wp.feeCommitment !== undefined) && (wp.feeCommitment.amount > proofSignals.withdrawnValue)) {
|
||||
throw WithdrawalValidationError.withdrawnValueTooSmall(
|
||||
`WithdrawnValue too small: expected "${wp.feeCommitment.amount}", got "${proofSignals.withdrawnValue}".`,
|
||||
);
|
||||
}
|
||||
|
||||
if (wp.withdrawal.processooor !== entrypointAddress) {
|
||||
throw WithdrawalValidationError.processooorMismatch(
|
||||
`Processooor mismatch: expected "${entrypointAddress}", got "${wp.withdrawal.processooor}".`,
|
||||
);
|
||||
}
|
||||
|
||||
if (getAddress(feeRecipient) !== feeReceiverAddress) {
|
||||
throw WithdrawalValidationError.feeReceiverMismatch(
|
||||
`Fee recipient mismatch: expected "${feeReceiverAddress}", got "${feeRecipient}".`,
|
||||
);
|
||||
if (extraGas && !isFeeReceiverSameAsSigner(chainId)) {
|
||||
if (getAddress(feeRecipient) !== getAddress(signerAddress)) {
|
||||
throw WithdrawalValidationError.feeReceiverMismatch(
|
||||
`Fee recipient with extraGas mismatch: expected "${signerAddress}", got "${feeRecipient}".`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (getAddress(feeRecipient) !== feeReceiverAddress) {
|
||||
throw WithdrawalValidationError.feeReceiverMismatch(
|
||||
`Fee recipient mismatch: expected "${feeReceiverAddress}", got "${feeRecipient}".`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const withdrawalContext = BigInt(
|
||||
this.sdkProvider.calculateContext(wp.withdrawal, wp.scope),
|
||||
this.sdkProvider.calculateContext({ processooor: wp.withdrawal.processooor, data: withdrawalData }, wp.scope),
|
||||
);
|
||||
if (proofSignals.context !== withdrawalContext) {
|
||||
throw WithdrawalValidationError.contextMismatch(
|
||||
@@ -202,6 +284,20 @@ export class PrivacyPoolRelayer {
|
||||
|
||||
if (wp.feeCommitment) {
|
||||
|
||||
if (wp.feeCommitment.asset != assetAddress) {
|
||||
throw WithdrawalValidationError.relayerCommitmentRejected(
|
||||
`Asset in commitment does not match withdrawal scope asset: expected ${wp.feeCommitment.asset}, received ${assetAddress}`,
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: remove this check beacuse we should already have errored out at the begining
|
||||
const { relayFeeBPS: commitmentRelayFeeBPS } = decodeWithdrawalData(wp.feeCommitment.withdrawalData);
|
||||
if (relayFeeBPS !== commitmentRelayFeeBPS) {
|
||||
throw WithdrawalValidationError.relayerCommitmentRejected(
|
||||
`Proof relay fee does not match signed commitment: pi:=${relayFeeBPS}, commitment:=${commitmentRelayFeeBPS}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (commitmentExpired(wp.feeCommitment)) {
|
||||
throw WithdrawalValidationError.relayerCommitmentRejected(
|
||||
`Relay fee commitment expired, please quote again`,
|
||||
@@ -217,10 +313,14 @@ export class PrivacyPoolRelayer {
|
||||
} else {
|
||||
|
||||
const currentFeeBPS = await quoteService.quoteFeeBPSNative({
|
||||
chainId, amountIn: proofSignals.withdrawnValue, assetAddress, baseFeeBPS: assetConfig.fee_bps, value: 0n
|
||||
chainId,
|
||||
amountIn: proofSignals.withdrawnValue,
|
||||
assetAddress,
|
||||
baseFeeBPS: assetConfig.fee_bps,
|
||||
extraGas
|
||||
});
|
||||
|
||||
if (relayFeeBPS < currentFeeBPS) {
|
||||
if (relayFeeBPS < currentFeeBPS.feeBPS) {
|
||||
throw WithdrawalValidationError.feeTooLow(
|
||||
`Relay fee too low: expected at least "${currentFeeBPS}", got "${relayFeeBPS}".`,
|
||||
);
|
||||
@@ -239,9 +339,9 @@ export class PrivacyPoolRelayer {
|
||||
}
|
||||
|
||||
function commitmentExpired(feeCommitment: FeeCommitment): boolean {
|
||||
return feeCommitment.expiration < Number(new Date())
|
||||
return feeCommitment.expiration < Number(new Date());
|
||||
}
|
||||
|
||||
async function validFeeCommitment(chainId: number, feeCommitment: FeeCommitment): Promise<boolean> {
|
||||
return web3Provider.verifyRelayerCommitment(chainId, feeCommitment)
|
||||
return web3Provider.verifyRelayerCommitment(chainId, feeCommitment);
|
||||
}
|
||||
|
||||
@@ -5,39 +5,66 @@ interface QuoteFeeBPSParams {
|
||||
chainId: number,
|
||||
assetAddress: Address,
|
||||
amountIn: bigint,
|
||||
value: bigint,
|
||||
baseFeeBPS: bigint
|
||||
baseFeeBPS: bigint,
|
||||
extraGas: boolean;
|
||||
};
|
||||
|
||||
const NativeAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
|
||||
export interface QuoteFee {
|
||||
feeBPS: bigint;
|
||||
path: (string | number)[];
|
||||
gasPrice: bigint;
|
||||
relayTxCost: bigint;
|
||||
extraGasTxCost?: bigint;
|
||||
extraGasFundAmount?: bigint;
|
||||
};
|
||||
|
||||
export class QuoteService {
|
||||
|
||||
readonly txCost: bigint;
|
||||
readonly relayTxCost: bigint;
|
||||
readonly extraGasTxCost: bigint;
|
||||
readonly extraGasFundAmount: bigint;
|
||||
|
||||
constructor() {
|
||||
// a typical withdrawal costs between 450k-650k gas
|
||||
this.txCost = 700_000n;
|
||||
this.relayTxCost = 650_000n;
|
||||
// approximate value of a uniswap Router call. Can vary greatly if doing multi-hop swaps.
|
||||
this.extraGasTxCost = 320_000n;
|
||||
// this gas will be transformed into equivalent native units at the time of the fund swap.
|
||||
this.extraGasFundAmount = 600_000n;
|
||||
}
|
||||
|
||||
async netFeeBPSNative(baseFee: bigint, balance: bigint, nativeQuote: { num: bigint, den: bigint }, gasPrice: bigint, value: bigint): Promise<bigint> {
|
||||
const nativeCosts = (1n * gasPrice * this.txCost + value)
|
||||
async netFeeBPSNative(baseFee: bigint, balance: bigint, nativeQuote: { num: bigint, den: bigint; }, gasPrice: bigint, extraGasUnits: bigint): Promise<bigint> {
|
||||
const totalGasUnits = this.relayTxCost + extraGasUnits;
|
||||
const nativeCosts = (1n * gasPrice * totalGasUnits);
|
||||
return baseFee + nativeQuote.den * 10_000n * nativeCosts / balance / nativeQuote.num;
|
||||
}
|
||||
|
||||
async quoteFeeBPSNative(quoteParams: QuoteFeeBPSParams): Promise<bigint> {
|
||||
const { chainId, assetAddress, amountIn, baseFeeBPS, value } = quoteParams;
|
||||
async quoteFeeBPSNative(quoteParams: QuoteFeeBPSParams): Promise<QuoteFee> {
|
||||
const { chainId, assetAddress, amountIn, baseFeeBPS, extraGas } = quoteParams;
|
||||
const gasPrice = await web3Provider.getGasPrice(chainId);
|
||||
|
||||
let quote: { num: bigint, den: bigint };
|
||||
const EXTRA_GAS_AMOUNT = this.extraGasTxCost + this.extraGasFundAmount;
|
||||
const extraGasUnits = extraGas ? EXTRA_GAS_AMOUNT : 0n;
|
||||
const extraGasDetail = extraGas ? { extraGasTxCost: this.extraGasTxCost, extraGasFundAmount: this.extraGasFundAmount } : undefined;
|
||||
|
||||
let quote: { num: bigint, den: bigint; path: (string | number)[]; };
|
||||
if (assetAddress.toLowerCase() === NativeAddress.toLowerCase()) {
|
||||
quote = { num: 1n, den: 1n };
|
||||
quote = { num: 1n, den: 1n, path: [] };
|
||||
} else {
|
||||
quote = await quoteProvider.quoteNativeTokenInERC20(chainId, assetAddress, amountIn);
|
||||
}
|
||||
|
||||
const feeBPS = await this.netFeeBPSNative(baseFeeBPS, amountIn, quote, gasPrice, value);
|
||||
return feeBPS
|
||||
const feeBPS = await this.netFeeBPSNative(baseFeeBPS, amountIn, quote, gasPrice, extraGasUnits);
|
||||
|
||||
return {
|
||||
feeBPS,
|
||||
gasPrice,
|
||||
relayTxCost: this.relayTxCost,
|
||||
...extraGasDetail,
|
||||
path: quote.path
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Address } from "viem/accounts";
|
||||
import { RelayerResponse } from "./interfaces/relayer/request.js";
|
||||
import { QuoteResponse } from "./interfaces/relayer/quote.js";
|
||||
import { FeeCommitment } from "./interfaces/relayer/common.js";
|
||||
|
||||
export abstract class RelayerMarshall {
|
||||
abstract toJSON(): object;
|
||||
@@ -52,19 +53,26 @@ export class QuoteMarshall extends RelayerMarshall {
|
||||
super();
|
||||
}
|
||||
|
||||
addFeeCommitment(feeCommitment: {
|
||||
expiration: number
|
||||
withdrawalData: `0x${string}`,
|
||||
signedRelayerCommitment: `0x${string}`
|
||||
}) {
|
||||
this.response.feeCommitment = feeCommitment;
|
||||
addFeeCommitment(feeCommitment: FeeCommitment) {
|
||||
this.response.feeCommitment = {
|
||||
...feeCommitment,
|
||||
amount: feeCommitment.amount.toString()
|
||||
};
|
||||
}
|
||||
|
||||
override toJSON(): object {
|
||||
const detail = Object.fromEntries(
|
||||
Object.entries(this.response.detail)
|
||||
.map(([k, v]) => {
|
||||
return [k, v ? { gas: v.gas.toString(), eth: v.eth.toString() } : undefined];
|
||||
})
|
||||
);
|
||||
return {
|
||||
baseFeeBPS: this.response.baseFeeBPS.toString(),
|
||||
feeBPS: this.response.feeBPS.toString(),
|
||||
feeCommitment: this.response.feeCommitment
|
||||
}
|
||||
gasPrice: this.response.gasPrice.toString(),
|
||||
feeCommitment: this.response.feeCommitment,
|
||||
detail,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,13 @@ import {
|
||||
WithdrawPublicSignals,
|
||||
} from "./interfaces/relayer/request.js";
|
||||
import { FeeDataAbi } from "./types/abi.types.js";
|
||||
import { getFeeReceiverAddress, getSignerPrivateKey } from "./config/index.js";
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
|
||||
interface WithdrawalData {
|
||||
recipient: Address,
|
||||
feeRecipient: Address,
|
||||
relayFeeBPS: bigint
|
||||
relayFeeBPS: bigint;
|
||||
}
|
||||
|
||||
export function decodeWithdrawalData(data: `0x${string}`): WithdrawalData {
|
||||
@@ -42,7 +44,7 @@ export function decodeWithdrawalData(data: `0x${string}`): WithdrawalData {
|
||||
|
||||
export function encodeWithdrawalData(withdrawalData: WithdrawalData): `0x${string}` {
|
||||
try {
|
||||
return encodeAbiParameters(FeeDataAbi, [withdrawalData])
|
||||
return encodeAbiParameters(FeeDataAbi, [withdrawalData]);
|
||||
} catch (e) {
|
||||
const error = e as EncodeAbiParametersErrorType;
|
||||
throw WithdrawalValidationError.invalidWithdrawalAbi({
|
||||
@@ -86,7 +88,7 @@ export function createChainObject(chainConfig: {
|
||||
chain_id: number;
|
||||
chain_name: string;
|
||||
rpc_url: string;
|
||||
native_currency?: { name: string; symbol: string; decimals: number };
|
||||
native_currency?: { name: string; symbol: string; decimals: number; };
|
||||
}): Chain {
|
||||
return {
|
||||
id: chainConfig.chain_id,
|
||||
@@ -107,6 +109,16 @@ export function isViemError(error: unknown): error is ViemError {
|
||||
const viemErrorNames = [
|
||||
ContractFunctionExecutionError.prototype.constructor.name,
|
||||
ContractFunctionRevertedError.prototype.constructor.name,
|
||||
]
|
||||
];
|
||||
return viemErrorNames.includes(error?.constructor?.name || "");
|
||||
}
|
||||
|
||||
export function isFeeReceiverSameAsSigner(chainId: number) {
|
||||
const feeReceiverAddress = getFeeReceiverAddress(chainId);
|
||||
const signerAddress = privateKeyToAccount(getSignerPrivateKey(chainId) as `0x${string}`).address;
|
||||
return feeReceiverAddress.toLowerCase() === signerAddress.toLowerCase();
|
||||
}
|
||||
|
||||
export function isNative(asset: `0x${string}`) {
|
||||
return asset.toLowerCase() === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
|
||||
}
|
||||
|
||||
@@ -4,15 +4,18 @@
|
||||
"main": "index.js",
|
||||
"license": "Apache-2.0",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"viem": "2.22.14"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -p ./tsconfig.json",
|
||||
"tree-cache": "node ./dist/main.js tree --fromBlock $(echo $(cast bn) - 50 | bc) --output ./tree-cache",
|
||||
"main": "node dist/main.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": "1.2.8",
|
||||
"viem": "2.22.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xbow/privacy-pools-core-sdk": "0.1.5",
|
||||
"@types/minimist": "1.2.5",
|
||||
"@0xbow/privacy-pools-core-sdk": "0.1.21",
|
||||
"@types/node": "^22.13.0",
|
||||
"typescript": "5.5.4"
|
||||
}
|
||||
|
||||
185
packages/relayer/test/integration/relay/src/abis/ERC20.abi.ts
Normal file
185
packages/relayer/test/integration/relay/src/abis/ERC20.abi.ts
Normal file
@@ -0,0 +1,185 @@
|
||||
export const abi = [
|
||||
{
|
||||
"type": "function",
|
||||
"name": "allowance",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "owner",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "spender",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "approve",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "spender",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool",
|
||||
"internalType": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "balanceOf",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "account",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "totalSupply",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "transfer",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "to",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool",
|
||||
"internalType": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "transferFrom",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "from",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "to",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool",
|
||||
"internalType": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "Approval",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "owner",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "spender",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "Transfer",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "from",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "to",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
}
|
||||
] as const;
|
||||
@@ -0,0 +1,681 @@
|
||||
export const abi = [
|
||||
{
|
||||
"type": "function",
|
||||
"name": "assetConfig",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"internalType": "contract IERC20"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPrivacyPool"
|
||||
},
|
||||
{
|
||||
"name": "_minimumDepositAmount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_vettingFeeBPS",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_maxRelayFeeBPS",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "associationSets",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_index",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_root",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_ipfsCID",
|
||||
"type": "string",
|
||||
"internalType": "string"
|
||||
},
|
||||
{
|
||||
"name": "_timestamp",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "deposit",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"internalType": "contract IERC20"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_precommitment",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_commitment",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "deposit",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_precommitment",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_commitment",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "payable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "initialize",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "_postman",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "latestRoot",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_root",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "registerPool",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"internalType": "contract IERC20"
|
||||
},
|
||||
{
|
||||
"name": "_pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPrivacyPool"
|
||||
},
|
||||
{
|
||||
"name": "_minimumDepositAmount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_vettingFeeBPS",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_maxRelayFeeBPS",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "relay",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_withdrawal",
|
||||
"type": "tuple",
|
||||
"internalType": "struct IPrivacyPool.Withdrawal",
|
||||
"components": [
|
||||
{
|
||||
"name": "processooor",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "data",
|
||||
"type": "bytes",
|
||||
"internalType": "bytes"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "_proof",
|
||||
"type": "tuple",
|
||||
"internalType": "struct ProofLib.WithdrawProof",
|
||||
"components": [
|
||||
{
|
||||
"name": "pA",
|
||||
"type": "uint256[2]",
|
||||
"internalType": "uint256[2]"
|
||||
},
|
||||
{
|
||||
"name": "pB",
|
||||
"type": "uint256[2][2]",
|
||||
"internalType": "uint256[2][2]"
|
||||
},
|
||||
{
|
||||
"name": "pC",
|
||||
"type": "uint256[2]",
|
||||
"internalType": "uint256[2]"
|
||||
},
|
||||
{
|
||||
"name": "pubSignals",
|
||||
"type": "uint256[8]",
|
||||
"internalType": "uint256[8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "_scope",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "removePool",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"internalType": "contract IERC20"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "rootByIndex",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_index",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_root",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "scopeToPool",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_scope",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPrivacyPool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "updatePoolConfiguration",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"internalType": "contract IERC20"
|
||||
},
|
||||
{
|
||||
"name": "_minimumDepositAmount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_vettingFeeBPS",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_maxRelayFeeBPS",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "updateRoot",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_root",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_ipfsCID",
|
||||
"type": "string",
|
||||
"internalType": "string"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_index",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "windDownPool",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPrivacyPool"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "withdrawFees",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"internalType": "contract IERC20"
|
||||
},
|
||||
{
|
||||
"name": "_recipient",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "Deposited",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_depositor",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "_pool",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "contract IPrivacyPool"
|
||||
},
|
||||
{
|
||||
"name": "_commitment",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_amount",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "FeesWithdrawn",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"indexed": false,
|
||||
"internalType": "contract IERC20"
|
||||
},
|
||||
{
|
||||
"name": "_recipient",
|
||||
"type": "address",
|
||||
"indexed": false,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amount",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "PoolConfigurationUpdated",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_pool",
|
||||
"type": "address",
|
||||
"indexed": false,
|
||||
"internalType": "contract IPrivacyPool"
|
||||
},
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"indexed": false,
|
||||
"internalType": "contract IERC20"
|
||||
},
|
||||
{
|
||||
"name": "_newMinimumDepositAmount",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_newVettingFeeBPS",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_newMaxRelayFeeBPS",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "PoolRegistered",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_pool",
|
||||
"type": "address",
|
||||
"indexed": false,
|
||||
"internalType": "contract IPrivacyPool"
|
||||
},
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"indexed": false,
|
||||
"internalType": "contract IERC20"
|
||||
},
|
||||
{
|
||||
"name": "_scope",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "PoolRemoved",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_pool",
|
||||
"type": "address",
|
||||
"indexed": false,
|
||||
"internalType": "contract IPrivacyPool"
|
||||
},
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"indexed": false,
|
||||
"internalType": "contract IERC20"
|
||||
},
|
||||
{
|
||||
"name": "_scope",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "PoolWindDown",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_pool",
|
||||
"type": "address",
|
||||
"indexed": false,
|
||||
"internalType": "contract IPrivacyPool"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "RootUpdated",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_root",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_ipfsCID",
|
||||
"type": "string",
|
||||
"indexed": false,
|
||||
"internalType": "string"
|
||||
},
|
||||
{
|
||||
"name": "_timestamp",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "WithdrawalRelayed",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_relayer",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "_recipient",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "contract IERC20"
|
||||
},
|
||||
{
|
||||
"name": "_amount",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_feeAmount",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "AssetMismatch",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "AssetPoolAlreadyRegistered",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "EmptyRoot",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidEntrypointForPool",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidFeeBPS",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidIPFSCIDLength",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidIndex",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidPoolState",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidProcessooor",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidWithdrawalAmount",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "MinimumDepositAmount",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "NativeAssetNotAccepted",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "NativeAssetTransferFailed",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "NoRootsAvailable",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "PoolIsDead",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "PoolNotFound",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "RelayFeeGreaterThanMax",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "ScopePoolAlreadyRegistered",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "ZeroAddress",
|
||||
"inputs": []
|
||||
}
|
||||
] as const;
|
||||
561
packages/relayer/test/integration/relay/src/abis/Pool.abi.ts
Normal file
561
packages/relayer/test/integration/relay/src/abis/Pool.abi.ts
Normal file
@@ -0,0 +1,561 @@
|
||||
export const abi = [
|
||||
{
|
||||
"type": "function",
|
||||
"name": "ASSET",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_asset",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "ENTRYPOINT",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_entrypoint",
|
||||
"type": "address",
|
||||
"internalType": "contract IEntrypoint"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "MAX_TREE_DEPTH",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_maxDepth",
|
||||
"type": "uint32",
|
||||
"internalType": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "RAGEQUIT_VERIFIER",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_verifier",
|
||||
"type": "address",
|
||||
"internalType": "contract IVerifier"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "ROOT_HISTORY_SIZE",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_size",
|
||||
"type": "uint32",
|
||||
"internalType": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "SCOPE",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_scope",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "WITHDRAWAL_VERIFIER",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_verifier",
|
||||
"type": "address",
|
||||
"internalType": "contract IVerifier"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "currentRoot",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_root",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "currentRootIndex",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_index",
|
||||
"type": "uint32",
|
||||
"internalType": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "currentTreeDepth",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_depth",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "currentTreeSize",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_size",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "dead",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_dead",
|
||||
"type": "bool",
|
||||
"internalType": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "deposit",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_depositor",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_precommitment",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_commitment",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "payable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "depositors",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_label",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_depositor",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "nonce",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_nonce",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "nullifierHashes",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_nullifierHash",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_spent",
|
||||
"type": "bool",
|
||||
"internalType": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "ragequit",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_p",
|
||||
"type": "tuple",
|
||||
"internalType": "struct ProofLib.RagequitProof",
|
||||
"components": [
|
||||
{
|
||||
"name": "pA",
|
||||
"type": "uint256[2]",
|
||||
"internalType": "uint256[2]"
|
||||
},
|
||||
{
|
||||
"name": "pB",
|
||||
"type": "uint256[2][2]",
|
||||
"internalType": "uint256[2][2]"
|
||||
},
|
||||
{
|
||||
"name": "pC",
|
||||
"type": "uint256[2]",
|
||||
"internalType": "uint256[2]"
|
||||
},
|
||||
{
|
||||
"name": "pubSignals",
|
||||
"type": "uint256[4]",
|
||||
"internalType": "uint256[4]"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "roots",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_index",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_root",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "windDown",
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "withdraw",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_w",
|
||||
"type": "tuple",
|
||||
"internalType": "struct IPrivacyPool.Withdrawal",
|
||||
"components": [
|
||||
{
|
||||
"name": "processooor",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "data",
|
||||
"type": "bytes",
|
||||
"internalType": "bytes"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "_p",
|
||||
"type": "tuple",
|
||||
"internalType": "struct ProofLib.WithdrawProof",
|
||||
"components": [
|
||||
{
|
||||
"name": "pA",
|
||||
"type": "uint256[2]",
|
||||
"internalType": "uint256[2]"
|
||||
},
|
||||
{
|
||||
"name": "pB",
|
||||
"type": "uint256[2][2]",
|
||||
"internalType": "uint256[2][2]"
|
||||
},
|
||||
{
|
||||
"name": "pC",
|
||||
"type": "uint256[2]",
|
||||
"internalType": "uint256[2]"
|
||||
},
|
||||
{
|
||||
"name": "pubSignals",
|
||||
"type": "uint256[8]",
|
||||
"internalType": "uint256[8]"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "Deposited",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_depositor",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "_commitment",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_label",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_precommitmentHash",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "LeafInserted",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_index",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_leaf",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_root",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "PoolDied",
|
||||
"inputs": [],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "Ragequit",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_ragequitter",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "_commitment",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_label",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "Withdrawn",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_processooor",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_spentNullifier",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_newCommitment",
|
||||
"type": "uint256",
|
||||
"indexed": false,
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "ContextMismatch",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "IncorrectASPRoot",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidCommitment",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidDepositValue",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidProcessooor",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidProof",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "InvalidTreeDepth",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "MaxTreeDepthReached",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "NotYetRagequitteable",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "NullifierAlreadySpent",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "OnlyEntrypoint",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "OnlyOriginalDepositor",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "PoolIsDead",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "ScopeMismatch",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "UnknownStateRoot",
|
||||
"inputs": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "ZeroAddress",
|
||||
"inputs": []
|
||||
}
|
||||
] as const;
|
||||
@@ -1,26 +1,26 @@
|
||||
export const ping = async () => {
|
||||
let r = await fetch("http://localhost:3000/ping", {
|
||||
const r = await fetch("http://localhost:3000/ping", {
|
||||
method: "get",
|
||||
});
|
||||
console.log(JSON.stringify(await r.text(), null, 2));
|
||||
};
|
||||
|
||||
export const details = async () => {
|
||||
let r = await fetch("http://localhost:3000/relayer/details", {
|
||||
const r = await fetch("http://localhost:3000/relayer/details", {
|
||||
method: "get",
|
||||
});
|
||||
console.log(JSON.stringify(await r.json(), null, 2));
|
||||
};
|
||||
|
||||
export const notFound = async () => {
|
||||
let r = await fetch("http://localhost:3000/HOLA", {
|
||||
const r = await fetch("http://localhost:3000/HOLA", {
|
||||
method: "get",
|
||||
});
|
||||
console.log(JSON.stringify(await r.json(), null, 2));
|
||||
};
|
||||
|
||||
export const request = async (requestBody) => {
|
||||
let r = await fetch("http://localhost:3000/relayer/request", {
|
||||
export const request = async (requestBody: object) => {
|
||||
const r = await fetch("http://localhost:3000/relayer/request", {
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -30,8 +30,18 @@ export const request = async (requestBody) => {
|
||||
console.log(JSON.stringify(await r.json(), null, 2));
|
||||
};
|
||||
|
||||
export const quote = async (quoteBody) => {
|
||||
let r = await fetch("http://localhost:3000/relayer/quote", {
|
||||
interface QuoteResponse {
|
||||
baseFeeBPS: bigint,
|
||||
feeBPS: bigint,
|
||||
feeCommitment?: {
|
||||
expiration: number,
|
||||
withdrawalData: `0x${string}`,
|
||||
signedRelayerCommitment: `0x${string}`,
|
||||
};
|
||||
}
|
||||
|
||||
export const quote = async (quoteBody: object) => {
|
||||
const r = await fetch("http://localhost:3000/relayer/quote", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
@@ -40,5 +50,5 @@ export const quote = async (quoteBody) => {
|
||||
})
|
||||
const quoteResponse = await r.json();
|
||||
console.log(JSON.stringify(quoteResponse, null, 2))
|
||||
return quoteResponse;
|
||||
return quoteResponse as QuoteResponse;
|
||||
}
|
||||
@@ -1,16 +1,86 @@
|
||||
import { createPublicClient, defineChain, getContract, http, parseAbi } from "viem";
|
||||
import { Account, createPublicClient, defineChain, getContract, GetContractReturnType, http, PublicClient } from "viem";
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
import { localhost } from "viem/chains";
|
||||
import { ETH_POOL_ADDRESS, LOCAL_ANVIL_RPC } from "./constants.js";
|
||||
import { abi as EntrypointAbi } from "./abis/Entrypoint.abi.js";
|
||||
import { abi as Erc20Abi } from "./abis/ERC20.abi.js";
|
||||
import { abi as PoolAbi } from "./abis/Pool.abi.js";
|
||||
import { ENTRYPOINT_ADDRESS, LOCAL_ANVIL_RPC } from "./constants.js";
|
||||
|
||||
export const anvilChain = defineChain({ ...localhost, id: 31337 });
|
||||
type PoolContract = GetContractReturnType<typeof PoolAbi, PublicClient, `0x${string}`>;
|
||||
|
||||
export const publicClient = createPublicClient({
|
||||
chain: anvilChain,
|
||||
transport: http(LOCAL_ANVIL_RPC),
|
||||
});
|
||||
export interface IChainContext {
|
||||
account: Account,
|
||||
chain: ReturnType<typeof defineChain>;
|
||||
client: PublicClient;
|
||||
entrypoint: GetContractReturnType<typeof EntrypointAbi, PublicClient, `0x${string}`>,
|
||||
getPoolContract: (asset: `0x${string}`) => Promise<PoolContract>;
|
||||
getPoolContractByScope: (scope: bigint) => PoolContract;
|
||||
getErc20Contract: (asset: `0x${string}`) => GetContractReturnType<typeof Erc20Abi, PublicClient, `0x${string}`>;
|
||||
}
|
||||
|
||||
export function ChainContext(chainId: number, privateKey: `0x${string}`): IChainContext {
|
||||
|
||||
const _poolCacheByAsset: { [key: `0x${string}`]: PoolContract; } = {};
|
||||
const _poolCacheByScope: { [key: string]: PoolContract; } = {};
|
||||
|
||||
const anvilChain = defineChain({ ...localhost, id: chainId });
|
||||
|
||||
const publicClient = createPublicClient({
|
||||
chain: anvilChain,
|
||||
transport: http(LOCAL_ANVIL_RPC),
|
||||
});
|
||||
|
||||
const entrypoint = getContract({
|
||||
address: ENTRYPOINT_ADDRESS,
|
||||
abi: EntrypointAbi,
|
||||
client: publicClient,
|
||||
});
|
||||
|
||||
async function getPoolContract(asset: `0x${string}`) {
|
||||
const cachedPool = _poolCacheByAsset[asset];
|
||||
if (cachedPool !== undefined)
|
||||
return cachedPool;
|
||||
const [
|
||||
poolAddress,
|
||||
_minimumDepositAmount, // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
_vettingFeeBPS, // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
_maxRelayFeeBPS // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
] = await entrypoint.read.assetConfig([asset]);
|
||||
const pool = getContract({
|
||||
address: poolAddress,
|
||||
abi: PoolAbi,
|
||||
client: publicClient,
|
||||
});
|
||||
const scope = await pool.read.SCOPE();
|
||||
_poolCacheByAsset[asset] = pool;
|
||||
_poolCacheByScope[scope.toString()] = pool;
|
||||
return pool;
|
||||
}
|
||||
|
||||
function getPoolContractByScope(scope: bigint) {
|
||||
const cachedPool = _poolCacheByScope[scope.toString()];
|
||||
if (cachedPool !== undefined)
|
||||
return cachedPool;
|
||||
throw Error("Pool is not instantiated")
|
||||
}
|
||||
|
||||
function getErc20Contract(asset: `0x${string}`) {
|
||||
return getContract({
|
||||
address: asset,
|
||||
client: publicClient,
|
||||
abi: Erc20Abi
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
account: privateKeyToAccount(privateKey),
|
||||
chain: anvilChain,
|
||||
client: publicClient,
|
||||
entrypoint,
|
||||
getPoolContract,
|
||||
getErc20Contract,
|
||||
getPoolContractByScope
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
export const pool = getContract({
|
||||
address: ETH_POOL_ADDRESS,
|
||||
abi: parseAbi(["function SCOPE() view returns (uint256)"]),
|
||||
client: publicClient,
|
||||
})
|
||||
|
||||
270
packages/relayer/test/integration/relay/src/cli.ts
Normal file
270
packages/relayer/test/integration/relay/src/cli.ts
Normal file
@@ -0,0 +1,270 @@
|
||||
import minimist from 'minimist';
|
||||
import { getAddress } from 'viem';
|
||||
import { quote, request } from "./api-test.js";
|
||||
import { ChainContext } from "./chain.js";
|
||||
import { feeRecipient, PRIVATE_KEY, processooor, recipient } from "./constants.js";
|
||||
import { encodeFeeData, isNative } from "./util.js";
|
||||
import { SdkWrapper } from './sdk-wrapper.js';
|
||||
import * as fs from "fs";
|
||||
|
||||
interface Context {
|
||||
chainId: number;
|
||||
privateKey: `0x${string}`;
|
||||
}
|
||||
|
||||
interface DepositCli {
|
||||
context: Context;
|
||||
accNonce: bigint;
|
||||
amount: bigint;
|
||||
asset: `0x${string}`;
|
||||
}
|
||||
|
||||
export async function depositCli({ accNonce, amount, asset, context }: DepositCli) {
|
||||
const { chainId, privateKey } = context;
|
||||
const sdkWrapper = new SdkWrapper(ChainContext(chainId, privateKey));
|
||||
let r;
|
||||
if (isNative(asset)) {
|
||||
r = await sdkWrapper.deposit(accNonce, amount);
|
||||
} else {
|
||||
r = await sdkWrapper.depositAsset(accNonce, amount, asset);
|
||||
}
|
||||
await r.wait();
|
||||
console.log(`Successful deposit, hash := ${r.hash}`);
|
||||
}
|
||||
|
||||
interface QuoteCli {
|
||||
context: Context;
|
||||
asset: `0x${string}`;
|
||||
amount: bigint;
|
||||
extraGas: boolean;
|
||||
}
|
||||
|
||||
export async function quoteCli({ context, asset, amount, extraGas }: QuoteCli) {
|
||||
return quote({
|
||||
chainId: context.chainId,
|
||||
amount: amount.toString(),
|
||||
asset,
|
||||
recipient,
|
||||
extraGas
|
||||
});
|
||||
}
|
||||
|
||||
interface RelayCli {
|
||||
context: Context;
|
||||
|
||||
asset: `0x${string}`;
|
||||
withQuote: boolean;
|
||||
extraGas: boolean;
|
||||
amount: bigint;
|
||||
|
||||
fromDeposit: boolean;
|
||||
fromLabel?: bigint;
|
||||
accNonce: bigint;
|
||||
value: bigint;
|
||||
|
||||
leaves: {
|
||||
index: bigint;
|
||||
leaf: bigint;
|
||||
root: bigint;
|
||||
block: bigint;
|
||||
}[];
|
||||
}
|
||||
|
||||
export async function relayCli({ asset, withQuote, amount, extraGas, fromDeposit, fromLabel, accNonce, value, context, leaves }: RelayCli) {
|
||||
|
||||
const { chainId, privateKey } = context;
|
||||
const sdkWrapper = new SdkWrapper(ChainContext(chainId, privateKey));
|
||||
|
||||
const pool = await sdkWrapper.chainContext.getPoolContract(asset);
|
||||
const scope = await pool.read.SCOPE();
|
||||
|
||||
let note: { nullifier: bigint, secret: bigint; };
|
||||
let newNote: { nullifier: bigint, secret: bigint; } | undefined;
|
||||
let label: bigint;
|
||||
if (fromDeposit) {
|
||||
note = sdkWrapper.depositSecret(scope, accNonce);
|
||||
const noteLabel = await sdkWrapper.findLabelFromDepositNote(asset, note);
|
||||
label = noteLabel;
|
||||
newNote = sdkWrapper.withdrawSecret(noteLabel, 0n);
|
||||
} else if (fromLabel !== undefined) {
|
||||
note = sdkWrapper.withdrawSecret(fromLabel, accNonce);
|
||||
newNote = sdkWrapper.withdrawSecret(fromLabel, accNonce + 1n);
|
||||
label = fromLabel;
|
||||
} else {
|
||||
throw new Error("No deposit or label");
|
||||
}
|
||||
|
||||
console.log("note", note);
|
||||
console.log("newnote", newNote);
|
||||
|
||||
// 0.1 ETH or 1.5 dollars
|
||||
const withdrawAmount = amount;
|
||||
|
||||
let data;
|
||||
let feeCommitment = undefined;
|
||||
if (withQuote) {
|
||||
const quoteRes = await quote({
|
||||
chainId,
|
||||
amount: withdrawAmount.toString(),
|
||||
asset,
|
||||
recipient,
|
||||
extraGas
|
||||
});
|
||||
data = quoteRes.feeCommitment!.withdrawalData as `0x${string}`;
|
||||
feeCommitment = {
|
||||
...quoteRes.feeCommitment,
|
||||
};
|
||||
} else {
|
||||
data = encodeFeeData({ recipient, feeRecipient, relayFeeBPS: 100n });
|
||||
}
|
||||
|
||||
const withdrawal = { processooor, data };
|
||||
|
||||
// prove
|
||||
const { proof, publicSignals } = await sdkWrapper.proveWithdrawal(withdrawAmount, withdrawal, scope, label, value, note, newNote, leaves);
|
||||
|
||||
const requestBody = {
|
||||
scope: scope.toString(),
|
||||
chainId: sdkWrapper.chainContext.chain.id,
|
||||
withdrawal,
|
||||
publicSignals,
|
||||
proof,
|
||||
feeCommitment
|
||||
};
|
||||
|
||||
await request(requestBody);
|
||||
}
|
||||
|
||||
interface DefArgs {
|
||||
_: string[],
|
||||
chainId: number;
|
||||
privateKey: `0x${string}`;
|
||||
}
|
||||
|
||||
export async function cli() {
|
||||
let args = minimist(process.argv.slice(2), {
|
||||
string: ["asset", "fromLabel", "accNonce", "output"],
|
||||
boolean: ["quote", "extraGas", "fromDeposit"],
|
||||
alias: {
|
||||
"private-key": "privateKey",
|
||||
"chain-id": "chainId",
|
||||
"from-deposit": "fromDeposit",
|
||||
"acc-nonce": "accNonce",
|
||||
"from-label": "fromLabel",
|
||||
"cache-file": "cacheFile"
|
||||
},
|
||||
default: {
|
||||
"chainId": process.env["CHAIN_ID"] || 1115511,
|
||||
"privateKey": process.env["PRIVATE_KEY"] || PRIVATE_KEY,
|
||||
"asset": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
||||
"extraGas": true,
|
||||
"quote": false,
|
||||
"fromDeposit": false,
|
||||
}
|
||||
});
|
||||
const action = process.argv[2]!;
|
||||
const actions = [
|
||||
"deposit",
|
||||
"quote",
|
||||
"relay",
|
||||
"tree"
|
||||
];
|
||||
|
||||
if (!actions.includes(action)) {
|
||||
console.log("No action selected");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const context = { chainId: Number.parseInt(args.chainId), privateKey: args.privateKey };
|
||||
|
||||
switch (action) {
|
||||
case "deposit": {
|
||||
args = args as DefArgs & { amount: string, asset?: string; note: string; };
|
||||
const r = await depositCli({ accNonce: BigInt(args.accNonce), amount: BigInt(args.amount), asset: args.asset, context });
|
||||
console.log(r);
|
||||
break;
|
||||
}
|
||||
case "quote": {
|
||||
if (args.length < 3) {
|
||||
throw Error("Not enough args");
|
||||
}
|
||||
args = args as DefArgs & { amount: string, asset: string; extraGas: boolean; };
|
||||
await quoteCli({
|
||||
context,
|
||||
asset: getAddress(args.asset),
|
||||
amount: BigInt(args.amount),
|
||||
extraGas: args.extraGas
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "relay": {
|
||||
args = args as DefArgs & {
|
||||
amount: string;
|
||||
asset: string;
|
||||
quote: boolean;
|
||||
extraGas: boolean;
|
||||
|
||||
fromDeposit: boolean;
|
||||
fromLabel: string;
|
||||
accNonce: string;
|
||||
value: string;
|
||||
|
||||
cacheFile: string;
|
||||
};
|
||||
|
||||
await relayCli({
|
||||
context,
|
||||
asset: getAddress(args.asset),
|
||||
amount: BigInt(args.amount),
|
||||
extraGas: args.extraGas,
|
||||
withQuote: args.quote,
|
||||
|
||||
fromDeposit: args.fromDeposit,
|
||||
fromLabel: args.fromLabel ? BigInt(args.fromLabel) : undefined,
|
||||
accNonce: BigInt(args.accNonce),
|
||||
value: BigInt(args.value),
|
||||
|
||||
leaves: readLeavesFromFile(args.cacheFile),
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "tree": {
|
||||
args = args as DefArgs & { fromBlock: string; asset: string; output?: string; };
|
||||
buildTreeCache({ context, asset: args.asset, fromBlock: args.fromBlock, output: args.output });
|
||||
break;
|
||||
}
|
||||
case undefined: {
|
||||
console.log("No action selected");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function buildTreeCache({ context, asset, fromBlock, output }: { fromBlock: string; asset: string; output?: string; } & { context: Context; }) {
|
||||
console.log("Building tree");
|
||||
const { chainId, privateKey } = context;
|
||||
const sdkWrapper = new SdkWrapper(ChainContext(chainId, privateKey));
|
||||
const pool = await sdkWrapper.chainContext.getPoolContract(asset as `0x${string}`);
|
||||
const leavesRaw = await pool.getEvents.LeafInserted({ fromBlock: BigInt(fromBlock) });
|
||||
const leaves = leavesRaw.map(l => ({
|
||||
index: l.args._index!.toString(),
|
||||
leaf: l.args._leaf!.toString(),
|
||||
root: l.args._root!.toString(),
|
||||
block: l.blockNumber.toString()
|
||||
}));
|
||||
const timestamp = (new Date()).toISOString().replaceAll(":", "_").replace(new RegExp(".[0-9]{3}Z"), "");
|
||||
const treeFileName = output || `./tree-cache-${timestamp}.json`;
|
||||
fs.writeFileSync(treeFileName, JSON.stringify(leaves, null, 2));
|
||||
console.log(`Wrote ${leaves.length} leaves to file ${treeFileName}`);
|
||||
}
|
||||
|
||||
function readLeavesFromFile(filePath: string) {
|
||||
const rawLeaves = JSON.parse(fs.readFileSync(filePath, { encoding: 'utf-8' })) as { index: string, leaf: string, root: string, block: string; }[];
|
||||
return rawLeaves.map(l => ({
|
||||
index: BigInt(l.index),
|
||||
leaf: BigInt(l.leaf),
|
||||
root: BigInt(l.root),
|
||||
block: BigInt(l.block),
|
||||
}));
|
||||
}
|
||||
@@ -1,12 +1,18 @@
|
||||
import { Address, Hex } from "viem";
|
||||
import { Address, getAddress, Hex } from "viem";
|
||||
|
||||
// // mainnet
|
||||
// export const ENTRYPOINT_ADDRESS: Address = "0x6818809EefCe719E480a7526D76bD3e561526b46";
|
||||
// export const ETH_POOL_ADDRESS: Address = "0xF241d57C6DebAe225c0F2e6eA1529373C9A9C9fB";
|
||||
|
||||
// localnet
|
||||
export const ENTRYPOINT_ADDRESS: Address = "0xd6DB18A83F9eE4e2d0FC8D6BEd075A2905A83FDA";
|
||||
export const ETH_POOL_ADDRESS: Address = "0x4Cb503503047b66aA5e64b9BDC8148E769ac52f6";
|
||||
// sepolia (localnet)
|
||||
export const ENTRYPOINT_ADDRESS: Address = "0x1fF2EA3C98E22d5589d66829a1599cB74b566E94";
|
||||
|
||||
|
||||
export const LOCAL_ANVIL_RPC = "http://127.0.0.1:8545";
|
||||
export const PRIVATE_KEY: Hex = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
|
||||
|
||||
// export const PRIVATE_KEY: Hex = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
|
||||
export const PRIVATE_KEY: Hex = "0xa278275fee36ebb6f4689e79bf1a8b4650c9aec0fc39e03c111461e5b08730eb"; // 0xb9edc9DD585C13891F5B2dE85f182d3Ea4AaEa09
|
||||
|
||||
export const processooor = ENTRYPOINT_ADDRESS;
|
||||
export const feeRecipient = getAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
|
||||
export const recipient = getAddress("0xabA6aeB1bCFF1096f4b8148085C4231FED9FE8E4");
|
||||
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
import {
|
||||
bigintToHash,
|
||||
calculateContext,
|
||||
Circuits,
|
||||
getCommitment,
|
||||
hashPrecommitment,
|
||||
LeanIMTMerkleProof,
|
||||
PrivacyPoolSDK,
|
||||
Secret,
|
||||
Withdrawal,
|
||||
WithdrawalProof,
|
||||
WithdrawalProofInput,
|
||||
Hash,
|
||||
} from "@0xbow/privacy-pools-core-sdk";
|
||||
import {
|
||||
ENTRYPOINT_ADDRESS,
|
||||
LOCAL_ANVIL_RPC,
|
||||
PRIVATE_KEY,
|
||||
} from "./constants.js";
|
||||
import { anvilChain } from "./chain.js";
|
||||
|
||||
/*
|
||||
TestToken deployed at: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
|
||||
Withdrawal Verifier deployed at: 0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
|
||||
Ragequit Verifier deployed at: 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9
|
||||
Entrypoint deployed at: 0x0165878A594ca255338adfa4d48449f69242Eb8F
|
||||
ETH Pool deployed at: 0xa513E6E4b8f2a923D98304ec87F64353C4D5C853
|
||||
TST Pool deployed at: 0x8A791620dd6260079BF849Dc5567aDC3F2FdC318
|
||||
*/
|
||||
|
||||
const sdk = new PrivacyPoolSDK(new Circuits({ browser: false }));
|
||||
|
||||
const contracts = sdk.createContractInstance(
|
||||
LOCAL_ANVIL_RPC,
|
||||
anvilChain,
|
||||
ENTRYPOINT_ADDRESS,
|
||||
PRIVATE_KEY,
|
||||
);
|
||||
|
||||
export async function deposit() {
|
||||
const existingValue = BigInt("5000000000000000000"); // 5 eth
|
||||
const existingNullifier = BigInt("2827991637673173") as Secret;
|
||||
const existingSecret = BigInt("7338940278733227") as Secret;
|
||||
const precommitment = {
|
||||
hash: hashPrecommitment(existingNullifier, existingSecret),
|
||||
nullifier: existingNullifier,
|
||||
secret: existingSecret,
|
||||
};
|
||||
return contracts.depositETH(existingValue, precommitment.hash);
|
||||
}
|
||||
|
||||
export async function proveWithdrawal(
|
||||
w: Withdrawal,
|
||||
scope: bigint,
|
||||
): Promise<WithdrawalProof> {
|
||||
try {
|
||||
console.log("🚀 Initializing PrivacyPoolSDK...");
|
||||
|
||||
// **Retrieve On-Chain Scope**
|
||||
console.log(
|
||||
"🔹 Retrieved Scope from Withdrawal:",
|
||||
`0x${scope.toString(16)}`,
|
||||
);
|
||||
|
||||
// **Load Valid Input Values**
|
||||
const withdrawnValue = BigInt("100000000000000000"); // 0.1 eth
|
||||
const stateRoot = BigInt(
|
||||
"11647068014638404411083963959916324311405860401109309104995569418439086324505",
|
||||
);
|
||||
const stateTreeDepth = BigInt("2");
|
||||
const aspRoot = BigInt(
|
||||
"17509119559942543382744731935952318540675152427220720285867932301410542597330",
|
||||
);
|
||||
const aspTreeDepth = BigInt("2");
|
||||
const label = BigInt("2310129299332319");
|
||||
|
||||
// **Commitment Data**
|
||||
const existingValue = BigInt("5000000000000000000");
|
||||
const existingNullifier = BigInt("2827991637673173") as Secret;
|
||||
const existingSecret = BigInt("7338940278733227") as Secret;
|
||||
const newNullifier = BigInt("1800210687471587") as Secret;
|
||||
const newSecret = BigInt("6593588285288381") as Secret;
|
||||
|
||||
console.log("🛠️ Generating commitments...");
|
||||
|
||||
const commitment = getCommitment(
|
||||
existingValue,
|
||||
label,
|
||||
existingNullifier,
|
||||
existingSecret,
|
||||
);
|
||||
|
||||
// **State Merkle Proof**
|
||||
const stateMerkleProof: LeanIMTMerkleProof = {
|
||||
root: stateRoot,
|
||||
leaf: commitment.hash,
|
||||
index: 3,
|
||||
siblings: [
|
||||
BigInt("6398878698952029"),
|
||||
BigInt(
|
||||
"13585012987205807684735841540436202984635744455909835202346884556845854938903",
|
||||
),
|
||||
...Array(30).fill(BigInt(0)),
|
||||
],
|
||||
};
|
||||
|
||||
// **ASP Merkle Proof**
|
||||
const aspMerkleProof: LeanIMTMerkleProof = {
|
||||
root: aspRoot,
|
||||
leaf: label,
|
||||
index: 3,
|
||||
siblings: [
|
||||
BigInt("3189334085279373"),
|
||||
BigInt(
|
||||
"1131383056830993841196498111009024161908281953428245130508088856824218714105",
|
||||
),
|
||||
...Array(30).fill(BigInt(0)),
|
||||
],
|
||||
};
|
||||
|
||||
// console.log("✅ State Merkle Proof:", stateMerkleProof);
|
||||
// console.log("✅ ASP Merkle Proof:", aspMerkleProof);
|
||||
|
||||
// **Correctly Compute Context Hash**
|
||||
const computedContext = calculateContext(w, scope as Hash);
|
||||
console.log("🔹 Computed Context:", computedContext.toString());
|
||||
|
||||
// **Create Withdrawal Proof Input**
|
||||
const proofInput: WithdrawalProofInput = {
|
||||
context: BigInt(computedContext),
|
||||
withdrawalAmount: withdrawnValue,
|
||||
stateMerkleProof: stateMerkleProof,
|
||||
aspMerkleProof: aspMerkleProof,
|
||||
stateRoot: bigintToHash(stateRoot),
|
||||
stateTreeDepth: stateTreeDepth,
|
||||
aspRoot: bigintToHash(aspRoot),
|
||||
aspTreeDepth: aspTreeDepth,
|
||||
newSecret: newSecret,
|
||||
newNullifier: newNullifier,
|
||||
};
|
||||
|
||||
console.log("🚀 Generating withdrawal proof...");
|
||||
const proofPayload: WithdrawalProof = await sdk.proveWithdrawal(
|
||||
commitment,
|
||||
proofInput,
|
||||
);
|
||||
return proofPayload;
|
||||
|
||||
// if (!proofPayload) {
|
||||
// throw new Error("❌ Withdrawal proof generation failed: proofPayload is null or undefined");
|
||||
// }
|
||||
|
||||
// console.log("✅ Proof Payload:", proofPayload);
|
||||
|
||||
// console.log("🚀 Sending withdrawal transaction...");
|
||||
// const withdrawalTx = await sdk.getContractInteractions().withdraw(withdrawObj, proofPayload);
|
||||
|
||||
// console.log("✅ Withdrawal transaction sent:", withdrawalTx?.hash ?? "❌ No transaction hash returned");
|
||||
|
||||
// if (!withdrawalTx?.hash) {
|
||||
// throw new Error("❌ Withdrawal transaction failed: No transaction hash returned.");
|
||||
// }
|
||||
|
||||
// await withdrawalTx.wait();
|
||||
// console.log("🎉 Withdrawal transaction confirmed!");
|
||||
} catch (error) {
|
||||
console.error("❌ **Error running testWithdraw script**:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -1,138 +1,7 @@
|
||||
import { Hash, Withdrawal } from "@0xbow/privacy-pools-core-sdk";
|
||||
import { encodeAbiParameters, getAddress, Hex } from "viem";
|
||||
import { request, quote } from "./api-test.js";
|
||||
import { anvilChain, pool } from "./chain.js";
|
||||
import { ENTRYPOINT_ADDRESS } from "./constants.js";
|
||||
import { deposit, proveWithdrawal } from "./create-withdrawal.js";
|
||||
|
||||
interface QuoteResponse {
|
||||
baseFeeBPS: bigint,
|
||||
feeBPS: bigint,
|
||||
feeCommitment?: {
|
||||
expiration: number,
|
||||
withdrawalData: `0x${string}`,
|
||||
signedRelayerCommitment: `0x${string}`,
|
||||
}
|
||||
}
|
||||
|
||||
const FeeDataAbi = [
|
||||
{
|
||||
name: "FeeData",
|
||||
type: "tuple",
|
||||
components: [
|
||||
{ name: "recipient", type: "address" },
|
||||
{ name: "feeRecipient", type: "address" },
|
||||
{ name: "relayFeeBPS", type: "uint256" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const recipient = getAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
|
||||
const processooor = ENTRYPOINT_ADDRESS;
|
||||
const FEE_RECEIVER_ADDRESS = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266";
|
||||
|
||||
async function prove(w: Withdrawal, scope: bigint) {
|
||||
return proveWithdrawal(w, scope);
|
||||
}
|
||||
|
||||
async function depositCli() {
|
||||
const r = await deposit();
|
||||
await r.wait();
|
||||
console.log(`Successful deposit, hash := ${r.hash}`);
|
||||
}
|
||||
|
||||
async function quoteReq(chainId: number, asset: string, recipient: string, amount: string) {
|
||||
return (await quote({
|
||||
chainId,
|
||||
amount,
|
||||
asset,
|
||||
recipient
|
||||
}) as QuoteResponse);
|
||||
}
|
||||
|
||||
async function quoteCli(chainId: string, asset: string, amount?: string) {
|
||||
const _amount = amount ? Number(amount) : 100_000_000_000_000_000n
|
||||
quoteReq(Number(chainId), asset, recipient, _amount.toString())
|
||||
}
|
||||
|
||||
async function relayCli(chainId: string, asset: string, withQuote: boolean) {
|
||||
|
||||
const scope = await pool.read.SCOPE() as Hash;
|
||||
|
||||
let data;
|
||||
let feeCommitment = undefined;
|
||||
if (withQuote) {
|
||||
const amount = "100000000000000000"; // 0.1 ETH
|
||||
const quoteRes = await quoteReq(Number(chainId), asset, recipient, amount);
|
||||
data = quoteRes.feeCommitment!.withdrawalData as Hex
|
||||
feeCommitment = {
|
||||
...quoteRes.feeCommitment,
|
||||
};
|
||||
} else {
|
||||
data = encodeAbiParameters(FeeDataAbi, [
|
||||
{
|
||||
recipient,
|
||||
feeRecipient: FEE_RECEIVER_ADDRESS,
|
||||
relayFeeBPS: 100n,
|
||||
},
|
||||
]) as Hex;
|
||||
}
|
||||
|
||||
const withdrawal = { processooor, data };
|
||||
|
||||
// prove
|
||||
const { proof, publicSignals } = await prove(withdrawal, scope);
|
||||
|
||||
const requestBody = {
|
||||
scope: scope.toString(),
|
||||
chainId: anvilChain.id,
|
||||
withdrawal,
|
||||
publicSignals,
|
||||
proof,
|
||||
feeCommitment
|
||||
};
|
||||
|
||||
await request(requestBody);
|
||||
}
|
||||
|
||||
async function cli() {
|
||||
const args = process.argv.slice(2)
|
||||
const action = args[0];
|
||||
switch (action) {
|
||||
case "deposit": {
|
||||
console.log(action)
|
||||
await depositCli();
|
||||
break;
|
||||
}
|
||||
case "quote": {
|
||||
console.log(action)
|
||||
if (args.length < 3) {
|
||||
throw Error("Not enough args")
|
||||
}
|
||||
await quoteCli(args[1]!, args[2]!, args[3])
|
||||
break;
|
||||
}
|
||||
case "relay": {
|
||||
console.log(...args)
|
||||
const withQuote = args.includes("--with-quote")
|
||||
const noFlags = args.slice(1).filter(a => a !== "--with-quote")
|
||||
if (noFlags.length < 2) {
|
||||
throw Error("Not enough args")
|
||||
}
|
||||
await relayCli(noFlags[0]!, noFlags[1]!, withQuote);
|
||||
break;
|
||||
}
|
||||
case undefined: {
|
||||
console.log("No action selected")
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
import { cli } from "./cli.js";
|
||||
|
||||
(async () => {
|
||||
|
||||
cli();
|
||||
await cli();
|
||||
|
||||
})();
|
||||
|
||||
272
packages/relayer/test/integration/relay/src/sdk-wrapper.ts
Normal file
272
packages/relayer/test/integration/relay/src/sdk-wrapper.ts
Normal file
@@ -0,0 +1,272 @@
|
||||
import {
|
||||
bigintToHash,
|
||||
calculateContext,
|
||||
Circuits,
|
||||
ContractInteractionsService,
|
||||
generateDepositSecrets,
|
||||
generateMasterKeys,
|
||||
generateMerkleProof,
|
||||
getCommitment,
|
||||
Hash,
|
||||
hashPrecommitment,
|
||||
LeanIMTMerkleProof,
|
||||
MasterKeys,
|
||||
PrivacyPoolSDK,
|
||||
Secret,
|
||||
Withdrawal,
|
||||
WithdrawalProof,
|
||||
WithdrawalProofInput
|
||||
} from "@0xbow/privacy-pools-core-sdk";
|
||||
|
||||
import { IChainContext } from "./chain.js";
|
||||
import {
|
||||
ENTRYPOINT_ADDRESS,
|
||||
PRIVATE_KEY
|
||||
} from "./constants.js";
|
||||
|
||||
type Note = { nullifier: bigint, secret: bigint; };
|
||||
|
||||
/*
|
||||
TestToken deployed at: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
|
||||
Withdrawal Verifier deployed at: 0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
|
||||
Ragequit Verifier deployed at: 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9
|
||||
Entrypoint deployed at: 0x0165878A594ca255338adfa4d48449f69242Eb8F
|
||||
ETH Pool deployed at: 0xa513E6E4b8f2a923D98304ec87F64353C4D5C853
|
||||
TST Pool deployed at: 0x8A791620dd6260079BF849Dc5567aDC3F2FdC318
|
||||
*/
|
||||
|
||||
export class SdkWrapper {
|
||||
|
||||
chainContext: IChainContext;
|
||||
sdk: PrivacyPoolSDK;
|
||||
contracts: ContractInteractionsService;
|
||||
mnemonic: string;
|
||||
masterKeys: MasterKeys;
|
||||
|
||||
constructor(chainContext: IChainContext) {
|
||||
this.chainContext = chainContext;
|
||||
this.sdk = new PrivacyPoolSDK(new Circuits({ browser: false }));
|
||||
this.contracts = this.sdk.createContractInstance(
|
||||
this.chainContext.client.transport.url,
|
||||
this.chainContext.chain,
|
||||
ENTRYPOINT_ADDRESS,
|
||||
PRIVATE_KEY,
|
||||
);
|
||||
this.mnemonic = "muscle horse fly praise focus mixed annual disorder false black bottom uncover";
|
||||
this.masterKeys = generateMasterKeys(this.mnemonic);
|
||||
|
||||
}
|
||||
|
||||
depositSecret(scope: bigint, index: bigint) {
|
||||
return generateDepositSecrets(this.masterKeys, scope as Hash, index);
|
||||
}
|
||||
|
||||
withdrawSecret(label: bigint, index: bigint) {
|
||||
return generateDepositSecrets(this.masterKeys, label as Hash, index);
|
||||
}
|
||||
|
||||
async findLabelFromDepositNote(asset: `0x${string}`, note: { nullifier: bigint; secret: bigint; }): Promise<bigint> {
|
||||
const pool = await this.chainContext.getPoolContract(asset);
|
||||
const depositEvents = await pool.getEvents.Deposited(undefined, { fromBlock: (await this.chainContext.client.getBlockNumber()) - 50n });
|
||||
const preCommitment = hashPrecommitment(note.nullifier as Secret, note.secret as Secret);
|
||||
const event = depositEvents.filter(de => de.args._precommitmentHash === preCommitment).pop();
|
||||
if (event && event?.args?._label !== undefined) {
|
||||
return event.args._label;
|
||||
} else {
|
||||
throw Error("Can't find matching label");
|
||||
}
|
||||
}
|
||||
|
||||
async deposit(accNonce: bigint, amount: bigint) {
|
||||
|
||||
const pool = await this.chainContext.getPoolContract("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE");
|
||||
const scope = await pool.read.SCOPE() as Hash;
|
||||
|
||||
const { secret, nullifier } = this.depositSecret(scope, accNonce);
|
||||
|
||||
const precommitment = {
|
||||
hash: hashPrecommitment(nullifier!, secret!),
|
||||
nullifier: secret,
|
||||
secret: nullifier,
|
||||
};
|
||||
|
||||
const tx = await this.contracts.depositETH(amount, precommitment.hash);
|
||||
await tx.wait();
|
||||
const depositEvents = await pool.getEvents.Deposited({ _depositor: this.chainContext.account.address });
|
||||
depositEvents.forEach(e => {
|
||||
console.log("Deposited<", {
|
||||
...e.args,
|
||||
blockNumber: e.blockNumber,
|
||||
blockHash: e.blockHash
|
||||
}, ">");
|
||||
});
|
||||
return tx;
|
||||
}
|
||||
|
||||
async depositAsset(accNonce: bigint, amount: bigint, assetAddress: `0x${string}`) {
|
||||
|
||||
const pool = await this.chainContext.getPoolContract(assetAddress);
|
||||
const scope = await pool.read.SCOPE() as Hash;
|
||||
|
||||
const { secret, nullifier } = this.depositSecret(scope, accNonce);
|
||||
|
||||
const precommitment = {
|
||||
hash: hashPrecommitment(nullifier!, secret!),
|
||||
nullifier: secret,
|
||||
secret: nullifier,
|
||||
};
|
||||
|
||||
const erc20 = this.chainContext.getErc20Contract(assetAddress);
|
||||
await erc20.write.approve([ENTRYPOINT_ADDRESS, 2n ** 256n - 1n], {
|
||||
account: this.chainContext.account,
|
||||
chain: this.chainContext.chain
|
||||
});
|
||||
const tx = await this.contracts.depositERC20(assetAddress, amount, precommitment.hash);
|
||||
await tx.wait();
|
||||
const depositEvents = await pool.getEvents.Deposited({ _depositor: this.chainContext.account.address });
|
||||
depositEvents.forEach(e => {
|
||||
console.log("Deposited<", {
|
||||
...e.args,
|
||||
blockNumber: e.blockNumber,
|
||||
blockHash: e.blockHash
|
||||
}, ">");
|
||||
});
|
||||
return tx;
|
||||
}
|
||||
|
||||
async proveWithdrawal(
|
||||
withdrawAmount: bigint,
|
||||
w: Withdrawal,
|
||||
scope: bigint,
|
||||
label: bigint,
|
||||
oldNoteValue: bigint,
|
||||
oldNote: Note,
|
||||
newNote: Note,
|
||||
leaves: {
|
||||
index: bigint;
|
||||
leaf: bigint;
|
||||
root: bigint;
|
||||
block: bigint;
|
||||
}[]
|
||||
): Promise<WithdrawalProof> {
|
||||
|
||||
try {
|
||||
console.log("🚀 Initializing PrivacyPoolSDK...");
|
||||
|
||||
// **Retrieve On-Chain Scope**
|
||||
console.log(
|
||||
"🔹 Retrieved Scope from Withdrawal:",
|
||||
`0x${scope.toString(16)}`,
|
||||
);
|
||||
|
||||
const pool = this.chainContext.getPoolContractByScope(scope);
|
||||
|
||||
// **Load Valid Input Values**
|
||||
const stateTreeDepth = await pool.read.currentTreeDepth();
|
||||
// pool.read.currentTreeSize();
|
||||
const stateRoot = await pool.read.currentRoot();
|
||||
|
||||
// const stateRoot = BigInt(
|
||||
// "11647068014638404411083963959916324311405860401109309104995569418439086324505",
|
||||
// );
|
||||
// const stateTreeDepth = BigInt("2");
|
||||
|
||||
const { secret: existingSecret, nullifier: existingNullifier } = oldNote;
|
||||
const { secret: newSecret, nullifier: newNullifier } = newNote;
|
||||
|
||||
console.log("🛠️ Generating commitments...");
|
||||
|
||||
const commitment = getCommitment(
|
||||
oldNoteValue,
|
||||
label,
|
||||
existingNullifier as Secret,
|
||||
existingSecret as Secret,
|
||||
);
|
||||
|
||||
const sortedLeaves = leaves.sort((a, b) => Number(a.index - b.index)).map(x => x.leaf);
|
||||
|
||||
// **State Merkle Proof**
|
||||
const stateMerkleProof: LeanIMTMerkleProof = generateMerkleProof(sortedLeaves, commitment.hash);
|
||||
stateMerkleProof.index = Number.isNaN(stateMerkleProof.index) ? 0 : stateMerkleProof.index;
|
||||
if (stateMerkleProof.siblings.length < 32) {
|
||||
const N = 32 - stateMerkleProof.siblings.length;
|
||||
const siblings = [...stateMerkleProof.siblings, ...Array(N).fill(0n)];
|
||||
stateMerkleProof.siblings = siblings;
|
||||
}
|
||||
stateMerkleProof.siblings = stateMerkleProof.siblings.length === 0 ? [stateRoot, ...Array(31).fill(0n)] : stateMerkleProof.siblings;
|
||||
console.log(stateMerkleProof);
|
||||
|
||||
// const stateMerkleProof: LeanIMTMerkleProof = {
|
||||
// root: stateRoot,
|
||||
// leaf: commitment.hash,
|
||||
// index: 3,
|
||||
// siblings: [
|
||||
// BigInt("6398878698952029"),
|
||||
// BigInt(
|
||||
// "13585012987205807684735841540436202984635744455909835202346884556845854938903",
|
||||
// ),
|
||||
// ...Array(30).fill(BigInt(0)),
|
||||
// ],
|
||||
// };
|
||||
|
||||
// const aspRoot = BigInt(
|
||||
// "17509119559942543382744731935952318540675152427220720285867932301410542597330",
|
||||
// );
|
||||
// const aspTreeDepth = BigInt("2");
|
||||
|
||||
const firstSib = 1n;
|
||||
const aspRoot = hashPrecommitment(label as Secret, firstSib as Secret);
|
||||
const aspTreeDepth = 2n;
|
||||
// **ASP Merkle Proof**
|
||||
const aspMerkleProof: LeanIMTMerkleProof = {
|
||||
root: aspRoot,
|
||||
leaf: label,
|
||||
index: 0,
|
||||
siblings: [
|
||||
firstSib,
|
||||
...Array(31).fill(BigInt(0)),
|
||||
// BigInt("3189334085279373"),
|
||||
// BigInt(
|
||||
// "1131383056830993841196498111009024161908281953428245130508088856824218714105",
|
||||
// ),
|
||||
// ...Array(30).fill(BigInt(0)),
|
||||
],
|
||||
};
|
||||
|
||||
// console.log("✅ State Merkle Proof:", stateMerkleProof);
|
||||
// console.log("✅ ASP Merkle Proof:", aspMerkleProof);
|
||||
|
||||
// **Correctly Compute Context Hash**
|
||||
const computedContext = calculateContext(w, scope as Hash);
|
||||
console.log("🔹 Computed Context:", computedContext.toString());
|
||||
|
||||
// **Create Withdrawal Proof Input**
|
||||
const proofInput: WithdrawalProofInput = {
|
||||
context: BigInt(computedContext),
|
||||
withdrawalAmount: withdrawAmount,
|
||||
stateMerkleProof: stateMerkleProof,
|
||||
aspMerkleProof: aspMerkleProof,
|
||||
stateRoot: bigintToHash(stateRoot),
|
||||
stateTreeDepth: stateTreeDepth,
|
||||
aspRoot: bigintToHash(aspRoot),
|
||||
aspTreeDepth: aspTreeDepth,
|
||||
newSecret: newSecret as Secret,
|
||||
newNullifier: newNullifier as Secret,
|
||||
};
|
||||
|
||||
console.log("🚀 Generating withdrawal proof...");
|
||||
const proofPayload: WithdrawalProof = await this.sdk.proveWithdrawal(
|
||||
commitment,
|
||||
proofInput,
|
||||
);
|
||||
|
||||
console.log(proofPayload)
|
||||
return proofPayload;
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ **Error running testWithdraw script**:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
31
packages/relayer/test/integration/relay/src/util.ts
Normal file
31
packages/relayer/test/integration/relay/src/util.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { encodeAbiParameters } from "viem";
|
||||
|
||||
const FeeDataAbi = [
|
||||
{
|
||||
name: "FeeData",
|
||||
type: "tuple",
|
||||
components: [
|
||||
{ name: "recipient", type: "address" },
|
||||
{ name: "feeRecipient", type: "address" },
|
||||
{ name: "relayFeeBPS", type: "uint256" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export function encodeFeeData({
|
||||
recipient, feeRecipient, relayFeeBPS
|
||||
}: {
|
||||
recipient: `0x${string}`; feeRecipient: `0x${string}`; relayFeeBPS: bigint;
|
||||
}) {
|
||||
return encodeAbiParameters(FeeDataAbi, [
|
||||
{
|
||||
recipient,
|
||||
feeRecipient,
|
||||
relayFeeBPS,
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
export function isNative(asset: `0x${string}`) {
|
||||
return asset.toLowerCase() === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
|
||||
}
|
||||
@@ -2,11 +2,48 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@0xbow/privacy-pools-core-sdk@0.1.21":
|
||||
version "0.1.21"
|
||||
resolved "https://registry.yarnpkg.com/@0xbow/privacy-pools-core-sdk/-/privacy-pools-core-sdk-0.1.21.tgz#8811694288525c7a12f14150fbea085c6da88b59"
|
||||
integrity sha512-UTNPHSkdR1XdQoU2u7XLaGcRCh09WP9C9yIlXrUgF0SUkiaaE2ZnyUIrhtT/oW7/zreYNZArWv8v647uVSNCzw==
|
||||
dependencies:
|
||||
"@types/snarkjs" "0.7.9"
|
||||
"@zk-kit/lean-imt" "2.2.2"
|
||||
maci-crypto "2.5.0"
|
||||
snarkjs "0.7.5"
|
||||
typescript "^5.7.3"
|
||||
viem "2.22.14"
|
||||
|
||||
"@adraffy/ens-normalize@1.10.1":
|
||||
version "1.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069"
|
||||
integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==
|
||||
|
||||
"@adraffy/ens-normalize@^1.10.1":
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33"
|
||||
integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==
|
||||
|
||||
"@iden3/bigarray@0.0.2":
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@iden3/bigarray/-/bigarray-0.0.2.tgz#6fc4ba5be18daf8a26ee393f2fb62b80d98c05e9"
|
||||
integrity sha512-Xzdyxqm1bOFF6pdIsiHLLl3HkSLjbhqJHVyqaTxXt3RqXBEnmsUmEW47H7VOi/ak7TdkRpNkxjyK5Zbkm+y52g==
|
||||
|
||||
"@iden3/binfileutils@0.0.12":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@iden3/binfileutils/-/binfileutils-0.0.12.tgz#3772552f57551814ff606fa68ea1e0ef52795ce3"
|
||||
integrity sha512-naAmzuDufRIcoNfQ1d99d7hGHufLA3wZSibtr4dMe6ZeiOPV1KwOZWTJ1YVz4HbaWlpDuzVU72dS4ATQS4PXBQ==
|
||||
dependencies:
|
||||
fastfile "0.0.20"
|
||||
ffjavascript "^0.3.0"
|
||||
|
||||
"@noble/curves@1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35"
|
||||
integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==
|
||||
dependencies:
|
||||
"@noble/hashes" "1.3.2"
|
||||
|
||||
"@noble/curves@1.8.1", "@noble/curves@^1.6.0", "@noble/curves@~1.8.1":
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.1.tgz#19bc3970e205c99e4bdb1c64a4785706bce497ff"
|
||||
@@ -14,6 +51,11 @@
|
||||
dependencies:
|
||||
"@noble/hashes" "1.7.1"
|
||||
|
||||
"@noble/hashes@1.3.2":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39"
|
||||
integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==
|
||||
|
||||
"@noble/hashes@1.7.1", "@noble/hashes@^1.5.0", "@noble/hashes@~1.7.1":
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.1.tgz#5738f6d765710921e7a751e00c20ae091ed8db0f"
|
||||
@@ -41,6 +83,18 @@
|
||||
"@noble/hashes" "~1.7.1"
|
||||
"@scure/base" "~1.2.4"
|
||||
|
||||
"@types/minimist@1.2.8":
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e"
|
||||
integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==
|
||||
|
||||
"@types/node@22.7.5":
|
||||
version "22.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b"
|
||||
integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==
|
||||
dependencies:
|
||||
undici-types "~6.19.2"
|
||||
|
||||
"@types/node@^22.13.0":
|
||||
version "22.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.0.tgz#d376dd9a0ee2f9382d86c2d5d7beb4d198b4ea8c"
|
||||
@@ -48,21 +102,377 @@
|
||||
dependencies:
|
||||
undici-types "~6.20.0"
|
||||
|
||||
"@types/snarkjs@0.7.9":
|
||||
version "0.7.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/snarkjs/-/snarkjs-0.7.9.tgz#7a3b99bd86009133a74dcb215a475382c772c37c"
|
||||
integrity sha512-pb4Bq3GI2YQOQOG0dR/YuQs/mqcuL6k/vnz68LIPtpA2frrUL3twf69a3AUK9eUmNNeW0RIKkq6scDlC75Is+g==
|
||||
|
||||
"@zk-kit/baby-jubjub@1.0.3", "@zk-kit/baby-jubjub@^1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@zk-kit/baby-jubjub/-/baby-jubjub-1.0.3.tgz#8d2eccd20d729f1dbd39203dbff9a245a61dea76"
|
||||
integrity sha512-Wl+QfV6XGOMk1yU2JTqHXeKWfJVXp83is0+dtqfj9wx4wsAPpb+qzYvwAxW5PBx5/Nu71Bh7jp/5vM+6QgHSwA==
|
||||
dependencies:
|
||||
"@zk-kit/utils" "1.2.1"
|
||||
|
||||
"@zk-kit/eddsa-poseidon@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@zk-kit/eddsa-poseidon/-/eddsa-poseidon-1.1.0.tgz#08ef95ccbb2fbb5260617b6b5120dfb25a25229b"
|
||||
integrity sha512-Djc+zOZjd73FpLLf32/XeVZi8GX4ShPQJGS4Iig1QMAR/2CggEi++6Jrkr9N2FM3M4MRCH1qxz2u22DjOLtASg==
|
||||
dependencies:
|
||||
"@zk-kit/baby-jubjub" "1.0.3"
|
||||
"@zk-kit/utils" "1.2.1"
|
||||
blakejs "^1.2.1"
|
||||
buffer "6.0.3"
|
||||
poseidon-lite "0.3.0"
|
||||
|
||||
"@zk-kit/lean-imt@2.2.2":
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@zk-kit/lean-imt/-/lean-imt-2.2.2.tgz#79c8bd70fc0d444638328cb4781479b14c69a9dd"
|
||||
integrity sha512-rscIPEgBBcu9vP/DJ3J+3187G/ObKETl343G5enPawNT81oeQSdHx3e2ZapTC+GfrZ/AS2AHHUOpRS1FfdSwjg==
|
||||
dependencies:
|
||||
"@zk-kit/utils" "1.2.1"
|
||||
|
||||
"@zk-kit/poseidon-cipher@^0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@zk-kit/poseidon-cipher/-/poseidon-cipher-0.3.2.tgz#a2afcc1e4fcfa9db3b245d584183cd7fb7fcd4ab"
|
||||
integrity sha512-Ezz1e0mj/GRDlHdU5m0uhj5iHY72zWJU0BP8DsCCvPubU7LPI2tVaPpxrAjT4JQqatbVRQHLIhixW7F7BPzaFg==
|
||||
dependencies:
|
||||
"@zk-kit/baby-jubjub" "1.0.3"
|
||||
"@zk-kit/utils" "1.2.1"
|
||||
|
||||
"@zk-kit/utils@1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@zk-kit/utils/-/utils-1.2.1.tgz#6cb38120535c73ab68cd0f09684882af148f256d"
|
||||
integrity sha512-H2nTsyWdicVOyvqC5AjgU7tsTgmR6PDrruFJNmlmdhKp7RxEia/E1B1swMZjaasYa2QMp4Zc6oB7cWchty7B2Q==
|
||||
dependencies:
|
||||
buffer "^6.0.3"
|
||||
|
||||
abitype@1.0.8, abitype@^1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.8.tgz#3554f28b2e9d6e9f35eb59878193eabd1b9f46ba"
|
||||
integrity sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==
|
||||
|
||||
aes-js@4.0.0-beta.5:
|
||||
version "4.0.0-beta.5"
|
||||
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873"
|
||||
integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==
|
||||
|
||||
ansi-styles@^4.1.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
|
||||
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
async@^3.2.3:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce"
|
||||
integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==
|
||||
|
||||
b4a@^1.0.1:
|
||||
version "1.6.7"
|
||||
resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.7.tgz#a99587d4ebbfbd5a6e3b21bdb5d5fa385767abe4"
|
||||
integrity sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
base64-js@^1.3.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
bfj@^7.0.2:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.1.0.tgz#c5177d522103f9040e1b12980fe8c38cf41d3f8b"
|
||||
integrity sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==
|
||||
dependencies:
|
||||
bluebird "^3.7.2"
|
||||
check-types "^11.2.3"
|
||||
hoopy "^0.1.4"
|
||||
jsonpath "^1.1.1"
|
||||
tryer "^1.0.1"
|
||||
|
||||
blake2b-wasm@^2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/blake2b-wasm/-/blake2b-wasm-2.4.0.tgz#9115649111edbbd87eb24ce7c04b427e4e2be5be"
|
||||
integrity sha512-S1kwmW2ZhZFFFOghcx73+ZajEfKBqhP82JMssxtLVMxlaPea1p9uoLiUZ5WYyHn0KddwbLc+0vh4wR0KBNoT5w==
|
||||
dependencies:
|
||||
b4a "^1.0.1"
|
||||
nanoassert "^2.0.0"
|
||||
|
||||
blakejs@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814"
|
||||
integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==
|
||||
|
||||
bluebird@^3.7.2:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
||||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
brace-expansion@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
|
||||
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
|
||||
buffer@6.0.3, buffer@^6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
|
||||
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
|
||||
dependencies:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.2.1"
|
||||
|
||||
chalk@^4.0.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
check-types@^11.2.3:
|
||||
version "11.2.3"
|
||||
resolved "https://registry.yarnpkg.com/check-types/-/check-types-11.2.3.tgz#1ffdf68faae4e941fce252840b1787b8edc93b71"
|
||||
integrity sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==
|
||||
|
||||
circom_runtime@0.1.28:
|
||||
version "0.1.28"
|
||||
resolved "https://registry.yarnpkg.com/circom_runtime/-/circom_runtime-0.1.28.tgz#4ea4606956eeac4499f71f65354f45b54faa93fe"
|
||||
integrity sha512-ACagpQ7zBRLKDl5xRZ4KpmYIcZDUjOiNRuxvXLqhnnlLSVY1Dbvh73TI853nqoR0oEbihtWmMSjgc5f+pXf/jQ==
|
||||
dependencies:
|
||||
ffjavascript "0.3.1"
|
||||
|
||||
color-convert@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
|
||||
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
|
||||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||
|
||||
deep-is@~0.1.3:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
|
||||
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
|
||||
|
||||
ejs@^3.1.6:
|
||||
version "3.1.10"
|
||||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b"
|
||||
integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==
|
||||
dependencies:
|
||||
jake "^10.8.5"
|
||||
|
||||
escodegen@^1.8.1:
|
||||
version "1.14.3"
|
||||
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
|
||||
integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
|
||||
dependencies:
|
||||
esprima "^4.0.1"
|
||||
estraverse "^4.2.0"
|
||||
esutils "^2.0.2"
|
||||
optionator "^0.8.1"
|
||||
optionalDependencies:
|
||||
source-map "~0.6.1"
|
||||
|
||||
esprima@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.2.2.tgz#76a0fd66fcfe154fd292667dc264019750b1657b"
|
||||
integrity sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==
|
||||
|
||||
esprima@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
||||
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
|
||||
|
||||
estraverse@^4.2.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
|
||||
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
|
||||
|
||||
esutils@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
ethers@^6.13.4:
|
||||
version "6.14.3"
|
||||
resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.14.3.tgz#7c4443c165ee59b2964e691600fd4586004b2000"
|
||||
integrity sha512-qq7ft/oCJohoTcsNPFaXSQUm457MA5iWqkf1Mb11ujONdg7jBI6sAOrHaTi3j0CBqIGFSCeR/RMc+qwRRub7IA==
|
||||
dependencies:
|
||||
"@adraffy/ens-normalize" "1.10.1"
|
||||
"@noble/curves" "1.2.0"
|
||||
"@noble/hashes" "1.3.2"
|
||||
"@types/node" "22.7.5"
|
||||
aes-js "4.0.0-beta.5"
|
||||
tslib "2.7.0"
|
||||
ws "8.17.1"
|
||||
|
||||
eventemitter3@5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
|
||||
integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
|
||||
|
||||
fast-levenshtein@~2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
||||
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
||||
|
||||
fastfile@0.0.20:
|
||||
version "0.0.20"
|
||||
resolved "https://registry.yarnpkg.com/fastfile/-/fastfile-0.0.20.tgz#794a143d58cfda2e24c298e5ef619c748c8a1879"
|
||||
integrity sha512-r5ZDbgImvVWCP0lA/cGNgQcZqR+aYdFx3u+CtJqUE510pBUVGMn4ulL/iRTI4tACTYsNJ736uzFxEBXesPAktA==
|
||||
|
||||
ffjavascript@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ffjavascript/-/ffjavascript-0.3.0.tgz#442cd8fbb1ee4cbb1be9d26fd7b2951a1ea45d6a"
|
||||
integrity sha512-l7sR5kmU3gRwDy8g0Z2tYBXy5ttmafRPFOqY7S6af5cq51JqJWt5eQ/lSR/rs2wQNbDYaYlQr5O+OSUf/oMLoQ==
|
||||
dependencies:
|
||||
wasmbuilder "0.0.16"
|
||||
wasmcurves "0.2.2"
|
||||
web-worker "1.2.0"
|
||||
|
||||
ffjavascript@0.3.1, ffjavascript@^0.3.0:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/ffjavascript/-/ffjavascript-0.3.1.tgz#3761bbb3f4a67b58a94a463080272bf6b5877b03"
|
||||
integrity sha512-4PbK1WYodQtuF47D4pRI5KUg3Q392vuP5WjE1THSnceHdXwU3ijaoS0OqxTzLknCtz4Z2TtABzkBdBdMn3B/Aw==
|
||||
dependencies:
|
||||
wasmbuilder "0.0.16"
|
||||
wasmcurves "0.2.2"
|
||||
web-worker "1.2.0"
|
||||
|
||||
filelist@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5"
|
||||
integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==
|
||||
dependencies:
|
||||
minimatch "^5.0.1"
|
||||
|
||||
has-flag@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
hoopy@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
|
||||
integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==
|
||||
|
||||
ieee754@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
isows@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.6.tgz#0da29d706fa51551c663c627ace42769850f86e7"
|
||||
integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==
|
||||
|
||||
jake@^10.8.5:
|
||||
version "10.9.2"
|
||||
resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f"
|
||||
integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==
|
||||
dependencies:
|
||||
async "^3.2.3"
|
||||
chalk "^4.0.2"
|
||||
filelist "^1.0.4"
|
||||
minimatch "^3.1.2"
|
||||
|
||||
js-sha3@^0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
|
||||
integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
|
||||
|
||||
jsonpath@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonpath/-/jsonpath-1.1.1.tgz#0ca1ed8fb65bb3309248cc9d5466d12d5b0b9901"
|
||||
integrity sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==
|
||||
dependencies:
|
||||
esprima "1.2.2"
|
||||
static-eval "2.0.2"
|
||||
underscore "1.12.1"
|
||||
|
||||
levn@~0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
|
||||
integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==
|
||||
dependencies:
|
||||
prelude-ls "~1.1.2"
|
||||
type-check "~0.3.2"
|
||||
|
||||
logplease@^1.2.15:
|
||||
version "1.2.15"
|
||||
resolved "https://registry.yarnpkg.com/logplease/-/logplease-1.2.15.tgz#3da442e93751a5992cc19010a826b08d0293c48a"
|
||||
integrity sha512-jLlHnlsPSJjpwUfcNyUxXCl33AYg2cHhIf9QhGL2T4iPT0XPB+xP1LRKFPgIg1M/sg9kAJvy94w9CzBNrfnstA==
|
||||
|
||||
maci-crypto@2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/maci-crypto/-/maci-crypto-2.5.0.tgz#89a99921517b79564af8a356863c446b49e4cb0f"
|
||||
integrity sha512-ozrLDH6kaK62TomNr5tnVgrUs6szXHCwcRyPzsQy07Wg2ZX61nyY0EFgWKAuU8kXqvYRdTtQdgflw6qpVz/4+w==
|
||||
dependencies:
|
||||
"@zk-kit/baby-jubjub" "^1.0.3"
|
||||
"@zk-kit/eddsa-poseidon" "^1.1.0"
|
||||
"@zk-kit/poseidon-cipher" "^0.3.2"
|
||||
ethers "^6.13.4"
|
||||
|
||||
minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@^5.0.1:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
|
||||
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimist@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||
|
||||
nanoassert@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nanoassert/-/nanoassert-2.0.0.tgz#a05f86de6c7a51618038a620f88878ed1e490c09"
|
||||
integrity sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==
|
||||
|
||||
optionator@^0.8.1:
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
|
||||
integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
|
||||
dependencies:
|
||||
deep-is "~0.1.3"
|
||||
fast-levenshtein "~2.0.6"
|
||||
levn "~0.3.0"
|
||||
prelude-ls "~1.1.2"
|
||||
type-check "~0.3.2"
|
||||
word-wrap "~1.2.3"
|
||||
|
||||
ox@0.6.7:
|
||||
version "0.6.7"
|
||||
resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.7.tgz#afd53f2ecef68b8526660e9d29dee6e6b599a832"
|
||||
@@ -76,11 +486,98 @@ ox@0.6.7:
|
||||
abitype "^1.0.6"
|
||||
eventemitter3 "5.0.1"
|
||||
|
||||
poseidon-lite@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/poseidon-lite/-/poseidon-lite-0.3.0.tgz#93c42f6f9b870f154f2722dfd686b909c4285765"
|
||||
integrity sha512-ilJj4MIve4uBEG7SrtPqUUNkvpJ/pLVbndxa0WvebcQqeIhe+h72JR4g0EvwchUzm9sOQDlOjiDNmRAgxNZl4A==
|
||||
|
||||
prelude-ls@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||
integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==
|
||||
|
||||
r1csfile@0.0.48:
|
||||
version "0.0.48"
|
||||
resolved "https://registry.yarnpkg.com/r1csfile/-/r1csfile-0.0.48.tgz#a317fc75407a9da92631666c75bdfc13f0a7835a"
|
||||
integrity sha512-kHRkKUJNaor31l05f2+RFzvcH5XSa7OfEfd/l4hzjte6NL6fjRkSMfZ4BjySW9wmfdwPOtq3mXurzPvPGEf5Tw==
|
||||
dependencies:
|
||||
"@iden3/bigarray" "0.0.2"
|
||||
"@iden3/binfileutils" "0.0.12"
|
||||
fastfile "0.0.20"
|
||||
ffjavascript "0.3.0"
|
||||
|
||||
snarkjs@0.7.5:
|
||||
version "0.7.5"
|
||||
resolved "https://registry.yarnpkg.com/snarkjs/-/snarkjs-0.7.5.tgz#334d83b61468bdffbbf922b20734ca47be50b8ab"
|
||||
integrity sha512-h+3c4rXZKLhLuHk4LHydZCk/h5GcNvk5GjVKRRkHmfb6Ntf8gHOA9zea3g656iclRuhqQ3iKDWFgiD9ypLrKiA==
|
||||
dependencies:
|
||||
"@iden3/binfileutils" "0.0.12"
|
||||
bfj "^7.0.2"
|
||||
blake2b-wasm "^2.4.0"
|
||||
circom_runtime "0.1.28"
|
||||
ejs "^3.1.6"
|
||||
fastfile "0.0.20"
|
||||
ffjavascript "0.3.1"
|
||||
js-sha3 "^0.8.0"
|
||||
logplease "^1.2.15"
|
||||
r1csfile "0.0.48"
|
||||
|
||||
source-map@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
static-eval@2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.2.tgz#2d1759306b1befa688938454c546b7871f806a42"
|
||||
integrity sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==
|
||||
dependencies:
|
||||
escodegen "^1.8.1"
|
||||
|
||||
supports-color@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
tryer@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
|
||||
integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==
|
||||
|
||||
tslib@2.7.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01"
|
||||
integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==
|
||||
|
||||
type-check@~0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
|
||||
integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==
|
||||
dependencies:
|
||||
prelude-ls "~1.1.2"
|
||||
|
||||
typescript@5.5.4:
|
||||
version "5.5.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba"
|
||||
integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==
|
||||
|
||||
typescript@^5.7.3:
|
||||
version "5.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
|
||||
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
|
||||
|
||||
underscore@1.12.1:
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e"
|
||||
integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==
|
||||
|
||||
undici-types@~6.19.2:
|
||||
version "6.19.8"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
|
||||
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
|
||||
|
||||
undici-types@~6.20.0:
|
||||
version "6.20.0"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
|
||||
@@ -100,6 +597,33 @@ viem@2.22.14:
|
||||
ox "0.6.7"
|
||||
ws "8.18.0"
|
||||
|
||||
wasmbuilder@0.0.16:
|
||||
version "0.0.16"
|
||||
resolved "https://registry.yarnpkg.com/wasmbuilder/-/wasmbuilder-0.0.16.tgz#f34c1f2c047d2f6e1065cbfec5603988f16d8549"
|
||||
integrity sha512-Qx3lEFqaVvp1cEYW7Bfi+ebRJrOiwz2Ieu7ZG2l7YyeSJIok/reEQCQCuicj/Y32ITIJuGIM9xZQppGx5LrQdA==
|
||||
|
||||
wasmcurves@0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/wasmcurves/-/wasmcurves-0.2.2.tgz#ca444f6a6f6e2a5cbe6629d98ff478a62b4ccb2b"
|
||||
integrity sha512-JRY908NkmKjFl4ytnTu5ED6AwPD+8VJ9oc94kdq7h5bIwbj0L4TDJ69mG+2aLs2SoCmGfqIesMWTEJjtYsoQXQ==
|
||||
dependencies:
|
||||
wasmbuilder "0.0.16"
|
||||
|
||||
web-worker@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.2.0.tgz#5d85a04a7fbc1e7db58f66595d7a3ac7c9c180da"
|
||||
integrity sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==
|
||||
|
||||
word-wrap@~1.2.3:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
|
||||
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
|
||||
|
||||
ws@8.17.1:
|
||||
version "8.17.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b"
|
||||
integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==
|
||||
|
||||
ws@8.18.0:
|
||||
version "8.18.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
|
||||
|
||||
@@ -58,12 +58,13 @@ const withdrawalPayload = {
|
||||
data: "0xfeeMismatch",
|
||||
},
|
||||
proof: {
|
||||
pi_a: ["0", "0"],
|
||||
pi_a: ["0", "0", "0"],
|
||||
pi_b: [
|
||||
["0", "0"],
|
||||
["0", "0"],
|
||||
["0", "0"],
|
||||
],
|
||||
pi_c: ["0", "0"],
|
||||
pi_c: ["0", "0", "0"],
|
||||
protocol: "groth16",
|
||||
curve: "bn128",
|
||||
},
|
||||
@@ -119,6 +120,7 @@ describe("relayRequestHandler", () => {
|
||||
vi.spyOn(privacyPoolRelayer, "handleRequest").mockResolvedValue(undefined);
|
||||
await relayRequestHandler(req, resMock, nextMock);
|
||||
const error = nextMock.mock.calls[0][0]
|
||||
console.log(error)
|
||||
expect(error).toBeInstanceOf(ConfigError)
|
||||
expect(error.code).toEqual(ErrorCode.MAX_GAS_PRICE);
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"declarationMap": true,
|
||||
"declaration": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
/* Base Options: */
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
@@ -26,5 +27,5 @@
|
||||
"lib": ["es2022"]
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "test"]
|
||||
"exclude": ["node_modules", "dist", "test", "coverage"]
|
||||
}
|
||||
|
||||
310
yarn.lock
310
yarn.lock
@@ -576,7 +576,7 @@
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@ethersproject/abi@^5.5.0":
|
||||
"@ethersproject/abi@5.8.0", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.8.0.tgz#e79bb51940ac35fe6f3262d7fe2cdb25ad5f07d9"
|
||||
integrity sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==
|
||||
@@ -604,7 +604,7 @@
|
||||
"@ethersproject/transactions" "^5.7.0"
|
||||
"@ethersproject/web" "^5.7.0"
|
||||
|
||||
"@ethersproject/abstract-provider@^5.8.0":
|
||||
"@ethersproject/abstract-provider@5.8.0", "@ethersproject/abstract-provider@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz#7581f9be601afa1d02b95d26b9d9840926a35b0c"
|
||||
integrity sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==
|
||||
@@ -628,7 +628,7 @@
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
|
||||
"@ethersproject/abstract-signer@^5.8.0":
|
||||
"@ethersproject/abstract-signer@5.8.0", "@ethersproject/abstract-signer@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz#8d7417e95e4094c1797a9762e6789c7356db0754"
|
||||
integrity sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==
|
||||
@@ -650,7 +650,7 @@
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/rlp" "^5.7.0"
|
||||
|
||||
"@ethersproject/address@^5.0.2", "@ethersproject/address@^5.8.0":
|
||||
"@ethersproject/address@5.8.0", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.8.0.tgz#3007a2c352eee566ad745dca1dbbebdb50a6a983"
|
||||
integrity sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==
|
||||
@@ -668,7 +668,7 @@
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
|
||||
"@ethersproject/base64@^5.8.0":
|
||||
"@ethersproject/base64@5.8.0", "@ethersproject/base64@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.8.0.tgz#61c669c648f6e6aad002c228465d52ac93ee83eb"
|
||||
integrity sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==
|
||||
@@ -683,6 +683,14 @@
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
|
||||
"@ethersproject/basex@5.8.0", "@ethersproject/basex@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.8.0.tgz#1d279a90c4be84d1c1139114a1f844869e57d03a"
|
||||
integrity sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.8.0"
|
||||
"@ethersproject/properties" "^5.8.0"
|
||||
|
||||
"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2"
|
||||
@@ -692,7 +700,7 @@
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
bn.js "^5.2.1"
|
||||
|
||||
"@ethersproject/bignumber@^5.8.0":
|
||||
"@ethersproject/bignumber@5.8.0", "@ethersproject/bignumber@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.8.0.tgz#c381d178f9eeb370923d389284efa19f69efa5d7"
|
||||
integrity sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==
|
||||
@@ -708,7 +716,7 @@
|
||||
dependencies:
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/bytes@^5.8.0":
|
||||
"@ethersproject/bytes@5.8.0", "@ethersproject/bytes@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.8.0.tgz#9074820e1cac7507a34372cadeb035461463be34"
|
||||
integrity sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==
|
||||
@@ -722,7 +730,7 @@
|
||||
dependencies:
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
|
||||
"@ethersproject/constants@^5.8.0":
|
||||
"@ethersproject/constants@5.8.0", "@ethersproject/constants@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.8.0.tgz#12f31c2f4317b113a4c19de94e50933648c90704"
|
||||
integrity sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==
|
||||
@@ -745,6 +753,22 @@
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/transactions" "^5.7.0"
|
||||
|
||||
"@ethersproject/contracts@5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.8.0.tgz#243a38a2e4aa3e757215ea64e276f8a8c9d8ed73"
|
||||
integrity sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==
|
||||
dependencies:
|
||||
"@ethersproject/abi" "^5.8.0"
|
||||
"@ethersproject/abstract-provider" "^5.8.0"
|
||||
"@ethersproject/abstract-signer" "^5.8.0"
|
||||
"@ethersproject/address" "^5.8.0"
|
||||
"@ethersproject/bignumber" "^5.8.0"
|
||||
"@ethersproject/bytes" "^5.8.0"
|
||||
"@ethersproject/constants" "^5.8.0"
|
||||
"@ethersproject/logger" "^5.8.0"
|
||||
"@ethersproject/properties" "^5.8.0"
|
||||
"@ethersproject/transactions" "^5.8.0"
|
||||
|
||||
"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7"
|
||||
@@ -760,7 +784,7 @@
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@ethersproject/hash@^5.8.0":
|
||||
"@ethersproject/hash@5.8.0", "@ethersproject/hash@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.8.0.tgz#b8893d4629b7f8462a90102572f8cd65a0192b4c"
|
||||
integrity sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==
|
||||
@@ -793,6 +817,24 @@
|
||||
"@ethersproject/transactions" "^5.7.0"
|
||||
"@ethersproject/wordlists" "^5.7.0"
|
||||
|
||||
"@ethersproject/hdnode@5.8.0", "@ethersproject/hdnode@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.8.0.tgz#a51ae2a50bcd48ef6fd108c64cbae5e6ff34a761"
|
||||
integrity sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-signer" "^5.8.0"
|
||||
"@ethersproject/basex" "^5.8.0"
|
||||
"@ethersproject/bignumber" "^5.8.0"
|
||||
"@ethersproject/bytes" "^5.8.0"
|
||||
"@ethersproject/logger" "^5.8.0"
|
||||
"@ethersproject/pbkdf2" "^5.8.0"
|
||||
"@ethersproject/properties" "^5.8.0"
|
||||
"@ethersproject/sha2" "^5.8.0"
|
||||
"@ethersproject/signing-key" "^5.8.0"
|
||||
"@ethersproject/strings" "^5.8.0"
|
||||
"@ethersproject/transactions" "^5.8.0"
|
||||
"@ethersproject/wordlists" "^5.8.0"
|
||||
|
||||
"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360"
|
||||
@@ -812,6 +854,25 @@
|
||||
aes-js "3.0.0"
|
||||
scrypt-js "3.0.1"
|
||||
|
||||
"@ethersproject/json-wallets@5.8.0", "@ethersproject/json-wallets@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.8.0.tgz#d18de0a4cf0f185f232eb3c17d5e0744d97eb8c9"
|
||||
integrity sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-signer" "^5.8.0"
|
||||
"@ethersproject/address" "^5.8.0"
|
||||
"@ethersproject/bytes" "^5.8.0"
|
||||
"@ethersproject/hdnode" "^5.8.0"
|
||||
"@ethersproject/keccak256" "^5.8.0"
|
||||
"@ethersproject/logger" "^5.8.0"
|
||||
"@ethersproject/pbkdf2" "^5.8.0"
|
||||
"@ethersproject/properties" "^5.8.0"
|
||||
"@ethersproject/random" "^5.8.0"
|
||||
"@ethersproject/strings" "^5.8.0"
|
||||
"@ethersproject/transactions" "^5.8.0"
|
||||
aes-js "3.0.0"
|
||||
scrypt-js "3.0.1"
|
||||
|
||||
"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a"
|
||||
@@ -820,7 +881,7 @@
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
js-sha3 "0.8.0"
|
||||
|
||||
"@ethersproject/keccak256@^5.8.0":
|
||||
"@ethersproject/keccak256@5.8.0", "@ethersproject/keccak256@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.8.0.tgz#d2123a379567faf2d75d2aaea074ffd4df349e6a"
|
||||
integrity sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==
|
||||
@@ -833,7 +894,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892"
|
||||
integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==
|
||||
|
||||
"@ethersproject/logger@^5.8.0":
|
||||
"@ethersproject/logger@5.8.0", "@ethersproject/logger@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.8.0.tgz#f0232968a4f87d29623a0481690a2732662713d6"
|
||||
integrity sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==
|
||||
@@ -845,7 +906,7 @@
|
||||
dependencies:
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/networks@^5.8.0":
|
||||
"@ethersproject/networks@5.8.0", "@ethersproject/networks@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.8.0.tgz#8b4517a3139380cba9fb00b63ffad0a979671fde"
|
||||
integrity sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==
|
||||
@@ -860,6 +921,14 @@
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/sha2" "^5.7.0"
|
||||
|
||||
"@ethersproject/pbkdf2@5.8.0", "@ethersproject/pbkdf2@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.8.0.tgz#cd2621130e5dd51f6a0172e63a6e4a0c0a0ec37e"
|
||||
integrity sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.8.0"
|
||||
"@ethersproject/sha2" "^5.8.0"
|
||||
|
||||
"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30"
|
||||
@@ -867,7 +936,7 @@
|
||||
dependencies:
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/properties@^5.8.0":
|
||||
"@ethersproject/properties@5.8.0", "@ethersproject/properties@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.8.0.tgz#405a8affb6311a49a91dabd96aeeae24f477020e"
|
||||
integrity sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==
|
||||
@@ -900,6 +969,32 @@
|
||||
bech32 "1.1.4"
|
||||
ws "7.4.6"
|
||||
|
||||
"@ethersproject/providers@5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.8.0.tgz#6c2ae354f7f96ee150439f7de06236928bc04cb4"
|
||||
integrity sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-provider" "^5.8.0"
|
||||
"@ethersproject/abstract-signer" "^5.8.0"
|
||||
"@ethersproject/address" "^5.8.0"
|
||||
"@ethersproject/base64" "^5.8.0"
|
||||
"@ethersproject/basex" "^5.8.0"
|
||||
"@ethersproject/bignumber" "^5.8.0"
|
||||
"@ethersproject/bytes" "^5.8.0"
|
||||
"@ethersproject/constants" "^5.8.0"
|
||||
"@ethersproject/hash" "^5.8.0"
|
||||
"@ethersproject/logger" "^5.8.0"
|
||||
"@ethersproject/networks" "^5.8.0"
|
||||
"@ethersproject/properties" "^5.8.0"
|
||||
"@ethersproject/random" "^5.8.0"
|
||||
"@ethersproject/rlp" "^5.8.0"
|
||||
"@ethersproject/sha2" "^5.8.0"
|
||||
"@ethersproject/strings" "^5.8.0"
|
||||
"@ethersproject/transactions" "^5.8.0"
|
||||
"@ethersproject/web" "^5.8.0"
|
||||
bech32 "1.1.4"
|
||||
ws "8.18.0"
|
||||
|
||||
"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c"
|
||||
@@ -908,6 +1003,14 @@
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/random@5.8.0", "@ethersproject/random@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.8.0.tgz#1bced04d49449f37c6437c701735a1a022f0057a"
|
||||
integrity sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.8.0"
|
||||
"@ethersproject/logger" "^5.8.0"
|
||||
|
||||
"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304"
|
||||
@@ -916,7 +1019,7 @@
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/rlp@^5.8.0":
|
||||
"@ethersproject/rlp@5.8.0", "@ethersproject/rlp@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.8.0.tgz#5a0d49f61bc53e051532a5179472779141451de5"
|
||||
integrity sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==
|
||||
@@ -933,7 +1036,7 @@
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
hash.js "1.1.7"
|
||||
|
||||
"@ethersproject/sha2@^5.8.0":
|
||||
"@ethersproject/sha2@5.8.0", "@ethersproject/sha2@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.8.0.tgz#8954a613bb78dac9b46829c0a95de561ef74e5e1"
|
||||
integrity sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==
|
||||
@@ -954,7 +1057,7 @@
|
||||
elliptic "6.5.4"
|
||||
hash.js "1.1.7"
|
||||
|
||||
"@ethersproject/signing-key@^5.8.0":
|
||||
"@ethersproject/signing-key@5.8.0", "@ethersproject/signing-key@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.8.0.tgz#9797e02c717b68239c6349394ea85febf8893119"
|
||||
integrity sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==
|
||||
@@ -978,7 +1081,7 @@
|
||||
"@ethersproject/sha2" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@ethersproject/solidity@^5.0.9":
|
||||
"@ethersproject/solidity@5.8.0", "@ethersproject/solidity@^5.0.9":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.8.0.tgz#429bb9fcf5521307a9448d7358c26b93695379b9"
|
||||
integrity sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA==
|
||||
@@ -999,7 +1102,7 @@
|
||||
"@ethersproject/constants" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/strings@^5.8.0":
|
||||
"@ethersproject/strings@5.8.0", "@ethersproject/strings@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.8.0.tgz#ad79fafbf0bd272d9765603215ac74fd7953908f"
|
||||
integrity sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==
|
||||
@@ -1023,7 +1126,7 @@
|
||||
"@ethersproject/rlp" "^5.7.0"
|
||||
"@ethersproject/signing-key" "^5.7.0"
|
||||
|
||||
"@ethersproject/transactions@^5.8.0":
|
||||
"@ethersproject/transactions@5.8.0", "@ethersproject/transactions@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.8.0.tgz#1e518822403abc99def5a043d1c6f6fe0007e46b"
|
||||
integrity sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==
|
||||
@@ -1047,6 +1150,15 @@
|
||||
"@ethersproject/constants" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/units@5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.8.0.tgz#c12f34ba7c3a2de0e9fa0ed0ee32f3e46c5c2c6a"
|
||||
integrity sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==
|
||||
dependencies:
|
||||
"@ethersproject/bignumber" "^5.8.0"
|
||||
"@ethersproject/constants" "^5.8.0"
|
||||
"@ethersproject/logger" "^5.8.0"
|
||||
|
||||
"@ethersproject/wallet@5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d"
|
||||
@@ -1068,6 +1180,27 @@
|
||||
"@ethersproject/transactions" "^5.7.0"
|
||||
"@ethersproject/wordlists" "^5.7.0"
|
||||
|
||||
"@ethersproject/wallet@5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.8.0.tgz#49c300d10872e6986d953e8310dc33d440da8127"
|
||||
integrity sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-provider" "^5.8.0"
|
||||
"@ethersproject/abstract-signer" "^5.8.0"
|
||||
"@ethersproject/address" "^5.8.0"
|
||||
"@ethersproject/bignumber" "^5.8.0"
|
||||
"@ethersproject/bytes" "^5.8.0"
|
||||
"@ethersproject/hash" "^5.8.0"
|
||||
"@ethersproject/hdnode" "^5.8.0"
|
||||
"@ethersproject/json-wallets" "^5.8.0"
|
||||
"@ethersproject/keccak256" "^5.8.0"
|
||||
"@ethersproject/logger" "^5.8.0"
|
||||
"@ethersproject/properties" "^5.8.0"
|
||||
"@ethersproject/random" "^5.8.0"
|
||||
"@ethersproject/signing-key" "^5.8.0"
|
||||
"@ethersproject/transactions" "^5.8.0"
|
||||
"@ethersproject/wordlists" "^5.8.0"
|
||||
|
||||
"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0":
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae"
|
||||
@@ -1079,7 +1212,7 @@
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@ethersproject/web@^5.8.0":
|
||||
"@ethersproject/web@5.8.0", "@ethersproject/web@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.8.0.tgz#3e54badc0013b7a801463a7008a87988efce8a37"
|
||||
integrity sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==
|
||||
@@ -1101,6 +1234,17 @@
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@ethersproject/wordlists@5.8.0", "@ethersproject/wordlists@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.8.0.tgz#7a5654ee8d1bb1f4dbe43f91d217356d650ad821"
|
||||
integrity sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.8.0"
|
||||
"@ethersproject/hash" "^5.8.0"
|
||||
"@ethersproject/logger" "^5.8.0"
|
||||
"@ethersproject/properties" "^5.8.0"
|
||||
"@ethersproject/strings" "^5.8.0"
|
||||
|
||||
"@gar/promisify@^1.0.1":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
|
||||
@@ -1349,6 +1493,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.2-solc-0.7.tgz#38f4dbab672631034076ccdf2f3201fab1726635"
|
||||
integrity sha512-W6QmqgkADuFcTLzHL8vVoNBtkwjvQRpYIAom7KiUNoLKghyx3FgH0GBjt8NRvigV1ZmMOBllvE1By1C+bi8WpA==
|
||||
|
||||
"@openzeppelin/contracts@4.7.0":
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.0.tgz#3092d70ea60e3d1835466266b1d68ad47035a2d5"
|
||||
integrity sha512-52Qb+A1DdOss8QvJrijYYPSf32GUg2pGaG/yCxtaA3cu4jduouTdg4XZSMLW9op54m1jH7J8hoajhHKOPsoJFw==
|
||||
|
||||
"@openzeppelin/contracts@5.0.2":
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.2.tgz#b1d03075e49290d06570b2fd42154d76c2a5d210"
|
||||
integrity sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==
|
||||
|
||||
"@openzeppelin/contracts@5.1.0":
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.1.0.tgz#4e61162f2a2bf414c4e10c45eca98ce5f1aadbd4"
|
||||
@@ -1937,7 +2091,27 @@
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/lib/-/lib-4.0.1-alpha.tgz#2881008e55f075344675b3bca93f020b028fbd02"
|
||||
integrity sha512-f6UIliwBbRsgVLxIaBANF6w09tYqc6Y/qXdsrbEmXHyFA7ILiKrIwRFXe1yOg8M3cksgVsO9N7yuL2DdCGQKBA==
|
||||
|
||||
"@uniswap/sdk-core@^7.7.1":
|
||||
"@uniswap/permit2-sdk@^1.3.0":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/permit2-sdk/-/permit2-sdk-1.3.1.tgz#831ced0240e2f9f323c53b9a0366e92ae351b2b8"
|
||||
integrity sha512-Eq2by4zVEVSZL3PJ1Yuf5+AZ/yE1GOuksWzPXPoxr5WRm3hqh34jKEqtyTImHqwuPrdILG8i02xJmgGLTH1QfA==
|
||||
dependencies:
|
||||
ethers "^5.7.0"
|
||||
tiny-invariant "^1.1.0"
|
||||
|
||||
"@uniswap/router-sdk@^2.0.2":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/router-sdk/-/router-sdk-2.0.3.tgz#4f7e1398bb4f9e01128810205e3b39e7f0ac091f"
|
||||
integrity sha512-LWDdkpg8qS3wGtLetNojQPdGvBDb9ZSJ9XePmFQhqy2VR/YcERcAsLEjVAKhObPxkazjULIIlmf2yIsCAYzX/w==
|
||||
dependencies:
|
||||
"@ethersproject/abi" "^5.5.0"
|
||||
"@uniswap/sdk-core" "^7.7.2"
|
||||
"@uniswap/swap-router-contracts" "^1.3.0"
|
||||
"@uniswap/v2-sdk" "^4.15.2"
|
||||
"@uniswap/v3-sdk" "^3.25.2"
|
||||
"@uniswap/v4-sdk" "^1.21.2"
|
||||
|
||||
"@uniswap/sdk-core@7.7.2", "@uniswap/sdk-core@^7.7.1", "@uniswap/sdk-core@^7.7.2":
|
||||
version "7.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/sdk-core/-/sdk-core-7.7.2.tgz#dc3a9b63b343640754860dce05d06972815eaee6"
|
||||
integrity sha512-0KqXw+y0opBo6eoPAEoLHEkNpOu0NG9gEk7GAYIGok+SHX89WlykWsRYeJKTg9tOwhLpcG9oHg8xZgQ390iOrA==
|
||||
@@ -1964,11 +2138,49 @@
|
||||
dotenv "^14.2.0"
|
||||
hardhat-watcher "^2.1.1"
|
||||
|
||||
"@uniswap/v2-core@^1.0.1":
|
||||
"@uniswap/universal-router-sdk@4.19.5":
|
||||
version "4.19.5"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/universal-router-sdk/-/universal-router-sdk-4.19.5.tgz#6c11ad0168e33c652014caffe21bf8c462253b14"
|
||||
integrity sha512-FpfvTrJnvxhLdfX1N+GqOfAbHEsbFHP7J3JbpSAFWl3QDW63BB1/rqgW3E17xQha+WnPdP7uMLHwe7oi6mr39Q==
|
||||
dependencies:
|
||||
"@openzeppelin/contracts" "4.7.0"
|
||||
"@uniswap/permit2-sdk" "^1.3.0"
|
||||
"@uniswap/router-sdk" "^2.0.2"
|
||||
"@uniswap/sdk-core" "^7.7.1"
|
||||
"@uniswap/universal-router" "2.0.0-beta.2"
|
||||
"@uniswap/v2-core" "^1.0.1"
|
||||
"@uniswap/v2-sdk" "^4.15.2"
|
||||
"@uniswap/v3-core" "1.0.0"
|
||||
"@uniswap/v3-sdk" "^3.25.2"
|
||||
"@uniswap/v4-sdk" "^1.21.2"
|
||||
bignumber.js "^9.0.2"
|
||||
ethers "^5.7.0"
|
||||
|
||||
"@uniswap/universal-router@2.0.0-beta.2":
|
||||
version "2.0.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/universal-router/-/universal-router-2.0.0-beta.2.tgz#0f891c4772733c356465d8ed2f76a43989ec9092"
|
||||
integrity sha512-/USVkWZrOCjLeZluR7Yk8SpfWDUKG/MLcOyuxuwnqM1xCJj5ekguSYhct+Yfo/3t9fsZcnL8vSYgz0MKqAomGg==
|
||||
dependencies:
|
||||
"@openzeppelin/contracts" "5.0.2"
|
||||
"@uniswap/v2-core" "1.0.1"
|
||||
"@uniswap/v3-core" "1.0.0"
|
||||
|
||||
"@uniswap/v2-core@1.0.1", "@uniswap/v2-core@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/v2-core/-/v2-core-1.0.1.tgz#af8f508bf183204779938969e2e54043e147d425"
|
||||
integrity sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q==
|
||||
|
||||
"@uniswap/v2-sdk@^4.15.2":
|
||||
version "4.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/v2-sdk/-/v2-sdk-4.15.2.tgz#904c09449e9012e6888c44f4cd0cfd8e61c8f4c8"
|
||||
integrity sha512-EtROgWTdhHzw4EUj7SdK9wjppOG7psJ16c656cRuv69nWbD9QyDL2shVcQccEiY7ak9WlJ+bIv/VldybXYBDuw==
|
||||
dependencies:
|
||||
"@ethersproject/address" "^5.0.2"
|
||||
"@ethersproject/solidity" "^5.0.9"
|
||||
"@uniswap/sdk-core" "^7.7.1"
|
||||
tiny-invariant "^1.1.0"
|
||||
tiny-warning "^1.0.3"
|
||||
|
||||
"@uniswap/v3-core@1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0.tgz#6c24adacc4c25dceee0ba3ca142b35adbd7e359d"
|
||||
@@ -1990,7 +2202,7 @@
|
||||
"@uniswap/v3-core" "^1.0.0"
|
||||
base64-sol "1.0.1"
|
||||
|
||||
"@uniswap/v3-sdk@^3.25.2":
|
||||
"@uniswap/v3-sdk@3.25.2", "@uniswap/v3-sdk@^3.25.2":
|
||||
version "3.25.2"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-3.25.2.tgz#cb6ee174b58d86a3b3b18b3ba72f662e58c415da"
|
||||
integrity sha512-0oiyJNGjUVbc958uZmAr+m4XBCjV7PfMs/OUeBv+XDl33MEYF/eH86oBhvqGDM8S/cYaK55tCXzoWkmRUByrHg==
|
||||
@@ -2013,6 +2225,17 @@
|
||||
"@uniswap/v3-core" "1.0.0"
|
||||
"@uniswap/v3-periphery" "^1.0.1"
|
||||
|
||||
"@uniswap/v4-sdk@^1.21.2":
|
||||
version "1.21.4"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/v4-sdk/-/v4-sdk-1.21.4.tgz#b009be0535e757d26fb01af7375ae11e96b6728f"
|
||||
integrity sha512-so3c/CmaRmRSvgKFyrUWy6DCSogyzyVaoYCec/TJ4k2hXlJ8MK4vumcuxtmRr1oMnZ5KmaCPBS12Knb4FC3nsw==
|
||||
dependencies:
|
||||
"@ethersproject/solidity" "^5.0.9"
|
||||
"@uniswap/sdk-core" "^7.7.1"
|
||||
"@uniswap/v3-sdk" "3.25.2"
|
||||
tiny-invariant "^1.1.0"
|
||||
tiny-warning "^1.0.3"
|
||||
|
||||
"@vitest/coverage-v8@3.0.5":
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-3.0.5.tgz#22a5f6730f13703ce6736f7d0032251a3619a300"
|
||||
@@ -2421,6 +2644,11 @@ big.js@^5.2.2:
|
||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
||||
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
|
||||
|
||||
bignumber.js@^9.0.2:
|
||||
version "9.3.0"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.3.0.tgz#bdba7e2a4c1a2eba08290e8dcad4f36393c92acd"
|
||||
integrity sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
|
||||
@@ -3535,6 +3763,42 @@ ethers@^5.5.1:
|
||||
"@ethersproject/web" "5.7.1"
|
||||
"@ethersproject/wordlists" "5.7.0"
|
||||
|
||||
ethers@^5.7.0:
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.8.0.tgz#97858dc4d4c74afce83ea7562fe9493cedb4d377"
|
||||
integrity sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==
|
||||
dependencies:
|
||||
"@ethersproject/abi" "5.8.0"
|
||||
"@ethersproject/abstract-provider" "5.8.0"
|
||||
"@ethersproject/abstract-signer" "5.8.0"
|
||||
"@ethersproject/address" "5.8.0"
|
||||
"@ethersproject/base64" "5.8.0"
|
||||
"@ethersproject/basex" "5.8.0"
|
||||
"@ethersproject/bignumber" "5.8.0"
|
||||
"@ethersproject/bytes" "5.8.0"
|
||||
"@ethersproject/constants" "5.8.0"
|
||||
"@ethersproject/contracts" "5.8.0"
|
||||
"@ethersproject/hash" "5.8.0"
|
||||
"@ethersproject/hdnode" "5.8.0"
|
||||
"@ethersproject/json-wallets" "5.8.0"
|
||||
"@ethersproject/keccak256" "5.8.0"
|
||||
"@ethersproject/logger" "5.8.0"
|
||||
"@ethersproject/networks" "5.8.0"
|
||||
"@ethersproject/pbkdf2" "5.8.0"
|
||||
"@ethersproject/properties" "5.8.0"
|
||||
"@ethersproject/providers" "5.8.0"
|
||||
"@ethersproject/random" "5.8.0"
|
||||
"@ethersproject/rlp" "5.8.0"
|
||||
"@ethersproject/sha2" "5.8.0"
|
||||
"@ethersproject/signing-key" "5.8.0"
|
||||
"@ethersproject/solidity" "5.8.0"
|
||||
"@ethersproject/strings" "5.8.0"
|
||||
"@ethersproject/transactions" "5.8.0"
|
||||
"@ethersproject/units" "5.8.0"
|
||||
"@ethersproject/wallet" "5.8.0"
|
||||
"@ethersproject/web" "5.8.0"
|
||||
"@ethersproject/wordlists" "5.8.0"
|
||||
|
||||
ethers@^6.13.4:
|
||||
version "6.13.5"
|
||||
resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.5.tgz#8c1d6ac988ac08abc3c1d8fabbd4b8b602851ac4"
|
||||
|
||||
Reference in New Issue
Block a user