Compare commits
1 Commits
8041bd7f78
...
f411159f15
| Author | SHA1 | Date | |
|---|---|---|---|
| f411159f15 |
@ -33,6 +33,7 @@ module.exports = {
|
|||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
tabWidth: 4,
|
tabWidth: 4,
|
||||||
|
printWidth: 120,
|
||||||
singleQuote: true,
|
singleQuote: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
4
dist/batch.d.ts
vendored
4
dist/batch.d.ts
vendored
@ -80,7 +80,7 @@ export declare class BatchEventsService {
|
|||||||
retryMax: number;
|
retryMax: number;
|
||||||
retryOn: number;
|
retryOn: number;
|
||||||
constructor({ provider, contract, onProgress, concurrencySize, blocksPerRequest, shouldRetry, retryMax, retryOn, }: BatchEventServiceConstructor);
|
constructor({ provider, contract, onProgress, concurrencySize, blocksPerRequest, shouldRetry, retryMax, retryOn, }: BatchEventServiceConstructor);
|
||||||
getPastEvents({ fromBlock, toBlock, type, }: EventInput): Promise<EventLog[]>;
|
getPastEvents({ fromBlock, toBlock, type }: EventInput): Promise<EventLog[]>;
|
||||||
createBatchRequest(batchArray: EventInput[]): Promise<EventLog[]>[];
|
createBatchRequest(batchArray: EventInput[]): Promise<EventLog[]>[];
|
||||||
getBatchEvents({ fromBlock, toBlock, type, }: EventInput): Promise<EventLog[]>;
|
getBatchEvents({ fromBlock, toBlock, type }: EventInput): Promise<EventLog[]>;
|
||||||
}
|
}
|
||||||
|
|||||||
4
dist/deposits.d.ts
vendored
4
dist/deposits.d.ts
vendored
@ -30,7 +30,7 @@ export interface parsedInvoiceExec extends DepositType {
|
|||||||
}
|
}
|
||||||
export declare function parseNote(noteString: string): parsedNoteExec | undefined;
|
export declare function parseNote(noteString: string): parsedNoteExec | undefined;
|
||||||
export declare function parseInvoice(invoiceString: string): parsedInvoiceExec | undefined;
|
export declare function parseInvoice(invoiceString: string): parsedInvoiceExec | undefined;
|
||||||
export declare function createDeposit({ nullifier, secret, }: createDepositParams): Promise<createDepositObject>;
|
export declare function createDeposit({ nullifier, secret }: createDepositParams): Promise<createDepositObject>;
|
||||||
export interface DepositConstructor {
|
export interface DepositConstructor {
|
||||||
currency: string;
|
currency: string;
|
||||||
amount: string;
|
amount: string;
|
||||||
@ -56,7 +56,7 @@ export declare class Deposit {
|
|||||||
nullifierHex: string;
|
nullifierHex: string;
|
||||||
constructor({ currency, amount, netId, nullifier, secret, note, noteHex, invoice, commitmentHex, nullifierHex, }: DepositConstructor);
|
constructor({ currency, amount, netId, nullifier, secret, note, noteHex, invoice, commitmentHex, nullifierHex, }: DepositConstructor);
|
||||||
toString(): string;
|
toString(): string;
|
||||||
static createNote({ currency, amount, netId, nullifier, secret, }: createNoteParams): Promise<Deposit>;
|
static createNote({ currency, amount, netId, nullifier, secret }: createNoteParams): Promise<Deposit>;
|
||||||
static parseNote(noteString: string): Promise<Deposit>;
|
static parseNote(noteString: string): Promise<Deposit>;
|
||||||
}
|
}
|
||||||
export declare class Invoice {
|
export declare class Invoice {
|
||||||
|
|||||||
2
dist/encryptedNotes.d.ts
vendored
2
dist/encryptedNotes.d.ts
vendored
@ -10,7 +10,7 @@ export interface DecryptedNotes {
|
|||||||
address: string;
|
address: string;
|
||||||
noteHex: string;
|
noteHex: string;
|
||||||
}
|
}
|
||||||
export declare function packEncryptedMessage({ nonce, ephemPublicKey, ciphertext, }: EthEncryptedData): string;
|
export declare function packEncryptedMessage({ nonce, ephemPublicKey, ciphertext }: EthEncryptedData): string;
|
||||||
export declare function unpackEncryptedMessage(encryptedMessage: string): EthEncryptedData & {
|
export declare function unpackEncryptedMessage(encryptedMessage: string): EthEncryptedData & {
|
||||||
messageBuff: string;
|
messageBuff: string;
|
||||||
};
|
};
|
||||||
|
|||||||
14
dist/events/base.d.ts
vendored
14
dist/events/base.d.ts
vendored
@ -50,10 +50,10 @@ export declare class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
getTovarishType(): string;
|
getTovarishType(): string;
|
||||||
getGraphMethod(): string;
|
getGraphMethod(): string;
|
||||||
getGraphParams(): BaseGraphParams;
|
getGraphParams(): BaseGraphParams;
|
||||||
updateEventProgress({ percentage, type, fromBlock, toBlock, count, }: Parameters<BatchEventOnProgress>[0]): void;
|
updateEventProgress({ percentage, type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
|
||||||
updateBlockProgress({ percentage, currentIndex, totalIndex, }: Parameters<BatchBlockOnProgress>[0]): void;
|
updateBlockProgress({ percentage, currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
|
||||||
updateTransactionProgress({ percentage, currentIndex, totalIndex, }: Parameters<BatchBlockOnProgress>[0]): void;
|
updateTransactionProgress({ percentage, currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
|
||||||
updateGraphProgress({ type, fromBlock, toBlock, count, }: Parameters<BatchGraphOnProgress>[0]): void;
|
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchGraphOnProgress>[0]): void;
|
||||||
formatEvents(events: EventLog[]): Promise<EventType[]>;
|
formatEvents(events: EventLog[]): Promise<EventType[]>;
|
||||||
/**
|
/**
|
||||||
* Get saved or cached events
|
* Get saved or cached events
|
||||||
@ -75,7 +75,7 @@ export declare class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
fromBlock: number;
|
fromBlock: number;
|
||||||
toBlock?: number;
|
toBlock?: number;
|
||||||
}): Promise<BaseEvents<EventType>>;
|
}): Promise<BaseEvents<EventType>>;
|
||||||
getLatestEvents({ fromBlock, }: {
|
getLatestEvents({ fromBlock }: {
|
||||||
fromBlock: number;
|
fromBlock: number;
|
||||||
}): Promise<BaseEvents<EventType>>;
|
}): Promise<BaseEvents<EventType>>;
|
||||||
validateEvents<S>({ events, lastBlock, hasNewEvents, }: BaseEvents<EventType> & {
|
validateEvents<S>({ events, lastBlock, hasNewEvents, }: BaseEvents<EventType> & {
|
||||||
@ -132,7 +132,7 @@ export declare class BaseEchoService extends BaseEventsService<EchoEvents> {
|
|||||||
getInstanceName(): string;
|
getInstanceName(): string;
|
||||||
getGraphMethod(): string;
|
getGraphMethod(): string;
|
||||||
formatEvents(events: EventLog[]): Promise<EchoEvents[]>;
|
formatEvents(events: EventLog[]): Promise<EchoEvents[]>;
|
||||||
getEventsFromGraph({ fromBlock, }: {
|
getEventsFromGraph({ fromBlock }: {
|
||||||
fromBlock: number;
|
fromBlock: number;
|
||||||
}): Promise<BaseEvents<EchoEvents>>;
|
}): Promise<BaseEvents<EchoEvents>>;
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ export declare class BaseGovernanceService extends BaseEventsService<AllGovernan
|
|||||||
getTovarishType(): string;
|
getTovarishType(): string;
|
||||||
getGraphMethod(): string;
|
getGraphMethod(): string;
|
||||||
formatEvents(events: EventLog[]): Promise<AllGovernanceEvents[]>;
|
formatEvents(events: EventLog[]): Promise<AllGovernanceEvents[]>;
|
||||||
getEventsFromGraph({ fromBlock, }: {
|
getEventsFromGraph({ fromBlock }: {
|
||||||
fromBlock: number;
|
fromBlock: number;
|
||||||
}): Promise<BaseEvents<AllGovernanceEvents>>;
|
}): Promise<BaseEvents<AllGovernanceEvents>>;
|
||||||
getAllProposals(): Promise<GovernanceProposals[]>;
|
getAllProposals(): Promise<GovernanceProposals[]>;
|
||||||
|
|||||||
2
dist/events/db.d.ts
vendored
2
dist/events/db.d.ts
vendored
@ -28,7 +28,7 @@ export declare class DBTornadoService extends BaseTornadoService {
|
|||||||
constructor(params: DBTornadoServiceConstructor);
|
constructor(params: DBTornadoServiceConstructor);
|
||||||
getEventsFromDB(): Promise<BaseEvents<DepositsEvents | WithdrawalsEvents>>;
|
getEventsFromDB(): Promise<BaseEvents<DepositsEvents | WithdrawalsEvents>>;
|
||||||
getEventsFromCache(): Promise<CachedEvents<DepositsEvents | WithdrawalsEvents>>;
|
getEventsFromCache(): Promise<CachedEvents<DepositsEvents | WithdrawalsEvents>>;
|
||||||
saveEvents({ events, lastBlock, }: BaseEvents<DepositsEvents | WithdrawalsEvents>): Promise<void>;
|
saveEvents({ events, lastBlock }: BaseEvents<DepositsEvents | WithdrawalsEvents>): Promise<void>;
|
||||||
}
|
}
|
||||||
export interface DBEchoServiceConstructor extends BaseEchoServiceConstructor {
|
export interface DBEchoServiceConstructor extends BaseEchoServiceConstructor {
|
||||||
staticUrl: string;
|
staticUrl: string;
|
||||||
|
|||||||
2
dist/graphql/index.d.ts
vendored
2
dist/graphql/index.d.ts
vendored
@ -57,7 +57,7 @@ export interface getMetaReturns {
|
|||||||
lastSyncBlock: null | number;
|
lastSyncBlock: null | number;
|
||||||
hasIndexingErrors: null | boolean;
|
hasIndexingErrors: null | boolean;
|
||||||
}
|
}
|
||||||
export declare function getMeta({ graphApi, subgraphName, fetchDataOptions, }: getMetaParams): Promise<getMetaReturns>;
|
export declare function getMeta({ graphApi, subgraphName, fetchDataOptions }: getMetaParams): Promise<getMetaReturns>;
|
||||||
export interface GraphRegisters {
|
export interface GraphRegisters {
|
||||||
relayers: {
|
relayers: {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
8
dist/idb.d.ts
vendored
8
dist/idb.d.ts
vendored
@ -35,16 +35,16 @@ export declare class IndexedDB {
|
|||||||
key?: string;
|
key?: string;
|
||||||
count?: number;
|
count?: number;
|
||||||
}): Promise<T>;
|
}): Promise<T>;
|
||||||
getItem<T>({ storeName, key, }: {
|
getItem<T>({ storeName, key }: {
|
||||||
storeName: string;
|
storeName: string;
|
||||||
key: string;
|
key: string;
|
||||||
}): Promise<T | undefined>;
|
}): Promise<T | undefined>;
|
||||||
addItem({ storeName, data, key, }: {
|
addItem({ storeName, data, key }: {
|
||||||
storeName: string;
|
storeName: string;
|
||||||
data: any;
|
data: any;
|
||||||
key: string;
|
key: string;
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
putItem({ storeName, data, key, }: {
|
putItem({ storeName, data, key }: {
|
||||||
storeName: string;
|
storeName: string;
|
||||||
data: any;
|
data: any;
|
||||||
key?: string;
|
key?: string;
|
||||||
@ -62,7 +62,7 @@ export declare class IndexedDB {
|
|||||||
getValue<T>(key: string): Promise<T | undefined>;
|
getValue<T>(key: string): Promise<T | undefined>;
|
||||||
setValue(key: string, data: any): Promise<void>;
|
setValue(key: string, data: any): Promise<void>;
|
||||||
delValue(key: string): Promise<void>;
|
delValue(key: string): Promise<void>;
|
||||||
clearStore({ storeName, mode, }: {
|
clearStore({ storeName, mode }: {
|
||||||
storeName: string;
|
storeName: string;
|
||||||
mode: IDBTransactionMode;
|
mode: IDBTransactionMode;
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
|
|||||||
1254
dist/index.js
vendored
1254
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
1254
dist/index.mjs
vendored
1254
dist/index.mjs
vendored
File diff suppressed because it is too large
Load Diff
2
dist/merkleTree.d.ts
vendored
2
dist/merkleTree.d.ts
vendored
@ -22,7 +22,7 @@ export declare class MerkleTreeService {
|
|||||||
merkleWorkerPath?: string;
|
merkleWorkerPath?: string;
|
||||||
constructor({ netId, amount, currency, Tornado, commitmentHex, merkleTreeHeight, emptyElement, merkleWorkerPath, }: MerkleTreeConstructor);
|
constructor({ netId, amount, currency, Tornado, commitmentHex, merkleTreeHeight, emptyElement, merkleWorkerPath, }: MerkleTreeConstructor);
|
||||||
createTree(events: Element[]): Promise<MerkleTree>;
|
createTree(events: Element[]): Promise<MerkleTree>;
|
||||||
createPartialTree({ edge, elements, }: {
|
createPartialTree({ edge, elements }: {
|
||||||
edge: TreeEdge;
|
edge: TreeEdge;
|
||||||
elements: Element[];
|
elements: Element[];
|
||||||
}): Promise<PartialMerkleTree>;
|
}): Promise<PartialMerkleTree>;
|
||||||
|
|||||||
38
dist/merkleTreeWorker.js
vendored
38
dist/merkleTreeWorker.js
vendored
@ -1814,9 +1814,7 @@ class Mimc {
|
|||||||
}
|
}
|
||||||
async initMimc() {
|
async initMimc() {
|
||||||
this.sponge = await buildMimcSponge();
|
this.sponge = await buildMimcSponge();
|
||||||
this.hash = (left, right) => this.sponge?.F.toString(
|
this.hash = (left, right) => this.sponge?.F.toString(this.sponge?.multiHash([BigInt(left), BigInt(right)]));
|
||||||
this.sponge?.multiHash([BigInt(left), BigInt(right)])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
async getHash() {
|
async getHash() {
|
||||||
await this.mimcPromise;
|
await this.mimcPromise;
|
||||||
@ -1837,27 +1835,18 @@ async function nodePostWork() {
|
|||||||
const { hash: hashFunction } = await mimc.getHash();
|
const { hash: hashFunction } = await mimc.getHash();
|
||||||
const { merkleTreeHeight, edge, elements, zeroElement } = workerThreads.workerData;
|
const { merkleTreeHeight, edge, elements, zeroElement } = workerThreads.workerData;
|
||||||
if (edge) {
|
if (edge) {
|
||||||
const merkleTree2 = new libExports.PartialMerkleTree(
|
const merkleTree2 = new libExports.PartialMerkleTree(merkleTreeHeight, edge, elements, {
|
||||||
merkleTreeHeight,
|
zeroElement,
|
||||||
edge,
|
hashFunction
|
||||||
elements,
|
});
|
||||||
{
|
workerThreads.parentPort.postMessage(merkleTree2.toString());
|
||||||
zeroElement,
|
|
||||||
hashFunction
|
|
||||||
}
|
|
||||||
);
|
|
||||||
workerThreads.parentPort.postMessage(
|
|
||||||
merkleTree2.toString()
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const merkleTree = new libExports.MerkleTree(merkleTreeHeight, elements, {
|
const merkleTree = new libExports.MerkleTree(merkleTreeHeight, elements, {
|
||||||
zeroElement,
|
zeroElement,
|
||||||
hashFunction
|
hashFunction
|
||||||
});
|
});
|
||||||
workerThreads.parentPort.postMessage(
|
workerThreads.parentPort.postMessage(merkleTree.toString());
|
||||||
merkleTree.toString()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (isNode && workerThreads) {
|
if (isNode && workerThreads) {
|
||||||
nodePostWork();
|
nodePostWork();
|
||||||
@ -1872,15 +1861,10 @@ if (isNode && workerThreads) {
|
|||||||
const { hash: hashFunction } = await mimc.getHash();
|
const { hash: hashFunction } = await mimc.getHash();
|
||||||
const { merkleTreeHeight, edge, elements, zeroElement } = data;
|
const { merkleTreeHeight, edge, elements, zeroElement } = data;
|
||||||
if (edge) {
|
if (edge) {
|
||||||
const merkleTree2 = new libExports.PartialMerkleTree(
|
const merkleTree2 = new libExports.PartialMerkleTree(merkleTreeHeight, edge, elements, {
|
||||||
merkleTreeHeight,
|
zeroElement,
|
||||||
edge,
|
hashFunction
|
||||||
elements,
|
});
|
||||||
{
|
|
||||||
zeroElement,
|
|
||||||
hashFunction
|
|
||||||
}
|
|
||||||
);
|
|
||||||
postMessage(merkleTree2.toString());
|
postMessage(merkleTree2.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
58
dist/merkleTreeWorker.umd.js
vendored
58
dist/merkleTreeWorker.umd.js
vendored
@ -101986,9 +101986,7 @@ class Mimc {
|
|||||||
}
|
}
|
||||||
async initMimc() {
|
async initMimc() {
|
||||||
this.sponge = await mimcsponge_buildMimcSponge();
|
this.sponge = await mimcsponge_buildMimcSponge();
|
||||||
this.hash = (left, right) => this.sponge?.F.toString(
|
this.hash = (left, right) => this.sponge?.F.toString(this.sponge?.multiHash([BigInt(left), BigInt(right)]));
|
||||||
this.sponge?.multiHash([BigInt(left), BigInt(right)])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
async getHash() {
|
async getHash() {
|
||||||
await this.mimcPromise;
|
await this.mimcPromise;
|
||||||
@ -102013,9 +102011,7 @@ BigInt.prototype.toJSON = function() {
|
|||||||
};
|
};
|
||||||
const isNode = !process.browser && typeof globalThis.window === "undefined";
|
const isNode = !process.browser && typeof globalThis.window === "undefined";
|
||||||
const utils_crypto = isNode ? crypto_browserify.webcrypto : globalThis.crypto;
|
const utils_crypto = isNode ? crypto_browserify.webcrypto : globalThis.crypto;
|
||||||
const chunk = (arr, size) => [...Array(Math.ceil(arr.length / size))].map(
|
const chunk = (arr, size) => [...Array(Math.ceil(arr.length / size))].map((_, i) => arr.slice(size * i, size + size * i));
|
||||||
(_, i) => arr.slice(size * i, size + size * i)
|
|
||||||
);
|
|
||||||
function utils_sleep(ms) {
|
function utils_sleep(ms) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
@ -102043,9 +102039,7 @@ function bufferToBytes(b) {
|
|||||||
return new Uint8Array(b.buffer);
|
return new Uint8Array(b.buffer);
|
||||||
}
|
}
|
||||||
function bytesToBase64(bytes) {
|
function bytesToBase64(bytes) {
|
||||||
return btoa(
|
return btoa(bytes.reduce((data, byte) => data + String.fromCharCode(byte), ""));
|
||||||
bytes.reduce((data, byte) => data + String.fromCharCode(byte), "")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
function base64ToBytes(base64) {
|
function base64ToBytes(base64) {
|
||||||
return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
|
return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
|
||||||
@ -102060,11 +102054,7 @@ function hexToBytes(hexString) {
|
|||||||
if (hexString.length % 2 !== 0) {
|
if (hexString.length % 2 !== 0) {
|
||||||
hexString = "0" + hexString;
|
hexString = "0" + hexString;
|
||||||
}
|
}
|
||||||
return Uint8Array.from(
|
return Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
|
||||||
hexString.match(/.{1,2}/g).map(
|
|
||||||
(byte) => parseInt(byte, 16)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
function bytesToBN(bytes) {
|
function bytesToBN(bytes) {
|
||||||
return BigInt(bytesToHex(bytes));
|
return BigInt(bytesToHex(bytes));
|
||||||
@ -102077,11 +102067,7 @@ function bnToBytes(bigint) {
|
|||||||
if (hexString.length % 2 !== 0) {
|
if (hexString.length % 2 !== 0) {
|
||||||
hexString = "0" + hexString;
|
hexString = "0" + hexString;
|
||||||
}
|
}
|
||||||
return Uint8Array.from(
|
return Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
|
||||||
hexString.match(/.{1,2}/g).map(
|
|
||||||
(byte) => parseInt(byte, 16)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
function leBuff2Int(bytes) {
|
function leBuff2Int(bytes) {
|
||||||
return new BN(bytes, 16, "le");
|
return new BN(bytes, 16, "le");
|
||||||
@ -102142,27 +102128,18 @@ async function nodePostWork() {
|
|||||||
const { hash: hashFunction } = await mimc.getHash();
|
const { hash: hashFunction } = await mimc.getHash();
|
||||||
const { merkleTreeHeight, edge, elements, zeroElement } = (worker_threads_ignored_default()).workerData;
|
const { merkleTreeHeight, edge, elements, zeroElement } = (worker_threads_ignored_default()).workerData;
|
||||||
if (edge) {
|
if (edge) {
|
||||||
const merkleTree2 = new lib.PartialMerkleTree(
|
const merkleTree2 = new lib.PartialMerkleTree(merkleTreeHeight, edge, elements, {
|
||||||
merkleTreeHeight,
|
zeroElement,
|
||||||
edge,
|
hashFunction
|
||||||
elements,
|
});
|
||||||
{
|
worker_threads_ignored_default().parentPort.postMessage(merkleTree2.toString());
|
||||||
zeroElement,
|
|
||||||
hashFunction
|
|
||||||
}
|
|
||||||
);
|
|
||||||
worker_threads_ignored_default().parentPort.postMessage(
|
|
||||||
merkleTree2.toString()
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const merkleTree = new lib.MerkleTree(merkleTreeHeight, elements, {
|
const merkleTree = new lib.MerkleTree(merkleTreeHeight, elements, {
|
||||||
zeroElement,
|
zeroElement,
|
||||||
hashFunction
|
hashFunction
|
||||||
});
|
});
|
||||||
worker_threads_ignored_default().parentPort.postMessage(
|
worker_threads_ignored_default().parentPort.postMessage(merkleTree.toString());
|
||||||
merkleTree.toString()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (isNode && (worker_threads_ignored_default())) {
|
if (isNode && (worker_threads_ignored_default())) {
|
||||||
nodePostWork();
|
nodePostWork();
|
||||||
@ -102177,15 +102154,10 @@ if (isNode && (worker_threads_ignored_default())) {
|
|||||||
const { hash: hashFunction } = await mimc.getHash();
|
const { hash: hashFunction } = await mimc.getHash();
|
||||||
const { merkleTreeHeight, edge, elements, zeroElement } = data;
|
const { merkleTreeHeight, edge, elements, zeroElement } = data;
|
||||||
if (edge) {
|
if (edge) {
|
||||||
const merkleTree2 = new lib.PartialMerkleTree(
|
const merkleTree2 = new lib.PartialMerkleTree(merkleTreeHeight, edge, elements, {
|
||||||
merkleTreeHeight,
|
zeroElement,
|
||||||
edge,
|
hashFunction
|
||||||
elements,
|
});
|
||||||
{
|
|
||||||
zeroElement,
|
|
||||||
hashFunction
|
|
||||||
}
|
|
||||||
);
|
|
||||||
postMessage(merkleTree2.toString());
|
postMessage(merkleTree2.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
6
dist/providers.d.ts
vendored
6
dist/providers.d.ts
vendored
@ -50,7 +50,7 @@ export declare class TornadoWallet extends Wallet {
|
|||||||
gasLimitBump: number;
|
gasLimitBump: number;
|
||||||
gasFailover: boolean;
|
gasFailover: boolean;
|
||||||
bumpNonce: boolean;
|
bumpNonce: boolean;
|
||||||
constructor(key: string | SigningKey, provider?: Provider, { gasPriceBump, gasLimitBump, gasFailover, bumpNonce, }?: TornadoWalletOptions);
|
constructor(key: string | SigningKey, provider?: Provider, { gasPriceBump, gasLimitBump, gasFailover, bumpNonce }?: TornadoWalletOptions);
|
||||||
static fromMnemonic(mneomnic: string, provider: Provider, index?: number, options?: TornadoWalletOptions): TornadoWallet;
|
static fromMnemonic(mneomnic: string, provider: Provider, index?: number, options?: TornadoWalletOptions): TornadoWallet;
|
||||||
populateTransaction(tx: TransactionRequest): Promise<import("ethers").TransactionLike<string>>;
|
populateTransaction(tx: TransactionRequest): Promise<import("ethers").TransactionLike<string>>;
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ export declare class TornadoVoidSigner extends VoidSigner {
|
|||||||
gasLimitBump: number;
|
gasLimitBump: number;
|
||||||
gasFailover: boolean;
|
gasFailover: boolean;
|
||||||
bumpNonce: boolean;
|
bumpNonce: boolean;
|
||||||
constructor(address: string, provider?: Provider, { gasPriceBump, gasLimitBump, gasFailover, bumpNonce, }?: TornadoWalletOptions);
|
constructor(address: string, provider?: Provider, { gasPriceBump, gasLimitBump, gasFailover, bumpNonce }?: TornadoWalletOptions);
|
||||||
populateTransaction(tx: TransactionRequest): Promise<import("ethers").TransactionLike<string>>;
|
populateTransaction(tx: TransactionRequest): Promise<import("ethers").TransactionLike<string>>;
|
||||||
}
|
}
|
||||||
export declare class TornadoRpcSigner extends JsonRpcSigner {
|
export declare class TornadoRpcSigner extends JsonRpcSigner {
|
||||||
@ -69,7 +69,7 @@ export declare class TornadoRpcSigner extends JsonRpcSigner {
|
|||||||
gasLimitBump: number;
|
gasLimitBump: number;
|
||||||
gasFailover: boolean;
|
gasFailover: boolean;
|
||||||
bumpNonce: boolean;
|
bumpNonce: boolean;
|
||||||
constructor(provider: JsonRpcApiProvider, address: string, { gasPriceBump, gasLimitBump, gasFailover, bumpNonce, }?: TornadoWalletOptions);
|
constructor(provider: JsonRpcApiProvider, address: string, { gasPriceBump, gasLimitBump, gasFailover, bumpNonce }?: TornadoWalletOptions);
|
||||||
sendUncheckedTransaction(tx: TransactionRequest): Promise<string>;
|
sendUncheckedTransaction(tx: TransactionRequest): Promise<string>;
|
||||||
}
|
}
|
||||||
export type connectWalletFunc = (...args: any[]) => Promise<void>;
|
export type connectWalletFunc = (...args: any[]) => Promise<void>;
|
||||||
|
|||||||
2
dist/relayerClient.d.ts
vendored
2
dist/relayerClient.d.ts
vendored
@ -109,7 +109,7 @@ export function isRelayerUpdated(relayerVersion: string, netId: NetIdType) {
|
|||||||
return isUpdatedMajor && (Number(patch) >= 5 || netId !== NetId.MAINNET); // Patch checking - also backwards compatibility for Mainnet
|
return isUpdatedMajor && (Number(patch) >= 5 || netId !== NetId.MAINNET); // Patch checking - also backwards compatibility for Mainnet
|
||||||
}
|
}
|
||||||
**/
|
**/
|
||||||
export declare function calculateScore({ stakeBalance, tornadoServiceFee, }: RelayerInfo): bigint;
|
export declare function calculateScore({ stakeBalance, tornadoServiceFee }: RelayerInfo): bigint;
|
||||||
export declare function getWeightRandom(weightsScores: bigint[], random: bigint): number;
|
export declare function getWeightRandom(weightsScores: bigint[], random: bigint): number;
|
||||||
export interface RelayerInstanceList {
|
export interface RelayerInstanceList {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
|
|||||||
1254
dist/tornado.umd.js
vendored
1254
dist/tornado.umd.js
vendored
File diff suppressed because it is too large
Load Diff
90
src/batch.ts
90
src/batch.ts
@ -1,12 +1,4 @@
|
|||||||
import type {
|
import type { Provider, BlockTag, Block, TransactionResponse, BaseContract, ContractEventName, EventLog } from 'ethers';
|
||||||
Provider,
|
|
||||||
BlockTag,
|
|
||||||
Block,
|
|
||||||
TransactionResponse,
|
|
||||||
BaseContract,
|
|
||||||
ContractEventName,
|
|
||||||
EventLog,
|
|
||||||
} from 'ethers';
|
|
||||||
import { chunk, sleep } from './utils';
|
import { chunk, sleep } from './utils';
|
||||||
|
|
||||||
export interface BatchBlockServiceConstructor {
|
export interface BatchBlockServiceConstructor {
|
||||||
@ -80,14 +72,9 @@ export class BatchBlockService {
|
|||||||
let err;
|
let err;
|
||||||
|
|
||||||
// eslint-disable-next-line no-unmodified-loop-condition
|
// eslint-disable-next-line no-unmodified-loop-condition
|
||||||
while (
|
while ((!this.shouldRetry && retries === 0) || (this.shouldRetry && retries < this.retryMax)) {
|
||||||
(!this.shouldRetry && retries === 0) ||
|
|
||||||
(this.shouldRetry && retries < this.retryMax)
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
return await Promise.all(
|
return await Promise.all(blocks.map((b) => this.getBlock(b)));
|
||||||
blocks.map((b) => this.getBlock(b)),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
retries++;
|
retries++;
|
||||||
err = e;
|
err = e;
|
||||||
@ -106,15 +93,8 @@ export class BatchBlockService {
|
|||||||
let blockCount = 0;
|
let blockCount = 0;
|
||||||
const results: Block[] = [];
|
const results: Block[] = [];
|
||||||
|
|
||||||
for (const chunks of chunk(
|
for (const chunks of chunk(blocks, this.concurrencySize * this.batchSize)) {
|
||||||
blocks,
|
const chunksResult = (await Promise.all(this.createBatchRequest(chunk(chunks, this.batchSize)))).flat();
|
||||||
this.concurrencySize * this.batchSize,
|
|
||||||
)) {
|
|
||||||
const chunksResult = (
|
|
||||||
await Promise.all(
|
|
||||||
this.createBatchRequest(chunk(chunks, this.batchSize)),
|
|
||||||
)
|
|
||||||
).flat();
|
|
||||||
|
|
||||||
results.push(...chunksResult);
|
results.push(...chunksResult);
|
||||||
|
|
||||||
@ -173,9 +153,7 @@ export class BatchTransactionService {
|
|||||||
return txObject;
|
return txObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
createBatchRequest(
|
createBatchRequest(batchArray: string[][]): Promise<TransactionResponse[]>[] {
|
||||||
batchArray: string[][],
|
|
||||||
): Promise<TransactionResponse[]>[] {
|
|
||||||
return batchArray.map(async (txs: string[], index: number) => {
|
return batchArray.map(async (txs: string[], index: number) => {
|
||||||
await sleep(20 * index);
|
await sleep(20 * index);
|
||||||
|
|
||||||
@ -184,14 +162,9 @@ export class BatchTransactionService {
|
|||||||
let err;
|
let err;
|
||||||
|
|
||||||
// eslint-disable-next-line no-unmodified-loop-condition
|
// eslint-disable-next-line no-unmodified-loop-condition
|
||||||
while (
|
while ((!this.shouldRetry && retries === 0) || (this.shouldRetry && retries < this.retryMax)) {
|
||||||
(!this.shouldRetry && retries === 0) ||
|
|
||||||
(this.shouldRetry && retries < this.retryMax)
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
return await Promise.all(
|
return await Promise.all(txs.map((tx) => this.getTransaction(tx)));
|
||||||
txs.map((tx) => this.getTransaction(tx)),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
retries++;
|
retries++;
|
||||||
err = e;
|
err = e;
|
||||||
@ -210,15 +183,8 @@ export class BatchTransactionService {
|
|||||||
let txCount = 0;
|
let txCount = 0;
|
||||||
const results = [];
|
const results = [];
|
||||||
|
|
||||||
for (const chunks of chunk(
|
for (const chunks of chunk(txs, this.concurrencySize * this.batchSize)) {
|
||||||
txs,
|
const chunksResult = (await Promise.all(this.createBatchRequest(chunk(chunks, this.batchSize)))).flat();
|
||||||
this.concurrencySize * this.batchSize,
|
|
||||||
)) {
|
|
||||||
const chunksResult = (
|
|
||||||
await Promise.all(
|
|
||||||
this.createBatchRequest(chunk(chunks, this.batchSize)),
|
|
||||||
)
|
|
||||||
).flat();
|
|
||||||
|
|
||||||
results.push(...chunksResult);
|
results.push(...chunksResult);
|
||||||
|
|
||||||
@ -301,25 +267,14 @@ export class BatchEventsService {
|
|||||||
this.retryOn = retryOn;
|
this.retryOn = retryOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPastEvents({
|
async getPastEvents({ fromBlock, toBlock, type }: EventInput): Promise<EventLog[]> {
|
||||||
fromBlock,
|
|
||||||
toBlock,
|
|
||||||
type,
|
|
||||||
}: EventInput): Promise<EventLog[]> {
|
|
||||||
let err;
|
let err;
|
||||||
let retries = 0;
|
let retries = 0;
|
||||||
|
|
||||||
// eslint-disable-next-line no-unmodified-loop-condition
|
// eslint-disable-next-line no-unmodified-loop-condition
|
||||||
while (
|
while ((!this.shouldRetry && retries === 0) || (this.shouldRetry && retries < this.retryMax)) {
|
||||||
(!this.shouldRetry && retries === 0) ||
|
|
||||||
(this.shouldRetry && retries < this.retryMax)
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
return (await this.contract.queryFilter(
|
return (await this.contract.queryFilter(type, fromBlock, toBlock)) as EventLog[];
|
||||||
type,
|
|
||||||
fromBlock,
|
|
||||||
toBlock,
|
|
||||||
)) as EventLog[];
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
err = e;
|
err = e;
|
||||||
@ -328,9 +283,7 @@ export class BatchEventsService {
|
|||||||
// If provider.getBlockNumber returned last block that isn't accepted (happened on Avalanche/Gnosis),
|
// If provider.getBlockNumber returned last block that isn't accepted (happened on Avalanche/Gnosis),
|
||||||
// get events to last accepted block
|
// get events to last accepted block
|
||||||
if (e.message.includes('after last accepted block')) {
|
if (e.message.includes('after last accepted block')) {
|
||||||
const acceptedBlock = parseInt(
|
const acceptedBlock = parseInt(e.message.split('after last accepted block ')[1]);
|
||||||
e.message.split('after last accepted block ')[1],
|
|
||||||
);
|
|
||||||
toBlock = acceptedBlock;
|
toBlock = acceptedBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,11 +303,7 @@ export class BatchEventsService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBatchEvents({
|
async getBatchEvents({ fromBlock, toBlock, type = '*' }: EventInput): Promise<EventLog[]> {
|
||||||
fromBlock,
|
|
||||||
toBlock,
|
|
||||||
type = '*',
|
|
||||||
}: EventInput): Promise<EventLog[]> {
|
|
||||||
if (!toBlock) {
|
if (!toBlock) {
|
||||||
toBlock = await this.provider.getBlockNumber();
|
toBlock = await this.provider.getBlockNumber();
|
||||||
}
|
}
|
||||||
@ -362,10 +311,7 @@ export class BatchEventsService {
|
|||||||
const eventsToSync = [];
|
const eventsToSync = [];
|
||||||
|
|
||||||
for (let i = fromBlock; i < toBlock; i += this.blocksPerRequest) {
|
for (let i = fromBlock; i < toBlock; i += this.blocksPerRequest) {
|
||||||
const j =
|
const j = i + this.blocksPerRequest - 1 > toBlock ? toBlock : i + this.blocksPerRequest - 1;
|
||||||
i + this.blocksPerRequest - 1 > toBlock
|
|
||||||
? toBlock
|
|
||||||
: i + this.blocksPerRequest - 1;
|
|
||||||
|
|
||||||
eventsToSync.push({ fromBlock: i, toBlock: j, type });
|
eventsToSync.push({ fromBlock: i, toBlock: j, type });
|
||||||
}
|
}
|
||||||
@ -378,9 +324,7 @@ export class BatchEventsService {
|
|||||||
for (const chunk of eventChunk) {
|
for (const chunk of eventChunk) {
|
||||||
chunkCount++;
|
chunkCount++;
|
||||||
|
|
||||||
const fetchedEvents = (
|
const fetchedEvents = (await Promise.all(this.createBatchRequest(chunk))).flat();
|
||||||
await Promise.all(this.createBatchRequest(chunk))
|
|
||||||
).flat();
|
|
||||||
events.push(...fetchedEvents);
|
events.push(...fetchedEvents);
|
||||||
|
|
||||||
if (typeof this.onProgress === 'function') {
|
if (typeof this.onProgress === 'function') {
|
||||||
|
|||||||
@ -1,11 +1,4 @@
|
|||||||
import {
|
import { bnToBytes, bytesToBN, leBuff2Int, leInt2Buff, rBigInt, toFixedHex } from './utils';
|
||||||
bnToBytes,
|
|
||||||
bytesToBN,
|
|
||||||
leBuff2Int,
|
|
||||||
leInt2Buff,
|
|
||||||
rBigInt,
|
|
||||||
toFixedHex,
|
|
||||||
} from './utils';
|
|
||||||
import { buffPedersenHash } from './pedersen';
|
import { buffPedersenHash } from './pedersen';
|
||||||
import type { NetIdType } from './networkConfig';
|
import type { NetIdType } from './networkConfig';
|
||||||
|
|
||||||
@ -45,15 +38,13 @@ export interface parsedInvoiceExec extends DepositType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function parseNote(noteString: string): parsedNoteExec | undefined {
|
export function parseNote(noteString: string): parsedNoteExec | undefined {
|
||||||
const noteRegex =
|
const noteRegex = /tornado-(?<currency>\w+)-(?<amount>[\d.]+)-(?<netId>\d+)-0x(?<noteHex>[0-9a-fA-F]{124})/g;
|
||||||
/tornado-(?<currency>\w+)-(?<amount>[\d.]+)-(?<netId>\d+)-0x(?<noteHex>[0-9a-fA-F]{124})/g;
|
|
||||||
const match = noteRegex.exec(noteString);
|
const match = noteRegex.exec(noteString);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { currency, amount, netId, noteHex } =
|
const { currency, amount, netId, noteHex } = match.groups as unknown as parsedNoteExec;
|
||||||
match.groups as unknown as parsedNoteExec;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currency: currency.toLowerCase(),
|
currency: currency.toLowerCase(),
|
||||||
@ -64,9 +55,7 @@ export function parseNote(noteString: string): parsedNoteExec | undefined {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseInvoice(
|
export function parseInvoice(invoiceString: string): parsedInvoiceExec | undefined {
|
||||||
invoiceString: string,
|
|
||||||
): parsedInvoiceExec | undefined {
|
|
||||||
const invoiceRegex =
|
const invoiceRegex =
|
||||||
/tornadoInvoice-(?<currency>\w+)-(?<amount>[\d.]+)-(?<netId>\d+)-0x(?<commitmentHex>[0-9a-fA-F]{64})/g;
|
/tornadoInvoice-(?<currency>\w+)-(?<amount>[\d.]+)-(?<netId>\d+)-0x(?<commitmentHex>[0-9a-fA-F]{64})/g;
|
||||||
const match = invoiceRegex.exec(invoiceString);
|
const match = invoiceRegex.exec(invoiceString);
|
||||||
@ -74,8 +63,7 @@ export function parseInvoice(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { currency, amount, netId, commitmentHex } =
|
const { currency, amount, netId, commitmentHex } = match.groups as unknown as parsedInvoiceExec;
|
||||||
match.groups as unknown as parsedInvoiceExec;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currency: currency.toLowerCase(),
|
currency: currency.toLowerCase(),
|
||||||
@ -86,14 +74,8 @@ export function parseInvoice(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createDeposit({
|
export async function createDeposit({ nullifier, secret }: createDepositParams): Promise<createDepositObject> {
|
||||||
nullifier,
|
const preimage = new Uint8Array([...leInt2Buff(nullifier), ...leInt2Buff(secret)]);
|
||||||
secret,
|
|
||||||
}: createDepositParams): Promise<createDepositObject> {
|
|
||||||
const preimage = new Uint8Array([
|
|
||||||
...leInt2Buff(nullifier),
|
|
||||||
...leInt2Buff(secret),
|
|
||||||
]);
|
|
||||||
const noteHex = toFixedHex(bytesToBN(preimage), 62);
|
const noteHex = toFixedHex(bytesToBN(preimage), 62);
|
||||||
const commitment = BigInt(await buffPedersenHash(preimage));
|
const commitment = BigInt(await buffPedersenHash(preimage));
|
||||||
const commitmentHex = toFixedHex(commitment);
|
const commitmentHex = toFixedHex(commitment);
|
||||||
@ -184,13 +166,7 @@ export class Deposit {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async createNote({
|
static async createNote({ currency, amount, netId, nullifier, secret }: createNoteParams): Promise<Deposit> {
|
||||||
currency,
|
|
||||||
amount,
|
|
||||||
netId,
|
|
||||||
nullifier,
|
|
||||||
secret,
|
|
||||||
}: createNoteParams): Promise<Deposit> {
|
|
||||||
if (!nullifier) {
|
if (!nullifier) {
|
||||||
nullifier = rBigInt(31);
|
nullifier = rBigInt(31);
|
||||||
}
|
}
|
||||||
@ -226,13 +202,7 @@ export class Deposit {
|
|||||||
throw new Error('The note has invalid format');
|
throw new Error('The note has invalid format');
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const { currency, amount, netId, note, noteHex: parsedNoteHex } = parsedNote;
|
||||||
currency,
|
|
||||||
amount,
|
|
||||||
netId,
|
|
||||||
note,
|
|
||||||
noteHex: parsedNoteHex,
|
|
||||||
} = parsedNote;
|
|
||||||
|
|
||||||
const bytes = bnToBytes(parsedNoteHex);
|
const bytes = bnToBytes(parsedNoteHex);
|
||||||
const nullifier = BigInt(leBuff2Int(bytes.slice(0, 31)).toString());
|
const nullifier = BigInt(leBuff2Int(bytes.slice(0, 31)).toString());
|
||||||
@ -276,8 +246,7 @@ export class Invoice {
|
|||||||
throw new Error('The invoice has invalid format');
|
throw new Error('The invoice has invalid format');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { currency, amount, netId, invoice, commitmentHex } =
|
const { currency, amount, netId, invoice, commitmentHex } = parsedInvoice;
|
||||||
parsedInvoice;
|
|
||||||
|
|
||||||
this.currency = currency;
|
this.currency = currency;
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
|
|||||||
@ -1,25 +1,6 @@
|
|||||||
import {
|
import { getEncryptionPublicKey, encrypt, decrypt, EthEncryptedData } from '@metamask/eth-sig-util';
|
||||||
getEncryptionPublicKey,
|
import { JsonRpcApiProvider, Signer, Wallet, computeAddress, getAddress } from 'ethers';
|
||||||
encrypt,
|
import { base64ToBytes, bytesToBase64, bytesToHex, hexToBytes, toFixedHex, concatBytes, rHex } from './utils';
|
||||||
decrypt,
|
|
||||||
EthEncryptedData,
|
|
||||||
} from '@metamask/eth-sig-util';
|
|
||||||
import {
|
|
||||||
JsonRpcApiProvider,
|
|
||||||
Signer,
|
|
||||||
Wallet,
|
|
||||||
computeAddress,
|
|
||||||
getAddress,
|
|
||||||
} from 'ethers';
|
|
||||||
import {
|
|
||||||
base64ToBytes,
|
|
||||||
bytesToBase64,
|
|
||||||
bytesToHex,
|
|
||||||
hexToBytes,
|
|
||||||
toFixedHex,
|
|
||||||
concatBytes,
|
|
||||||
rHex,
|
|
||||||
} from './utils';
|
|
||||||
import { EchoEvents, EncryptedNotesEvents } from './events';
|
import { EchoEvents, EncryptedNotesEvents } from './events';
|
||||||
|
|
||||||
export interface NoteToEncrypt {
|
export interface NoteToEncrypt {
|
||||||
@ -33,23 +14,12 @@ export interface DecryptedNotes {
|
|||||||
noteHex: string;
|
noteHex: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function packEncryptedMessage({
|
export function packEncryptedMessage({ nonce, ephemPublicKey, ciphertext }: EthEncryptedData) {
|
||||||
nonce,
|
|
||||||
ephemPublicKey,
|
|
||||||
ciphertext,
|
|
||||||
}: EthEncryptedData) {
|
|
||||||
const nonceBuf = toFixedHex(bytesToHex(base64ToBytes(nonce)), 24);
|
const nonceBuf = toFixedHex(bytesToHex(base64ToBytes(nonce)), 24);
|
||||||
const ephemPublicKeyBuf = toFixedHex(
|
const ephemPublicKeyBuf = toFixedHex(bytesToHex(base64ToBytes(ephemPublicKey)), 32);
|
||||||
bytesToHex(base64ToBytes(ephemPublicKey)),
|
|
||||||
32,
|
|
||||||
);
|
|
||||||
const ciphertextBuf = bytesToHex(base64ToBytes(ciphertext));
|
const ciphertextBuf = bytesToHex(base64ToBytes(ciphertext));
|
||||||
|
|
||||||
const messageBuff = concatBytes(
|
const messageBuff = concatBytes(hexToBytes(nonceBuf), hexToBytes(ephemPublicKeyBuf), hexToBytes(ciphertextBuf));
|
||||||
hexToBytes(nonceBuf),
|
|
||||||
hexToBytes(ephemPublicKeyBuf),
|
|
||||||
hexToBytes(ciphertextBuf),
|
|
||||||
);
|
|
||||||
|
|
||||||
return bytesToHex(messageBuff);
|
return bytesToHex(messageBuff);
|
||||||
}
|
}
|
||||||
@ -105,10 +75,7 @@ export class NoteAccount {
|
|||||||
static async getSignerPublicKey(signer: Signer | Wallet) {
|
static async getSignerPublicKey(signer: Signer | Wallet) {
|
||||||
if ((signer as Wallet).privateKey) {
|
if ((signer as Wallet).privateKey) {
|
||||||
const wallet = signer as Wallet;
|
const wallet = signer as Wallet;
|
||||||
const privateKey =
|
const privateKey = wallet.privateKey.slice(0, 2) === '0x' ? wallet.privateKey.slice(2) : wallet.privateKey;
|
||||||
wallet.privateKey.slice(0, 2) === '0x'
|
|
||||||
? wallet.privateKey.slice(2)
|
|
||||||
: wallet.privateKey;
|
|
||||||
|
|
||||||
// Should return base64 encoded public key
|
// Should return base64 encoded public key
|
||||||
return getEncryptionPublicKey(privateKey);
|
return getEncryptionPublicKey(privateKey);
|
||||||
@ -146,13 +113,8 @@ export class NoteAccount {
|
|||||||
/**
|
/**
|
||||||
* Decrypt Echoer backuped note encryption account with private keys
|
* Decrypt Echoer backuped note encryption account with private keys
|
||||||
*/
|
*/
|
||||||
static async decryptSignerNoteAccounts(
|
static async decryptSignerNoteAccounts(signer: Signer | Wallet, events: EchoEvents[]): Promise<NoteAccount[]> {
|
||||||
signer: Signer | Wallet,
|
const signerAddress = (signer as (Signer & { address: string }) | Wallet).address;
|
||||||
events: EchoEvents[],
|
|
||||||
): Promise<NoteAccount[]> {
|
|
||||||
const signerAddress = (
|
|
||||||
signer as (Signer & { address: string }) | Wallet
|
|
||||||
).address;
|
|
||||||
|
|
||||||
const decryptedEvents = [];
|
const decryptedEvents = [];
|
||||||
|
|
||||||
@ -162,26 +124,21 @@ export class NoteAccount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const unpackedMessage = unpackEncryptedMessage(
|
const unpackedMessage = unpackEncryptedMessage(event.encryptedAccount);
|
||||||
event.encryptedAccount,
|
|
||||||
);
|
|
||||||
|
|
||||||
let recoveryKey;
|
let recoveryKey;
|
||||||
|
|
||||||
if ((signer as Wallet).privateKey) {
|
if ((signer as Wallet).privateKey) {
|
||||||
const wallet = signer as Wallet;
|
const wallet = signer as Wallet;
|
||||||
const privateKey =
|
const privateKey =
|
||||||
wallet.privateKey.slice(0, 2) === '0x'
|
wallet.privateKey.slice(0, 2) === '0x' ? wallet.privateKey.slice(2) : wallet.privateKey;
|
||||||
? wallet.privateKey.slice(2)
|
|
||||||
: wallet.privateKey;
|
|
||||||
|
|
||||||
recoveryKey = decrypt({
|
recoveryKey = decrypt({
|
||||||
encryptedData: unpackedMessage,
|
encryptedData: unpackedMessage,
|
||||||
privateKey,
|
privateKey,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const { version, nonce, ephemPublicKey, ciphertext } =
|
const { version, nonce, ephemPublicKey, ciphertext } = unpackedMessage;
|
||||||
unpackedMessage;
|
|
||||||
|
|
||||||
const unpackedBuffer = bytesToHex(
|
const unpackedBuffer = bytesToHex(
|
||||||
new TextEncoder().encode(
|
new TextEncoder().encode(
|
||||||
@ -196,10 +153,7 @@ export class NoteAccount {
|
|||||||
|
|
||||||
const provider = signer.provider as JsonRpcApiProvider;
|
const provider = signer.provider as JsonRpcApiProvider;
|
||||||
|
|
||||||
recoveryKey = await provider.send('eth_decrypt', [
|
recoveryKey = await provider.send('eth_decrypt', [unpackedBuffer, signerAddress]);
|
||||||
unpackedBuffer,
|
|
||||||
signerAddress,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptedEvents.push(
|
decryptedEvents.push(
|
||||||
@ -222,9 +176,7 @@ export class NoteAccount {
|
|||||||
|
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
try {
|
try {
|
||||||
const unpackedMessage = unpackEncryptedMessage(
|
const unpackedMessage = unpackEncryptedMessage(event.encryptedNote);
|
||||||
event.encryptedNote,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [address, noteHex] = decrypt({
|
const [address, noteHex] = decrypt({
|
||||||
encryptedData: unpackedMessage,
|
encryptedData: unpackedMessage,
|
||||||
|
|||||||
48
src/ens.ts
48
src/ens.ts
@ -1,10 +1,4 @@
|
|||||||
import {
|
import { namehash, EnsResolver, AbstractProvider, keccak256, Signer } from 'ethers';
|
||||||
namehash,
|
|
||||||
EnsResolver,
|
|
||||||
AbstractProvider,
|
|
||||||
keccak256,
|
|
||||||
Signer,
|
|
||||||
} from 'ethers';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ENSNameWrapper,
|
ENSNameWrapper,
|
||||||
@ -30,10 +24,7 @@ export function labelhash(label: string) {
|
|||||||
if (!label) {
|
if (!label) {
|
||||||
return bytesToHex(new Uint8Array(32).fill(0));
|
return bytesToHex(new Uint8Array(32).fill(0));
|
||||||
}
|
}
|
||||||
return (
|
return encodedLabelToLabelhash(label) || keccak256(new TextEncoder().encode(label));
|
||||||
encodedLabelToLabelhash(label) ||
|
|
||||||
keccak256(new TextEncoder().encode(label))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeLabelNodeAndParent(name: string) {
|
export function makeLabelNodeAndParent(name: string) {
|
||||||
@ -84,21 +75,11 @@ export class ENSUtils {
|
|||||||
async getContracts() {
|
async getContracts() {
|
||||||
const { chainId } = await this.provider.getNetwork();
|
const { chainId } = await this.provider.getNetwork();
|
||||||
|
|
||||||
const { ensRegistry, ensPublicResolver, ensNameWrapper } =
|
const { ensRegistry, ensPublicResolver, ensNameWrapper } = EnsContracts[Number(chainId)];
|
||||||
EnsContracts[Number(chainId)];
|
|
||||||
|
|
||||||
this.ENSRegistry = ENSRegistry__factory.connect(
|
this.ENSRegistry = ENSRegistry__factory.connect(ensRegistry, this.provider);
|
||||||
ensRegistry,
|
this.ENSResolver = ENSResolver__factory.connect(ensPublicResolver, this.provider);
|
||||||
this.provider,
|
this.ENSNameWrapper = ENSNameWrapper__factory.connect(ensNameWrapper, this.provider);
|
||||||
);
|
|
||||||
this.ENSResolver = ENSResolver__factory.connect(
|
|
||||||
ensPublicResolver,
|
|
||||||
this.provider,
|
|
||||||
);
|
|
||||||
this.ENSNameWrapper = ENSNameWrapper__factory.connect(
|
|
||||||
ensNameWrapper,
|
|
||||||
this.provider,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOwner(name: string) {
|
async getOwner(name: string) {
|
||||||
@ -117,9 +98,7 @@ export class ENSUtils {
|
|||||||
|
|
||||||
const owner = (signer as unknown as { address: string }).address;
|
const owner = (signer as unknown as { address: string }).address;
|
||||||
|
|
||||||
const nameWrapper = (this.ENSNameWrapper as ENSNameWrapper).connect(
|
const nameWrapper = (this.ENSNameWrapper as ENSNameWrapper).connect(signer);
|
||||||
signer,
|
|
||||||
);
|
|
||||||
|
|
||||||
const { labelhash } = makeLabelNodeAndParent(name);
|
const { labelhash } = makeLabelNodeAndParent(name);
|
||||||
|
|
||||||
@ -139,21 +118,12 @@ export class ENSUtils {
|
|||||||
|
|
||||||
const { labelhash, parentNode } = makeLabelNodeAndParent(name);
|
const { labelhash, parentNode } = makeLabelNodeAndParent(name);
|
||||||
|
|
||||||
return registry.setSubnodeRecord(
|
return registry.setSubnodeRecord(parentNode, labelhash, owner, resolver.target, BigInt(0));
|
||||||
parentNode,
|
|
||||||
labelhash,
|
|
||||||
owner,
|
|
||||||
resolver.target,
|
|
||||||
BigInt(0),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/ensdomains/ensjs/blob/main/packages/ensjs/src/functions/wallet/setTextRecord.ts
|
// https://github.com/ensdomains/ensjs/blob/main/packages/ensjs/src/functions/wallet/setTextRecord.ts
|
||||||
async setText(signer: Signer, name: string, key: string, value: string) {
|
async setText(signer: Signer, name: string, key: string, value: string) {
|
||||||
const resolver = ENSResolver__factory.connect(
|
const resolver = ENSResolver__factory.connect((await this.getResolver(name))?.address as string, signer);
|
||||||
(await this.getResolver(name))?.address as string,
|
|
||||||
signer,
|
|
||||||
);
|
|
||||||
|
|
||||||
return resolver.setText(namehash(name), key, value);
|
return resolver.setText(namehash(name), key, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,11 +34,7 @@ import {
|
|||||||
} from '../batch';
|
} from '../batch';
|
||||||
|
|
||||||
import { fetchData, fetchDataOptions } from '../providers';
|
import { fetchData, fetchDataOptions } from '../providers';
|
||||||
import {
|
import { enabledChains, type NetIdType, type SubdomainMap } from '../networkConfig';
|
||||||
enabledChains,
|
|
||||||
type NetIdType,
|
|
||||||
type SubdomainMap,
|
|
||||||
} from '../networkConfig';
|
|
||||||
import { RelayerParams, MIN_STAKE_BALANCE } from '../relayerClient';
|
import { RelayerParams, MIN_STAKE_BALANCE } from '../relayerClient';
|
||||||
import type { TovarishClient } from '../tovarishClient';
|
import type { TovarishClient } from '../tovarishClient';
|
||||||
|
|
||||||
@ -163,39 +159,18 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
updateEventProgress({
|
updateEventProgress({ percentage, type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]) {}
|
||||||
percentage,
|
|
||||||
type,
|
|
||||||
fromBlock,
|
|
||||||
toBlock,
|
|
||||||
count,
|
|
||||||
}: Parameters<BatchEventOnProgress>[0]) {}
|
|
||||||
|
|
||||||
updateBlockProgress({
|
updateBlockProgress({ percentage, currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]) {}
|
||||||
percentage,
|
|
||||||
currentIndex,
|
|
||||||
totalIndex,
|
|
||||||
}: Parameters<BatchBlockOnProgress>[0]) {}
|
|
||||||
|
|
||||||
updateTransactionProgress({
|
updateTransactionProgress({ percentage, currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]) {}
|
||||||
percentage,
|
|
||||||
currentIndex,
|
|
||||||
totalIndex,
|
|
||||||
}: Parameters<BatchBlockOnProgress>[0]) {}
|
|
||||||
|
|
||||||
updateGraphProgress({
|
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchGraphOnProgress>[0]) {}
|
||||||
type,
|
|
||||||
fromBlock,
|
|
||||||
toBlock,
|
|
||||||
count,
|
|
||||||
}: Parameters<BatchGraphOnProgress>[0]) {}
|
|
||||||
/* eslint-enable @typescript-eslint/no-unused-vars */
|
/* eslint-enable @typescript-eslint/no-unused-vars */
|
||||||
|
|
||||||
async formatEvents(events: EventLog[]): Promise<EventType[]> {
|
async formatEvents(events: EventLog[]): Promise<EventType[]> {
|
||||||
// eslint-disable-next-line no-return-await
|
// eslint-disable-next-line no-return-await
|
||||||
return await new Promise((resolve) =>
|
return await new Promise((resolve) => resolve(events as unknown as EventType[]));
|
||||||
resolve(events as unknown as EventType[]),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,9 +195,7 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSavedEvents(): Promise<
|
async getSavedEvents(): Promise<BaseEvents<EventType> | CachedEvents<EventType>> {
|
||||||
BaseEvents<EventType> | CachedEvents<EventType>
|
|
||||||
> {
|
|
||||||
let dbEvents = await this.getEventsFromDB();
|
let dbEvents = await this.getEventsFromDB();
|
||||||
|
|
||||||
if (!dbEvents.lastBlock) {
|
if (!dbEvents.lastBlock) {
|
||||||
@ -251,9 +224,7 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const { events, lastSyncBlock } = (await (graph as any)[
|
const { events, lastSyncBlock } = (await (graph as any)[methodName || this.getGraphMethod()]({
|
||||||
methodName || this.getGraphMethod()
|
|
||||||
]({
|
|
||||||
fromBlock,
|
fromBlock,
|
||||||
...this.getGraphParams(),
|
...this.getGraphParams(),
|
||||||
})) as BaseGraphEvents<EventType>;
|
})) as BaseGraphEvents<EventType>;
|
||||||
@ -305,20 +276,12 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLatestEvents({
|
async getLatestEvents({ fromBlock }: { fromBlock: number }): Promise<BaseEvents<EventType>> {
|
||||||
fromBlock,
|
if (this.tovarishClient?.selectedRelayer && ![DEPOSIT, WITHDRAWAL].includes(this.type.toLowerCase())) {
|
||||||
}: {
|
const { events, lastSyncBlock: lastBlock } = await this.tovarishClient.getEvents<EventType>({
|
||||||
fromBlock: number;
|
type: this.getTovarishType(),
|
||||||
}): Promise<BaseEvents<EventType>> {
|
fromBlock,
|
||||||
if (
|
});
|
||||||
this.tovarishClient?.selectedRelayer &&
|
|
||||||
![DEPOSIT, WITHDRAWAL].includes(this.type.toLowerCase())
|
|
||||||
) {
|
|
||||||
const { events, lastSyncBlock: lastBlock } =
|
|
||||||
await this.tovarishClient.getEvents<EventType>({
|
|
||||||
type: this.getTovarishType(),
|
|
||||||
fromBlock,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
events,
|
events,
|
||||||
@ -328,9 +291,7 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
|
|
||||||
const graphEvents = await this.getEventsFromGraph({ fromBlock });
|
const graphEvents = await this.getEventsFromGraph({ fromBlock });
|
||||||
const lastSyncBlock =
|
const lastSyncBlock =
|
||||||
graphEvents.lastBlock && graphEvents.lastBlock >= fromBlock
|
graphEvents.lastBlock && graphEvents.lastBlock >= fromBlock ? graphEvents.lastBlock : fromBlock;
|
||||||
? graphEvents.lastBlock
|
|
||||||
: fromBlock;
|
|
||||||
const rpcEvents = await this.getEventsFromRpc({
|
const rpcEvents = await this.getEventsFromRpc({
|
||||||
fromBlock: lastSyncBlock,
|
fromBlock: lastSyncBlock,
|
||||||
});
|
});
|
||||||
@ -374,10 +335,7 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
|
|
||||||
const eventSet = new Set();
|
const eventSet = new Set();
|
||||||
|
|
||||||
const allEvents: EventType[] = [
|
const allEvents: EventType[] = [...savedEvents.events, ...newEvents.events]
|
||||||
...savedEvents.events,
|
|
||||||
...newEvents.events,
|
|
||||||
]
|
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
if (a.blockNumber === b.blockNumber) {
|
if (a.blockNumber === b.blockNumber) {
|
||||||
return a.logIndex - b.logIndex;
|
return a.logIndex - b.logIndex;
|
||||||
@ -391,8 +349,7 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
return !hasEvent;
|
return !hasEvent;
|
||||||
});
|
});
|
||||||
|
|
||||||
const lastBlock =
|
const lastBlock = newEvents.lastBlock || allEvents[allEvents.length - 1]?.blockNumber;
|
||||||
newEvents.lastBlock || allEvents[allEvents.length - 1]?.blockNumber;
|
|
||||||
|
|
||||||
const validateResult = await this.validateEvents<S>({
|
const validateResult = await this.validateEvents<S>({
|
||||||
events: allEvents,
|
events: allEvents,
|
||||||
@ -401,10 +358,7 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// If the events are loaded from cache or we have found new events, save them
|
// If the events are loaded from cache or we have found new events, save them
|
||||||
if (
|
if ((savedEvents as CachedEvents<EventType>).fromCache || newEvents.events.length) {
|
||||||
(savedEvents as CachedEvents<EventType>).fromCache ||
|
|
||||||
newEvents.events.length
|
|
||||||
) {
|
|
||||||
await this.saveEvents({ events: allEvents, lastBlock });
|
await this.saveEvents({ events: allEvents, lastBlock });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,8 +370,7 @@ export class BaseEventsService<EventType extends MinimalEvents> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BaseTornadoServiceConstructor
|
export interface BaseTornadoServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract'> {
|
||||||
extends Omit<BaseEventsServiceConstructor, 'contract'> {
|
|
||||||
Tornado: Tornado;
|
Tornado: Tornado;
|
||||||
amount: string;
|
amount: string;
|
||||||
currency: string;
|
currency: string;
|
||||||
@ -430,9 +383,7 @@ export interface DepositsGraphParams extends BaseGraphParams {
|
|||||||
currency: string;
|
currency: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BaseTornadoService extends BaseEventsService<
|
export class BaseTornadoService extends BaseEventsService<DepositsEvents | WithdrawalsEvents> {
|
||||||
DepositsEvents | WithdrawalsEvents
|
|
||||||
> {
|
|
||||||
amount: string;
|
amount: string;
|
||||||
currency: string;
|
currency: string;
|
||||||
|
|
||||||
@ -442,14 +393,7 @@ export class BaseTornadoService extends BaseEventsService<
|
|||||||
batchBlockService: BatchBlockService;
|
batchBlockService: BatchBlockService;
|
||||||
|
|
||||||
constructor(serviceConstructor: BaseTornadoServiceConstructor) {
|
constructor(serviceConstructor: BaseTornadoServiceConstructor) {
|
||||||
const {
|
const { Tornado: contract, amount, currency, provider, optionalTree, merkleTreeService } = serviceConstructor;
|
||||||
Tornado: contract,
|
|
||||||
amount,
|
|
||||||
currency,
|
|
||||||
provider,
|
|
||||||
optionalTree,
|
|
||||||
merkleTreeService,
|
|
||||||
} = serviceConstructor;
|
|
||||||
|
|
||||||
super({
|
super({
|
||||||
...serviceConstructor,
|
...serviceConstructor,
|
||||||
@ -492,40 +436,28 @@ export class BaseTornadoService extends BaseEventsService<
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async formatEvents(
|
async formatEvents(events: EventLog[]): Promise<(DepositsEvents | WithdrawalsEvents)[]> {
|
||||||
events: EventLog[],
|
|
||||||
): Promise<(DepositsEvents | WithdrawalsEvents)[]> {
|
|
||||||
const type = this.getType().toLowerCase();
|
const type = this.getType().toLowerCase();
|
||||||
if (type === DEPOSIT) {
|
if (type === DEPOSIT) {
|
||||||
const formattedEvents = events.map(
|
const formattedEvents = events.map(({ blockNumber, index: logIndex, transactionHash, args }) => {
|
||||||
({ blockNumber, index: logIndex, transactionHash, args }) => {
|
const { commitment, leafIndex, timestamp } = args;
|
||||||
const { commitment, leafIndex, timestamp } = args;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
blockNumber,
|
blockNumber,
|
||||||
logIndex,
|
logIndex,
|
||||||
transactionHash,
|
transactionHash,
|
||||||
commitment: commitment as string,
|
commitment: commitment as string,
|
||||||
leafIndex: Number(leafIndex),
|
leafIndex: Number(leafIndex),
|
||||||
timestamp: Number(timestamp),
|
timestamp: Number(timestamp),
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const txs = await this.batchTransactionService.getBatchTransactions(
|
const txs = await this.batchTransactionService.getBatchTransactions([
|
||||||
[
|
...new Set(formattedEvents.map(({ transactionHash }) => transactionHash)),
|
||||||
...new Set(
|
]);
|
||||||
formattedEvents.map(
|
|
||||||
({ transactionHash }) => transactionHash,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
return formattedEvents.map((event) => {
|
return formattedEvents.map((event) => {
|
||||||
const { from } = txs.find(
|
const { from } = txs.find(({ hash }) => hash === event.transactionHash) as TransactionResponse;
|
||||||
({ hash }) => hash === event.transactionHash,
|
|
||||||
) as TransactionResponse;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...event,
|
...event,
|
||||||
@ -533,31 +465,25 @@ export class BaseTornadoService extends BaseEventsService<
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const formattedEvents = events.map(
|
const formattedEvents = events.map(({ blockNumber, index: logIndex, transactionHash, args }) => {
|
||||||
({ blockNumber, index: logIndex, transactionHash, args }) => {
|
const { nullifierHash, to, fee } = args;
|
||||||
const { nullifierHash, to, fee } = args;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
blockNumber,
|
blockNumber,
|
||||||
logIndex,
|
logIndex,
|
||||||
transactionHash,
|
transactionHash,
|
||||||
nullifierHash: String(nullifierHash),
|
nullifierHash: String(nullifierHash),
|
||||||
to: getAddress(to),
|
to: getAddress(to),
|
||||||
fee: String(fee),
|
fee: String(fee),
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const blocks = await this.batchBlockService.getBatchBlocks([
|
const blocks = await this.batchBlockService.getBatchBlocks([
|
||||||
...new Set(
|
...new Set(formattedEvents.map(({ blockNumber }) => blockNumber)),
|
||||||
formattedEvents.map(({ blockNumber }) => blockNumber),
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return formattedEvents.map((event) => {
|
return formattedEvents.map((event) => {
|
||||||
const { timestamp } = blocks.find(
|
const { timestamp } = blocks.find(({ number }) => number === event.blockNumber) as Block;
|
||||||
({ number }) => number === event.blockNumber,
|
|
||||||
) as Block;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...event,
|
...event,
|
||||||
@ -583,13 +509,8 @@ export class BaseTornadoService extends BaseEventsService<
|
|||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.merkleTreeService && (!this.optionalTree || hasNewEvents)) {
|
||||||
this.merkleTreeService &&
|
return (await this.merkleTreeService.verifyTree(depositEvents)) as S;
|
||||||
(!this.optionalTree || hasNewEvents)
|
|
||||||
) {
|
|
||||||
return (await this.merkleTreeService.verifyTree(
|
|
||||||
depositEvents,
|
|
||||||
)) as S;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,15 +523,14 @@ export class BaseTornadoService extends BaseEventsService<
|
|||||||
fromBlock: number;
|
fromBlock: number;
|
||||||
}): Promise<BaseEvents<DepositsEvents | WithdrawalsEvents>> {
|
}): Promise<BaseEvents<DepositsEvents | WithdrawalsEvents>> {
|
||||||
if (this.tovarishClient?.selectedRelayer) {
|
if (this.tovarishClient?.selectedRelayer) {
|
||||||
const { events, lastSyncBlock: lastBlock } =
|
const { events, lastSyncBlock: lastBlock } = await this.tovarishClient.getEvents<
|
||||||
await this.tovarishClient.getEvents<
|
DepositsEvents | WithdrawalsEvents
|
||||||
DepositsEvents | WithdrawalsEvents
|
>({
|
||||||
>({
|
type: this.getTovarishType(),
|
||||||
type: this.getTovarishType(),
|
currency: this.currency,
|
||||||
currency: this.currency,
|
amount: this.amount,
|
||||||
amount: this.amount,
|
fromBlock,
|
||||||
fromBlock,
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
events,
|
events,
|
||||||
@ -622,8 +542,7 @@ export class BaseTornadoService extends BaseEventsService<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BaseEchoServiceConstructor
|
export interface BaseEchoServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||||
extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
|
||||||
Echoer: Echoer;
|
Echoer: Echoer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,11 +585,7 @@ export class BaseEchoService extends BaseEventsService<EchoEvents> {
|
|||||||
.filter((e) => e) as EchoEvents[];
|
.filter((e) => e) as EchoEvents[];
|
||||||
}
|
}
|
||||||
|
|
||||||
async getEventsFromGraph({
|
async getEventsFromGraph({ fromBlock }: { fromBlock: number }): Promise<BaseEvents<EchoEvents>> {
|
||||||
fromBlock,
|
|
||||||
}: {
|
|
||||||
fromBlock: number;
|
|
||||||
}): Promise<BaseEvents<EchoEvents>> {
|
|
||||||
// TheGraph doesn't support our batch sync due to missing blockNumber field
|
// TheGraph doesn't support our batch sync due to missing blockNumber field
|
||||||
if (!this.graphApi || this.graphApi.includes('api.thegraph.com')) {
|
if (!this.graphApi || this.graphApi.includes('api.thegraph.com')) {
|
||||||
return {
|
return {
|
||||||
@ -683,8 +598,7 @@ export class BaseEchoService extends BaseEventsService<EchoEvents> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BaseEncryptedNotesServiceConstructor
|
export interface BaseEncryptedNotesServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||||
extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
|
||||||
Router: TornadoRouter | TornadoProxyLight;
|
Router: TornadoRouter | TornadoProxyLight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,16 +657,12 @@ export const proposalState: { [key: string]: string } = {
|
|||||||
6: 'Expired',
|
6: 'Expired',
|
||||||
};
|
};
|
||||||
|
|
||||||
function parseDescription(
|
function parseDescription(id: number, text: string): { title: string; description: string } {
|
||||||
id: number,
|
|
||||||
text: string,
|
|
||||||
): { title: string; description: string } {
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 1:
|
case 1:
|
||||||
return {
|
return {
|
||||||
title: text,
|
title: text,
|
||||||
description:
|
description: 'See: https://torn.community/t/proposal-1-enable-torn-transfers/38',
|
||||||
'See: https://torn.community/t/proposal-1-enable-torn-transfers/38',
|
|
||||||
};
|
};
|
||||||
case 10:
|
case 10:
|
||||||
text = text.replace('\n', '\\n\\n');
|
text = text.replace('\n', '\\n\\n');
|
||||||
@ -795,16 +705,10 @@ function parseDescription(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseComment(
|
function parseComment(Governance: Governance, calldata: string): { contact: string; message: string } {
|
||||||
Governance: Governance,
|
|
||||||
calldata: string,
|
|
||||||
): { contact: string; message: string } {
|
|
||||||
try {
|
try {
|
||||||
const methodLength = 4;
|
const methodLength = 4;
|
||||||
const result = abiCoder.decode(
|
const result = abiCoder.decode(['address[]', 'uint256', 'bool'], dataSlice(calldata, methodLength));
|
||||||
['address[]', 'uint256', 'bool'],
|
|
||||||
dataSlice(calldata, methodLength),
|
|
||||||
);
|
|
||||||
const data = Governance.interface.encodeFunctionData(
|
const data = Governance.interface.encodeFunctionData(
|
||||||
// @ts-expect-error encodeFunctionData is broken lol
|
// @ts-expect-error encodeFunctionData is broken lol
|
||||||
'castDelegatedVote',
|
'castDelegatedVote',
|
||||||
@ -812,10 +716,7 @@ function parseComment(
|
|||||||
);
|
);
|
||||||
const length = dataLength(data);
|
const length = dataLength(data);
|
||||||
|
|
||||||
const str: string = abiCoder.decode(
|
const str: string = abiCoder.decode(['string'], dataSlice(calldata, length))[0];
|
||||||
['string'],
|
|
||||||
dataSlice(calldata, length),
|
|
||||||
)[0];
|
|
||||||
const [contact, message] = JSON.parse(str) as string[];
|
const [contact, message] = JSON.parse(str) as string[];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -848,8 +749,7 @@ export interface GovernanceVotes extends GovernanceVotedEvents {
|
|||||||
voterName?: string;
|
voterName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BaseGovernanceServiceConstructor
|
export interface BaseGovernanceServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||||
extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
|
||||||
Governance: Governance;
|
Governance: Governance;
|
||||||
Aggregator: Aggregator;
|
Aggregator: Aggregator;
|
||||||
ReverseRecords: ReverseRecords;
|
ReverseRecords: ReverseRecords;
|
||||||
@ -863,8 +763,7 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
batchTransactionService: BatchTransactionService;
|
batchTransactionService: BatchTransactionService;
|
||||||
|
|
||||||
constructor(serviceConstructor: BaseGovernanceServiceConstructor) {
|
constructor(serviceConstructor: BaseGovernanceServiceConstructor) {
|
||||||
const { Governance, Aggregator, ReverseRecords, provider } =
|
const { Governance, Aggregator, ReverseRecords, provider } = serviceConstructor;
|
||||||
serviceConstructor;
|
|
||||||
|
|
||||||
super({
|
super({
|
||||||
...serviceConstructor,
|
...serviceConstructor,
|
||||||
@ -900,96 +799,73 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
const delegatedEvents: GovernanceDelegatedEvents[] = [];
|
const delegatedEvents: GovernanceDelegatedEvents[] = [];
|
||||||
const undelegatedEvents: GovernanceUndelegatedEvents[] = [];
|
const undelegatedEvents: GovernanceUndelegatedEvents[] = [];
|
||||||
|
|
||||||
events.forEach(
|
events.forEach(({ blockNumber, index: logIndex, transactionHash, args, eventName: event }) => {
|
||||||
({
|
const eventObjects = {
|
||||||
blockNumber,
|
blockNumber,
|
||||||
index: logIndex,
|
logIndex,
|
||||||
transactionHash,
|
transactionHash,
|
||||||
args,
|
event,
|
||||||
eventName: event,
|
};
|
||||||
}) => {
|
|
||||||
const eventObjects = {
|
|
||||||
blockNumber,
|
|
||||||
logIndex,
|
|
||||||
transactionHash,
|
|
||||||
event,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (event === 'ProposalCreated') {
|
if (event === 'ProposalCreated') {
|
||||||
const {
|
const { id, proposer, target, startTime, endTime, description } = args;
|
||||||
id,
|
|
||||||
proposer,
|
|
||||||
target,
|
|
||||||
startTime,
|
|
||||||
endTime,
|
|
||||||
description,
|
|
||||||
} = args;
|
|
||||||
|
|
||||||
proposalEvents.push({
|
proposalEvents.push({
|
||||||
...eventObjects,
|
...eventObjects,
|
||||||
id: Number(id),
|
id: Number(id),
|
||||||
proposer,
|
proposer,
|
||||||
target,
|
target,
|
||||||
startTime: Number(startTime),
|
startTime: Number(startTime),
|
||||||
endTime: Number(endTime),
|
endTime: Number(endTime),
|
||||||
description,
|
description,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event === 'Voted') {
|
if (event === 'Voted') {
|
||||||
const { proposalId, voter, support, votes } = args;
|
const { proposalId, voter, support, votes } = args;
|
||||||
|
|
||||||
votedEvents.push({
|
votedEvents.push({
|
||||||
...eventObjects,
|
...eventObjects,
|
||||||
proposalId: Number(proposalId),
|
proposalId: Number(proposalId),
|
||||||
voter,
|
voter,
|
||||||
support,
|
support,
|
||||||
votes,
|
votes,
|
||||||
from: '',
|
from: '',
|
||||||
input: '',
|
input: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event === 'Delegated') {
|
if (event === 'Delegated') {
|
||||||
const { account, to: delegateTo } = args;
|
const { account, to: delegateTo } = args;
|
||||||
|
|
||||||
delegatedEvents.push({
|
delegatedEvents.push({
|
||||||
...eventObjects,
|
...eventObjects,
|
||||||
account,
|
account,
|
||||||
delegateTo,
|
delegateTo,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event === 'Undelegated') {
|
if (event === 'Undelegated') {
|
||||||
const { account, from: delegateFrom } = args;
|
const { account, from: delegateFrom } = args;
|
||||||
|
|
||||||
undelegatedEvents.push({
|
undelegatedEvents.push({
|
||||||
...eventObjects,
|
...eventObjects,
|
||||||
account,
|
account,
|
||||||
delegateFrom,
|
delegateFrom,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
if (votedEvents.length) {
|
if (votedEvents.length) {
|
||||||
this.updateTransactionProgress({ percentage: 0 });
|
this.updateTransactionProgress({ percentage: 0 });
|
||||||
|
|
||||||
const txs = await this.batchTransactionService.getBatchTransactions(
|
const txs = await this.batchTransactionService.getBatchTransactions([
|
||||||
[
|
...new Set(votedEvents.map(({ transactionHash }) => transactionHash)),
|
||||||
...new Set(
|
]);
|
||||||
votedEvents.map(
|
|
||||||
({ transactionHash }) => transactionHash,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
votedEvents.forEach((event, index) => {
|
votedEvents.forEach((event, index) => {
|
||||||
// eslint-disable-next-line prefer-const
|
// eslint-disable-next-line prefer-const
|
||||||
let { data: input, from } = txs.find(
|
let { data: input, from } = txs.find((t) => t.hash === event.transactionHash) as TransactionResponse;
|
||||||
(t) => t.hash === event.transactionHash,
|
|
||||||
) as TransactionResponse;
|
|
||||||
|
|
||||||
// Filter spammy txs
|
// Filter spammy txs
|
||||||
if (!input || input.length > 2048) {
|
if (!input || input.length > 2048) {
|
||||||
@ -1001,25 +877,12 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [...proposalEvents, ...votedEvents, ...delegatedEvents, ...undelegatedEvents];
|
||||||
...proposalEvents,
|
|
||||||
...votedEvents,
|
|
||||||
...delegatedEvents,
|
|
||||||
...undelegatedEvents,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getEventsFromGraph({
|
async getEventsFromGraph({ fromBlock }: { fromBlock: number }): Promise<BaseEvents<AllGovernanceEvents>> {
|
||||||
fromBlock,
|
|
||||||
}: {
|
|
||||||
fromBlock: number;
|
|
||||||
}): Promise<BaseEvents<AllGovernanceEvents>> {
|
|
||||||
// TheGraph doesn't support governance subgraphs
|
// TheGraph doesn't support governance subgraphs
|
||||||
if (
|
if (!this.graphApi || !this.subgraphName || this.graphApi.includes('api.thegraph.com')) {
|
||||||
!this.graphApi ||
|
|
||||||
!this.subgraphName ||
|
|
||||||
this.graphApi.includes('api.thegraph.com')
|
|
||||||
) {
|
|
||||||
return {
|
return {
|
||||||
events: [],
|
events: [],
|
||||||
lastBlock: fromBlock,
|
lastBlock: fromBlock,
|
||||||
@ -1032,20 +895,15 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
async getAllProposals(): Promise<GovernanceProposals[]> {
|
async getAllProposals(): Promise<GovernanceProposals[]> {
|
||||||
const { events } = await this.updateEvents();
|
const { events } = await this.updateEvents();
|
||||||
|
|
||||||
const proposalEvents = events.filter(
|
const proposalEvents = events.filter((e) => e.event === 'ProposalCreated') as GovernanceProposalCreatedEvents[];
|
||||||
(e) => e.event === 'ProposalCreated',
|
|
||||||
) as GovernanceProposalCreatedEvents[];
|
|
||||||
|
|
||||||
const allProposers = [
|
const allProposers = [...new Set(proposalEvents.map((e) => [e.proposer]).flat())];
|
||||||
...new Set(proposalEvents.map((e) => [e.proposer]).flat()),
|
|
||||||
];
|
|
||||||
|
|
||||||
const [QUORUM_VOTES, proposalStatus, proposerNameRecords] =
|
const [QUORUM_VOTES, proposalStatus, proposerNameRecords] = await Promise.all([
|
||||||
await Promise.all([
|
this.Governance.QUORUM_VOTES(),
|
||||||
this.Governance.QUORUM_VOTES(),
|
this.Aggregator.getAllProposals(this.Governance.target),
|
||||||
this.Aggregator.getAllProposals(this.Governance.target),
|
this.ReverseRecords.getNames(allProposers),
|
||||||
this.ReverseRecords.getNames(allProposers),
|
]);
|
||||||
]);
|
|
||||||
|
|
||||||
const proposerNames = allProposers.reduce(
|
const proposerNames = allProposers.reduce(
|
||||||
(acc, address, index) => {
|
(acc, address, index) => {
|
||||||
@ -1062,16 +920,11 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
|
|
||||||
const status = proposalStatus[index];
|
const status = proposalStatus[index];
|
||||||
|
|
||||||
const { forVotes, againstVotes, executed, extended, state } =
|
const { forVotes, againstVotes, executed, extended, state } = status;
|
||||||
status;
|
|
||||||
|
|
||||||
const { title, description } = parseDescription(id, text);
|
const { title, description } = parseDescription(id, text);
|
||||||
|
|
||||||
const quorum =
|
const quorum = ((Number(forVotes + againstVotes) / Number(QUORUM_VOTES)) * 100).toFixed(0) + '%';
|
||||||
(
|
|
||||||
(Number(forVotes + againstVotes) / Number(QUORUM_VOTES)) *
|
|
||||||
100
|
|
||||||
).toFixed(0) + '%';
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...event,
|
...event,
|
||||||
@ -1092,14 +945,10 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
const { events } = await this.getSavedEvents();
|
const { events } = await this.getSavedEvents();
|
||||||
|
|
||||||
const votedEvents = events.filter(
|
const votedEvents = events.filter(
|
||||||
(e) =>
|
(e) => e.event === 'Voted' && (e as GovernanceVotedEvents).proposalId === proposalId,
|
||||||
e.event === 'Voted' &&
|
|
||||||
(e as GovernanceVotedEvents).proposalId === proposalId,
|
|
||||||
) as GovernanceVotedEvents[];
|
) as GovernanceVotedEvents[];
|
||||||
|
|
||||||
const allVoters = [
|
const allVoters = [...new Set(votedEvents.map((e) => [e.from, e.voter]).flat())];
|
||||||
...new Set(votedEvents.map((e) => [e.from, e.voter]).flat()),
|
|
||||||
];
|
|
||||||
|
|
||||||
const names = await this.ReverseRecords.getNames(allVoters);
|
const names = await this.ReverseRecords.getNames(allVoters);
|
||||||
|
|
||||||
@ -1116,10 +965,7 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
const votes = votedEvents.map((event) => {
|
const votes = votedEvents.map((event) => {
|
||||||
const { from, voter } = event;
|
const { from, voter } = event;
|
||||||
|
|
||||||
const { contact, message } = parseComment(
|
const { contact, message } = parseComment(this.Governance, event.input);
|
||||||
this.Governance,
|
|
||||||
event.input,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...event,
|
...event,
|
||||||
@ -1137,20 +983,11 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
const { events } = await this.getSavedEvents();
|
const { events } = await this.getSavedEvents();
|
||||||
|
|
||||||
const delegatedAccs = events
|
const delegatedAccs = events
|
||||||
.filter(
|
.filter((e) => e.event === 'Delegated' && (e as GovernanceDelegatedEvents).delegateTo === ethAccount)
|
||||||
(e) =>
|
|
||||||
e.event === 'Delegated' &&
|
|
||||||
(e as GovernanceDelegatedEvents).delegateTo === ethAccount,
|
|
||||||
)
|
|
||||||
.map((e) => (e as GovernanceDelegatedEvents).account);
|
.map((e) => (e as GovernanceDelegatedEvents).account);
|
||||||
|
|
||||||
const undelegatedAccs = events
|
const undelegatedAccs = events
|
||||||
.filter(
|
.filter((e) => e.event === 'Undelegated' && (e as GovernanceUndelegatedEvents).delegateFrom === ethAccount)
|
||||||
(e) =>
|
|
||||||
e.event === 'Undelegated' &&
|
|
||||||
(e as GovernanceUndelegatedEvents).delegateFrom ===
|
|
||||||
ethAccount,
|
|
||||||
)
|
|
||||||
.map((e) => (e as GovernanceUndelegatedEvents).account);
|
.map((e) => (e as GovernanceUndelegatedEvents).account);
|
||||||
|
|
||||||
const undel = [...undelegatedAccs];
|
const undel = [...undelegatedAccs];
|
||||||
@ -1190,28 +1027,20 @@ export class BaseGovernanceService extends BaseEventsService<AllGovernanceEvents
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getTovarishNetworks(
|
export async function getTovarishNetworks(registryService: BaseRegistryService, relayers: CachedRelayerInfo[]) {
|
||||||
registryService: BaseRegistryService,
|
|
||||||
relayers: CachedRelayerInfo[],
|
|
||||||
) {
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
relayers
|
relayers
|
||||||
.filter((r) => r.tovarishHost)
|
.filter((r) => r.tovarishHost)
|
||||||
.map(async (relayer) => {
|
.map(async (relayer) => {
|
||||||
try {
|
try {
|
||||||
relayer.tovarishNetworks = await fetchData(
|
relayer.tovarishNetworks = await fetchData(relayer.tovarishHost as string, {
|
||||||
relayer.tovarishHost as string,
|
...registryService.fetchDataOptions,
|
||||||
{
|
headers: {
|
||||||
...registryService.fetchDataOptions,
|
'Content-Type': 'application/json',
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
timeout: 30000,
|
|
||||||
maxRetry: registryService.fetchDataOptions?.torPort
|
|
||||||
? 2
|
|
||||||
: 0,
|
|
||||||
},
|
},
|
||||||
);
|
timeout: 30000,
|
||||||
|
maxRetry: registryService.fetchDataOptions?.torPort ? 2 : 0,
|
||||||
|
});
|
||||||
} catch {
|
} catch {
|
||||||
// Ignore error and disable relayer
|
// Ignore error and disable relayer
|
||||||
relayer.tovarishNetworks = [];
|
relayer.tovarishNetworks = [];
|
||||||
@ -1256,8 +1085,7 @@ export interface CachedRelayers {
|
|||||||
fromCache?: boolean;
|
fromCache?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BaseRegistryServiceConstructor
|
export interface BaseRegistryServiceConstructor extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
||||||
extends Omit<BaseEventsServiceConstructor, 'contract' | 'type'> {
|
|
||||||
RelayerRegistry: RelayerRegistry;
|
RelayerRegistry: RelayerRegistry;
|
||||||
Aggregator: Aggregator;
|
Aggregator: Aggregator;
|
||||||
relayerEnsSubdomains: SubdomainMap;
|
relayerEnsSubdomains: SubdomainMap;
|
||||||
@ -1269,11 +1097,7 @@ export class BaseRegistryService extends BaseEventsService<RegistersEvents> {
|
|||||||
updateInterval: number;
|
updateInterval: number;
|
||||||
|
|
||||||
constructor(serviceConstructor: BaseRegistryServiceConstructor) {
|
constructor(serviceConstructor: BaseRegistryServiceConstructor) {
|
||||||
const {
|
const { RelayerRegistry: contract, Aggregator, relayerEnsSubdomains } = serviceConstructor;
|
||||||
RelayerRegistry: contract,
|
|
||||||
Aggregator,
|
|
||||||
relayerEnsSubdomains,
|
|
||||||
} = serviceConstructor;
|
|
||||||
|
|
||||||
super({
|
super({
|
||||||
...serviceConstructor,
|
...serviceConstructor,
|
||||||
@ -1301,21 +1125,19 @@ export class BaseRegistryService extends BaseEventsService<RegistersEvents> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async formatEvents(events: EventLog[]) {
|
async formatEvents(events: EventLog[]) {
|
||||||
return events.map(
|
return events.map(({ blockNumber, index: logIndex, transactionHash, args }) => {
|
||||||
({ blockNumber, index: logIndex, transactionHash, args }) => {
|
const eventObjects = {
|
||||||
const eventObjects = {
|
blockNumber,
|
||||||
blockNumber,
|
logIndex,
|
||||||
logIndex,
|
transactionHash,
|
||||||
transactionHash,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...eventObjects,
|
...eventObjects,
|
||||||
ensName: args.ensName,
|
ensName: args.ensName,
|
||||||
relayerAddress: args.relayerAddress,
|
relayerAddress: args.relayerAddress,
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1366,73 +1188,48 @@ export class BaseRegistryService extends BaseEventsService<RegistersEvents> {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
const relayerNameHashes = uniqueRegisters.map((r) =>
|
const relayerNameHashes = uniqueRegisters.map((r) => namehash(r.ensName));
|
||||||
namehash(r.ensName),
|
|
||||||
);
|
|
||||||
|
|
||||||
const [relayersData, timestamp] = await Promise.all([
|
const [relayersData, timestamp] = await Promise.all([
|
||||||
this.Aggregator.relayersData.staticCall(
|
this.Aggregator.relayersData.staticCall(relayerNameHashes, subdomains.concat('tovarish-relayer')),
|
||||||
relayerNameHashes,
|
|
||||||
subdomains.concat('tovarish-relayer'),
|
|
||||||
),
|
|
||||||
this.provider.getBlock(lastBlock).then((b) => Number(b?.timestamp)),
|
this.provider.getBlock(lastBlock).then((b) => Number(b?.timestamp)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const relayers = relayersData
|
const relayers = relayersData
|
||||||
.map(
|
.map(({ owner, balance: stakeBalance, records, isRegistered }, index) => {
|
||||||
(
|
const { ensName, relayerAddress } = uniqueRegisters[index];
|
||||||
{ owner, balance: stakeBalance, records, isRegistered },
|
|
||||||
index,
|
|
||||||
) => {
|
|
||||||
const { ensName, relayerAddress } = uniqueRegisters[index];
|
|
||||||
|
|
||||||
let tovarishHost = undefined;
|
let tovarishHost = undefined;
|
||||||
|
|
||||||
const hostnames = records.reduce(
|
const hostnames = records.reduce((acc, record, recordIndex) => {
|
||||||
(acc, record, recordIndex) => {
|
if (record) {
|
||||||
if (record) {
|
// tovarish-relayer.relayer.eth
|
||||||
// tovarish-relayer.relayer.eth
|
if (recordIndex === records.length - 1) {
|
||||||
if (recordIndex === records.length - 1) {
|
tovarishHost = record;
|
||||||
tovarishHost = record;
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
acc[
|
|
||||||
Number(
|
|
||||||
Object.keys(this.relayerEnsSubdomains)[
|
|
||||||
recordIndex
|
|
||||||
],
|
|
||||||
)
|
|
||||||
] = record;
|
|
||||||
}
|
|
||||||
return acc;
|
return acc;
|
||||||
},
|
}
|
||||||
{} as SubdomainMap,
|
|
||||||
);
|
|
||||||
|
|
||||||
const hasMinBalance = stakeBalance >= MIN_STAKE_BALANCE;
|
acc[Number(Object.keys(this.relayerEnsSubdomains)[recordIndex])] = record;
|
||||||
|
|
||||||
const preCondition =
|
|
||||||
Object.keys(hostnames).length &&
|
|
||||||
isRegistered &&
|
|
||||||
hasMinBalance;
|
|
||||||
|
|
||||||
if (preCondition) {
|
|
||||||
return {
|
|
||||||
ensName,
|
|
||||||
relayerAddress: owner,
|
|
||||||
registeredAddress:
|
|
||||||
owner !== relayerAddress
|
|
||||||
? relayerAddress
|
|
||||||
: undefined,
|
|
||||||
isRegistered,
|
|
||||||
stakeBalance: formatEther(stakeBalance),
|
|
||||||
hostnames,
|
|
||||||
tovarishHost,
|
|
||||||
} as CachedRelayerInfo;
|
|
||||||
}
|
}
|
||||||
},
|
return acc;
|
||||||
)
|
}, {} as SubdomainMap);
|
||||||
|
|
||||||
|
const hasMinBalance = stakeBalance >= MIN_STAKE_BALANCE;
|
||||||
|
|
||||||
|
const preCondition = Object.keys(hostnames).length && isRegistered && hasMinBalance;
|
||||||
|
|
||||||
|
if (preCondition) {
|
||||||
|
return {
|
||||||
|
ensName,
|
||||||
|
relayerAddress: owner,
|
||||||
|
registeredAddress: owner !== relayerAddress ? relayerAddress : undefined,
|
||||||
|
isRegistered,
|
||||||
|
stakeBalance: formatEther(stakeBalance),
|
||||||
|
hostnames,
|
||||||
|
tovarishHost,
|
||||||
|
} as CachedRelayerInfo;
|
||||||
|
}
|
||||||
|
})
|
||||||
.filter((r) => r) as CachedRelayerInfo[];
|
.filter((r) => r) as CachedRelayerInfo[];
|
||||||
|
|
||||||
await getTovarishNetworks(this, relayers);
|
await getTovarishNetworks(this, relayers);
|
||||||
@ -1459,19 +1256,14 @@ export class BaseRegistryService extends BaseEventsService<RegistersEvents> {
|
|||||||
*/
|
*/
|
||||||
async updateRelayers(): Promise<CachedRelayers> {
|
async updateRelayers(): Promise<CachedRelayers> {
|
||||||
// eslint-disable-next-line prefer-const
|
// eslint-disable-next-line prefer-const
|
||||||
let { lastBlock, timestamp, relayers, fromCache } =
|
let { lastBlock, timestamp, relayers, fromCache } = await this.getSavedRelayers();
|
||||||
await this.getSavedRelayers();
|
|
||||||
|
|
||||||
let shouldSave = fromCache ?? false;
|
let shouldSave = fromCache ?? false;
|
||||||
|
|
||||||
if (
|
if (!relayers.length || timestamp + this.updateInterval < Math.floor(Date.now() / 1000)) {
|
||||||
!relayers.length ||
|
|
||||||
timestamp + this.updateInterval < Math.floor(Date.now() / 1000)
|
|
||||||
) {
|
|
||||||
console.log('\nUpdating relayers from registry\n');
|
console.log('\nUpdating relayers from registry\n');
|
||||||
|
|
||||||
({ lastBlock, timestamp, relayers } =
|
({ lastBlock, timestamp, relayers } = await this.getLatestRelayers());
|
||||||
await this.getLatestRelayers());
|
|
||||||
|
|
||||||
shouldSave = true;
|
shouldSave = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -152,8 +152,7 @@ export async function loadRemoteEvents<T extends MinimalEvents>({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DBTornadoServiceConstructor
|
export interface DBTornadoServiceConstructor extends BaseTornadoServiceConstructor {
|
||||||
extends BaseTornadoServiceConstructor {
|
|
||||||
staticUrl: string;
|
staticUrl: string;
|
||||||
idb: IndexedDB;
|
idb: IndexedDB;
|
||||||
}
|
}
|
||||||
@ -187,10 +186,7 @@ export class DBTornadoService extends BaseTornadoService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveEvents({
|
async saveEvents({ events, lastBlock }: BaseEvents<DepositsEvents | WithdrawalsEvents>) {
|
||||||
events,
|
|
||||||
lastBlock,
|
|
||||||
}: BaseEvents<DepositsEvents | WithdrawalsEvents>) {
|
|
||||||
await saveDBEvents<DepositsEvents | WithdrawalsEvents>({
|
await saveDBEvents<DepositsEvents | WithdrawalsEvents>({
|
||||||
idb: this.idb,
|
idb: this.idb,
|
||||||
instanceName: this.getInstanceName(),
|
instanceName: this.getInstanceName(),
|
||||||
@ -244,8 +240,7 @@ export class DBEchoService extends BaseEchoService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DBEncryptedNotesServiceConstructor
|
export interface DBEncryptedNotesServiceConstructor extends BaseEncryptedNotesServiceConstructor {
|
||||||
extends BaseEncryptedNotesServiceConstructor {
|
|
||||||
staticUrl: string;
|
staticUrl: string;
|
||||||
idb: IndexedDB;
|
idb: IndexedDB;
|
||||||
}
|
}
|
||||||
@ -289,8 +284,7 @@ export class DBEncryptedNotesService extends BaseEncryptedNotesService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DBGovernanceServiceConstructor
|
export interface DBGovernanceServiceConstructor extends BaseGovernanceServiceConstructor {
|
||||||
extends BaseGovernanceServiceConstructor {
|
|
||||||
staticUrl: string;
|
staticUrl: string;
|
||||||
idb: IndexedDB;
|
idb: IndexedDB;
|
||||||
}
|
}
|
||||||
@ -334,8 +328,7 @@ export class DBGovernanceService extends BaseGovernanceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DBRegistryServiceConstructor
|
export interface DBRegistryServiceConstructor extends BaseRegistryServiceConstructor {
|
||||||
extends BaseRegistryServiceConstructor {
|
|
||||||
staticUrl: string;
|
staticUrl: string;
|
||||||
idb: IndexedDB;
|
idb: IndexedDB;
|
||||||
}
|
}
|
||||||
|
|||||||
60
src/fees.ts
60
src/fees.ts
@ -20,10 +20,7 @@ export function convertETHToTokenAmount(
|
|||||||
tokenDecimals: number = 18,
|
tokenDecimals: number = 18,
|
||||||
): bigint {
|
): bigint {
|
||||||
const tokenDecimalsMultiplier = BigInt(10 ** Number(tokenDecimals));
|
const tokenDecimalsMultiplier = BigInt(10 ** Number(tokenDecimals));
|
||||||
return (
|
return (BigInt(amountInWei) * tokenDecimalsMultiplier) / BigInt(tokenPriceInWei);
|
||||||
(BigInt(amountInWei) * tokenDecimalsMultiplier) /
|
|
||||||
BigInt(tokenPriceInWei)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RelayerFeeParams {
|
export interface RelayerFeeParams {
|
||||||
@ -43,10 +40,7 @@ export class TornadoFeeOracle {
|
|||||||
provider: JsonRpcApiProvider;
|
provider: JsonRpcApiProvider;
|
||||||
ovmGasPriceOracle?: OvmGasPriceOracle;
|
ovmGasPriceOracle?: OvmGasPriceOracle;
|
||||||
|
|
||||||
constructor(
|
constructor(provider: JsonRpcApiProvider, ovmGasPriceOracle?: OvmGasPriceOracle) {
|
||||||
provider: JsonRpcApiProvider,
|
|
||||||
ovmGasPriceOracle?: OvmGasPriceOracle,
|
|
||||||
) {
|
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
|
|
||||||
if (ovmGasPriceOracle) {
|
if (ovmGasPriceOracle) {
|
||||||
@ -73,21 +67,14 @@ export class TornadoFeeOracle {
|
|||||||
})(),
|
})(),
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
return BigInt(
|
return BigInt(await this.provider.send('eth_maxPriorityFeePerGas', []));
|
||||||
await this.provider.send(
|
|
||||||
'eth_maxPriorityFeePerGas',
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} catch {
|
} catch {
|
||||||
return BigInt(0);
|
return BigInt(0);
|
||||||
}
|
}
|
||||||
})(),
|
})(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return block?.baseFeePerGas
|
return block?.baseFeePerGas ? (block.baseFeePerGas * BigInt(15)) / BigInt(10) + getPriorityFee : getGasPrice;
|
||||||
? (block.baseFeePerGas * BigInt(15)) / BigInt(10) + getPriorityFee
|
|
||||||
: getGasPrice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,9 +100,7 @@ export class TornadoFeeOracle {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.ovmGasPriceOracle.getL1Fee.staticCall(
|
return this.ovmGasPriceOracle.getL1Fee.staticCall(Transaction.from(tx).unsignedSerialized);
|
||||||
Transaction.from(tx).unsignedSerialized,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,25 +109,14 @@ export class TornadoFeeOracle {
|
|||||||
* Using 30 gwei for default but it is recommended to supply cached gasPrice value from the UI
|
* Using 30 gwei for default but it is recommended to supply cached gasPrice value from the UI
|
||||||
*/
|
*/
|
||||||
defaultEthRefund(gasPrice?: BigNumberish, gasLimit?: BigNumberish): bigint {
|
defaultEthRefund(gasPrice?: BigNumberish, gasLimit?: BigNumberish): bigint {
|
||||||
return (
|
return (gasPrice ? BigInt(gasPrice) : parseUnits('30', 'gwei')) * BigInt(gasLimit || 1_000_000);
|
||||||
(gasPrice ? BigInt(gasPrice) : parseUnits('30', 'gwei')) *
|
|
||||||
BigInt(gasLimit || 1_000_000)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates token amount for required ethRefund purchases required to calculate fees
|
* Calculates token amount for required ethRefund purchases required to calculate fees
|
||||||
*/
|
*/
|
||||||
calculateTokenAmount(
|
calculateTokenAmount(ethRefund: BigNumberish, tokenPriceInEth: BigNumberish, tokenDecimals?: number): bigint {
|
||||||
ethRefund: BigNumberish,
|
return convertETHToTokenAmount(ethRefund, tokenPriceInEth, tokenDecimals);
|
||||||
tokenPriceInEth: BigNumberish,
|
|
||||||
tokenDecimals?: number,
|
|
||||||
): bigint {
|
|
||||||
return convertETHToTokenAmount(
|
|
||||||
ethRefund,
|
|
||||||
tokenPriceInEth,
|
|
||||||
tokenDecimals,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,29 +137,17 @@ export class TornadoFeeOracle {
|
|||||||
}: RelayerFeeParams): bigint {
|
}: RelayerFeeParams): bigint {
|
||||||
const gasCosts = BigInt(gasPrice) * BigInt(gasLimit) + BigInt(l1Fee);
|
const gasCosts = BigInt(gasPrice) * BigInt(gasLimit) + BigInt(l1Fee);
|
||||||
|
|
||||||
const relayerFee =
|
const relayerFee = (BigInt(denomination) * BigInt(Math.floor(10000 * relayerFeePercent))) / BigInt(10000 * 100);
|
||||||
(BigInt(denomination) *
|
|
||||||
BigInt(Math.floor(10000 * relayerFeePercent))) /
|
|
||||||
BigInt(10000 * 100);
|
|
||||||
|
|
||||||
if (isEth) {
|
if (isEth) {
|
||||||
// Add 20% premium
|
// Add 20% premium
|
||||||
return (
|
return ((gasCosts + relayerFee) * BigInt(premiumPercent ? 100 + premiumPercent : 100)) / BigInt(100);
|
||||||
((gasCosts + relayerFee) *
|
|
||||||
BigInt(premiumPercent ? 100 + premiumPercent : 100)) /
|
|
||||||
BigInt(100)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const feeInEth = gasCosts + BigInt(ethRefund);
|
const feeInEth = gasCosts + BigInt(ethRefund);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
((convertETHToTokenAmount(
|
((convertETHToTokenAmount(feeInEth, tokenPriceInWei, tokenDecimals) + relayerFee) *
|
||||||
feeInEth,
|
|
||||||
tokenPriceInWei,
|
|
||||||
tokenDecimals,
|
|
||||||
) +
|
|
||||||
relayerFee) *
|
|
||||||
BigInt(premiumPercent ? 100 + premiumPercent : 100)) /
|
BigInt(premiumPercent ? 100 + premiumPercent : 100)) /
|
||||||
BigInt(100)
|
BigInt(100)
|
||||||
);
|
);
|
||||||
|
|||||||
@ -147,9 +147,7 @@ export async function getStatistic({
|
|||||||
return {
|
return {
|
||||||
events,
|
events,
|
||||||
lastSyncBlock:
|
lastSyncBlock:
|
||||||
lastEvent && lastEvent.blockNumber >= lastSyncBlock
|
lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock,
|
||||||
? lastEvent.blockNumber + 1
|
|
||||||
: lastSyncBlock,
|
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Error from getStatistic query');
|
console.log('Error from getStatistic query');
|
||||||
@ -181,11 +179,7 @@ export interface getMetaReturns {
|
|||||||
hasIndexingErrors: null | boolean;
|
hasIndexingErrors: null | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getMeta({
|
export async function getMeta({ graphApi, subgraphName, fetchDataOptions }: getMetaParams): Promise<getMetaReturns> {
|
||||||
graphApi,
|
|
||||||
subgraphName,
|
|
||||||
fetchDataOptions,
|
|
||||||
}: getMetaParams): Promise<getMetaReturns> {
|
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
_meta: {
|
_meta: {
|
||||||
@ -303,10 +297,7 @@ export async function getAllRegisters({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = result.filter(
|
result = result.filter(({ blockRegistration }) => blockRegistration !== lastEvent.blockRegistration);
|
||||||
({ blockRegistration }) =>
|
|
||||||
blockRegistration !== lastEvent.blockRegistration,
|
|
||||||
);
|
|
||||||
fromBlock = Number(lastEvent.blockRegistration);
|
fromBlock = Number(lastEvent.blockRegistration);
|
||||||
|
|
||||||
events.push(...result);
|
events.push(...result);
|
||||||
@ -319,19 +310,17 @@ export async function getAllRegisters({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = events.map(
|
const result = events.map(({ id, address, ensName, blockRegistration }) => {
|
||||||
({ id, address, ensName, blockRegistration }) => {
|
const [transactionHash, logIndex] = id.split('-');
|
||||||
const [transactionHash, logIndex] = id.split('-');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
blockNumber: Number(blockRegistration),
|
blockNumber: Number(blockRegistration),
|
||||||
logIndex: Number(logIndex),
|
logIndex: Number(logIndex),
|
||||||
transactionHash,
|
transactionHash,
|
||||||
ensName,
|
ensName,
|
||||||
relayerAddress: getAddress(address),
|
relayerAddress: getAddress(address),
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
events: result,
|
events: result,
|
||||||
@ -446,9 +435,7 @@ export async function getAllDeposits({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = result.filter(
|
result = result.filter(({ blockNumber }) => blockNumber !== lastEvent.blockNumber);
|
||||||
({ blockNumber }) => blockNumber !== lastEvent.blockNumber,
|
|
||||||
);
|
|
||||||
fromBlock = Number(lastEvent.blockNumber);
|
fromBlock = Number(lastEvent.blockNumber);
|
||||||
|
|
||||||
events.push(...result);
|
events.push(...result);
|
||||||
@ -461,30 +448,26 @@ export async function getAllDeposits({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = events.map(
|
const result = events.map(({ id, blockNumber, commitment, index, timestamp, from }) => {
|
||||||
({ id, blockNumber, commitment, index, timestamp, from }) => {
|
const [transactionHash, logIndex] = id.split('-');
|
||||||
const [transactionHash, logIndex] = id.split('-');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
blockNumber: Number(blockNumber),
|
blockNumber: Number(blockNumber),
|
||||||
logIndex: Number(logIndex),
|
logIndex: Number(logIndex),
|
||||||
transactionHash,
|
transactionHash,
|
||||||
commitment,
|
commitment,
|
||||||
leafIndex: Number(index),
|
leafIndex: Number(index),
|
||||||
timestamp: Number(timestamp),
|
timestamp: Number(timestamp),
|
||||||
from: getAddress(from),
|
from: getAddress(from),
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const [lastEvent] = result.slice(-1);
|
const [lastEvent] = result.slice(-1);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
events: result,
|
events: result,
|
||||||
lastSyncBlock:
|
lastSyncBlock:
|
||||||
lastEvent && lastEvent.blockNumber >= lastSyncBlock
|
lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock,
|
||||||
? lastEvent.blockNumber + 1
|
|
||||||
: lastSyncBlock,
|
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Error from getAllDeposits query');
|
console.log('Error from getAllDeposits query');
|
||||||
@ -598,9 +581,7 @@ export async function getAllWithdrawals({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = result.filter(
|
result = result.filter(({ blockNumber }) => blockNumber !== lastEvent.blockNumber);
|
||||||
({ blockNumber }) => blockNumber !== lastEvent.blockNumber,
|
|
||||||
);
|
|
||||||
fromBlock = Number(lastEvent.blockNumber);
|
fromBlock = Number(lastEvent.blockNumber);
|
||||||
|
|
||||||
events.push(...result);
|
events.push(...result);
|
||||||
@ -613,30 +594,26 @@ export async function getAllWithdrawals({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = events.map(
|
const result = events.map(({ id, blockNumber, nullifier, to, fee, timestamp }) => {
|
||||||
({ id, blockNumber, nullifier, to, fee, timestamp }) => {
|
const [transactionHash, logIndex] = id.split('-');
|
||||||
const [transactionHash, logIndex] = id.split('-');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
blockNumber: Number(blockNumber),
|
blockNumber: Number(blockNumber),
|
||||||
logIndex: Number(logIndex),
|
logIndex: Number(logIndex),
|
||||||
transactionHash,
|
transactionHash,
|
||||||
nullifierHash: nullifier,
|
nullifierHash: nullifier,
|
||||||
to: getAddress(to),
|
to: getAddress(to),
|
||||||
fee,
|
fee,
|
||||||
timestamp: Number(timestamp),
|
timestamp: Number(timestamp),
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const [lastEvent] = result.slice(-1);
|
const [lastEvent] = result.slice(-1);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
events: result,
|
events: result,
|
||||||
lastSyncBlock:
|
lastSyncBlock:
|
||||||
lastEvent && lastEvent.blockNumber >= lastSyncBlock
|
lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock,
|
||||||
? lastEvent.blockNumber + 1
|
|
||||||
: lastSyncBlock,
|
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Error from getAllWithdrawals query');
|
console.log('Error from getAllWithdrawals query');
|
||||||
@ -806,9 +783,7 @@ export async function getAllGraphEchoEvents({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = result.filter(
|
result = result.filter(({ blockNumber }) => blockNumber !== lastEvent.blockNumber);
|
||||||
({ blockNumber }) => blockNumber !== lastEvent.blockNumber,
|
|
||||||
);
|
|
||||||
fromBlock = Number(lastEvent.blockNumber);
|
fromBlock = Number(lastEvent.blockNumber);
|
||||||
|
|
||||||
events.push(...result);
|
events.push(...result);
|
||||||
@ -838,9 +813,7 @@ export async function getAllGraphEchoEvents({
|
|||||||
return {
|
return {
|
||||||
events: result,
|
events: result,
|
||||||
lastSyncBlock:
|
lastSyncBlock:
|
||||||
lastEvent && lastEvent.blockNumber >= lastSyncBlock
|
lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock,
|
||||||
? lastEvent.blockNumber + 1
|
|
||||||
: lastSyncBlock,
|
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Error from getAllGraphEchoEvents query');
|
console.log('Error from getAllGraphEchoEvents query');
|
||||||
@ -942,9 +915,7 @@ export async function getAllEncryptedNotes({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = result.filter(
|
result = result.filter(({ blockNumber }) => blockNumber !== lastEvent.blockNumber);
|
||||||
({ blockNumber }) => blockNumber !== lastEvent.blockNumber,
|
|
||||||
);
|
|
||||||
fromBlock = Number(lastEvent.blockNumber);
|
fromBlock = Number(lastEvent.blockNumber);
|
||||||
|
|
||||||
events.push(...result);
|
events.push(...result);
|
||||||
@ -969,9 +940,7 @@ export async function getAllEncryptedNotes({
|
|||||||
return {
|
return {
|
||||||
events: result,
|
events: result,
|
||||||
lastSyncBlock:
|
lastSyncBlock:
|
||||||
lastEvent && lastEvent.blockNumber >= lastSyncBlock
|
lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock,
|
||||||
? lastEvent.blockNumber + 1
|
|
||||||
: lastSyncBlock,
|
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Error from getAllEncryptedNotes query');
|
console.log('Error from getAllEncryptedNotes query');
|
||||||
@ -1085,56 +1054,41 @@ export async function getAllGovernanceEvents({
|
|||||||
|
|
||||||
lastSyncBlock = currentBlock;
|
lastSyncBlock = currentBlock;
|
||||||
|
|
||||||
const eventsLength =
|
const eventsLength = proposals.length + votes.length + delegates.length + undelegates.length;
|
||||||
proposals.length +
|
|
||||||
votes.length +
|
|
||||||
delegates.length +
|
|
||||||
undelegates.length;
|
|
||||||
|
|
||||||
if (eventsLength === 0) {
|
if (eventsLength === 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const formattedProposals: GovernanceProposalCreatedEvents[] =
|
const formattedProposals: GovernanceProposalCreatedEvents[] = proposals.map(
|
||||||
proposals.map(
|
|
||||||
({
|
|
||||||
blockNumber,
|
|
||||||
logIndex,
|
|
||||||
transactionHash,
|
|
||||||
proposalId,
|
|
||||||
proposer,
|
|
||||||
target,
|
|
||||||
startTime,
|
|
||||||
endTime,
|
|
||||||
description,
|
|
||||||
}) => {
|
|
||||||
return {
|
|
||||||
blockNumber: Number(blockNumber),
|
|
||||||
logIndex: Number(logIndex),
|
|
||||||
transactionHash,
|
|
||||||
event: 'ProposalCreated',
|
|
||||||
id: Number(proposalId),
|
|
||||||
proposer: getAddress(proposer),
|
|
||||||
target: getAddress(target),
|
|
||||||
startTime: Number(startTime),
|
|
||||||
endTime: Number(endTime),
|
|
||||||
description,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const formattedVotes: GovernanceVotedEvents[] = votes.map(
|
|
||||||
({
|
({
|
||||||
blockNumber,
|
blockNumber,
|
||||||
logIndex,
|
logIndex,
|
||||||
transactionHash,
|
transactionHash,
|
||||||
proposalId,
|
proposalId,
|
||||||
voter,
|
proposer,
|
||||||
support,
|
target,
|
||||||
votes,
|
startTime,
|
||||||
from,
|
endTime,
|
||||||
input,
|
description,
|
||||||
}) => {
|
}) => {
|
||||||
|
return {
|
||||||
|
blockNumber: Number(blockNumber),
|
||||||
|
logIndex: Number(logIndex),
|
||||||
|
transactionHash,
|
||||||
|
event: 'ProposalCreated',
|
||||||
|
id: Number(proposalId),
|
||||||
|
proposer: getAddress(proposer),
|
||||||
|
target: getAddress(target),
|
||||||
|
startTime: Number(startTime),
|
||||||
|
endTime: Number(endTime),
|
||||||
|
description,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const formattedVotes: GovernanceVotedEvents[] = votes.map(
|
||||||
|
({ blockNumber, logIndex, transactionHash, proposalId, voter, support, votes, from, input }) => {
|
||||||
// Filter spammy txs
|
// Filter spammy txs
|
||||||
if (!input || input.length > 2048) {
|
if (!input || input.length > 2048) {
|
||||||
input = '';
|
input = '';
|
||||||
@ -1155,45 +1109,31 @@ export async function getAllGovernanceEvents({
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const formattedDelegates: GovernanceDelegatedEvents[] =
|
const formattedDelegates: GovernanceDelegatedEvents[] = delegates.map(
|
||||||
delegates.map(
|
({ blockNumber, logIndex, transactionHash, account, delegateTo }) => {
|
||||||
({
|
return {
|
||||||
blockNumber,
|
blockNumber: Number(blockNumber),
|
||||||
logIndex,
|
logIndex: Number(logIndex),
|
||||||
transactionHash,
|
transactionHash,
|
||||||
account,
|
event: 'Delegated',
|
||||||
delegateTo,
|
account: getAddress(account),
|
||||||
}) => {
|
delegateTo: getAddress(delegateTo),
|
||||||
return {
|
};
|
||||||
blockNumber: Number(blockNumber),
|
},
|
||||||
logIndex: Number(logIndex),
|
);
|
||||||
transactionHash,
|
|
||||||
event: 'Delegated',
|
|
||||||
account: getAddress(account),
|
|
||||||
delegateTo: getAddress(delegateTo),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const formattedUndelegates: GovernanceUndelegatedEvents[] =
|
const formattedUndelegates: GovernanceUndelegatedEvents[] = undelegates.map(
|
||||||
undelegates.map(
|
({ blockNumber, logIndex, transactionHash, account, delegateFrom }) => {
|
||||||
({
|
return {
|
||||||
blockNumber,
|
blockNumber: Number(blockNumber),
|
||||||
logIndex,
|
logIndex: Number(logIndex),
|
||||||
transactionHash,
|
transactionHash,
|
||||||
account,
|
event: 'Undelegated',
|
||||||
delegateFrom,
|
account: getAddress(account),
|
||||||
}) => {
|
delegateFrom: getAddress(delegateFrom),
|
||||||
return {
|
};
|
||||||
blockNumber: Number(blockNumber),
|
},
|
||||||
logIndex: Number(logIndex),
|
);
|
||||||
transactionHash,
|
|
||||||
event: 'Undelegated',
|
|
||||||
account: getAddress(account),
|
|
||||||
delegateFrom: getAddress(delegateFrom),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let formattedEvents = [
|
let formattedEvents = [
|
||||||
...formattedProposals,
|
...formattedProposals,
|
||||||
@ -1224,9 +1164,7 @@ export async function getAllGovernanceEvents({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
formattedEvents = formattedEvents.filter(
|
formattedEvents = formattedEvents.filter(({ blockNumber }) => blockNumber !== lastEvent.blockNumber);
|
||||||
({ blockNumber }) => blockNumber !== lastEvent.blockNumber,
|
|
||||||
);
|
|
||||||
|
|
||||||
fromBlock = Number(lastEvent.blockNumber);
|
fromBlock = Number(lastEvent.blockNumber);
|
||||||
|
|
||||||
@ -1238,9 +1176,7 @@ export async function getAllGovernanceEvents({
|
|||||||
return {
|
return {
|
||||||
events: result,
|
events: result,
|
||||||
lastSyncBlock:
|
lastSyncBlock:
|
||||||
lastEvent && lastEvent.blockNumber >= lastSyncBlock
|
lastEvent && lastEvent.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock,
|
||||||
? lastEvent.blockNumber + 1
|
|
||||||
: lastSyncBlock,
|
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Error from getAllGovernance query');
|
console.log('Error from getAllGovernance query');
|
||||||
|
|||||||
92
src/idb.ts
92
src/idb.ts
@ -2,8 +2,7 @@
|
|||||||
import { openDB, deleteDB, OpenDBCallbacks, IDBPDatabase } from 'idb';
|
import { openDB, deleteDB, OpenDBCallbacks, IDBPDatabase } from 'idb';
|
||||||
import { getConfig, NetIdType } from './networkConfig';
|
import { getConfig, NetIdType } from './networkConfig';
|
||||||
|
|
||||||
export const INDEX_DB_ERROR =
|
export const INDEX_DB_ERROR = 'A mutation operation was attempted on a database that did not allow mutations.';
|
||||||
'A mutation operation was attempted on a database that did not allow mutations.';
|
|
||||||
|
|
||||||
export interface IDBIndex {
|
export interface IDBIndex {
|
||||||
name: string;
|
name: string;
|
||||||
@ -40,20 +39,18 @@ export class IndexedDB {
|
|||||||
db.deleteObjectStore(value);
|
db.deleteObjectStore(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
[{ name: 'keyval' }, ...(stores || [])].forEach(
|
[{ name: 'keyval' }, ...(stores || [])].forEach(({ name, keyPath, indexes }) => {
|
||||||
({ name, keyPath, indexes }) => {
|
const store = db.createObjectStore(name, {
|
||||||
const store = db.createObjectStore(name, {
|
keyPath,
|
||||||
keyPath,
|
autoIncrement: true,
|
||||||
autoIncrement: true,
|
});
|
||||||
});
|
|
||||||
|
|
||||||
if (Array.isArray(indexes)) {
|
if (Array.isArray(indexes)) {
|
||||||
indexes.forEach(({ name, unique = false }) => {
|
indexes.forEach(({ name, unique = false }) => {
|
||||||
store.createIndex(name, name, { unique });
|
store.createIndex(name, name, { unique });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -138,24 +135,13 @@ export class IndexedDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return (await this.db.getAllFromIndex(
|
return (await this.db.getAllFromIndex(storeName, indexName, key, count)) as T;
|
||||||
storeName,
|
|
||||||
indexName,
|
|
||||||
key,
|
|
||||||
count,
|
|
||||||
)) as T;
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
throw new Error(`Method getAllFromIndex has error: ${err.message}`);
|
throw new Error(`Method getAllFromIndex has error: ${err.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getItem<T>({
|
async getItem<T>({ storeName, key }: { storeName: string; key: string }): Promise<T | undefined> {
|
||||||
storeName,
|
|
||||||
key,
|
|
||||||
}: {
|
|
||||||
storeName: string;
|
|
||||||
key: string;
|
|
||||||
}): Promise<T | undefined> {
|
|
||||||
await this.initDB();
|
await this.initDB();
|
||||||
|
|
||||||
if (!this.db) {
|
if (!this.db) {
|
||||||
@ -171,15 +157,7 @@ export class IndexedDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async addItem({
|
async addItem({ storeName, data, key = '' }: { storeName: string; data: any; key: string }) {
|
||||||
storeName,
|
|
||||||
data,
|
|
||||||
key = '',
|
|
||||||
}: {
|
|
||||||
storeName: string;
|
|
||||||
data: any;
|
|
||||||
key: string;
|
|
||||||
}) {
|
|
||||||
await this.initDB();
|
await this.initDB();
|
||||||
|
|
||||||
if (!this.db) {
|
if (!this.db) {
|
||||||
@ -198,15 +176,7 @@ export class IndexedDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async putItem({
|
async putItem({ storeName, data, key }: { storeName: string; data: any; key?: string }) {
|
||||||
storeName,
|
|
||||||
data,
|
|
||||||
key,
|
|
||||||
}: {
|
|
||||||
storeName: string;
|
|
||||||
data: any;
|
|
||||||
key?: string;
|
|
||||||
}) {
|
|
||||||
await this.initDB();
|
await this.initDB();
|
||||||
|
|
||||||
if (!this.db) {
|
if (!this.db) {
|
||||||
@ -269,13 +239,7 @@ export class IndexedDB {
|
|||||||
return this.deleteItem({ storeName: 'keyval', key });
|
return this.deleteItem({ storeName: 'keyval', key });
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearStore({
|
async clearStore({ storeName, mode = 'readwrite' }: { storeName: string; mode: IDBTransactionMode }) {
|
||||||
storeName,
|
|
||||||
mode = 'readwrite',
|
|
||||||
}: {
|
|
||||||
storeName: string;
|
|
||||||
mode: IDBTransactionMode;
|
|
||||||
}) {
|
|
||||||
await this.initDB();
|
await this.initDB();
|
||||||
|
|
||||||
if (!this.db) {
|
if (!this.db) {
|
||||||
@ -309,17 +273,10 @@ export class IndexedDB {
|
|||||||
try {
|
try {
|
||||||
const tx = this.db.transaction(storeName, mode);
|
const tx = this.db.transaction(storeName, mode);
|
||||||
|
|
||||||
await (
|
await (tx.objectStore(storeName).add as (value: any, key?: any) => Promise<any>)(data);
|
||||||
tx.objectStore(storeName).add as (
|
|
||||||
value: any,
|
|
||||||
key?: any,
|
|
||||||
) => Promise<any>
|
|
||||||
)(data);
|
|
||||||
await tx.done;
|
await tx.done;
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
throw new Error(
|
throw new Error(`Method createTransactions has error: ${err.message}`);
|
||||||
`Method createTransactions has error: ${err.message}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,15 +302,11 @@ export class IndexedDB {
|
|||||||
|
|
||||||
for (const item of data) {
|
for (const item of data) {
|
||||||
if (item) {
|
if (item) {
|
||||||
await (
|
await (tx.store.put as (value: any, key?: any) => Promise<any>)({ ...item, ...index });
|
||||||
tx.store.put as (value: any, key?: any) => Promise<any>
|
|
||||||
)({ ...item, ...index });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
throw new Error(
|
throw new Error(`Method createMultipleTransactions has error: ${err.message}`);
|
||||||
`Method createMultipleTransactions has error: ${err.message}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -411,8 +364,7 @@ export async function getIndexedDB(netId?: NetIdType) {
|
|||||||
|
|
||||||
const config = getConfig(netId);
|
const config = getConfig(netId);
|
||||||
|
|
||||||
const { tokens, nativeCurrency, registryContract, governanceContract } =
|
const { tokens, nativeCurrency, registryContract, governanceContract } = config;
|
||||||
config;
|
|
||||||
|
|
||||||
const stores = [...defaultState];
|
const stores = [...defaultState];
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,5 @@
|
|||||||
import { Worker as NodeWorker } from 'worker_threads';
|
import { Worker as NodeWorker } from 'worker_threads';
|
||||||
import {
|
import { MerkleTree, PartialMerkleTree, Element, TreeEdge } from '@tornado/fixed-merkle-tree';
|
||||||
MerkleTree,
|
|
||||||
PartialMerkleTree,
|
|
||||||
Element,
|
|
||||||
TreeEdge,
|
|
||||||
} from '@tornado/fixed-merkle-tree';
|
|
||||||
import type { Tornado } from '@tornado/contracts';
|
import type { Tornado } from '@tornado/contracts';
|
||||||
import { isNode, toFixedHex } from './utils';
|
import { isNode, toFixedHex } from './utils';
|
||||||
import { mimc } from './mimc';
|
import { mimc } from './mimc';
|
||||||
@ -66,70 +61,49 @@ export class MerkleTreeService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (isNode) {
|
if (isNode) {
|
||||||
const merkleWorkerPromise = new Promise(
|
const merkleWorkerPromise = new Promise((resolve, reject) => {
|
||||||
(resolve, reject) => {
|
const worker = new NodeWorker(this.merkleWorkerPath as string, {
|
||||||
const worker = new NodeWorker(
|
workerData: {
|
||||||
this.merkleWorkerPath as string,
|
|
||||||
{
|
|
||||||
workerData: {
|
|
||||||
merkleTreeHeight: this.merkleTreeHeight,
|
|
||||||
elements: events,
|
|
||||||
zeroElement: this.emptyElement,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
worker.on('message', resolve);
|
|
||||||
worker.on('error', reject);
|
|
||||||
worker.on('exit', (code) => {
|
|
||||||
if (code !== 0) {
|
|
||||||
reject(
|
|
||||||
new Error(
|
|
||||||
`Worker stopped with exit code ${code}`,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
) as Promise<string>;
|
|
||||||
|
|
||||||
return MerkleTree.deserialize(
|
|
||||||
JSON.parse(await merkleWorkerPromise),
|
|
||||||
hashFunction,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const merkleWorkerPromise = new Promise(
|
|
||||||
(resolve, reject) => {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const worker = new (Worker as any)(
|
|
||||||
this.merkleWorkerPath,
|
|
||||||
);
|
|
||||||
|
|
||||||
worker.onmessage = (e: { data: string }) => {
|
|
||||||
resolve(e.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
worker.onerror = (e: any) => {
|
|
||||||
reject(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
worker.postMessage({
|
|
||||||
merkleTreeHeight: this.merkleTreeHeight,
|
merkleTreeHeight: this.merkleTreeHeight,
|
||||||
elements: events,
|
elements: events,
|
||||||
zeroElement: this.emptyElement,
|
zeroElement: this.emptyElement,
|
||||||
});
|
},
|
||||||
},
|
});
|
||||||
) as Promise<string>;
|
worker.on('message', resolve);
|
||||||
|
worker.on('error', reject);
|
||||||
|
worker.on('exit', (code) => {
|
||||||
|
if (code !== 0) {
|
||||||
|
reject(new Error(`Worker stopped with exit code ${code}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}) as Promise<string>;
|
||||||
|
|
||||||
return MerkleTree.deserialize(
|
return MerkleTree.deserialize(JSON.parse(await merkleWorkerPromise), hashFunction);
|
||||||
JSON.parse(await merkleWorkerPromise),
|
} else {
|
||||||
hashFunction,
|
const merkleWorkerPromise = new Promise((resolve, reject) => {
|
||||||
);
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const worker = new (Worker as any)(this.merkleWorkerPath);
|
||||||
|
|
||||||
|
worker.onmessage = (e: { data: string }) => {
|
||||||
|
resolve(e.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
worker.onerror = (e: any) => {
|
||||||
|
reject(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
worker.postMessage({
|
||||||
|
merkleTreeHeight: this.merkleTreeHeight,
|
||||||
|
elements: events,
|
||||||
|
zeroElement: this.emptyElement,
|
||||||
|
});
|
||||||
|
}) as Promise<string>;
|
||||||
|
|
||||||
|
return MerkleTree.deserialize(JSON.parse(await merkleWorkerPromise), hashFunction);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(
|
console.log('merkleWorker failed, falling back to synchronous merkle tree');
|
||||||
'merkleWorker failed, falling back to synchronous merkle tree',
|
|
||||||
);
|
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,13 +114,7 @@ export class MerkleTreeService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async createPartialTree({
|
async createPartialTree({ edge, elements }: { edge: TreeEdge; elements: Element[] }) {
|
||||||
edge,
|
|
||||||
elements,
|
|
||||||
}: {
|
|
||||||
edge: TreeEdge;
|
|
||||||
elements: Element[];
|
|
||||||
}) {
|
|
||||||
const { hash: hashFunction } = await mimc.getHash();
|
const { hash: hashFunction } = await mimc.getHash();
|
||||||
|
|
||||||
if (this.merkleWorkerPath) {
|
if (this.merkleWorkerPath) {
|
||||||
@ -154,72 +122,51 @@ export class MerkleTreeService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (isNode) {
|
if (isNode) {
|
||||||
const merkleWorkerPromise = new Promise(
|
const merkleWorkerPromise = new Promise((resolve, reject) => {
|
||||||
(resolve, reject) => {
|
const worker = new NodeWorker(this.merkleWorkerPath as string, {
|
||||||
const worker = new NodeWorker(
|
workerData: {
|
||||||
this.merkleWorkerPath as string,
|
|
||||||
{
|
|
||||||
workerData: {
|
|
||||||
merkleTreeHeight: this.merkleTreeHeight,
|
|
||||||
edge,
|
|
||||||
elements,
|
|
||||||
zeroElement: this.emptyElement,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
worker.on('message', resolve);
|
|
||||||
worker.on('error', reject);
|
|
||||||
worker.on('exit', (code) => {
|
|
||||||
if (code !== 0) {
|
|
||||||
reject(
|
|
||||||
new Error(
|
|
||||||
`Worker stopped with exit code ${code}`,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
) as Promise<string>;
|
|
||||||
|
|
||||||
return PartialMerkleTree.deserialize(
|
|
||||||
JSON.parse(await merkleWorkerPromise),
|
|
||||||
hashFunction,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const merkleWorkerPromise = new Promise(
|
|
||||||
(resolve, reject) => {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const worker = new (Worker as any)(
|
|
||||||
this.merkleWorkerPath,
|
|
||||||
);
|
|
||||||
|
|
||||||
worker.onmessage = (e: { data: string }) => {
|
|
||||||
resolve(e.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
worker.onerror = (e: any) => {
|
|
||||||
reject(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
worker.postMessage({
|
|
||||||
merkleTreeHeight: this.merkleTreeHeight,
|
merkleTreeHeight: this.merkleTreeHeight,
|
||||||
edge,
|
edge,
|
||||||
elements,
|
elements,
|
||||||
zeroElement: this.emptyElement,
|
zeroElement: this.emptyElement,
|
||||||
});
|
},
|
||||||
},
|
});
|
||||||
) as Promise<string>;
|
worker.on('message', resolve);
|
||||||
|
worker.on('error', reject);
|
||||||
|
worker.on('exit', (code) => {
|
||||||
|
if (code !== 0) {
|
||||||
|
reject(new Error(`Worker stopped with exit code ${code}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}) as Promise<string>;
|
||||||
|
|
||||||
return PartialMerkleTree.deserialize(
|
return PartialMerkleTree.deserialize(JSON.parse(await merkleWorkerPromise), hashFunction);
|
||||||
JSON.parse(await merkleWorkerPromise),
|
} else {
|
||||||
hashFunction,
|
const merkleWorkerPromise = new Promise((resolve, reject) => {
|
||||||
);
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const worker = new (Worker as any)(this.merkleWorkerPath);
|
||||||
|
|
||||||
|
worker.onmessage = (e: { data: string }) => {
|
||||||
|
resolve(e.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
worker.onerror = (e: any) => {
|
||||||
|
reject(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
worker.postMessage({
|
||||||
|
merkleTreeHeight: this.merkleTreeHeight,
|
||||||
|
edge,
|
||||||
|
elements,
|
||||||
|
zeroElement: this.emptyElement,
|
||||||
|
});
|
||||||
|
}) as Promise<string>;
|
||||||
|
|
||||||
|
return PartialMerkleTree.deserialize(JSON.parse(await merkleWorkerPromise), hashFunction);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(
|
console.log('merkleWorker failed, falling back to synchronous merkle tree');
|
||||||
'merkleWorker failed, falling back to synchronous merkle tree',
|
|
||||||
);
|
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,13 +184,9 @@ export class MerkleTreeService {
|
|||||||
|
|
||||||
const timeStart = Date.now();
|
const timeStart = Date.now();
|
||||||
|
|
||||||
const tree = await this.createTree(
|
const tree = await this.createTree(events.map(({ commitment }) => commitment));
|
||||||
events.map(({ commitment }) => commitment),
|
|
||||||
);
|
|
||||||
|
|
||||||
const isKnownRoot = await this.Tornado.isKnownRoot(
|
const isKnownRoot = await this.Tornado.isKnownRoot(toFixedHex(BigInt(tree.root)));
|
||||||
toFixedHex(BigInt(tree.root)),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!isKnownRoot) {
|
if (!isKnownRoot) {
|
||||||
const errMsg = `Deposit Event ${this.netId} ${this.amount} ${this.currency} is invalid`;
|
const errMsg = `Deposit Event ${this.netId} ${this.amount} ${this.currency} is invalid`;
|
||||||
|
|||||||
@ -1,11 +1,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import workerThreads from 'worker_threads';
|
import workerThreads from 'worker_threads';
|
||||||
import {
|
import { MerkleTree, Element, TreeEdge, PartialMerkleTree } from '@tornado/fixed-merkle-tree';
|
||||||
MerkleTree,
|
|
||||||
Element,
|
|
||||||
TreeEdge,
|
|
||||||
PartialMerkleTree,
|
|
||||||
} from '@tornado/fixed-merkle-tree';
|
|
||||||
import { mimc } from './mimc';
|
import { mimc } from './mimc';
|
||||||
import { isNode } from './utils';
|
import { isNode } from './utils';
|
||||||
|
|
||||||
@ -18,23 +13,15 @@ interface WorkData {
|
|||||||
|
|
||||||
async function nodePostWork() {
|
async function nodePostWork() {
|
||||||
const { hash: hashFunction } = await mimc.getHash();
|
const { hash: hashFunction } = await mimc.getHash();
|
||||||
const { merkleTreeHeight, edge, elements, zeroElement } =
|
const { merkleTreeHeight, edge, elements, zeroElement } = workerThreads.workerData as WorkData;
|
||||||
workerThreads.workerData as WorkData;
|
|
||||||
|
|
||||||
if (edge) {
|
if (edge) {
|
||||||
const merkleTree = new PartialMerkleTree(
|
const merkleTree = new PartialMerkleTree(merkleTreeHeight, edge, elements, {
|
||||||
merkleTreeHeight,
|
zeroElement,
|
||||||
edge,
|
hashFunction,
|
||||||
elements,
|
});
|
||||||
{
|
|
||||||
zeroElement,
|
|
||||||
hashFunction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
(workerThreads.parentPort as workerThreads.MessagePort).postMessage(
|
(workerThreads.parentPort as workerThreads.MessagePort).postMessage(merkleTree.toString());
|
||||||
merkleTree.toString(),
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,18 +30,12 @@ async function nodePostWork() {
|
|||||||
hashFunction,
|
hashFunction,
|
||||||
});
|
});
|
||||||
|
|
||||||
(workerThreads.parentPort as workerThreads.MessagePort).postMessage(
|
(workerThreads.parentPort as workerThreads.MessagePort).postMessage(merkleTree.toString());
|
||||||
merkleTree.toString(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNode && workerThreads) {
|
if (isNode && workerThreads) {
|
||||||
nodePostWork();
|
nodePostWork();
|
||||||
} else if (
|
} else if (!isNode && typeof addEventListener === 'function' && typeof postMessage === 'function') {
|
||||||
!isNode &&
|
|
||||||
typeof addEventListener === 'function' &&
|
|
||||||
typeof postMessage === 'function'
|
|
||||||
) {
|
|
||||||
addEventListener('message', async (e: any) => {
|
addEventListener('message', async (e: any) => {
|
||||||
let data;
|
let data;
|
||||||
|
|
||||||
@ -65,19 +46,13 @@ if (isNode && workerThreads) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { hash: hashFunction } = await mimc.getHash();
|
const { hash: hashFunction } = await mimc.getHash();
|
||||||
const { merkleTreeHeight, edge, elements, zeroElement } =
|
const { merkleTreeHeight, edge, elements, zeroElement } = data as WorkData;
|
||||||
data as WorkData;
|
|
||||||
|
|
||||||
if (edge) {
|
if (edge) {
|
||||||
const merkleTree = new PartialMerkleTree(
|
const merkleTree = new PartialMerkleTree(merkleTreeHeight, edge, elements, {
|
||||||
merkleTreeHeight,
|
zeroElement,
|
||||||
edge,
|
hashFunction,
|
||||||
elements,
|
});
|
||||||
{
|
|
||||||
zeroElement,
|
|
||||||
hashFunction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
postMessage(merkleTree.toString());
|
postMessage(merkleTree.toString());
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -12,10 +12,7 @@ export class Mimc {
|
|||||||
|
|
||||||
async initMimc() {
|
async initMimc() {
|
||||||
this.sponge = await buildMimcSponge();
|
this.sponge = await buildMimcSponge();
|
||||||
this.hash = (left, right) =>
|
this.hash = (left, right) => this.sponge?.F.toString(this.sponge?.multiHash([BigInt(left), BigInt(right)]));
|
||||||
this.sponge?.F.toString(
|
|
||||||
this.sponge?.multiHash([BigInt(left), BigInt(right)]),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getHash() {
|
async getHash() {
|
||||||
|
|||||||
@ -14,8 +14,7 @@ export interface Call3 {
|
|||||||
export async function multicall(Multicall: Multicall, calls: Call3[]) {
|
export async function multicall(Multicall: Multicall, calls: Call3[]) {
|
||||||
const calldata = calls.map((call) => {
|
const calldata = calls.map((call) => {
|
||||||
const target = (call.contract?.target || call.address) as string;
|
const target = (call.contract?.target || call.address) as string;
|
||||||
const callInterface = (call.contract?.interface ||
|
const callInterface = (call.contract?.interface || call.interface) as Interface;
|
||||||
call.interface) as Interface;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
target,
|
target,
|
||||||
@ -27,18 +26,11 @@ export async function multicall(Multicall: Multicall, calls: Call3[]) {
|
|||||||
const returnData = await Multicall.aggregate3.staticCall(calldata);
|
const returnData = await Multicall.aggregate3.staticCall(calldata);
|
||||||
|
|
||||||
const res = returnData.map((call, i) => {
|
const res = returnData.map((call, i) => {
|
||||||
const callInterface = (calls[i].contract?.interface ||
|
const callInterface = (calls[i].contract?.interface || calls[i].interface) as Interface;
|
||||||
calls[i].interface) as Interface;
|
|
||||||
const [result, data] = call;
|
const [result, data] = call;
|
||||||
const decodeResult =
|
const decodeResult =
|
||||||
result && data && data !== '0x'
|
result && data && data !== '0x' ? callInterface.decodeFunctionResult(calls[i].name, data) : null;
|
||||||
? callInterface.decodeFunctionResult(calls[i].name, data)
|
return !decodeResult ? null : decodeResult.length === 1 ? decodeResult[0] : decodeResult;
|
||||||
: null;
|
|
||||||
return !decodeResult
|
|
||||||
? null
|
|
||||||
: decodeResult.length === 1
|
|
||||||
? decodeResult[0]
|
|
||||||
: decodeResult;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@ -122,8 +122,7 @@ export const defaultConfig: networkConfig = {
|
|||||||
currencyName: 'ETH',
|
currencyName: 'ETH',
|
||||||
explorerUrl: 'https://etherscan.io',
|
explorerUrl: 'https://etherscan.io',
|
||||||
merkleTreeHeight: 20,
|
merkleTreeHeight: 20,
|
||||||
emptyElement:
|
emptyElement: '21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
||||||
'21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
|
||||||
networkName: 'Ethereum Mainnet',
|
networkName: 'Ethereum Mainnet',
|
||||||
deployedBlock: 9116966,
|
deployedBlock: 9116966,
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
@ -259,8 +258,7 @@ export const defaultConfig: networkConfig = {
|
|||||||
currencyName: 'BNB',
|
currencyName: 'BNB',
|
||||||
explorerUrl: 'https://bscscan.com',
|
explorerUrl: 'https://bscscan.com',
|
||||||
merkleTreeHeight: 20,
|
merkleTreeHeight: 20,
|
||||||
emptyElement:
|
emptyElement: '21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
||||||
'21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
|
||||||
networkName: 'Binance Smart Chain',
|
networkName: 'Binance Smart Chain',
|
||||||
deployedBlock: 8158799,
|
deployedBlock: 8158799,
|
||||||
stablecoin: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',
|
stablecoin: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',
|
||||||
@ -323,8 +321,7 @@ export const defaultConfig: networkConfig = {
|
|||||||
currencyName: 'MATIC',
|
currencyName: 'MATIC',
|
||||||
explorerUrl: 'https://polygonscan.com',
|
explorerUrl: 'https://polygonscan.com',
|
||||||
merkleTreeHeight: 20,
|
merkleTreeHeight: 20,
|
||||||
emptyElement:
|
emptyElement: '21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
||||||
'21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
|
||||||
networkName: 'Polygon (Matic) Network',
|
networkName: 'Polygon (Matic) Network',
|
||||||
deployedBlock: 16257962,
|
deployedBlock: 16257962,
|
||||||
stablecoin: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',
|
stablecoin: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',
|
||||||
@ -375,8 +372,7 @@ export const defaultConfig: networkConfig = {
|
|||||||
currencyName: 'ETH',
|
currencyName: 'ETH',
|
||||||
explorerUrl: 'https://optimistic.etherscan.io',
|
explorerUrl: 'https://optimistic.etherscan.io',
|
||||||
merkleTreeHeight: 20,
|
merkleTreeHeight: 20,
|
||||||
emptyElement:
|
emptyElement: '21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
||||||
'21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
|
||||||
networkName: 'Optimism',
|
networkName: 'Optimism',
|
||||||
deployedBlock: 2243689,
|
deployedBlock: 2243689,
|
||||||
stablecoin: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
|
stablecoin: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
|
||||||
@ -428,8 +424,7 @@ export const defaultConfig: networkConfig = {
|
|||||||
currencyName: 'ETH',
|
currencyName: 'ETH',
|
||||||
explorerUrl: 'https://arbiscan.io',
|
explorerUrl: 'https://arbiscan.io',
|
||||||
merkleTreeHeight: 20,
|
merkleTreeHeight: 20,
|
||||||
emptyElement:
|
emptyElement: '21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
||||||
'21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
|
||||||
networkName: 'Arbitrum One',
|
networkName: 'Arbitrum One',
|
||||||
deployedBlock: 3430648,
|
deployedBlock: 3430648,
|
||||||
stablecoin: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
|
stablecoin: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
|
||||||
@ -484,8 +479,7 @@ export const defaultConfig: networkConfig = {
|
|||||||
currencyName: 'xDAI',
|
currencyName: 'xDAI',
|
||||||
explorerUrl: 'https://gnosisscan.io',
|
explorerUrl: 'https://gnosisscan.io',
|
||||||
merkleTreeHeight: 20,
|
merkleTreeHeight: 20,
|
||||||
emptyElement:
|
emptyElement: '21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
||||||
'21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
|
||||||
networkName: 'Gnosis Chain',
|
networkName: 'Gnosis Chain',
|
||||||
deployedBlock: 17754561,
|
deployedBlock: 17754561,
|
||||||
stablecoin: '0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83',
|
stablecoin: '0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83',
|
||||||
@ -536,8 +530,7 @@ export const defaultConfig: networkConfig = {
|
|||||||
currencyName: 'AVAX',
|
currencyName: 'AVAX',
|
||||||
explorerUrl: 'https://snowtrace.io',
|
explorerUrl: 'https://snowtrace.io',
|
||||||
merkleTreeHeight: 20,
|
merkleTreeHeight: 20,
|
||||||
emptyElement:
|
emptyElement: '21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
||||||
'21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
|
||||||
networkName: 'Avalanche Mainnet',
|
networkName: 'Avalanche Mainnet',
|
||||||
deployedBlock: 4429818,
|
deployedBlock: 4429818,
|
||||||
stablecoin: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
|
stablecoin: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
|
||||||
@ -587,8 +580,7 @@ export const defaultConfig: networkConfig = {
|
|||||||
currencyName: 'SepoliaETH',
|
currencyName: 'SepoliaETH',
|
||||||
explorerUrl: 'https://sepolia.etherscan.io',
|
explorerUrl: 'https://sepolia.etherscan.io',
|
||||||
merkleTreeHeight: 20,
|
merkleTreeHeight: 20,
|
||||||
emptyElement:
|
emptyElement: '21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
||||||
'21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
|
||||||
networkName: 'Ethereum Sepolia',
|
networkName: 'Ethereum Sepolia',
|
||||||
deployedBlock: 5594395,
|
deployedBlock: 5594395,
|
||||||
stablecoin: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',
|
stablecoin: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',
|
||||||
@ -658,9 +650,7 @@ export const defaultConfig: networkConfig = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const enabledChains = Object.values(NetId).filter(
|
export const enabledChains = Object.values(NetId).filter((n) => typeof n === 'number') as NetIdType[];
|
||||||
(n) => typeof n === 'number',
|
|
||||||
) as NetIdType[];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom config object to extend default config
|
* Custom config object to extend default config
|
||||||
|
|||||||
@ -16,9 +16,7 @@ export class Pedersen {
|
|||||||
|
|
||||||
async unpackPoint(buffer: Uint8Array) {
|
async unpackPoint(buffer: Uint8Array) {
|
||||||
await this.pedersenPromise;
|
await this.pedersenPromise;
|
||||||
return this.babyJub?.unpackPoint(
|
return this.babyJub?.unpackPoint(this.pedersenHash?.hash(buffer) as Uint8Array);
|
||||||
this.pedersenHash?.hash(buffer) as Uint8Array,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toStringBuffer(buffer: Uint8Array): string {
|
toStringBuffer(buffer: Uint8Array): string {
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
import {
|
import { ERC20Permit, ERC20Mock, TORN, PermitTornado } from '@tornado/contracts';
|
||||||
ERC20Permit,
|
|
||||||
ERC20Mock,
|
|
||||||
TORN,
|
|
||||||
PermitTornado,
|
|
||||||
} from '@tornado/contracts';
|
|
||||||
import {
|
import {
|
||||||
BaseContract,
|
BaseContract,
|
||||||
MaxUint256,
|
MaxUint256,
|
||||||
@ -105,10 +100,7 @@ export async function getPermitCommitmentsSignature({
|
|||||||
signer?: Signer;
|
signer?: Signer;
|
||||||
}) {
|
}) {
|
||||||
const value = BigInt(commitments.length) * denomination;
|
const value = BigInt(commitments.length) * denomination;
|
||||||
const commitmentsHash = solidityPackedKeccak256(
|
const commitmentsHash = solidityPackedKeccak256(['bytes32[]'], [commitments]);
|
||||||
['bytes32[]'],
|
|
||||||
[commitments],
|
|
||||||
);
|
|
||||||
|
|
||||||
return await getPermitSignature({
|
return await getPermitSignature({
|
||||||
Token,
|
Token,
|
||||||
@ -199,9 +191,7 @@ export async function getPermit2Signature({
|
|||||||
|
|
||||||
const hash = new TypedDataEncoder(types).hash(values);
|
const hash = new TypedDataEncoder(types).hash(values);
|
||||||
|
|
||||||
const signature = Signature.from(
|
const signature = Signature.from(await sigSigner.signTypedData(domain, types, values));
|
||||||
await sigSigner.signTypedData(domain, types, values),
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
domain,
|
domain,
|
||||||
@ -226,10 +216,7 @@ export async function getPermit2CommitmentsSignature({
|
|||||||
signer?: Signer;
|
signer?: Signer;
|
||||||
}) {
|
}) {
|
||||||
const value = BigInt(commitments.length) * denomination;
|
const value = BigInt(commitments.length) * denomination;
|
||||||
const commitmentsHash = solidityPackedKeccak256(
|
const commitmentsHash = solidityPackedKeccak256(['bytes32[]'], [commitments]);
|
||||||
['bytes32[]'],
|
|
||||||
[commitments],
|
|
||||||
);
|
|
||||||
|
|
||||||
return await getPermit2Signature({
|
return await getPermit2Signature({
|
||||||
Token,
|
Token,
|
||||||
|
|||||||
@ -9,11 +9,7 @@ export class TokenPriceOracle {
|
|||||||
|
|
||||||
fallbackPrice: bigint;
|
fallbackPrice: bigint;
|
||||||
|
|
||||||
constructor(
|
constructor(provider: Provider, multicall: Multicall, oracle?: OffchainOracle) {
|
||||||
provider: Provider,
|
|
||||||
multicall: Multicall,
|
|
||||||
oracle?: OffchainOracle,
|
|
||||||
) {
|
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.multicall = multicall;
|
this.multicall = multicall;
|
||||||
this.oracle = oracle;
|
this.oracle = oracle;
|
||||||
@ -35,10 +31,7 @@ export class TokenPriceOracle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildStable(stablecoinAddress: string): Call3[] {
|
buildStable(stablecoinAddress: string): Call3[] {
|
||||||
const stablecoin = ERC20__factory.connect(
|
const stablecoin = ERC20__factory.connect(stablecoinAddress, this.provider);
|
||||||
stablecoinAddress,
|
|
||||||
this.provider,
|
|
||||||
);
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -81,44 +74,29 @@ export class TokenPriceOracle {
|
|||||||
): Promise<bigint[]> {
|
): Promise<bigint[]> {
|
||||||
// setup mock price for testnets
|
// setup mock price for testnets
|
||||||
if (!this.oracle) {
|
if (!this.oracle) {
|
||||||
return new Promise((resolve) =>
|
return new Promise((resolve) => resolve(tokens.map(() => this.fallbackPrice)));
|
||||||
resolve(tokens.map(() => this.fallbackPrice)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const prices = (await multicall(
|
const prices = (await multicall(this.multicall, this.buildCalls(tokens))) as (bigint | null)[];
|
||||||
this.multicall,
|
|
||||||
this.buildCalls(tokens),
|
|
||||||
)) as (bigint | null)[];
|
|
||||||
|
|
||||||
return prices.map((price, index) => {
|
return prices.map((price, index) => {
|
||||||
if (!price) {
|
if (!price) {
|
||||||
price = this.fallbackPrice;
|
price = this.fallbackPrice;
|
||||||
}
|
}
|
||||||
return (
|
return (price * BigInt(10 ** tokens[index].decimals)) / BigInt(10 ** 18);
|
||||||
(price * BigInt(10 ** tokens[index].decimals)) /
|
|
||||||
BigInt(10 ** 18)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchEthUSD(stablecoinAddress: string): Promise<number> {
|
async fetchEthUSD(stablecoinAddress: string): Promise<number> {
|
||||||
// setup mock price for testnets
|
// setup mock price for testnets
|
||||||
if (!this.oracle) {
|
if (!this.oracle) {
|
||||||
return new Promise((resolve) =>
|
return new Promise((resolve) => resolve(10 ** 18 / Number(this.fallbackPrice)));
|
||||||
resolve(10 ** 18 / Number(this.fallbackPrice)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const [decimals, price] = await multicall(
|
const [decimals, price] = await multicall(this.multicall, this.buildStable(stablecoinAddress));
|
||||||
this.multicall,
|
|
||||||
this.buildStable(stablecoinAddress),
|
|
||||||
);
|
|
||||||
|
|
||||||
// eth wei price of usdc token
|
// eth wei price of usdc token
|
||||||
const ethPrice =
|
const ethPrice = ((price || this.fallbackPrice) * BigInt(10n ** decimals)) / BigInt(10 ** 18);
|
||||||
((price || this.fallbackPrice) * BigInt(10n ** decimals)) /
|
|
||||||
BigInt(10 ** 18);
|
|
||||||
|
|
||||||
return 1 / Number(formatEther(ethPrice));
|
return 1 / Number(formatEther(ethPrice));
|
||||||
}
|
}
|
||||||
|
|||||||
120
src/providers.ts
120
src/providers.ts
@ -20,12 +20,7 @@ import {
|
|||||||
EnsPlugin,
|
EnsPlugin,
|
||||||
GasCostPlugin,
|
GasCostPlugin,
|
||||||
} from 'ethers';
|
} from 'ethers';
|
||||||
import type {
|
import type { RequestInfo, RequestInit, Response, HeadersInit } from 'node-fetch';
|
||||||
RequestInfo,
|
|
||||||
RequestInit,
|
|
||||||
Response,
|
|
||||||
HeadersInit,
|
|
||||||
} from 'node-fetch';
|
|
||||||
// Temporary workaround until @types/node-fetch is compatible with @types/node
|
// Temporary workaround until @types/node-fetch is compatible with @types/node
|
||||||
import type { AbortSignal as FetchAbortSignal } from 'node-fetch/externals';
|
import type { AbortSignal as FetchAbortSignal } from 'node-fetch/externals';
|
||||||
import { isNode, sleep } from './utils';
|
import { isNode, sleep } from './utils';
|
||||||
@ -38,15 +33,11 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update this for every Tor Browser release
|
// Update this for every Tor Browser release
|
||||||
export const defaultUserAgent =
|
export const defaultUserAgent = 'Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0';
|
||||||
'Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0';
|
|
||||||
|
|
||||||
export const fetch = crossFetch as unknown as nodeFetch;
|
export const fetch = crossFetch as unknown as nodeFetch;
|
||||||
|
|
||||||
export type nodeFetch = (
|
export type nodeFetch = (url: RequestInfo, init?: RequestInit) => Promise<Response>;
|
||||||
url: RequestInfo,
|
|
||||||
init?: RequestInit,
|
|
||||||
) => Promise<Response>;
|
|
||||||
|
|
||||||
export type fetchDataOptions = RequestInit & {
|
export type fetchDataOptions = RequestInit & {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@ -62,9 +53,7 @@ export type fetchDataOptions = RequestInit & {
|
|||||||
returnResponse?: boolean;
|
returnResponse?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NodeAgent =
|
export type NodeAgent = RequestOptions['agent'] | ((parsedUrl: URL) => RequestOptions['agent']);
|
||||||
| RequestOptions['agent']
|
|
||||||
| ((parsedUrl: URL) => RequestOptions['agent']);
|
|
||||||
|
|
||||||
export function getHttpAgent({
|
export function getHttpAgent({
|
||||||
fetchUrl,
|
fetchUrl,
|
||||||
@ -84,9 +73,7 @@ export function getHttpAgent({
|
|||||||
/* eslint-enable @typescript-eslint/no-require-imports */
|
/* eslint-enable @typescript-eslint/no-require-imports */
|
||||||
|
|
||||||
if (torPort) {
|
if (torPort) {
|
||||||
return new SocksProxyAgent(
|
return new SocksProxyAgent(`socks5h://tor${retry}@127.0.0.1:${torPort}`);
|
||||||
`socks5h://tor${retry}@127.0.0.1:${torPort}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!proxyUrl) {
|
if (!proxyUrl) {
|
||||||
@ -95,11 +82,7 @@ export function getHttpAgent({
|
|||||||
|
|
||||||
const isHttps = fetchUrl.includes('https://');
|
const isHttps = fetchUrl.includes('https://');
|
||||||
|
|
||||||
if (
|
if (proxyUrl.includes('socks://') || proxyUrl.includes('socks4://') || proxyUrl.includes('socks5://')) {
|
||||||
proxyUrl.includes('socks://') ||
|
|
||||||
proxyUrl.includes('socks4://') ||
|
|
||||||
proxyUrl.includes('socks5://')
|
|
||||||
) {
|
|
||||||
return new SocksProxyAgent(proxyUrl);
|
return new SocksProxyAgent(proxyUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,9 +167,7 @@ export async function fetchData(url: string, options: fetchDataOptions = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!resp.ok) {
|
if (!resp.ok) {
|
||||||
const errMsg =
|
const errMsg = `Request to ${url} failed with error code ${resp.status}:\n` + (await resp.text());
|
||||||
`Request to ${url} failed with error code ${resp.status}:\n` +
|
|
||||||
(await resp.text());
|
|
||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,10 +262,7 @@ export type getProviderOptions = fetchDataOptions & {
|
|||||||
pollingInterval?: number;
|
pollingInterval?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getProvider(
|
export async function getProvider(rpcUrl: string, fetchOptions?: getProviderOptions): Promise<JsonRpcProvider> {
|
||||||
rpcUrl: string,
|
|
||||||
fetchOptions?: getProviderOptions,
|
|
||||||
): Promise<JsonRpcProvider> {
|
|
||||||
const fetchReq = new FetchRequest(rpcUrl);
|
const fetchReq = new FetchRequest(rpcUrl);
|
||||||
|
|
||||||
fetchReq.getUrlFunc = fetchGetUrlFunc(fetchOptions);
|
fetchReq.getUrlFunc = fetchGetUrlFunc(fetchOptions);
|
||||||
@ -344,9 +322,7 @@ export const populateTransaction = async (
|
|||||||
|
|
||||||
const [feeData, nonce] = await Promise.all([
|
const [feeData, nonce] = await Promise.all([
|
||||||
tx.maxFeePerGas || tx.gasPrice ? undefined : provider.getFeeData(),
|
tx.maxFeePerGas || tx.gasPrice ? undefined : provider.getFeeData(),
|
||||||
tx.nonce
|
tx.nonce ? undefined : provider.getTransactionCount(signer.address, 'pending'),
|
||||||
? undefined
|
|
||||||
: provider.getTransactionCount(signer.address, 'pending'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (feeData) {
|
if (feeData) {
|
||||||
@ -356,10 +332,7 @@ export const populateTransaction = async (
|
|||||||
tx.type = 2;
|
tx.type = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.maxFeePerGas =
|
tx.maxFeePerGas = (feeData.maxFeePerGas * (BigInt(10000) + BigInt(signer.gasPriceBump))) / BigInt(10000);
|
||||||
(feeData.maxFeePerGas *
|
|
||||||
(BigInt(10000) + BigInt(signer.gasPriceBump))) /
|
|
||||||
BigInt(10000);
|
|
||||||
tx.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas;
|
tx.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas;
|
||||||
delete tx.gasPrice;
|
delete tx.gasPrice;
|
||||||
} else if (feeData.gasPrice) {
|
} else if (feeData.gasPrice) {
|
||||||
@ -383,14 +356,10 @@ export const populateTransaction = async (
|
|||||||
tx.gasLimit =
|
tx.gasLimit =
|
||||||
gasLimit === BigInt(21000)
|
gasLimit === BigInt(21000)
|
||||||
? gasLimit
|
? gasLimit
|
||||||
: (gasLimit *
|
: (gasLimit * (BigInt(10000) + BigInt(signer.gasLimitBump))) / BigInt(10000);
|
||||||
(BigInt(10000) + BigInt(signer.gasLimitBump))) /
|
|
||||||
BigInt(10000);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (signer.gasFailover) {
|
if (signer.gasFailover) {
|
||||||
console.log(
|
console.log('populateTransaction: warning gas estimation failed falling back to 3M gas');
|
||||||
'populateTransaction: warning gas estimation failed falling back to 3M gas',
|
|
||||||
);
|
|
||||||
// Gas failover
|
// Gas failover
|
||||||
tx.gasLimit = BigInt('3000000');
|
tx.gasLimit = BigInt('3000000');
|
||||||
} else {
|
} else {
|
||||||
@ -418,12 +387,7 @@ export class TornadoWallet extends Wallet {
|
|||||||
constructor(
|
constructor(
|
||||||
key: string | SigningKey,
|
key: string | SigningKey,
|
||||||
provider?: Provider,
|
provider?: Provider,
|
||||||
{
|
{ gasPriceBump, gasLimitBump, gasFailover, bumpNonce }: TornadoWalletOptions = {},
|
||||||
gasPriceBump,
|
|
||||||
gasLimitBump,
|
|
||||||
gasFailover,
|
|
||||||
bumpNonce,
|
|
||||||
}: TornadoWalletOptions = {},
|
|
||||||
) {
|
) {
|
||||||
super(key, provider);
|
super(key, provider);
|
||||||
// 10% bump from the recommended fee
|
// 10% bump from the recommended fee
|
||||||
@ -435,23 +399,10 @@ export class TornadoWallet extends Wallet {
|
|||||||
this.bumpNonce = bumpNonce ?? false;
|
this.bumpNonce = bumpNonce ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromMnemonic(
|
static fromMnemonic(mneomnic: string, provider: Provider, index = 0, options?: TornadoWalletOptions) {
|
||||||
mneomnic: string,
|
|
||||||
provider: Provider,
|
|
||||||
index = 0,
|
|
||||||
options?: TornadoWalletOptions,
|
|
||||||
) {
|
|
||||||
const defaultPath = `m/44'/60'/0'/0/${index}`;
|
const defaultPath = `m/44'/60'/0'/0/${index}`;
|
||||||
const { privateKey } = HDNodeWallet.fromPhrase(
|
const { privateKey } = HDNodeWallet.fromPhrase(mneomnic, undefined, defaultPath);
|
||||||
mneomnic,
|
return new TornadoWallet(privateKey as unknown as SigningKey, provider, options);
|
||||||
undefined,
|
|
||||||
defaultPath,
|
|
||||||
);
|
|
||||||
return new TornadoWallet(
|
|
||||||
privateKey as unknown as SigningKey,
|
|
||||||
provider,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async populateTransaction(tx: TransactionRequest) {
|
async populateTransaction(tx: TransactionRequest) {
|
||||||
@ -471,12 +422,7 @@ export class TornadoVoidSigner extends VoidSigner {
|
|||||||
constructor(
|
constructor(
|
||||||
address: string,
|
address: string,
|
||||||
provider?: Provider,
|
provider?: Provider,
|
||||||
{
|
{ gasPriceBump, gasLimitBump, gasFailover, bumpNonce }: TornadoWalletOptions = {},
|
||||||
gasPriceBump,
|
|
||||||
gasLimitBump,
|
|
||||||
gasFailover,
|
|
||||||
bumpNonce,
|
|
||||||
}: TornadoWalletOptions = {},
|
|
||||||
) {
|
) {
|
||||||
super(address, provider);
|
super(address, provider);
|
||||||
// 10% bump from the recommended fee
|
// 10% bump from the recommended fee
|
||||||
@ -505,12 +451,7 @@ export class TornadoRpcSigner extends JsonRpcSigner {
|
|||||||
constructor(
|
constructor(
|
||||||
provider: JsonRpcApiProvider,
|
provider: JsonRpcApiProvider,
|
||||||
address: string,
|
address: string,
|
||||||
{
|
{ gasPriceBump, gasLimitBump, gasFailover, bumpNonce }: TornadoWalletOptions = {},
|
||||||
gasPriceBump,
|
|
||||||
gasLimitBump,
|
|
||||||
gasFailover,
|
|
||||||
bumpNonce,
|
|
||||||
}: TornadoWalletOptions = {},
|
|
||||||
) {
|
) {
|
||||||
super(provider, address);
|
super(provider, address);
|
||||||
// 10% bump from the recommended fee
|
// 10% bump from the recommended fee
|
||||||
@ -523,9 +464,7 @@ export class TornadoRpcSigner extends JsonRpcSigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async sendUncheckedTransaction(tx: TransactionRequest) {
|
async sendUncheckedTransaction(tx: TransactionRequest) {
|
||||||
return super.sendUncheckedTransaction(
|
return super.sendUncheckedTransaction(await populateTransaction(this, tx));
|
||||||
await populateTransaction(this, tx),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,11 +484,7 @@ export interface TornadoBrowserProviderOptions extends TornadoWalletOptions {
|
|||||||
|
|
||||||
export class TornadoBrowserProvider extends BrowserProvider {
|
export class TornadoBrowserProvider extends BrowserProvider {
|
||||||
options?: TornadoBrowserProviderOptions;
|
options?: TornadoBrowserProviderOptions;
|
||||||
constructor(
|
constructor(ethereum: Eip1193Provider, network?: Networkish, options?: TornadoBrowserProviderOptions) {
|
||||||
ethereum: Eip1193Provider,
|
|
||||||
network?: Networkish,
|
|
||||||
options?: TornadoBrowserProviderOptions,
|
|
||||||
) {
|
|
||||||
super(ethereum, network);
|
super(ethereum, network);
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
@ -566,24 +501,15 @@ export class TornadoBrowserProvider extends BrowserProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.options?.handleNetworkChanges) {
|
if (this.options?.handleNetworkChanges) {
|
||||||
window?.ethereum?.on(
|
window?.ethereum?.on('chainChanged', this.options.handleNetworkChanges);
|
||||||
'chainChanged',
|
|
||||||
this.options.handleNetworkChanges,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options?.handleAccountChanges) {
|
if (this.options?.handleAccountChanges) {
|
||||||
window?.ethereum?.on(
|
window?.ethereum?.on('accountsChanged', this.options.handleAccountChanges);
|
||||||
'accountsChanged',
|
|
||||||
this.options.handleAccountChanges,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options?.handleAccountDisconnect) {
|
if (this.options?.handleAccountDisconnect) {
|
||||||
window?.ethereum?.on(
|
window?.ethereum?.on('disconnect', this.options.handleAccountDisconnect);
|
||||||
'disconnect',
|
|
||||||
this.options.handleAccountDisconnect,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TornadoRpcSigner(this, signerAddress, this.options);
|
return new TornadoRpcSigner(this, signerAddress, this.options);
|
||||||
|
|||||||
@ -125,10 +125,7 @@ export function isRelayerUpdated(relayerVersion: string, netId: NetIdType) {
|
|||||||
}
|
}
|
||||||
**/
|
**/
|
||||||
|
|
||||||
export function calculateScore({
|
export function calculateScore({ stakeBalance, tornadoServiceFee }: RelayerInfo) {
|
||||||
stakeBalance,
|
|
||||||
tornadoServiceFee,
|
|
||||||
}: RelayerInfo) {
|
|
||||||
if (tornadoServiceFee < MIN_FEE) {
|
if (tornadoServiceFee < MIN_FEE) {
|
||||||
tornadoServiceFee = MIN_FEE;
|
tornadoServiceFee = MIN_FEE;
|
||||||
} else if (tornadoServiceFee >= MAX_FEE) {
|
} else if (tornadoServiceFee >= MAX_FEE) {
|
||||||
@ -137,12 +134,9 @@ export function calculateScore({
|
|||||||
|
|
||||||
const serviceFeeCoefficient = (tornadoServiceFee - MIN_FEE) ** 2;
|
const serviceFeeCoefficient = (tornadoServiceFee - MIN_FEE) ** 2;
|
||||||
const feeDiffCoefficient = 1 / (MAX_FEE - MIN_FEE) ** 2;
|
const feeDiffCoefficient = 1 / (MAX_FEE - MIN_FEE) ** 2;
|
||||||
const coefficientsMultiplier =
|
const coefficientsMultiplier = 1 - feeDiffCoefficient * serviceFeeCoefficient;
|
||||||
1 - feeDiffCoefficient * serviceFeeCoefficient;
|
|
||||||
|
|
||||||
return BigInt(
|
return BigInt(Math.floor(Number(stakeBalance || '0') * coefficientsMultiplier));
|
||||||
Math.floor(Number(stakeBalance || '0') * coefficientsMultiplier),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getWeightRandom(weightsScores: bigint[], random: bigint) {
|
export function getWeightRandom(weightsScores: bigint[], random: bigint) {
|
||||||
@ -227,16 +221,13 @@ export class RelayerClient {
|
|||||||
const rawStatus = (await fetchData(`${url}status`, {
|
const rawStatus = (await fetchData(`${url}status`, {
|
||||||
...this.fetchDataOptions,
|
...this.fetchDataOptions,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type':
|
'Content-Type': 'application/json, application/x-www-form-urlencoded',
|
||||||
'application/json, application/x-www-form-urlencoded',
|
|
||||||
},
|
},
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
maxRetry: this.fetchDataOptions?.torPort ? 2 : 0,
|
maxRetry: this.fetchDataOptions?.torPort ? 2 : 0,
|
||||||
})) as object;
|
})) as object;
|
||||||
|
|
||||||
const statusValidator = ajv.compile(
|
const statusValidator = ajv.compile(getStatusSchema(this.netId, this.config, this.tovarish));
|
||||||
getStatusSchema(this.netId, this.config, this.tovarish),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!statusValidator(rawStatus)) {
|
if (!statusValidator(rawStatus)) {
|
||||||
throw new Error('Invalid status schema');
|
throw new Error('Invalid status schema');
|
||||||
@ -255,22 +246,14 @@ export class RelayerClient {
|
|||||||
throw new Error('This relayer serves a different network');
|
throw new Error('This relayer serves a different network');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (relayerAddress && this.netId === NetId.MAINNET && status.rewardAccount !== relayerAddress) {
|
||||||
relayerAddress &&
|
throw new Error('The Relayer reward address must match registered address');
|
||||||
this.netId === NetId.MAINNET &&
|
|
||||||
status.rewardAccount !== relayerAddress
|
|
||||||
) {
|
|
||||||
throw new Error(
|
|
||||||
'The Relayer reward address must match registered address',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
async filterRelayer(
|
async filterRelayer(relayer: CachedRelayerInfo): Promise<RelayerInfo | RelayerError | undefined> {
|
||||||
relayer: CachedRelayerInfo,
|
|
||||||
): Promise<RelayerInfo | RelayerError | undefined> {
|
|
||||||
const hostname = relayer.hostnames[this.netId];
|
const hostname = relayer.hostnames[this.netId];
|
||||||
const { ensName, relayerAddress } = relayer;
|
const { ensName, relayerAddress } = relayer;
|
||||||
|
|
||||||
@ -315,20 +298,18 @@ export class RelayerClient {
|
|||||||
}> {
|
}> {
|
||||||
const invalidRelayers: RelayerError[] = [];
|
const invalidRelayers: RelayerError[] = [];
|
||||||
|
|
||||||
const validRelayers = (
|
const validRelayers = (await Promise.all(relayers.map((relayer) => this.filterRelayer(relayer)))).filter(
|
||||||
await Promise.all(
|
(r) => {
|
||||||
relayers.map((relayer) => this.filterRelayer(relayer)),
|
if (!r) {
|
||||||
)
|
return false;
|
||||||
).filter((r) => {
|
}
|
||||||
if (!r) {
|
if ((r as RelayerError).hasError) {
|
||||||
return false;
|
invalidRelayers.push(r as RelayerError);
|
||||||
}
|
return false;
|
||||||
if ((r as RelayerError).hasError) {
|
}
|
||||||
invalidRelayers.push(r as RelayerError);
|
return true;
|
||||||
return false;
|
},
|
||||||
}
|
) as RelayerInfo[];
|
||||||
return true;
|
|
||||||
}) as RelayerInfo[];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
validRelayers,
|
validRelayers,
|
||||||
@ -342,9 +323,7 @@ export class RelayerClient {
|
|||||||
|
|
||||||
async tornadoWithdraw(
|
async tornadoWithdraw(
|
||||||
{ contract, proof, args }: TornadoWithdrawParams,
|
{ contract, proof, args }: TornadoWithdrawParams,
|
||||||
callback?: (
|
callback?: (jobResp: RelayerTornadoWithdraw | RelayerTornadoJobs) => void,
|
||||||
jobResp: RelayerTornadoWithdraw | RelayerTornadoJobs,
|
|
||||||
) => void,
|
|
||||||
) {
|
) {
|
||||||
const { url } = this.selectedRelayer as RelayerInfo;
|
const { url } = this.selectedRelayer as RelayerInfo;
|
||||||
|
|
||||||
@ -392,10 +371,7 @@ export class RelayerClient {
|
|||||||
|
|
||||||
console.log(`Job submitted: ${jobUrl}\n`);
|
console.log(`Job submitted: ${jobUrl}\n`);
|
||||||
|
|
||||||
while (
|
while (!relayerStatus || !['FAILED', 'CONFIRMED'].includes(relayerStatus)) {
|
||||||
!relayerStatus ||
|
|
||||||
!['FAILED', 'CONFIRMED'].includes(relayerStatus)
|
|
||||||
) {
|
|
||||||
const jobResponse = await fetchData(jobUrl, {
|
const jobResponse = await fetchData(jobUrl, {
|
||||||
...this.fetchDataOptions,
|
...this.fetchDataOptions,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -415,25 +391,18 @@ export class RelayerClient {
|
|||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { status, txHash, confirmations, failedReason } =
|
const { status, txHash, confirmations, failedReason } = jobResponse as unknown as RelayerTornadoJobs;
|
||||||
jobResponse as unknown as RelayerTornadoJobs;
|
|
||||||
|
|
||||||
if (relayerStatus !== status) {
|
if (relayerStatus !== status) {
|
||||||
if (status === 'FAILED') {
|
if (status === 'FAILED') {
|
||||||
const errMsg = `Job ${status}: ${jobUrl} failed reason: ${failedReason}`;
|
const errMsg = `Job ${status}: ${jobUrl} failed reason: ${failedReason}`;
|
||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
} else if (status === 'SENT') {
|
} else if (status === 'SENT') {
|
||||||
console.log(
|
console.log(`Job ${status}: ${jobUrl}, txhash: ${txHash}\n`);
|
||||||
`Job ${status}: ${jobUrl}, txhash: ${txHash}\n`,
|
|
||||||
);
|
|
||||||
} else if (status === 'MINED') {
|
} else if (status === 'MINED') {
|
||||||
console.log(
|
console.log(`Job ${status}: ${jobUrl}, txhash: ${txHash}, confirmations: ${confirmations}\n`);
|
||||||
`Job ${status}: ${jobUrl}, txhash: ${txHash}, confirmations: ${confirmations}\n`,
|
|
||||||
);
|
|
||||||
} else if (status === 'CONFIRMED') {
|
} else if (status === 'CONFIRMED') {
|
||||||
console.log(
|
console.log(`Job ${status}: ${jobUrl}, txhash: ${txHash}, confirmations: ${confirmations}\n`);
|
||||||
`Job ${status}: ${jobUrl}, txhash: ${txHash}, confirmations: ${confirmations}\n`,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
console.log(`Job ${status}: ${jobUrl}\n`);
|
console.log(`Job ${status}: ${jobUrl}\n`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,9 +12,7 @@ const baseEventsSchemaProperty = {
|
|||||||
transactionHash: bytes32SchemaType,
|
transactionHash: bytes32SchemaType,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const baseEventsSchemaRequired = Object.keys(
|
const baseEventsSchemaRequired = Object.keys(baseEventsSchemaProperty) as string[];
|
||||||
baseEventsSchemaProperty,
|
|
||||||
) as string[];
|
|
||||||
|
|
||||||
export const governanceEventsSchema = {
|
export const governanceEventsSchema = {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
@ -76,11 +74,7 @@ export const governanceEventsSchema = {
|
|||||||
account: addressSchemaType,
|
account: addressSchemaType,
|
||||||
delegateTo: addressSchemaType,
|
delegateTo: addressSchemaType,
|
||||||
},
|
},
|
||||||
required: [
|
required: [...baseEventsSchemaRequired, 'account', 'delegateTo'],
|
||||||
...baseEventsSchemaRequired,
|
|
||||||
'account',
|
|
||||||
'delegateTo',
|
|
||||||
],
|
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -91,11 +85,7 @@ export const governanceEventsSchema = {
|
|||||||
account: addressSchemaType,
|
account: addressSchemaType,
|
||||||
delegateFrom: addressSchemaType,
|
delegateFrom: addressSchemaType,
|
||||||
},
|
},
|
||||||
required: [
|
required: [...baseEventsSchemaRequired, 'account', 'delegateFrom'],
|
||||||
...baseEventsSchemaRequired,
|
|
||||||
'account',
|
|
||||||
'delegateFrom',
|
|
||||||
],
|
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -127,13 +117,7 @@ export const depositsEventsSchema = {
|
|||||||
timestamp: { type: 'number' },
|
timestamp: { type: 'number' },
|
||||||
from: addressSchemaType,
|
from: addressSchemaType,
|
||||||
},
|
},
|
||||||
required: [
|
required: [...baseEventsSchemaRequired, 'commitment', 'leafIndex', 'timestamp', 'from'],
|
||||||
...baseEventsSchemaRequired,
|
|
||||||
'commitment',
|
|
||||||
'leafIndex',
|
|
||||||
'timestamp',
|
|
||||||
'from',
|
|
||||||
],
|
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
@ -149,13 +133,7 @@ export const withdrawalsEventsSchema = {
|
|||||||
fee: bnSchemaType,
|
fee: bnSchemaType,
|
||||||
timestamp: { type: 'number' },
|
timestamp: { type: 'number' },
|
||||||
},
|
},
|
||||||
required: [
|
required: [...baseEventsSchemaRequired, 'nullifierHash', 'to', 'fee', 'timestamp'],
|
||||||
...baseEventsSchemaRequired,
|
|
||||||
'nullifierHash',
|
|
||||||
'to',
|
|
||||||
'fee',
|
|
||||||
'timestamp',
|
|
||||||
],
|
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
@ -129,22 +129,10 @@ const statusSchema: statusSchema = {
|
|||||||
onSyncEvents: { type: 'boolean' },
|
onSyncEvents: { type: 'boolean' },
|
||||||
currentQueue: { type: 'number' },
|
currentQueue: { type: 'number' },
|
||||||
},
|
},
|
||||||
required: [
|
required: ['rewardAccount', 'instances', 'netId', 'tornadoServiceFee', 'version', 'health', 'currentQueue'],
|
||||||
'rewardAccount',
|
|
||||||
'instances',
|
|
||||||
'netId',
|
|
||||||
'tornadoServiceFee',
|
|
||||||
'version',
|
|
||||||
'health',
|
|
||||||
'currentQueue',
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getStatusSchema(
|
export function getStatusSchema(netId: NetIdType, config: Config, tovarish: boolean) {
|
||||||
netId: NetIdType,
|
|
||||||
config: Config,
|
|
||||||
tovarish: boolean,
|
|
||||||
) {
|
|
||||||
const { tokens, optionalTokens, disabledTokens, nativeCurrency } = config;
|
const { tokens, optionalTokens, disabledTokens, nativeCurrency } = config;
|
||||||
|
|
||||||
// deep copy schema
|
// deep copy schema
|
||||||
@ -152,13 +140,7 @@ export function getStatusSchema(
|
|||||||
|
|
||||||
const instances = Object.keys(tokens).reduce(
|
const instances = Object.keys(tokens).reduce(
|
||||||
(acc: statusInstancesType, token) => {
|
(acc: statusInstancesType, token) => {
|
||||||
const {
|
const { instanceAddress, tokenAddress, symbol, decimals, optionalInstances = [] } = tokens[token];
|
||||||
instanceAddress,
|
|
||||||
tokenAddress,
|
|
||||||
symbol,
|
|
||||||
decimals,
|
|
||||||
optionalInstances = [],
|
|
||||||
} = tokens[token];
|
|
||||||
const amounts = Object.keys(instanceAddress);
|
const amounts = Object.keys(instanceAddress);
|
||||||
|
|
||||||
const instanceProperties: statusInstanceType = {
|
const instanceProperties: statusInstanceType = {
|
||||||
@ -178,9 +160,7 @@ export function getStatusSchema(
|
|||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
),
|
),
|
||||||
required: amounts.filter(
|
required: amounts.filter((amount) => !optionalInstances.includes(amount)),
|
||||||
(amount) => !optionalInstances.includes(amount),
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
decimals: { enum: [decimals] },
|
decimals: { enum: [decimals] },
|
||||||
},
|
},
|
||||||
@ -198,10 +178,7 @@ export function getStatusSchema(
|
|||||||
}
|
}
|
||||||
|
|
||||||
acc.properties[token] = instanceProperties;
|
acc.properties[token] = instanceProperties;
|
||||||
if (
|
if (!optionalTokens?.includes(token) && !disabledTokens?.includes(token)) {
|
||||||
!optionalTokens?.includes(token) &&
|
|
||||||
!disabledTokens?.includes(token)
|
|
||||||
) {
|
|
||||||
acc.required.push(token);
|
acc.required.push(token);
|
||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
@ -216,10 +193,7 @@ export function getStatusSchema(
|
|||||||
schema.properties.instances = instances;
|
schema.properties.instances = instances;
|
||||||
|
|
||||||
const _tokens = Object.keys(tokens).filter(
|
const _tokens = Object.keys(tokens).filter(
|
||||||
(t) =>
|
(t) => t !== nativeCurrency && !config.optionalTokens?.includes(t) && !config.disabledTokens?.includes(t),
|
||||||
t !== nativeCurrency &&
|
|
||||||
!config.optionalTokens?.includes(t) &&
|
|
||||||
!config.disabledTokens?.includes(t),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (netId === NetId.MAINNET) {
|
if (netId === NetId.MAINNET) {
|
||||||
@ -229,16 +203,10 @@ export function getStatusSchema(
|
|||||||
if (_tokens.length) {
|
if (_tokens.length) {
|
||||||
const ethPrices: statusEthPricesType = {
|
const ethPrices: statusEthPricesType = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: _tokens.reduce(
|
properties: _tokens.reduce((acc: { [key in string]: typeof bnSchemaType }, token: string) => {
|
||||||
(
|
acc[token] = bnSchemaType;
|
||||||
acc: { [key in string]: typeof bnSchemaType },
|
return acc;
|
||||||
token: string,
|
}, {}),
|
||||||
) => {
|
|
||||||
acc[token] = bnSchemaType;
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{},
|
|
||||||
),
|
|
||||||
required: _tokens,
|
required: _tokens,
|
||||||
};
|
};
|
||||||
schema.properties.ethPrices = ethPrices;
|
schema.properties.ethPrices = ethPrices;
|
||||||
@ -246,13 +214,7 @@ export function getStatusSchema(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tovarish) {
|
if (tovarish) {
|
||||||
schema.required.push(
|
schema.required.push('gasPrices', 'latestBlock', 'latestBalance', 'syncStatus', 'onSyncEvents');
|
||||||
'gasPrices',
|
|
||||||
'latestBlock',
|
|
||||||
'latestBalance',
|
|
||||||
'syncStatus',
|
|
||||||
'onSyncEvents',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return schema;
|
return schema;
|
||||||
|
|||||||
@ -61,15 +61,11 @@ export async function getTokenBalances({
|
|||||||
|
|
||||||
const ethResults = multicallResults[0];
|
const ethResults = multicallResults[0];
|
||||||
const tokenResults = multicallResults.slice(1).length
|
const tokenResults = multicallResults.slice(1).length
|
||||||
? chunk(
|
? chunk(multicallResults.slice(1), tokenCalls.length / tokenAddresses.length)
|
||||||
multicallResults.slice(1),
|
|
||||||
tokenCalls.length / tokenAddresses.length,
|
|
||||||
)
|
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const tokenBalances = tokenResults.map((tokenResult, index) => {
|
const tokenBalances = tokenResults.map((tokenResult, index) => {
|
||||||
const [tokenBalance, tokenName, tokenSymbol, tokenDecimals] =
|
const [tokenBalance, tokenName, tokenSymbol, tokenDecimals] = tokenResult;
|
||||||
tokenResult;
|
|
||||||
const tokenAddress = tokenAddresses[index];
|
const tokenAddress = tokenAddresses[index];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -138,8 +138,7 @@ export class TovarishClient extends RelayerClient {
|
|||||||
const statusArray = (await fetchData(`${url}status`, {
|
const statusArray = (await fetchData(`${url}status`, {
|
||||||
...this.fetchDataOptions,
|
...this.fetchDataOptions,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type':
|
'Content-Type': 'application/json, application/x-www-form-urlencoded',
|
||||||
'application/json, application/x-www-form-urlencoded',
|
|
||||||
},
|
},
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
maxRetry: this.fetchDataOptions?.torPort ? 2 : 0,
|
maxRetry: this.fetchDataOptions?.torPort ? 2 : 0,
|
||||||
@ -182,14 +181,8 @@ export class TovarishClient extends RelayerClient {
|
|||||||
throw new Error('This relayer serves a different network');
|
throw new Error('This relayer serves a different network');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (relayerAddress && status.netId === NetId.MAINNET && status.rewardAccount !== relayerAddress) {
|
||||||
relayerAddress &&
|
throw new Error('The Relayer reward address must match registered address');
|
||||||
status.netId === NetId.MAINNET &&
|
|
||||||
status.rewardAccount !== relayerAddress
|
|
||||||
) {
|
|
||||||
throw new Error(
|
|
||||||
'The Relayer reward address must match registered address',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!status.version.includes('tovarish')) {
|
if (!status.version.includes('tovarish')) {
|
||||||
@ -202,11 +195,8 @@ export class TovarishClient extends RelayerClient {
|
|||||||
return tovarishStatus;
|
return tovarishStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
async filterRelayer(
|
async filterRelayer(relayer: CachedRelayerInfo): Promise<TovarishInfo | RelayerError | undefined> {
|
||||||
relayer: CachedRelayerInfo,
|
const { ensName, relayerAddress, tovarishHost, tovarishNetworks } = relayer;
|
||||||
): Promise<TovarishInfo | RelayerError | undefined> {
|
|
||||||
const { ensName, relayerAddress, tovarishHost, tovarishNetworks } =
|
|
||||||
relayer;
|
|
||||||
|
|
||||||
if (!tovarishHost || !tovarishNetworks?.includes(this.netId)) {
|
if (!tovarishHost || !tovarishNetworks?.includes(this.netId)) {
|
||||||
return;
|
return;
|
||||||
@ -258,20 +248,18 @@ export class TovarishClient extends RelayerClient {
|
|||||||
}> {
|
}> {
|
||||||
const invalidRelayers: RelayerError[] = [];
|
const invalidRelayers: RelayerError[] = [];
|
||||||
|
|
||||||
const validRelayers = (
|
const validRelayers = (await Promise.all(relayers.map((relayer) => this.filterRelayer(relayer)))).filter(
|
||||||
await Promise.all(
|
(r) => {
|
||||||
relayers.map((relayer) => this.filterRelayer(relayer)),
|
if (!r) {
|
||||||
)
|
return false;
|
||||||
).filter((r) => {
|
}
|
||||||
if (!r) {
|
if ((r as RelayerError).hasError) {
|
||||||
return false;
|
invalidRelayers.push(r as RelayerError);
|
||||||
}
|
return false;
|
||||||
if ((r as RelayerError).hasError) {
|
}
|
||||||
invalidRelayers.push(r as RelayerError);
|
return true;
|
||||||
return false;
|
},
|
||||||
}
|
) as TovarishInfo[];
|
||||||
return true;
|
|
||||||
}) as TovarishInfo[];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
validRelayers,
|
validRelayers,
|
||||||
@ -306,9 +294,7 @@ export class TovarishClient extends RelayerClient {
|
|||||||
ensName,
|
ensName,
|
||||||
relayerAddress,
|
relayerAddress,
|
||||||
rewardAccount: getAddress(status.rewardAccount),
|
rewardAccount: getAddress(status.rewardAccount),
|
||||||
instances: getSupportedInstances(
|
instances: getSupportedInstances(status.instances),
|
||||||
status.instances,
|
|
||||||
),
|
|
||||||
stakeBalance: relayer.stakeBalance,
|
stakeBalance: relayer.stakeBalance,
|
||||||
gasPrice: status.gasPrices?.fast,
|
gasPrice: status.gasPrices?.fast,
|
||||||
ethPrices: status.ethPrices,
|
ethPrices: status.ethPrices,
|
||||||
@ -358,21 +344,20 @@ export class TovarishClient extends RelayerClient {
|
|||||||
// eslint-disable-next-line no-constant-condition
|
// eslint-disable-next-line no-constant-condition
|
||||||
while (true) {
|
while (true) {
|
||||||
// eslint-disable-next-line prefer-const
|
// eslint-disable-next-line prefer-const
|
||||||
let { events: fetchedEvents, lastSyncBlock: currentBlock } =
|
let { events: fetchedEvents, lastSyncBlock: currentBlock } = (await fetchData(url, {
|
||||||
(await fetchData(url, {
|
...this.fetchDataOptions,
|
||||||
...this.fetchDataOptions,
|
method: 'POST',
|
||||||
method: 'POST',
|
headers: {
|
||||||
headers: {
|
'Content-Type': 'application/json',
|
||||||
'Content-Type': 'application/json',
|
},
|
||||||
},
|
body: JSON.stringify({
|
||||||
body: JSON.stringify({
|
type,
|
||||||
type,
|
currency,
|
||||||
currency,
|
amount,
|
||||||
amount,
|
fromBlock,
|
||||||
fromBlock,
|
recent,
|
||||||
recent,
|
}),
|
||||||
}),
|
})) as BaseTovarishEvents<T>;
|
||||||
})) as BaseTovarishEvents<T>;
|
|
||||||
|
|
||||||
if (!schemaValidator(fetchedEvents)) {
|
if (!schemaValidator(fetchedEvents)) {
|
||||||
const errMsg = `Schema validation failed for ${type} events`;
|
const errMsg = `Schema validation failed for ${type} events`;
|
||||||
@ -406,9 +391,7 @@ export class TovarishClient extends RelayerClient {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchedEvents = fetchedEvents.filter(
|
fetchedEvents = fetchedEvents.filter((e) => e.blockNumber !== lastEvent.blockNumber);
|
||||||
(e) => e.blockNumber !== lastEvent.blockNumber,
|
|
||||||
);
|
|
||||||
fromBlock = Number(lastEvent.blockNumber);
|
fromBlock = Number(lastEvent.blockNumber);
|
||||||
|
|
||||||
events.push(...fetchedEvents);
|
events.push(...fetchedEvents);
|
||||||
|
|||||||
43
src/utils.ts
43
src/utils.ts
@ -16,14 +16,10 @@ export const isNode =
|
|||||||
}
|
}
|
||||||
).browser && typeof globalThis.window === 'undefined';
|
).browser && typeof globalThis.window === 'undefined';
|
||||||
|
|
||||||
export const crypto = isNode
|
export const crypto = isNode ? webcrypto : (globalThis.crypto as typeof webcrypto);
|
||||||
? webcrypto
|
|
||||||
: (globalThis.crypto as typeof webcrypto);
|
|
||||||
|
|
||||||
export const chunk = <T>(arr: T[], size: number): T[][] =>
|
export const chunk = <T>(arr: T[], size: number): T[][] =>
|
||||||
[...Array(Math.ceil(arr.length / size))].map((_, i) =>
|
[...Array(Math.ceil(arr.length / size))].map((_, i) => arr.slice(size * i, size + size * i));
|
||||||
arr.slice(size * i, size + size * i),
|
|
||||||
);
|
|
||||||
|
|
||||||
export function sleep(ms: number) {
|
export function sleep(ms: number) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
@ -33,9 +29,7 @@ export function validateUrl(url: string, protocols?: string[]) {
|
|||||||
try {
|
try {
|
||||||
const parsedUrl = new URL(url);
|
const parsedUrl = new URL(url);
|
||||||
if (protocols && protocols.length) {
|
if (protocols && protocols.length) {
|
||||||
return protocols
|
return protocols.map((p) => p.toLowerCase()).includes(parsedUrl.protocol);
|
||||||
.map((p) => p.toLowerCase())
|
|
||||||
.includes(parsedUrl.protocol);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
@ -60,9 +54,7 @@ export function bufferToBytes(b: Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function bytesToBase64(bytes: Uint8Array) {
|
export function bytesToBase64(bytes: Uint8Array) {
|
||||||
return btoa(
|
return btoa(bytes.reduce((data, byte) => data + String.fromCharCode(byte), ''));
|
||||||
bytes.reduce((data, byte) => data + String.fromCharCode(byte), ''),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function base64ToBytes(base64: string) {
|
export function base64ToBytes(base64: string) {
|
||||||
@ -85,11 +77,7 @@ export function hexToBytes(hexString: string) {
|
|||||||
if (hexString.length % 2 !== 0) {
|
if (hexString.length % 2 !== 0) {
|
||||||
hexString = '0' + hexString;
|
hexString = '0' + hexString;
|
||||||
}
|
}
|
||||||
return Uint8Array.from(
|
return Uint8Array.from((hexString.match(/.{1,2}/g) as string[]).map((byte) => parseInt(byte, 16)));
|
||||||
(hexString.match(/.{1,2}/g) as string[]).map((byte) =>
|
|
||||||
parseInt(byte, 16),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert BE encoded bytes (Buffer | Uint8Array) array to BigInt
|
// Convert BE encoded bytes (Buffer | Uint8Array) array to BigInt
|
||||||
@ -100,8 +88,7 @@ export function bytesToBN(bytes: Uint8Array) {
|
|||||||
// Convert BigInt to BE encoded Uint8Array type
|
// Convert BigInt to BE encoded Uint8Array type
|
||||||
export function bnToBytes(bigint: bigint | string) {
|
export function bnToBytes(bigint: bigint | string) {
|
||||||
// Parse bigint to hex string
|
// Parse bigint to hex string
|
||||||
let hexString: string =
|
let hexString: string = typeof bigint === 'bigint' ? bigint.toString(16) : bigint;
|
||||||
typeof bigint === 'bigint' ? bigint.toString(16) : bigint;
|
|
||||||
// Remove hex string prefix if exists
|
// Remove hex string prefix if exists
|
||||||
if (hexString.slice(0, 2) === '0x') {
|
if (hexString.slice(0, 2) === '0x') {
|
||||||
hexString = hexString.slice(2);
|
hexString = hexString.slice(2);
|
||||||
@ -110,11 +97,7 @@ export function bnToBytes(bigint: bigint | string) {
|
|||||||
if (hexString.length % 2 !== 0) {
|
if (hexString.length % 2 !== 0) {
|
||||||
hexString = '0' + hexString;
|
hexString = '0' + hexString;
|
||||||
}
|
}
|
||||||
return Uint8Array.from(
|
return Uint8Array.from((hexString.match(/.{1,2}/g) as string[]).map((byte) => parseInt(byte, 16)));
|
||||||
(hexString.match(/.{1,2}/g) as string[]).map((byte) =>
|
|
||||||
parseInt(byte, 16),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert LE encoded bytes (Buffer | Uint8Array) array to BigInt
|
// Convert LE encoded bytes (Buffer | Uint8Array) array to BigInt
|
||||||
@ -169,10 +152,7 @@ export async function digest(bytes: Uint8Array, algo: string = 'SHA-384') {
|
|||||||
return new Uint8Array(await crypto.subtle.digest(algo, bytes));
|
return new Uint8Array(await crypto.subtle.digest(algo, bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function numberFormatter(
|
export function numberFormatter(num: string | number | bigint, digits: number = 3): string {
|
||||||
num: string | number | bigint,
|
|
||||||
digits: number = 3,
|
|
||||||
): string {
|
|
||||||
const lookup = [
|
const lookup = [
|
||||||
{ value: 1, symbol: '' },
|
{ value: 1, symbol: '' },
|
||||||
{ value: 1e3, symbol: 'K' },
|
{ value: 1e3, symbol: 'K' },
|
||||||
@ -187,12 +167,7 @@ export function numberFormatter(
|
|||||||
.slice()
|
.slice()
|
||||||
.reverse()
|
.reverse()
|
||||||
.find((item) => Number(num) >= item.value);
|
.find((item) => Number(num) >= item.value);
|
||||||
return item
|
return item ? (Number(num) / item.value).toFixed(digits).replace(regexp, '').concat(item.symbol) : '0';
|
||||||
? (Number(num) / item.value)
|
|
||||||
.toFixed(digits)
|
|
||||||
.replace(regexp, '')
|
|
||||||
.concat(item.symbol)
|
|
||||||
: '0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isHex(value: string) {
|
export function isHex(value: string) {
|
||||||
|
|||||||
@ -69,12 +69,7 @@ export async function calculateSnarkProof(
|
|||||||
|
|
||||||
console.log('Start generating SNARK proof', snarkInput);
|
console.log('Start generating SNARK proof', snarkInput);
|
||||||
console.time('SNARK proof time');
|
console.time('SNARK proof time');
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(
|
const proofData = await websnarkUtils.genWitnessAndProve(await groth16, snarkInput, circuit, provingKey);
|
||||||
await groth16,
|
|
||||||
snarkInput,
|
|
||||||
circuit,
|
|
||||||
provingKey,
|
|
||||||
);
|
|
||||||
const proof = websnarkUtils.toSolidityInput(proofData).proof;
|
const proof = websnarkUtils.toSolidityInput(proofData).proof;
|
||||||
console.timeEnd('SNARK proof time');
|
console.timeEnd('SNARK proof time');
|
||||||
|
|
||||||
|
|||||||
@ -58,9 +58,7 @@ export async function downloadZip<T>({
|
|||||||
|
|
||||||
const { [zipName]: content } = await unzipAsync(data);
|
const { [zipName]: content } = await unzipAsync(data);
|
||||||
|
|
||||||
console.log(
|
console.log(`Downloaded ${url}${zipDigest ? ` ( Digest: ${zipDigest} )` : ''}`);
|
||||||
`Downloaded ${url}${zipDigest ? ` ( Digest: ${zipDigest} )` : ''}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (parseJson) {
|
if (parseJson) {
|
||||||
return JSON.parse(new TextDecoder().decode(content)) as T;
|
return JSON.parse(new TextDecoder().decode(content)) as T;
|
||||||
|
|||||||
@ -15,17 +15,11 @@ describe('./src/deposit.ts', function () {
|
|||||||
const instanceFixture = async () => {
|
const instanceFixture = async () => {
|
||||||
const [owner] = await getSigners();
|
const [owner] = await getSigners();
|
||||||
|
|
||||||
const Hasher = (await (await deployHasher(owner)).wait())
|
const Hasher = (await (await deployHasher(owner)).wait())?.contractAddress as string;
|
||||||
?.contractAddress as string;
|
|
||||||
|
|
||||||
const Verifier = await new Verifier__factory(owner).deploy();
|
const Verifier = await new Verifier__factory(owner).deploy();
|
||||||
|
|
||||||
const Instance = await new ETHTornado__factory(owner).deploy(
|
const Instance = await new ETHTornado__factory(owner).deploy(Verifier.target, Hasher, 1n, 20);
|
||||||
Verifier.target,
|
|
||||||
Hasher,
|
|
||||||
1n,
|
|
||||||
20,
|
|
||||||
);
|
|
||||||
|
|
||||||
return { Instance };
|
return { Instance };
|
||||||
};
|
};
|
||||||
@ -47,9 +41,7 @@ describe('./src/deposit.ts', function () {
|
|||||||
value: 1n,
|
value: 1n,
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(resp)
|
await expect(resp).to.emit(Instance, 'Deposit').withArgs(deposit.commitmentHex, 0, anyValue);
|
||||||
.to.emit(Instance, 'Deposit')
|
|
||||||
.withArgs(deposit.commitmentHex, 0, anyValue);
|
|
||||||
|
|
||||||
expect(await Instance.commitments(deposit.commitmentHex)).to.be.true;
|
expect(await Instance.commitments(deposit.commitmentHex)).to.be.true;
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user