mirror of
https://github.com/0xbow-io/privacy-pools-core.git
synced 2026-01-09 17:37:58 -05:00
fix: added proper nullifier matching and ragequit fetching
This commit is contained in:
@@ -9,8 +9,10 @@ import {
|
||||
PoolInfo,
|
||||
PrivacyPoolAccount,
|
||||
} from "../types/account.js";
|
||||
import { DepositEvent, RagequitEvent, WithdrawalEvent } from "../types/events.js";
|
||||
import { Logger } from "../utils/logger.js";
|
||||
import { AccountError } from "../errors/account.error.js";
|
||||
import { ErrorCode } from "../errors/base.error.js";
|
||||
|
||||
/**
|
||||
* Service responsible for managing privacy pool accounts and their associated commitments.
|
||||
@@ -42,6 +44,21 @@ export class AccountService {
|
||||
this.account = account || this._initializeAccount(mnemonic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new account from a mnemonic phrase.
|
||||
*
|
||||
* @param mnemonic - The mnemonic phrase to derive keys from
|
||||
* @returns A new PrivacyPoolAccount with derived master keys
|
||||
*
|
||||
* @remarks
|
||||
* This method derives two master keys from the mnemonic:
|
||||
* 1. A master nullifier key from account index 0
|
||||
* 2. A master secret key from account index 1
|
||||
* These keys are used to deterministically generate nullifiers and secrets for deposits and withdrawals.
|
||||
*
|
||||
* @throws {AccountError} If account initialization fails
|
||||
* @private
|
||||
*/
|
||||
private _initializeAccount(mnemonic: string): PrivacyPoolAccount {
|
||||
try {
|
||||
this.logger.debug("Initializing account with mnemonic");
|
||||
@@ -70,26 +87,67 @@ export class AccountService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a deterministic nullifier for a deposit.
|
||||
*
|
||||
* @param scope - The scope of the pool
|
||||
* @param index - The index of the deposit
|
||||
* @returns A deterministic nullifier for the deposit
|
||||
* @private
|
||||
*/
|
||||
private _genDepositNullifier(scope: Hash, index: bigint): Secret {
|
||||
const [masterNullifier] = this.account.masterKeys;
|
||||
return poseidon([masterNullifier, scope, index]) as Secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a deterministic secret for a deposit.
|
||||
*
|
||||
* @param scope - The scope of the pool
|
||||
* @param index - The index of the deposit
|
||||
* @returns A deterministic secret for the deposit
|
||||
* @private
|
||||
*/
|
||||
private _genDepositSecret(scope: Hash, index: bigint): Secret {
|
||||
const [, masterSecret] = this.account.masterKeys;
|
||||
return poseidon([masterSecret, scope, index]) as Secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a deterministic nullifier for a withdrawal.
|
||||
*
|
||||
* @param label - The label of the commitment
|
||||
* @param index - The index of the withdrawal
|
||||
* @returns A deterministic nullifier for the withdrawal
|
||||
* @private
|
||||
*/
|
||||
private _genWithdrawalNullifier(label: Hash, index: bigint): Secret {
|
||||
const [masterNullifier] = this.account.masterKeys;
|
||||
return poseidon([masterNullifier, label, index]) as Secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a deterministic secret for a withdrawal.
|
||||
*
|
||||
* @param label - The label of the commitment
|
||||
* @param index - The index of the withdrawal
|
||||
* @returns A deterministic secret for the withdrawal
|
||||
* @private
|
||||
*/
|
||||
private _genWithdrawalSecret(label: Hash, index: bigint): Secret {
|
||||
const [, masterSecret] = this.account.masterKeys;
|
||||
return poseidon([masterSecret, label, index]) as Secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes a commitment using the Poseidon hash function.
|
||||
*
|
||||
* @param value - The value of the commitment
|
||||
* @param label - The label of the commitment
|
||||
* @param precommitment - The precommitment hash
|
||||
* @returns The commitment hash
|
||||
* @private
|
||||
*/
|
||||
private _hashCommitment(
|
||||
value: bigint,
|
||||
label: Hash,
|
||||
@@ -98,6 +156,14 @@ export class AccountService {
|
||||
return poseidon([value, label, precommitment]) as Hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes a precommitment using the Poseidon hash function.
|
||||
*
|
||||
* @param nullifier - The nullifier for the commitment
|
||||
* @param secret - The secret for the commitment
|
||||
* @returns The precommitment hash
|
||||
* @private
|
||||
*/
|
||||
private _hashPrecommitment(nullifier: Secret, secret: Secret): Hash {
|
||||
return poseidon([nullifier, secret]) as Hash;
|
||||
}
|
||||
@@ -106,6 +172,11 @@ export class AccountService {
|
||||
* Gets all spendable commitments across all pools.
|
||||
*
|
||||
* @returns A map of scope to array of spendable commitments
|
||||
*
|
||||
* @remarks
|
||||
* A commitment is considered spendable if:
|
||||
* 1. It has a non-zero value
|
||||
* 2. The account it belongs to has not been ragequit
|
||||
*/
|
||||
public getSpendableCommitments(): Map<bigint, AccountCommitment[]> {
|
||||
const result = new Map<bigint, AccountCommitment[]>();
|
||||
@@ -114,6 +185,11 @@ export class AccountService {
|
||||
const nonZeroCommitments: AccountCommitment[] = [];
|
||||
|
||||
for (const account of accounts) {
|
||||
// Skip accounts that have been ragequit
|
||||
if (account.ragequit) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const lastCommitment =
|
||||
account.children.length > 0
|
||||
? account.children[account.children.length - 1]
|
||||
@@ -137,6 +213,10 @@ export class AccountService {
|
||||
* @param scope - The scope of the pool to deposit into
|
||||
* @param index - Optional index for deterministic generation
|
||||
* @returns The nullifier, secret, and precommitment for the deposit
|
||||
*
|
||||
* @remarks
|
||||
* If no index is provided, it uses the current number of accounts for the scope.
|
||||
* The precommitment is a hash of the nullifier and secret, used in the deposit process.
|
||||
*/
|
||||
public createDepositSecrets(
|
||||
scope: Hash,
|
||||
@@ -161,6 +241,12 @@ export class AccountService {
|
||||
*
|
||||
* @param commitment - The commitment to spend
|
||||
* @returns The nullifier and secret for the new commitment
|
||||
*
|
||||
* @remarks
|
||||
* The index used for generating the withdrawal nullifier and secret is based on
|
||||
* the number of children the account already has, ensuring each withdrawal has
|
||||
* a unique nullifier.
|
||||
*
|
||||
* @throws {AccountError} If no account is found for the commitment
|
||||
*/
|
||||
public createWithdrawalSecrets(commitment: AccountCommitment): {
|
||||
@@ -198,6 +284,11 @@ export class AccountService {
|
||||
* @param blockNumber - The block number of the deposit
|
||||
* @param txHash - The transaction hash of the deposit
|
||||
* @returns The new pool account
|
||||
*
|
||||
* @remarks
|
||||
* This method creates a new account with the deposit commitment and adds it to the
|
||||
* pool accounts map under the specified scope. The commitment hash is calculated
|
||||
* from the value, label, and precommitment.
|
||||
*/
|
||||
public addPoolAccount(
|
||||
scope: Hash,
|
||||
@@ -248,6 +339,12 @@ export class AccountService {
|
||||
* @param blockNumber - The block number of the withdrawal
|
||||
* @param txHash - The transaction hash of the withdrawal
|
||||
* @returns The new commitment
|
||||
*
|
||||
* @remarks
|
||||
* This method finds the account containing the parent commitment, creates a new
|
||||
* commitment with the provided parameters, and adds it to the account's children.
|
||||
* The new commitment inherits the label from the parent commitment.
|
||||
*
|
||||
* @throws {AccountError} If no account is found for the commitment
|
||||
*/
|
||||
public addWithdrawalCommitment(
|
||||
@@ -299,6 +396,53 @@ export class AccountService {
|
||||
return newCommitment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a ragequit event to an existing pool account
|
||||
*
|
||||
* @param label - The label of the account to add the ragequit to
|
||||
* @param ragequit - The ragequit event to add
|
||||
* @returns The updated pool account
|
||||
*
|
||||
* @remarks
|
||||
* When an account has a ragequit event, it can no longer be spent.
|
||||
* This method finds the account with the matching label and attaches
|
||||
* the ragequit event to it.
|
||||
*
|
||||
* @throws {AccountError} If no account is found with the given label
|
||||
*/
|
||||
public addRagequitToAccount(
|
||||
label: Hash,
|
||||
ragequit: RagequitEvent
|
||||
): PoolAccount {
|
||||
let foundAccount: PoolAccount | undefined;
|
||||
let foundScope: Hash | undefined;
|
||||
|
||||
// Find the account with the matching label
|
||||
for (const [scope, accounts] of this.account.poolAccounts.entries()) {
|
||||
foundAccount = accounts.find((account) => account.label === label);
|
||||
if (foundAccount) {
|
||||
foundScope = scope;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundAccount || !foundScope) {
|
||||
throw new AccountError(
|
||||
`No account found with label ${label}`,
|
||||
ErrorCode.INVALID_INPUT
|
||||
);
|
||||
}
|
||||
|
||||
// Add the ragequit event to the account
|
||||
foundAccount.ragequit = ragequit;
|
||||
|
||||
this.logger.info(
|
||||
`Added ragequit event to account with label ${label}, value ${ragequit.value}`
|
||||
);
|
||||
|
||||
return foundAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the history of deposits and withdrawals for the given pools.
|
||||
*
|
||||
@@ -306,68 +450,97 @@ export class AccountService {
|
||||
*
|
||||
* @remarks
|
||||
* This method performs the following steps:
|
||||
* 1. Fetches all deposit events for each pool
|
||||
* 2. Reconstructs account state from deposits
|
||||
* 3. Processes withdrawals to update account state
|
||||
* 1. Initializes pool accounts for each pool if they don't exist
|
||||
* 2. For each pool, fetches deposit events and reconstructs accounts
|
||||
* 3. Processes withdrawals and ragequits to update account state
|
||||
*
|
||||
* The account reconstruction is deterministic based on the master keys,
|
||||
* allowing the full state to be recovered from on-chain events.
|
||||
*
|
||||
* @throws {DataError} If event fetching fails
|
||||
* @throws {AccountError} If account state reconstruction fails
|
||||
*/
|
||||
public async retrieveHistory(pools: PoolInfo[]): Promise<void> {
|
||||
// Log the start of the history retrieval process
|
||||
this.logger.info(`Fetching events for ${pools.length} pools`);
|
||||
|
||||
// Initialize pool accounts map for each pool if it doesn't exist
|
||||
for (const pool of pools) {
|
||||
if (!this.account.poolAccounts.has(pool.scope)) {
|
||||
this.account.poolAccounts.set(pool.scope, []);
|
||||
}
|
||||
}
|
||||
|
||||
// Process all pools in parallel for better performance
|
||||
await Promise.all(
|
||||
pools.map(async (pool) => {
|
||||
// Log which pool is being processed
|
||||
this.logger.info(
|
||||
`Processing pool ${pool.address} on chain ${pool.chainId} from block ${pool.deploymentBlock}`,
|
||||
);
|
||||
|
||||
const deposits = await this.dataService.getDeposits(pool.chainId, {
|
||||
fromBlock: pool.deploymentBlock,
|
||||
});
|
||||
// Fetch all deposit events for this pool
|
||||
const deposits = await this.dataService.getDeposits(pool);
|
||||
|
||||
this.logger.info(
|
||||
`Found ${deposits.length} deposits for pool ${pool.address}`,
|
||||
);
|
||||
|
||||
const depositMap = new Map<Hash, (typeof deposits)[0]>();
|
||||
// Create a map of deposits by precommitment for efficient lookup
|
||||
const depositMap = new Map<Hash, DepositEvent>();
|
||||
for (const deposit of deposits) {
|
||||
depositMap.set(deposit.precommitment, deposit);
|
||||
}
|
||||
|
||||
// Track found deposits for logging and debugging
|
||||
const foundDeposits: Array<{
|
||||
index: bigint;
|
||||
nullifier: Secret;
|
||||
secret: Secret;
|
||||
pool: PoolInfo;
|
||||
deposit: (typeof deposits)[0];
|
||||
}> = [];
|
||||
|
||||
// Start with index 0 and try to find deposits deterministically
|
||||
let index = BigInt(0);
|
||||
let firstDepositBlock: bigint | undefined;
|
||||
|
||||
// Deterministically generate deposit secrets and check if they match on-chain deposits
|
||||
while (true) {
|
||||
// Generate nullifier, secret, and precommitment for this index
|
||||
const nullifier = this._genDepositNullifier(pool.scope, index);
|
||||
const secret = this._genDepositSecret(pool.scope, index);
|
||||
const precommitment = this._hashPrecommitment(nullifier, secret);
|
||||
|
||||
// Look for a deposit with this precommitment
|
||||
const deposit = depositMap.get(precommitment);
|
||||
if (!deposit) break;
|
||||
if (!deposit) break; // No more deposits found, exit the loop
|
||||
|
||||
// Track the earliest deposit block for later withdrawal processing
|
||||
if (!firstDepositBlock || deposit.blockNumber < firstDepositBlock) {
|
||||
firstDepositBlock = deposit.blockNumber;
|
||||
}
|
||||
|
||||
foundDeposits.push({ index, nullifier, secret, deposit });
|
||||
// Create a new pool account for this deposit
|
||||
this.addPoolAccount(
|
||||
pool.scope,
|
||||
deposit.value,
|
||||
nullifier,
|
||||
secret,
|
||||
deposit.label,
|
||||
deposit.blockNumber,
|
||||
deposit.transactionHash,
|
||||
);
|
||||
|
||||
// Track the found deposit
|
||||
foundDeposits.push({ index, nullifier, secret, pool, deposit });
|
||||
|
||||
// Move to the next index
|
||||
index++;
|
||||
}
|
||||
|
||||
if (foundDeposits.length === 0) {
|
||||
// If no accounts were found for this scope, log and skip further processing
|
||||
if (this.account.poolAccounts.get(pool.scope)!.length === 0) {
|
||||
this.logger.info(
|
||||
`No Pool Accounts were found for scope ${pool.scope}`,
|
||||
);
|
||||
@@ -378,71 +551,123 @@ export class AccountService {
|
||||
`Found ${foundDeposits.length} deposits for pool ${pool.address}`,
|
||||
);
|
||||
|
||||
// Process deposits first
|
||||
const accounts = foundDeposits.map(({ nullifier, secret, deposit }) => {
|
||||
return this.addPoolAccount(
|
||||
pool.scope,
|
||||
deposit.value,
|
||||
nullifier,
|
||||
secret,
|
||||
deposit.label,
|
||||
deposit.blockNumber,
|
||||
deposit.transactionHash,
|
||||
);
|
||||
});
|
||||
|
||||
// Create a map for faster account lookups
|
||||
const accountMap = new Map<Hash, PoolAccount>();
|
||||
for (const account of accounts) {
|
||||
accountMap.set(account.label, account);
|
||||
}
|
||||
|
||||
// Process withdrawals
|
||||
await this._processWithdrawals(
|
||||
pool.chainId,
|
||||
firstDepositBlock!,
|
||||
accountMap,
|
||||
);
|
||||
// Process withdrawals and ragequits for all pools
|
||||
// This is done after all deposits are processed to ensure we have the complete account state
|
||||
await this._processWithdrawals(pools);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes withdrawal events for all pools and updates account state.
|
||||
*
|
||||
* @param pools - Array of pool configurations to process withdrawals for
|
||||
*
|
||||
* @remarks
|
||||
* This method performs the following steps for each pool:
|
||||
* 1. Identifies the earliest deposit block for each scope
|
||||
* 2. Fetches withdrawal and ragequit events from that block
|
||||
* 3. Maps withdrawals by nullifier hash and ragequits by label for efficient lookup
|
||||
* 4. For each account, reconstructs the withdrawal history by:
|
||||
* - Generating nullifiers sequentially
|
||||
* - Matching them against on-chain events
|
||||
* - Adding matched withdrawals to the account state
|
||||
* 5. Adds ragequit events to accounts if found
|
||||
*
|
||||
* @throws {DataError} If event fetching fails
|
||||
* @private
|
||||
*/
|
||||
private async _processWithdrawals(
|
||||
chainId: number,
|
||||
fromBlock: bigint,
|
||||
foundAccounts: Map<Hash, PoolAccount>,
|
||||
pools: PoolInfo[]
|
||||
): Promise<void> {
|
||||
const withdrawals = await this.dataService.getWithdrawals(chainId, {
|
||||
fromBlock,
|
||||
});
|
||||
await Promise.all(
|
||||
pools.map(async (pool) => {
|
||||
const accounts = this.account.poolAccounts.get(pool.scope);
|
||||
|
||||
for (const withdrawal of withdrawals) {
|
||||
for (const account of foundAccounts.values()) {
|
||||
const isParentCommitment =
|
||||
BigInt(account.deposit.nullifier) === BigInt(withdrawal.spentNullifier) ||
|
||||
account.children.some(child => BigInt(child.nullifier) === BigInt(withdrawal.spentNullifier));
|
||||
// Skip if no accounts for this scope
|
||||
if (!accounts || accounts.length === 0) {
|
||||
this.logger.info(
|
||||
`No accounts found for pool ${pool.address} with scope ${pool.scope}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isParentCommitment) {
|
||||
const parentCommitment = account.children.length > 0
|
||||
? account.children[account.children.length - 1]
|
||||
: account.deposit;
|
||||
// Find the earliest deposit block for this scope
|
||||
let firstDepositBlock = BigInt(Number.MAX_SAFE_INTEGER);
|
||||
for (const account of accounts) {
|
||||
if (account.deposit.blockNumber < firstDepositBlock) {
|
||||
firstDepositBlock = account.deposit.blockNumber;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parentCommitment) {
|
||||
this.logger.warn(`No parent commitment found for withdrawal ${withdrawal.spentNullifier.toString()}`);
|
||||
continue;
|
||||
// Fetch withdrawal events from the first deposit block
|
||||
const withdrawals = await this.dataService.getWithdrawals(pool, firstDepositBlock);
|
||||
const ragequits = await this.dataService.getRagequits(pool, firstDepositBlock);
|
||||
|
||||
this.logger.info(
|
||||
`Found ${withdrawals.length} withdrawals for pool ${pool.address}`
|
||||
);
|
||||
|
||||
if (withdrawals.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Map withdrawals by spent nullifier for quick lookup
|
||||
const withdrawalMap = new Map<Hash, WithdrawalEvent>();
|
||||
for (const withdrawal of withdrawals) {
|
||||
withdrawalMap.set(withdrawal.spentNullifier, withdrawal);
|
||||
}
|
||||
|
||||
// Map ragequits by label for quick lookup
|
||||
const ragequitMap = new Map<Hash, RagequitEvent>();
|
||||
for (const ragequit of ragequits) {
|
||||
ragequitMap.set(ragequit.label, ragequit);
|
||||
}
|
||||
|
||||
// Process each account
|
||||
for (const account of accounts) {
|
||||
let currentCommitment = account.deposit;
|
||||
let index = BigInt(0);
|
||||
|
||||
// Continue processing withdrawals until no more are found
|
||||
while (true) {
|
||||
// Generate nullifier for this withdrawal
|
||||
const nullifier = this._genWithdrawalNullifier(account.label, index);
|
||||
const nullifierHash = poseidon([nullifier]) as Hash;
|
||||
|
||||
// Look for a withdrawal event with this nullifier
|
||||
const withdrawal = withdrawalMap.get(nullifierHash);
|
||||
if (!withdrawal) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Generate secret for this withdrawal
|
||||
const secret = this._genWithdrawalSecret(account.label, index);
|
||||
|
||||
// Add the withdrawal commitment to the account
|
||||
const newCommitment = this.addWithdrawalCommitment(
|
||||
currentCommitment,
|
||||
withdrawal.withdrawn,
|
||||
nullifier,
|
||||
secret,
|
||||
withdrawal.blockNumber,
|
||||
withdrawal.transactionHash
|
||||
);
|
||||
|
||||
// Update current commitment to the newly created one
|
||||
currentCommitment = newCommitment;
|
||||
|
||||
// Increment index for next potential withdrawal
|
||||
index++;
|
||||
}
|
||||
|
||||
this.addWithdrawalCommitment(
|
||||
parentCommitment,
|
||||
withdrawal.withdrawn,
|
||||
withdrawal.spentNullifier as unknown as Secret,
|
||||
parentCommitment.secret,
|
||||
withdrawal.blockNumber,
|
||||
withdrawal.transactionHash,
|
||||
);
|
||||
break;
|
||||
const ragequit = ragequitMap.get(account.label);
|
||||
if (ragequit) {
|
||||
this.addRagequitToAccount(account.label, ragequit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
WithdrawalEvent,
|
||||
RagequitEvent,
|
||||
} from "../types/events.js";
|
||||
import { PoolInfo } from "../types/account.js";
|
||||
import { Hash } from "../types/commitment.js";
|
||||
import { Logger } from "../utils/logger.js";
|
||||
import { DataError } from "../errors/data.error.js";
|
||||
@@ -73,18 +74,16 @@ export class DataService {
|
||||
* @throws {DataError} If client is not configured, network error occurs, or event data is invalid
|
||||
*/
|
||||
async getDeposits(
|
||||
chainId: number,
|
||||
options: EventFilterOptions = {},
|
||||
pool: PoolInfo
|
||||
): Promise<DepositEvent[]> {
|
||||
try {
|
||||
const client = this.getClientForChain(chainId);
|
||||
const config = this.getConfigForChain(chainId);
|
||||
const client = this.getClientForChain(pool.chainId);
|
||||
const config = this.getConfigForChain(pool.chainId);
|
||||
|
||||
const logs = await client.getLogs({
|
||||
address: config.privacyPoolAddress,
|
||||
address: pool.address,
|
||||
event: DEPOSIT_EVENT,
|
||||
fromBlock: options.fromBlock ?? config.startBlock,
|
||||
toBlock: options.toBlock,
|
||||
fromBlock: pool.deploymentBlock ?? config.startBlock
|
||||
}).catch(error => {
|
||||
throw new DataError(
|
||||
"Failed to fetch deposit logs",
|
||||
@@ -127,7 +126,7 @@ export class DataService {
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof DataError) throw error;
|
||||
throw DataError.networkError(chainId, error instanceof Error ? error : new Error(String(error)));
|
||||
throw DataError.networkError(pool.chainId, error instanceof Error ? error : new Error(String(error)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,18 +139,17 @@ export class DataService {
|
||||
* @throws {DataError} If client is not configured, network error occurs, or event data is invalid
|
||||
*/
|
||||
async getWithdrawals(
|
||||
chainId: number,
|
||||
options: EventFilterOptions = {},
|
||||
pool: PoolInfo,
|
||||
fromBlock: bigint = pool.deploymentBlock
|
||||
): Promise<WithdrawalEvent[]> {
|
||||
try {
|
||||
const client = this.getClientForChain(chainId);
|
||||
const config = this.getConfigForChain(chainId);
|
||||
const client = this.getClientForChain(pool.chainId);
|
||||
const config = this.getConfigForChain(pool.chainId);
|
||||
|
||||
const logs = await client.getLogs({
|
||||
address: config.privacyPoolAddress,
|
||||
address: pool.address,
|
||||
event: WITHDRAWAL_EVENT,
|
||||
fromBlock: options.fromBlock ?? config.startBlock,
|
||||
toBlock: options.toBlock,
|
||||
fromBlock: fromBlock ?? config.startBlock,
|
||||
}).catch(error => {
|
||||
throw new DataError(
|
||||
"Failed to fetch withdrawal logs",
|
||||
@@ -190,7 +188,7 @@ export class DataService {
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof DataError) throw error;
|
||||
throw DataError.networkError(chainId, error instanceof Error ? error : new Error(String(error)));
|
||||
throw DataError.networkError(pool.chainId, error instanceof Error ? error : new Error(String(error)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,18 +201,17 @@ export class DataService {
|
||||
* @throws {DataError} If client is not configured, network error occurs, or event data is invalid
|
||||
*/
|
||||
async getRagequits(
|
||||
chainId: number,
|
||||
options: EventFilterOptions = {},
|
||||
pool: PoolInfo,
|
||||
fromBlock: bigint = pool.deploymentBlock
|
||||
): Promise<RagequitEvent[]> {
|
||||
try {
|
||||
const client = this.getClientForChain(chainId);
|
||||
const config = this.getConfigForChain(chainId);
|
||||
const client = this.getClientForChain(pool.chainId);
|
||||
const config = this.getConfigForChain(pool.chainId);
|
||||
|
||||
const logs = await client.getLogs({
|
||||
address: config.privacyPoolAddress,
|
||||
address: pool.address,
|
||||
event: RAGEQUIT_EVENT,
|
||||
fromBlock: options.fromBlock ?? config.startBlock,
|
||||
toBlock: options.toBlock,
|
||||
fromBlock: fromBlock ?? config.startBlock,
|
||||
}).catch(error => {
|
||||
throw new DataError(
|
||||
"Failed to fetch ragequit logs",
|
||||
@@ -255,7 +252,7 @@ export class DataService {
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof DataError) throw error;
|
||||
throw DataError.networkError(chainId, error instanceof Error ? error : new Error(String(error)));
|
||||
throw DataError.networkError(pool.chainId, error instanceof Error ? error : new Error(String(error)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Hash, Secret } from "./commitment.js";
|
||||
import { Hex } from "viem";
|
||||
import { RagequitEvent } from "./events.js";
|
||||
|
||||
export interface PoolAccount {
|
||||
label: Hash;
|
||||
deposit: AccountCommitment;
|
||||
children: AccountCommitment[];
|
||||
ragequit?: RagequitEvent
|
||||
}
|
||||
|
||||
export interface AccountCommitment {
|
||||
@@ -27,7 +29,7 @@ export interface PrivacyPoolAccount {
|
||||
|
||||
export interface PoolInfo {
|
||||
chainId: number;
|
||||
address: string;
|
||||
address: Hex;
|
||||
scope: Hash;
|
||||
deploymentBlock: bigint;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user