mirror of
https://github.com/0xbow-io/privacy-pools-core.git
synced 2026-01-10 09:58:00 -05:00
feat: relayer basic implementation (#53)
There are a lot of TODOs related to code quality, mostly happy path assumptions, input sanitization, error handling and tests. Feature wise it's missing the contract interaction (should be straight forward once it's implemented in the SDK) and the sqlite database for request tracking.
This commit is contained in:
@@ -5,8 +5,9 @@ import tseslint from "typescript-eslint";
|
||||
|
||||
/** @type {import('eslint').Linter.Config[]} */
|
||||
export default [
|
||||
{files: ["**/*.{js,mjs,cjs,ts}"]},
|
||||
{languageOptions: { globals: {...globals.browser, ...globals.node} }},
|
||||
{ ignores: ["**/dist/**"] },
|
||||
{ files: ["**/*.{js,mjs,cjs,ts}"] },
|
||||
{ languageOptions: { globals: { ...globals.browser, ...globals.node } } },
|
||||
pluginJs.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
];
|
||||
];
|
||||
|
||||
14
package.json
14
package.json
@@ -9,6 +9,16 @@
|
||||
"workspaces": [
|
||||
"packages/circuits",
|
||||
"packages/contracts",
|
||||
"packages/sdk"
|
||||
]
|
||||
"packages/sdk",
|
||||
"packages/relayer"
|
||||
],
|
||||
"devDependencies": {
|
||||
"prettier": "3.3.3",
|
||||
"@typescript-eslint/eslint-plugin": "7.18.0",
|
||||
"@typescript-eslint/parser": "7.18.0",
|
||||
"eslint": "9.18.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-plugin-prettier": "5.2.1",
|
||||
"typescript-eslint": "8.20.0"
|
||||
}
|
||||
}
|
||||
|
||||
35
packages/relayer/README.md
Normal file
35
packages/relayer/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# ts-turborepo-boilerplate: relayer package
|
||||
|
||||
Description of your package goes here.
|
||||
|
||||
## Setup
|
||||
|
||||
1. Install dependencies running `pnpm install`
|
||||
|
||||
## Available Scripts
|
||||
|
||||
Available scripts that can be run using `pnpm`:
|
||||
|
||||
| Script | Description |
|
||||
| ------------- | ------------------------------------------------------- |
|
||||
| `build` | Build library using tsc |
|
||||
| `check-types` | Check types issues using tsc |
|
||||
| `clean` | Remove `dist` folder |
|
||||
| `lint` | Run ESLint to check for coding standards |
|
||||
| `lint:fix` | Run linter and automatically fix code formatting issues |
|
||||
| `format` | Check code formatting and style using Prettier |
|
||||
| `format:fix` | Run formatter and automatically fix issues |
|
||||
| `test` | Run tests using vitest |
|
||||
| `test:cov` | Run tests with coverage report |
|
||||
|
||||
## Usage
|
||||
|
||||
Describe how to use your package here.
|
||||
|
||||
## API
|
||||
|
||||
Describe your package's API here.
|
||||
|
||||
## References
|
||||
|
||||
Add any relevant references here.
|
||||
43
packages/relayer/package.json
Normal file
43
packages/relayer/package.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "@privacy-pool-core/relayer",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "A simple note relayer",
|
||||
"license": "MIT",
|
||||
"author": "Wonderland",
|
||||
"type": "module",
|
||||
"main": "./dist/src/index.js",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"directories": {
|
||||
"src": "src"
|
||||
},
|
||||
"files": [
|
||||
"dist/*",
|
||||
"package.json",
|
||||
"!**/*.tsbuildinfo"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.build.json",
|
||||
"start": "node ./dist/src/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",
|
||||
"clean": "rm -rf dist/",
|
||||
"format": "prettier --check \"{src,test}/**/*.{js,ts,json}\"",
|
||||
"format:fix": "prettier --write \"{src,test}/**/*.{js,ts,json}\"",
|
||||
"lint": "eslint \"{src,test}/**/*.{js,ts,json}\"",
|
||||
"lint:fix": "eslint \"{src,test}/**/*.{js,ts,json}\" --fix",
|
||||
"test": "vitest run --config vitest.config.ts --passWithNoTests",
|
||||
"test:cov": "vitest run --config vitest.config.ts --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": "8.17.1",
|
||||
"express": "4.21.2",
|
||||
"sqlite": "5.1.1",
|
||||
"sqlite3": "5.1.7",
|
||||
"viem": "2.22.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "5.0.0"
|
||||
}
|
||||
}
|
||||
29
packages/relayer/src/app.ts
Normal file
29
packages/relayer/src/app.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import bodyParser from "body-parser";
|
||||
import express, { NextFunction, Request, Response } from "express";
|
||||
import {
|
||||
errorHandlerMiddleware,
|
||||
marshalResponseMiddleware,
|
||||
notFoundMiddleware,
|
||||
} from "./middlewares/index.js";
|
||||
import { relayerRouter } from "./routes/index.js";
|
||||
|
||||
// Initialize the express app
|
||||
const app = express();
|
||||
|
||||
// Middleware functions
|
||||
const parseJsonMiddleware = bodyParser.json();
|
||||
|
||||
// Apply middleware and routes
|
||||
app.use(parseJsonMiddleware);
|
||||
app.use(marshalResponseMiddleware);
|
||||
|
||||
app.use("/ping", (req: Request, res: Response, next: NextFunction) => {
|
||||
res.send("pong");
|
||||
next();
|
||||
});
|
||||
app.use("/relayer", relayerRouter);
|
||||
|
||||
// Error and 404 handling
|
||||
app.use([errorHandlerMiddleware, notFoundMiddleware]);
|
||||
|
||||
export { app };
|
||||
76
packages/relayer/src/config.ts
Normal file
76
packages/relayer/src/config.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
import { getAddress } from "viem";
|
||||
import { ConfigError } from "./exceptions/base.exception.js";
|
||||
|
||||
const enum ConfigEnv {
|
||||
FEE_RECEIVER_ADDRESS = "FEE_RECEIVER_ADDRESS",
|
||||
PROVIDER_URL = "PROVIDER_URL",
|
||||
SIGNER_PRIVATE_KEY = "SIGNER_PRIVATE_KEY",
|
||||
FEE_BPS = "FEE_BPS",
|
||||
SQLITE_DB_PATH = "SQLITE_DB_PATH",
|
||||
}
|
||||
|
||||
type ConfigEnvString = `${ConfigEnv}`;
|
||||
|
||||
interface ConfigEnvVarChecker {
|
||||
(varNameValue: string): void;
|
||||
}
|
||||
|
||||
function checkConfigVar(
|
||||
varName: ConfigEnvString,
|
||||
checker?: ConfigEnvVarChecker,
|
||||
) {
|
||||
const varNameValue = process.env[varName];
|
||||
if (varNameValue === undefined) {
|
||||
throw ConfigError.default({
|
||||
context: `Environment variable \`${varName}\` is undefined`,
|
||||
});
|
||||
}
|
||||
if (checker) {
|
||||
try {
|
||||
checker(varNameValue);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw ConfigError.default({
|
||||
context: `Environment variable \`${varName}\` has an incorrect format`,
|
||||
});
|
||||
}
|
||||
}
|
||||
return varNameValue;
|
||||
}
|
||||
|
||||
function getFeeReceiverAddress(): string {
|
||||
return checkConfigVar(ConfigEnv.FEE_RECEIVER_ADDRESS, (v) => getAddress(v));
|
||||
}
|
||||
|
||||
function getProviderURL() {
|
||||
// TODO: check provider url format
|
||||
return checkConfigVar(ConfigEnv.PROVIDER_URL);
|
||||
}
|
||||
|
||||
function getSignerPrivateKey() {
|
||||
// TODO: check pk format
|
||||
return checkConfigVar(ConfigEnv.SIGNER_PRIVATE_KEY);
|
||||
}
|
||||
|
||||
function getFeeBps() {
|
||||
// TODO: check feeBPS format
|
||||
return checkConfigVar(ConfigEnv.FEE_BPS);
|
||||
}
|
||||
|
||||
function getSqliteDbPath() {
|
||||
// check path exists of warn of new one
|
||||
return checkConfigVar(ConfigEnv.SQLITE_DB_PATH, (v) => {
|
||||
const dbPath = path.resolve(v);
|
||||
if (!fs.existsSync(v)) {
|
||||
console.log("Creating new DB at", dbPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const FEE_RECEIVER_ADDRESS = getFeeReceiverAddress();
|
||||
export const PROVIDER_URL = getProviderURL();
|
||||
export const SIGNER_PRIVATE_KEY = getSignerPrivateKey();
|
||||
export const FEE_BPS = getFeeBps();
|
||||
export const SQLITE_DB_PATH = getSqliteDbPath();
|
||||
113
packages/relayer/src/exceptions/base.exception.ts
Normal file
113
packages/relayer/src/exceptions/base.exception.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Unified error codes for the Relayer.
|
||||
*/
|
||||
export enum ErrorCode {
|
||||
// Base errors
|
||||
UNKNOWN = "UNKNOWN",
|
||||
INVALID_INPUT = "INVALID_INPUT",
|
||||
|
||||
// Config errors
|
||||
INVALID_CONFIG = "INVALID_CONFIG",
|
||||
|
||||
// Proof errors
|
||||
INVALID_PROOF = "INVALID_PROOF",
|
||||
|
||||
// Contract errors
|
||||
CONTRACT_ERROR = "CONTRACT_ERROR",
|
||||
}
|
||||
|
||||
/**
|
||||
* Base error class for the Relayer.
|
||||
* All other error classes should extend this.
|
||||
*/
|
||||
export class RelayerError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public readonly code: ErrorCode = ErrorCode.UNKNOWN,
|
||||
public readonly details?: Record<string, unknown>,
|
||||
) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
|
||||
// Maintains proper stack trace
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON representation of the error.
|
||||
*/
|
||||
public toJSON(): Record<string, unknown> {
|
||||
return {
|
||||
name: this.name,
|
||||
message: this.message,
|
||||
code: this.code,
|
||||
details: this.details,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class ValidationError extends RelayerError {
|
||||
constructor(
|
||||
message: string,
|
||||
code: ErrorCode = ErrorCode.INVALID_INPUT,
|
||||
details?: Record<string, unknown>,
|
||||
) {
|
||||
super(message, code, details);
|
||||
this.name = this.constructor.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an error for input validation failures.
|
||||
*/
|
||||
public static invalidInput(
|
||||
details?: Record<string, unknown>,
|
||||
): ValidationError {
|
||||
return new ValidationError(
|
||||
"Failed to parse request payload",
|
||||
ErrorCode.INVALID_INPUT,
|
||||
details,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class ZkError extends RelayerError {
|
||||
constructor(
|
||||
message: string,
|
||||
code: ErrorCode = ErrorCode.INVALID_PROOF,
|
||||
details?: Record<string, unknown>,
|
||||
) {
|
||||
super(message, code, details);
|
||||
this.name = this.constructor.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an error for input validation failures.
|
||||
*/
|
||||
public static invalidProof(details?: Record<string, unknown>): ZkError {
|
||||
return new ZkError("Invalid proof", ErrorCode.INVALID_PROOF, details);
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigError extends RelayerError {
|
||||
constructor(
|
||||
message: string,
|
||||
code: ErrorCode = ErrorCode.INVALID_CONFIG,
|
||||
details?: Record<string, unknown>,
|
||||
) {
|
||||
super(message, code, details);
|
||||
this.name = this.constructor.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an error for input validation failures.
|
||||
*/
|
||||
public static default(details?: Record<string, unknown>): ConfigError {
|
||||
return new ConfigError("Invalid config", ErrorCode.INVALID_CONFIG, details);
|
||||
}
|
||||
|
||||
public static unknown(message: string): ConfigError {
|
||||
return new ConfigError("Invalid config", ErrorCode.INVALID_CONFIG, {
|
||||
context: `Unknown error for ${message}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
0
packages/relayer/src/exceptions/index.ts
Normal file
0
packages/relayer/src/exceptions/index.ts
Normal file
1
packages/relayer/src/external.ts
Normal file
1
packages/relayer/src/external.ts
Normal file
@@ -0,0 +1 @@
|
||||
// Add your external exports here
|
||||
2
packages/relayer/src/handlers/index.ts
Normal file
2
packages/relayer/src/handlers/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./relayer/details.js";
|
||||
export * from "./relayer/request.js";
|
||||
21
packages/relayer/src/handlers/relayer/details.ts
Normal file
21
packages/relayer/src/handlers/relayer/details.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { DetailsMarshall } from "../../types.js";
|
||||
import { getAddress } from "viem/utils";
|
||||
import { FEE_BPS, FEE_RECEIVER_ADDRESS } from "../../config.js";
|
||||
|
||||
export function relayerDetailsHandler(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
const feeBPS = BigInt(FEE_BPS);
|
||||
const feeReceiverAddress = getAddress(FEE_RECEIVER_ADDRESS);
|
||||
res
|
||||
.status(200)
|
||||
.json(
|
||||
res.locals.marshalResponse(
|
||||
new DetailsMarshall(feeBPS, feeReceiverAddress),
|
||||
),
|
||||
);
|
||||
next();
|
||||
}
|
||||
66
packages/relayer/src/handlers/relayer/request.ts
Normal file
66
packages/relayer/src/handlers/relayer/request.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { Hash, WithdrawalPayload } from "@privacy-pool-core/sdk";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { getAddress } from "viem";
|
||||
import { ValidationError } from "../../exceptions/base.exception.js";
|
||||
import {
|
||||
RelayerResponse,
|
||||
RelayRequestBody,
|
||||
} from "../../interfaces/relayer/request.js";
|
||||
import { validateRelayRequestBody } from "../../schemes/relayer/request.scheme.js";
|
||||
import { RequestMashall } from "../../types.js";
|
||||
import { PrivacyPoolRelayer } from "../../services/index.js";
|
||||
|
||||
function relayRequestBodyToWithdrawalPayload(
|
||||
body: RelayRequestBody,
|
||||
): WithdrawalPayload {
|
||||
const proof = { ...body.proof, protocol: "groth16", curve: "bn128" };
|
||||
const publicSignals = body.publicSignals;
|
||||
const withdrawal = {
|
||||
procesooor: getAddress(body.withdrawal.procesooor),
|
||||
scope: BigInt(body.withdrawal.scope) as Hash,
|
||||
data: Uint8Array.from(Buffer.from(body.withdrawal.data, "hex")),
|
||||
};
|
||||
const wp = {
|
||||
proof: {
|
||||
proof,
|
||||
publicSignals,
|
||||
},
|
||||
withdrawal,
|
||||
};
|
||||
return wp;
|
||||
}
|
||||
|
||||
function parseWithdrawal(body: Request["body"]): WithdrawalPayload {
|
||||
if (validateRelayRequestBody(body)) {
|
||||
try {
|
||||
return relayRequestBodyToWithdrawalPayload(body);
|
||||
} catch (error) {
|
||||
console.error(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" });
|
||||
}
|
||||
}
|
||||
|
||||
export async function relayRequestHandler(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
try {
|
||||
const privacyPoolRelayer = new PrivacyPoolRelayer();
|
||||
const withdrawalPayload = parseWithdrawal(req.body);
|
||||
const requestResponse: RelayerResponse =
|
||||
await privacyPoolRelayer.handleRequest(withdrawalPayload);
|
||||
res
|
||||
.status(200)
|
||||
.json(res.locals.marshalResponse(new RequestMashall(requestResponse)));
|
||||
next();
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
18
packages/relayer/src/index.ts
Normal file
18
packages/relayer/src/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export * from "./external.js";
|
||||
import { app } from "./app.js";
|
||||
import { db } from "./providers/db.provider.js";
|
||||
|
||||
const port = 3000;
|
||||
|
||||
async function main() {
|
||||
await db.init();
|
||||
// Start the server
|
||||
app.listen(port, () => {
|
||||
console.log(`Server running at http://localhost:${port}`);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
43
packages/relayer/src/interfaces/relayer/request.ts
Normal file
43
packages/relayer/src/interfaces/relayer/request.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
export interface ProofRelayerPayload {
|
||||
pi_a: string[];
|
||||
pi_b: string[][];
|
||||
pi_c: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdrawal
|
||||
*/
|
||||
export interface WithdrawalRelayerPayload {
|
||||
/**
|
||||
* Relayer address (0xAdDrEsS)
|
||||
*/
|
||||
procesooor: string;
|
||||
/**
|
||||
* Relayer scope (bigint as string)
|
||||
*/
|
||||
scope: string;
|
||||
/**
|
||||
* Tx data (hex encoded)
|
||||
*/
|
||||
data: string;
|
||||
}
|
||||
|
||||
export interface RelayRequestBody {
|
||||
withdrawal: WithdrawalRelayerPayload;
|
||||
publicSignals: string[];
|
||||
proof: ProofRelayerPayload;
|
||||
}
|
||||
|
||||
export interface RelayerResponse {
|
||||
success: boolean;
|
||||
timestamp: number;
|
||||
requestId: string;
|
||||
txHash?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export const enum RequestStatus {
|
||||
BROADCASTED = "BROADCASTED",
|
||||
FAILED = "FAILED",
|
||||
RECEIVED = "RECEIVED",
|
||||
}
|
||||
1
packages/relayer/src/internal.ts
Normal file
1
packages/relayer/src/internal.ts
Normal file
@@ -0,0 +1 @@
|
||||
// Add your internal exports here
|
||||
41
packages/relayer/src/middlewares/index.ts
Normal file
41
packages/relayer/src/middlewares/index.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { RelayerError } from "../exceptions/base.exception.js";
|
||||
import { RelayerMarshall } from "../types.js";
|
||||
|
||||
export function marshalResponseMiddleware(
|
||||
_req: Request,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
res.locals.marshalResponse = (data: RelayerMarshall) => ({
|
||||
success: true,
|
||||
data: data.toJSON(),
|
||||
});
|
||||
next();
|
||||
}
|
||||
|
||||
export function errorHandlerMiddleware(
|
||||
err: Error,
|
||||
_req: Request,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
if (err instanceof RelayerError) {
|
||||
// TODO: error handling based in RelayerError subtypes should be done by checking `err.name`
|
||||
res.status(400).json({ error: err.toJSON() });
|
||||
} else {
|
||||
res.status(500).json({ error: "Internal Server Error" });
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
export function notFoundMiddleware(
|
||||
_req: Request,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
if (!res.writableFinished) {
|
||||
res.status(404).json({ error: "Route not found" });
|
||||
}
|
||||
next();
|
||||
}
|
||||
19
packages/relayer/src/middlewares/relayer/request.ts
Normal file
19
packages/relayer/src/middlewares/relayer/request.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { validateRelayRequestBody } from "../../schemes/relayer/request.scheme.js";
|
||||
|
||||
// Middleware to validate the relay-request body
|
||||
export function validateRelayRequestMiddleware(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
const isValid = validateRelayRequestBody(req.body);
|
||||
if (!isValid) {
|
||||
res.status(400).json({
|
||||
error: "Validation Error",
|
||||
details: validateRelayRequestBody.errors,
|
||||
});
|
||||
return;
|
||||
}
|
||||
next();
|
||||
}
|
||||
3
packages/relayer/src/providers/db.provider.ts
Normal file
3
packages/relayer/src/providers/db.provider.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { SqliteDatabase } from "./sqlite.provider.js";
|
||||
|
||||
export const db = new SqliteDatabase();
|
||||
3
packages/relayer/src/providers/index.ts
Normal file
3
packages/relayer/src/providers/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { SdkProvider } from "./sdk.provider.js";
|
||||
export { SqliteDatabase } from "./sqlite.provider.js";
|
||||
export { db } from "./db.provider.js";
|
||||
24
packages/relayer/src/providers/sdk.provider.ts
Normal file
24
packages/relayer/src/providers/sdk.provider.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import {
|
||||
Circuits,
|
||||
PrivacyPoolSDK,
|
||||
WithdrawalPayload,
|
||||
WithdrawalProof,
|
||||
} from "@privacy-pool-core/sdk";
|
||||
|
||||
export class SdkProvider {
|
||||
private sdk: PrivacyPoolSDK;
|
||||
constructor() {
|
||||
this.sdk = new PrivacyPoolSDK(new Circuits());
|
||||
}
|
||||
async verifyWithdrawal(withdrawalPayload: WithdrawalProof) {
|
||||
return await this.sdk.verifyWithdrawal(withdrawalPayload);
|
||||
}
|
||||
async broadcastWithdrawal(
|
||||
_withdrawalPayload: WithdrawalPayload, // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
_brodacastDetails: { privateKey: string; rpcUrl: string }, // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
): Promise<{ hash: string }> {
|
||||
return {
|
||||
hash: "0x",
|
||||
};
|
||||
}
|
||||
}
|
||||
92
packages/relayer/src/providers/sqlite.provider.ts
Normal file
92
packages/relayer/src/providers/sqlite.provider.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import sqlite3 from "sqlite3";
|
||||
import { open, Database } from "sqlite";
|
||||
|
||||
import { WithdrawalPayload } from "@privacy-pool-core/sdk";
|
||||
import path from "path";
|
||||
import { SQLITE_DB_PATH } from "../config.js";
|
||||
import { RelayerDatabase } from "../types/db.types.js";
|
||||
import { RequestStatus } from "../interfaces/relayer/request.js";
|
||||
|
||||
function replacer(key: string, value: unknown) {
|
||||
return typeof value === "bigint" ? { $bigint: value.toString() } : value;
|
||||
}
|
||||
|
||||
// TODO
|
||||
export class SqliteDatabase implements RelayerDatabase {
|
||||
readonly dbPath: string;
|
||||
private _initialized: boolean = false;
|
||||
private db!: Database<sqlite3.Database, sqlite3.Statement>;
|
||||
|
||||
private createTableRequest = `
|
||||
CREATE TABLE IF NOT EXISTS requests (
|
||||
id UUID PRIMARY KEY,
|
||||
timestamp INTEGER NOT NULL,
|
||||
request JSON,
|
||||
status TEXT CHECK(status IN ('BROADCASTED', 'FAILED', 'RECEIVED')) NOT NULL,
|
||||
txHash TEXT,
|
||||
error TEXT
|
||||
);
|
||||
`;
|
||||
|
||||
constructor() {
|
||||
this.dbPath = path.resolve(SQLITE_DB_PATH);
|
||||
}
|
||||
|
||||
get initialized(): boolean {
|
||||
return this._initialized;
|
||||
}
|
||||
|
||||
async init() {
|
||||
try {
|
||||
this.db = await open({
|
||||
driver: sqlite3.Database,
|
||||
filename: this.dbPath,
|
||||
});
|
||||
await this.db.run(this.createTableRequest);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
this._initialized = true;
|
||||
console.log("sqlite db initialized");
|
||||
}
|
||||
|
||||
async createNewRequest(
|
||||
requestId: string,
|
||||
timestamp: number,
|
||||
req: WithdrawalPayload,
|
||||
) {
|
||||
const strigifiedPayload = JSON.stringify(req, replacer);
|
||||
// Store initial request
|
||||
await this.db.run(
|
||||
`
|
||||
INSERT INTO requests (id, timestamp, request, status)
|
||||
VALUES (?, ?, ?, ?)
|
||||
`,
|
||||
[requestId, timestamp, strigifiedPayload, RequestStatus.RECEIVED],
|
||||
);
|
||||
}
|
||||
|
||||
async updateBroadcastedRequest(requestId: string, txHash: string) {
|
||||
// Update database
|
||||
await this.db.run(
|
||||
`
|
||||
UPDATE requests
|
||||
SET status = ?, txHash = ?
|
||||
WHERE id = ?
|
||||
`,
|
||||
[RequestStatus.BROADCASTED, txHash, requestId],
|
||||
);
|
||||
}
|
||||
|
||||
async updateFailedRequest(requestId: string, errorMessage: string) {
|
||||
// Update database with error
|
||||
await this.db.run(
|
||||
`
|
||||
UPDATE requests
|
||||
SET status = ?, error = ?
|
||||
WHERE id = ?
|
||||
`,
|
||||
[RequestStatus.FAILED, errorMessage, requestId],
|
||||
);
|
||||
}
|
||||
}
|
||||
17
packages/relayer/src/routes/index.ts
Normal file
17
packages/relayer/src/routes/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Router } from "express";
|
||||
import {
|
||||
relayerDetailsHandler,
|
||||
relayRequestHandler,
|
||||
} from "../handlers/index.js";
|
||||
import { validateRelayRequestMiddleware } from "../middlewares/relayer/request.js";
|
||||
|
||||
// Router setup
|
||||
const relayerRouter = Router();
|
||||
relayerRouter.get("/details", [relayerDetailsHandler]);
|
||||
|
||||
relayerRouter.post("/request", [
|
||||
validateRelayRequestMiddleware,
|
||||
relayRequestHandler,
|
||||
]);
|
||||
|
||||
export { relayerRouter };
|
||||
48
packages/relayer/src/schemes/relayer/request.scheme.ts
Normal file
48
packages/relayer/src/schemes/relayer/request.scheme.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Ajv, JSONSchemaType } from "ajv";
|
||||
import { RelayRequestBody } from "../../interfaces/relayer/request.js";
|
||||
|
||||
// AJV schema for validation
|
||||
const ajv = new Ajv();
|
||||
|
||||
const relayRequestSchema: JSONSchemaType<RelayRequestBody> = {
|
||||
type: "object",
|
||||
properties: {
|
||||
withdrawal: {
|
||||
type: "object",
|
||||
properties: {
|
||||
procesooor: { type: "string" },
|
||||
scope: { type: "string" },
|
||||
data: { type: "string" },
|
||||
},
|
||||
required: ["procesooor", "scope", "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"],
|
||||
},
|
||||
},
|
||||
required: ["withdrawal", "proof", "publicSignals"],
|
||||
} as const;
|
||||
|
||||
export const validateRelayRequestBody = ajv.compile(relayRequestSchema);
|
||||
1
packages/relayer/src/services/index.ts
Normal file
1
packages/relayer/src/services/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { PrivacyPoolRelayer } from "./privacyPoolRelayer.service.js";
|
||||
79
packages/relayer/src/services/privacyPoolRelayer.service.ts
Normal file
79
packages/relayer/src/services/privacyPoolRelayer.service.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { WithdrawalPayload } from "@privacy-pool-core/sdk";
|
||||
import { PROVIDER_URL, SIGNER_PRIVATE_KEY } from "../config.js";
|
||||
import { RelayerError, ZkError } from "../exceptions/base.exception.js";
|
||||
import { RelayerResponse } from "../interfaces/relayer/request.js";
|
||||
import { db, SdkProvider } from "../providers/index.js";
|
||||
import { RelayerDatabase } from "../types/db.types.js";
|
||||
|
||||
export class PrivacyPoolRelayer {
|
||||
private db: RelayerDatabase;
|
||||
private sdkService: SdkProvider;
|
||||
private readonly rpcUrl: string = PROVIDER_URL;
|
||||
private readonly privateKey: string = SIGNER_PRIVATE_KEY;
|
||||
|
||||
constructor() {
|
||||
// Initialize database, provider, wallet, contract...
|
||||
this.db = db;
|
||||
this.sdkService = new SdkProvider();
|
||||
}
|
||||
|
||||
async handleRequest(req: WithdrawalPayload): Promise<RelayerResponse> {
|
||||
const requestId = crypto.randomUUID();
|
||||
const timestamp = Date.now();
|
||||
|
||||
try {
|
||||
// Store initial request
|
||||
this.db.createNewRequest(requestId, timestamp, req);
|
||||
|
||||
// Verify commitment proof
|
||||
const isValidWithdrawal = await this.verifyProof(req.proof);
|
||||
if (!isValidWithdrawal) {
|
||||
throw ZkError.invalidProof();
|
||||
}
|
||||
|
||||
const response = await this.broadcastWithdrawal(req);
|
||||
|
||||
// Update database
|
||||
await this.db.updateBroadcastedRequest(requestId, response.hash);
|
||||
|
||||
// Return success response
|
||||
return {
|
||||
success: true,
|
||||
txHash: response.hash,
|
||||
timestamp,
|
||||
requestId,
|
||||
};
|
||||
} catch (error) {
|
||||
let message: string;
|
||||
if (error instanceof RelayerError) {
|
||||
message = error.message;
|
||||
} else {
|
||||
message = JSON.stringify(error);
|
||||
}
|
||||
|
||||
// Update database with error
|
||||
await this.db.updateFailedRequest(requestId, message);
|
||||
// Return error response
|
||||
return {
|
||||
success: false,
|
||||
error: message,
|
||||
timestamp,
|
||||
requestId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
private async verifyProof(
|
||||
proof: WithdrawalPayload["proof"],
|
||||
): Promise<boolean> {
|
||||
return this.sdkService.verifyWithdrawal(proof);
|
||||
}
|
||||
|
||||
private async broadcastWithdrawal(withdrawal: WithdrawalPayload) {
|
||||
return this.sdkService.broadcastWithdrawal(withdrawal, {
|
||||
privateKey: this.privateKey,
|
||||
rpcUrl: this.rpcUrl,
|
||||
});
|
||||
}
|
||||
}
|
||||
30
packages/relayer/src/types.ts
Normal file
30
packages/relayer/src/types.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Address } from "viem/accounts";
|
||||
import { RelayerResponse } from "./interfaces/relayer/request.js";
|
||||
|
||||
export abstract class RelayerMarshall {
|
||||
abstract toJSON(): object;
|
||||
}
|
||||
|
||||
export class DetailsMarshall extends RelayerMarshall {
|
||||
constructor(
|
||||
private feeBPS: bigint,
|
||||
private feeReceiverAddress: Address,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
override toJSON(): object {
|
||||
return {
|
||||
feeBPS: this.feeBPS.toString(),
|
||||
feeReceiverAddress: this.feeReceiverAddress.toString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class RequestMashall extends RelayerMarshall {
|
||||
constructor(readonly response: RelayerResponse) {
|
||||
super();
|
||||
}
|
||||
override toJSON(): object {
|
||||
return this.response;
|
||||
}
|
||||
}
|
||||
12
packages/relayer/src/types/db.types.ts
Normal file
12
packages/relayer/src/types/db.types.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { WithdrawalPayload } from "@privacy-pool-core/sdk";
|
||||
|
||||
export interface RelayerDatabase {
|
||||
initialized: boolean;
|
||||
createNewRequest(
|
||||
requestId: string,
|
||||
timestamp: number,
|
||||
req: WithdrawalPayload,
|
||||
): Promise<void>;
|
||||
updateBroadcastedRequest(requestId: string, txHash: string): Promise<void>;
|
||||
updateFailedRequest(requestId: string, errorMessage: string): Promise<void>;
|
||||
}
|
||||
5
packages/relayer/test/index.spec.ts
Normal file
5
packages/relayer/test/index.spec.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { describe, it } from "vitest";
|
||||
|
||||
describe("dummy", () => {
|
||||
it.skip("dummy", () => {});
|
||||
});
|
||||
11
packages/relayer/tsconfig.build.json
Normal file
11
packages/relayer/tsconfig.build.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"declarationMap": true,
|
||||
"declaration": true,
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "test"]
|
||||
}
|
||||
4
packages/relayer/tsconfig.json
Normal file
4
packages/relayer/tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
21
packages/relayer/vitest.config.ts
Normal file
21
packages/relayer/vitest.config.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import path from "path";
|
||||
import { configDefaults, defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: "node",
|
||||
include: ["test/**/*.spec.ts"],
|
||||
exclude: ["node_modules", "dist"],
|
||||
coverage: {
|
||||
provider: "v8",
|
||||
reporter: ["text", "json", "html"],
|
||||
exclude: ["node_modules", "dist", "src/index.ts", ...configDefaults.exclude],
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "src"),
|
||||
},
|
||||
},
|
||||
});
|
||||
757
packages/relayer/yarn.lock
Normal file
757
packages/relayer/yarn.lock
Normal file
@@ -0,0 +1,757 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@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==
|
||||
|
||||
"@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"
|
||||
integrity sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==
|
||||
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"
|
||||
integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==
|
||||
|
||||
"@scure/base@~1.2.2", "@scure/base@~1.2.4":
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.4.tgz#002eb571a35d69bdb4c214d0995dff76a8dcd2a9"
|
||||
integrity sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==
|
||||
|
||||
"@scure/bip32@1.6.2", "@scure/bip32@^1.5.0":
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.2.tgz#093caa94961619927659ed0e711a6e4bf35bffd0"
|
||||
integrity sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==
|
||||
dependencies:
|
||||
"@noble/curves" "~1.8.1"
|
||||
"@noble/hashes" "~1.7.1"
|
||||
"@scure/base" "~1.2.2"
|
||||
|
||||
"@scure/bip39@1.5.4", "@scure/bip39@^1.4.0":
|
||||
version "1.5.4"
|
||||
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.4.tgz#07fd920423aa671be4540d59bdd344cc1461db51"
|
||||
integrity sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==
|
||||
dependencies:
|
||||
"@noble/hashes" "~1.7.1"
|
||||
"@scure/base" "~1.2.4"
|
||||
|
||||
"@types/body-parser@*":
|
||||
version "1.19.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4"
|
||||
integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==
|
||||
dependencies:
|
||||
"@types/connect" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/connect@*":
|
||||
version "3.4.38"
|
||||
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858"
|
||||
integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/express-serve-static-core@^5.0.0":
|
||||
version "5.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.5.tgz#f6a851c7fd512e5da087f6f20d29f44b162a6a95"
|
||||
integrity sha512-GLZPrd9ckqEBFMcVM/qRFAP0Hg3qiVEojgEFsx/N/zKXsBzbGF6z5FBDpZ0+Xhp1xr+qRZYjfGr1cWHB9oFHSA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/qs" "*"
|
||||
"@types/range-parser" "*"
|
||||
"@types/send" "*"
|
||||
|
||||
"@types/express@5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.0.tgz#13a7d1f75295e90d19ed6e74cab3678488eaa96c"
|
||||
integrity sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==
|
||||
dependencies:
|
||||
"@types/body-parser" "*"
|
||||
"@types/express-serve-static-core" "^5.0.0"
|
||||
"@types/qs" "*"
|
||||
"@types/serve-static" "*"
|
||||
|
||||
"@types/http-errors@*":
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f"
|
||||
integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==
|
||||
|
||||
"@types/mime@^1":
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690"
|
||||
integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==
|
||||
|
||||
"@types/node@*":
|
||||
version "22.10.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.10.tgz#85fe89f8bf459dc57dfef1689bd5b52ad1af07e6"
|
||||
integrity sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww==
|
||||
dependencies:
|
||||
undici-types "~6.20.0"
|
||||
|
||||
"@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/qs@*":
|
||||
version "6.9.18"
|
||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.18.tgz#877292caa91f7c1b213032b34626505b746624c2"
|
||||
integrity sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==
|
||||
|
||||
"@types/range-parser@*":
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
|
||||
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==
|
||||
|
||||
"@types/send@*":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a"
|
||||
integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==
|
||||
dependencies:
|
||||
"@types/mime" "^1"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/serve-static@*":
|
||||
version "1.15.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714"
|
||||
integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==
|
||||
dependencies:
|
||||
"@types/http-errors" "*"
|
||||
"@types/node" "*"
|
||||
"@types/send" "*"
|
||||
|
||||
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==
|
||||
|
||||
accepts@~1.3.8:
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
||||
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
|
||||
dependencies:
|
||||
mime-types "~2.1.34"
|
||||
negotiator "0.6.3"
|
||||
|
||||
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==
|
||||
|
||||
ajv@8.17.1:
|
||||
version "8.17.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6"
|
||||
integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.3"
|
||||
fast-uri "^3.0.1"
|
||||
json-schema-traverse "^1.0.0"
|
||||
require-from-string "^2.0.2"
|
||||
|
||||
array-flatten@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||
integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
|
||||
|
||||
body-parser@1.20.3:
|
||||
version "1.20.3"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
|
||||
integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
content-type "~1.0.5"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
on-finished "2.4.1"
|
||||
qs "6.13.0"
|
||||
raw-body "2.5.2"
|
||||
type-is "~1.6.18"
|
||||
unpipe "1.0.0"
|
||||
|
||||
bytes@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
|
||||
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
|
||||
|
||||
call-bind-apply-helpers@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz#32e5892e6361b29b0b545ba6f7763378daca2840"
|
||||
integrity sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
|
||||
call-bound@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681"
|
||||
integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.1"
|
||||
get-intrinsic "^1.2.6"
|
||||
|
||||
content-disposition@0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
|
||||
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
|
||||
dependencies:
|
||||
safe-buffer "5.2.1"
|
||||
|
||||
content-type@~1.0.4, content-type@~1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
|
||||
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
|
||||
|
||||
cookie-signature@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
|
||||
|
||||
cookie@0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9"
|
||||
integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==
|
||||
|
||||
debug@2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
depd@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
||||
|
||||
destroy@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
|
||||
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
|
||||
|
||||
dunder-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
|
||||
integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.1"
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.2.0"
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
|
||||
|
||||
encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
|
||||
|
||||
encodeurl@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
|
||||
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
|
||||
|
||||
es-define-property@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
|
||||
integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
|
||||
|
||||
es-errors@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
es-object-atoms@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1"
|
||||
integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
|
||||
escape-html@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
|
||||
|
||||
etag@~1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
||||
|
||||
ethers@6.13.5:
|
||||
version "6.13.5"
|
||||
resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.5.tgz#8c1d6ac988ac08abc3c1d8fabbd4b8b602851ac4"
|
||||
integrity sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==
|
||||
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==
|
||||
|
||||
express@4.21.2:
|
||||
version "4.21.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32"
|
||||
integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==
|
||||
dependencies:
|
||||
accepts "~1.3.8"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.20.3"
|
||||
content-disposition "0.5.4"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.7.1"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
encodeurl "~2.0.0"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
finalhandler "1.3.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
merge-descriptors "1.0.3"
|
||||
methods "~1.1.2"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
path-to-regexp "0.1.12"
|
||||
proxy-addr "~2.0.7"
|
||||
qs "6.13.0"
|
||||
range-parser "~1.2.1"
|
||||
safe-buffer "5.2.1"
|
||||
send "0.19.0"
|
||||
serve-static "1.16.2"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
type-is "~1.6.18"
|
||||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
|
||||
fast-uri@^3.0.1:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748"
|
||||
integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==
|
||||
|
||||
finalhandler@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019"
|
||||
integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
encodeurl "~2.0.0"
|
||||
escape-html "~1.0.3"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
statuses "2.0.1"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
forwarded@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
|
||||
|
||||
fresh@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||
|
||||
get-intrinsic@^1.2.5, get-intrinsic@^1.2.6:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.7.tgz#dcfcb33d3272e15f445d15124bc0a216189b9044"
|
||||
integrity sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.1"
|
||||
es-define-property "^1.0.1"
|
||||
es-errors "^1.3.0"
|
||||
es-object-atoms "^1.0.0"
|
||||
function-bind "^1.1.2"
|
||||
get-proto "^1.0.0"
|
||||
gopd "^1.2.0"
|
||||
has-symbols "^1.1.0"
|
||||
hasown "^2.0.2"
|
||||
math-intrinsics "^1.1.0"
|
||||
|
||||
get-proto@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
|
||||
integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
|
||||
dependencies:
|
||||
dunder-proto "^1.0.1"
|
||||
es-object-atoms "^1.0.0"
|
||||
|
||||
gopd@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
|
||||
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
|
||||
|
||||
has-symbols@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
|
||||
integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
|
||||
|
||||
hasown@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
http-errors@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
|
||||
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
|
||||
dependencies:
|
||||
depd "2.0.0"
|
||||
inherits "2.0.4"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
toidentifier "1.0.1"
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
inherits@2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
|
||||
|
||||
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==
|
||||
|
||||
json-schema-traverse@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
|
||||
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
|
||||
|
||||
math-intrinsics@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
|
||||
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
|
||||
|
||||
merge-descriptors@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5"
|
||||
integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==
|
||||
|
||||
methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
|
||||
|
||||
mime-db@1.52.0:
|
||||
version "1.52.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||
|
||||
mime-types@~2.1.24, mime-types@~2.1.34:
|
||||
version "2.1.35"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
mime@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
|
||||
|
||||
ms@2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
negotiator@0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
||||
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
|
||||
|
||||
object-inspect@^1.13.3:
|
||||
version "1.13.3"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a"
|
||||
integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==
|
||||
|
||||
on-finished@2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
|
||||
integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
ox@0.6.7:
|
||||
version "0.6.7"
|
||||
resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.7.tgz#afd53f2ecef68b8526660e9d29dee6e6b599a832"
|
||||
integrity sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==
|
||||
dependencies:
|
||||
"@adraffy/ens-normalize" "^1.10.1"
|
||||
"@noble/curves" "^1.6.0"
|
||||
"@noble/hashes" "^1.5.0"
|
||||
"@scure/bip32" "^1.5.0"
|
||||
"@scure/bip39" "^1.4.0"
|
||||
abitype "^1.0.6"
|
||||
eventemitter3 "5.0.1"
|
||||
|
||||
parseurl@~1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
|
||||
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
|
||||
|
||||
path-to-regexp@0.1.12:
|
||||
version "0.1.12"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7"
|
||||
integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==
|
||||
|
||||
proxy-addr@~2.0.7:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
|
||||
integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
|
||||
dependencies:
|
||||
forwarded "0.2.0"
|
||||
ipaddr.js "1.9.1"
|
||||
|
||||
qs@6.13.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
|
||||
integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
|
||||
dependencies:
|
||||
side-channel "^1.0.6"
|
||||
|
||||
range-parser@~1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||
|
||||
raw-body@2.5.2:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
|
||||
integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
require-from-string@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
||||
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
|
||||
|
||||
safe-buffer@5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
"safer-buffer@>= 2.1.2 < 3":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
send@0.19.0:
|
||||
version "0.19.0"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
|
||||
integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
mime "1.6.0"
|
||||
ms "2.1.3"
|
||||
on-finished "2.4.1"
|
||||
range-parser "~1.2.1"
|
||||
statuses "2.0.1"
|
||||
|
||||
serve-static@1.16.2:
|
||||
version "1.16.2"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296"
|
||||
integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==
|
||||
dependencies:
|
||||
encodeurl "~2.0.0"
|
||||
escape-html "~1.0.3"
|
||||
parseurl "~1.3.3"
|
||||
send "0.19.0"
|
||||
|
||||
setprototypeof@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
|
||||
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
|
||||
|
||||
side-channel-list@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad"
|
||||
integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
object-inspect "^1.13.3"
|
||||
|
||||
side-channel-map@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42"
|
||||
integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==
|
||||
dependencies:
|
||||
call-bound "^1.0.2"
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.5"
|
||||
object-inspect "^1.13.3"
|
||||
|
||||
side-channel-weakmap@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea"
|
||||
integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==
|
||||
dependencies:
|
||||
call-bound "^1.0.2"
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.5"
|
||||
object-inspect "^1.13.3"
|
||||
side-channel-map "^1.0.1"
|
||||
|
||||
side-channel@^1.0.6:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9"
|
||||
integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
object-inspect "^1.13.3"
|
||||
side-channel-list "^1.0.0"
|
||||
side-channel-map "^1.0.1"
|
||||
side-channel-weakmap "^1.0.2"
|
||||
|
||||
statuses@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
|
||||
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
|
||||
|
||||
toidentifier@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
|
||||
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
|
||||
|
||||
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-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
||||
dependencies:
|
||||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
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"
|
||||
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
|
||||
|
||||
utils-merge@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||
integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
|
||||
|
||||
vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||
|
||||
viem@2.22.14:
|
||||
version "2.22.14"
|
||||
resolved "https://registry.yarnpkg.com/viem/-/viem-2.22.14.tgz#acf1367704b29f0c00a58260702c9bee05c5dcbd"
|
||||
integrity sha512-HfWnMmSPHNY+F3+I01ZKvIbwdn8qZUEhV/rzBi094F6gmqHA1KBXdF7P9po5/OYkvBjzxduUlLBgownyZkV+uA==
|
||||
dependencies:
|
||||
"@noble/curves" "1.8.1"
|
||||
"@noble/hashes" "1.7.1"
|
||||
"@scure/bip32" "1.6.2"
|
||||
"@scure/bip39" "1.5.4"
|
||||
abitype "1.0.8"
|
||||
isows "1.0.6"
|
||||
ox "0.6.7"
|
||||
ws "8.18.0"
|
||||
|
||||
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"
|
||||
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
|
||||
@@ -69,24 +69,17 @@
|
||||
"@rollup/plugin-wasm": "6.2.2",
|
||||
"@types/node": "20.3.1",
|
||||
"@types/snarkjs": "0.7.9",
|
||||
"@typescript-eslint/eslint-plugin": "7.18.0",
|
||||
"@typescript-eslint/parser": "7.18.0",
|
||||
"@vitest/coverage-v8": "2.0.5",
|
||||
"commitlint": "19.4.1",
|
||||
"eslint": "9.18.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-plugin-prettier": "5.2.1",
|
||||
"globals": "15.14.0",
|
||||
"husky": "9.1.5",
|
||||
"lint-staged": "15.2.10",
|
||||
"memfs": "4.17.0",
|
||||
"prettier": "3.3.3",
|
||||
"rollup": "4.30.1",
|
||||
"rollup-plugin-dts": "6.1.1",
|
||||
"snarkjs": "0.7.5",
|
||||
"sort-package-json": "2.10.1",
|
||||
"typescript": "5.5.4",
|
||||
"typescript-eslint": "8.20.0",
|
||||
"vitest": "2.0.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Commitment, CommitmentProof } from "../types/commitment.js";
|
||||
import {
|
||||
Withdrawal,
|
||||
WithdrawalPayload,
|
||||
WithdrawalProof,
|
||||
WithdrawalProofInput,
|
||||
} from "../types/withdrawal.js";
|
||||
|
||||
@@ -62,18 +63,19 @@ export class PrivacyPoolSDK {
|
||||
public async proveWithdrawal(
|
||||
commitment: Commitment,
|
||||
input: WithdrawalProofInput,
|
||||
): Promise<WithdrawalPayload> {
|
||||
return this.withdrawalService.proveWithdrawal(commitment, input);
|
||||
): Promise<WithdrawalProof> {
|
||||
const withdrawalProof = await this.withdrawalService.proveWithdrawal(commitment, input);
|
||||
return withdrawalProof;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a withdrawal proof.
|
||||
*
|
||||
* @param withdrawalPayload - The withdrawal payload to verify
|
||||
* @param withdrawalProof - The withdrawal payload to verify
|
||||
*/
|
||||
public async verifyWithdrawal(
|
||||
withdrawalPayload: WithdrawalPayload,
|
||||
withdrawalProof: WithdrawalProof,
|
||||
): Promise<boolean> {
|
||||
return this.withdrawalService.verifyWithdrawal(withdrawalPayload);
|
||||
return this.withdrawalService.verifyWithdrawal(withdrawalProof);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,10 @@ import {
|
||||
} from "../interfaces/circuits.interface.js";
|
||||
import { Commitment } from "../types/commitment.js";
|
||||
import {
|
||||
Withdrawal,
|
||||
WithdrawalPayload,
|
||||
WithdrawalProofInput,
|
||||
Withdrawal,
|
||||
WithdrawalPayload,
|
||||
WithdrawalProof,
|
||||
WithdrawalProofInput,
|
||||
} from "../types/withdrawal.js";
|
||||
|
||||
/**
|
||||
@@ -31,7 +32,7 @@ export class WithdrawalService {
|
||||
public async proveWithdrawal(
|
||||
commitment: Commitment,
|
||||
input: WithdrawalProofInput,
|
||||
): Promise<WithdrawalPayload> {
|
||||
): Promise<WithdrawalProof> {
|
||||
try {
|
||||
const inputSignals = this.prepareInputSignals(commitment, input);
|
||||
|
||||
@@ -63,14 +64,13 @@ export class WithdrawalService {
|
||||
* @throws {ProofError} If verification fails
|
||||
*/
|
||||
public async verifyWithdrawal(
|
||||
withdrawalPayload: WithdrawalPayload,
|
||||
withdrawalPayload: WithdrawalProof,
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const vkeyBin = await this.circuits.getVerificationKey(
|
||||
CircuitName.Withdraw,
|
||||
);
|
||||
const vkey = JSON.parse(new TextDecoder("utf-8").decode(vkeyBin));
|
||||
|
||||
return await snarkjs.groth16.verify(
|
||||
vkey,
|
||||
withdrawalPayload.publicSignals,
|
||||
|
||||
@@ -12,12 +12,17 @@ export interface Withdrawal {
|
||||
readonly data: Uint8Array;
|
||||
}
|
||||
|
||||
export interface WithdrawalProof {
|
||||
readonly proof: Groth16Proof;
|
||||
readonly publicSignals: PublicSignals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete withdrawal payload including proof and public signals.
|
||||
*/
|
||||
export interface WithdrawalPayload {
|
||||
readonly proof: Groth16Proof;
|
||||
readonly publicSignals: PublicSignals;
|
||||
readonly proof: WithdrawalProof;
|
||||
readonly withdrawal: Withdrawal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user