Skip to content

Commit

Permalink
[feat]: Enhance wallet port communication (#30)
Browse files Browse the repository at this point in the history
* fix: Variable name

* feat: Better structure wallet communication

* feat: Add 'getFeeData' query to wallet worker and overhaul gas calculation logic
  • Loading branch information
jsanmigimeno authored Jun 25, 2024
1 parent b86a097 commit dc44835
Show file tree
Hide file tree
Showing 8 changed files with 295 additions and 118 deletions.
2 changes: 2 additions & 0 deletions src/submitter/queues/submit-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class SubmitQueue extends ProcessingQueue<
maxTries: number,
private readonly incentivesContracts: Map<string, IncentivizedMessageEscrow>,
relayerAddress: string,
private readonly chainId: string,
private readonly wallet: WalletInterface,
private readonly logger: pino.Logger,
) {
Expand Down Expand Up @@ -65,6 +66,7 @@ export class SubmitQueue extends ProcessingQueue<
};

const txPromise = this.wallet.submitTransaction(
this.chainId,
txRequest,
order,
).then((transactionResult): SubmitOrderResult => {
Expand Down
2 changes: 1 addition & 1 deletion src/submitter/submitter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ export class SubmitterService {
),

walletPublicKey: globalConfig.walletPublicKey,
walletPort: await this.walletService.attachToWallet(chainId),
walletPort: await this.walletService.attachToWallet(),
loggerOptions: this.loggerService.loggerOptions,
};
}
Expand Down
1 change: 1 addition & 0 deletions src/submitter/submitter.worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class SubmitterWorker {
maxTries,
incentivesContracts,
walletPublicKey,
chainId,
wallet,
logger,
);
Expand Down
104 changes: 64 additions & 40 deletions src/wallet/transaction-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,78 +224,102 @@ export class TransactionHelper {
}
}

getFeeDataForTransaction(priority?: boolean): GasFeeOverrides {
const queriedFeeData = this.feeData;
if (queriedFeeData == undefined) {
return {};
getCachedFeeData(): FeeData | undefined {
return this.feeData;
}

getAdjustedFeeData(
priority?: boolean,
): FeeData | undefined {
const feeData = {...this.feeData};
if (feeData == undefined) {
return undefined;
}

const queriedMaxPriorityFeePerGas = queriedFeeData.maxPriorityFeePerGas;
if (queriedMaxPriorityFeePerGas != null) {
// Set fee data for an EIP 1559 transactions
let maxFeePerGas = this.maxFeePerGas;
// Override 'maxFeePerGas' if it is specified on the config.
if (this.maxFeePerGas) {
feeData.maxFeePerGas = this.maxFeePerGas;
}

// Adjust the 'maxPriorityFeePerGas' if present.
if (feeData.maxPriorityFeePerGas != undefined) {
// Adjust the 'maxPriorityFeePerGas' by the adjustment factor
let maxPriorityFeePerGas;
if (this.maxPriorityFeeAdjustmentFactor != undefined) {
maxPriorityFeePerGas = queriedMaxPriorityFeePerGas
feeData.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas
* this.maxPriorityFeeAdjustmentFactor
/ DECIMAL_BASE_BIG_INT;
}

// Apply the max allowed 'maxPriorityFeePerGas'
if (
maxPriorityFeePerGas != undefined &&
this.maxAllowedPriorityFeePerGas != undefined &&
this.maxAllowedPriorityFeePerGas < maxPriorityFeePerGas
this.maxAllowedPriorityFeePerGas < feeData.maxPriorityFeePerGas
) {
maxPriorityFeePerGas = this.maxAllowedPriorityFeePerGas;
}

if (priority) {
if (maxFeePerGas != undefined) {
maxFeePerGas = maxFeePerGas * this.priorityAdjustmentFactor / DECIMAL_BASE_BIG_INT;
}

if (maxPriorityFeePerGas != undefined) {
maxPriorityFeePerGas = maxPriorityFeePerGas * this.priorityAdjustmentFactor / DECIMAL_BASE_BIG_INT;
}
feeData.maxPriorityFeePerGas = this.maxAllowedPriorityFeePerGas;
}
}

return {
maxFeePerGas,
maxPriorityFeePerGas,
};
} else {
// Set traditional gasPrice
const queriedGasPrice = queriedFeeData.gasPrice;
if (queriedGasPrice == null) return {};

// Adjust the 'gasPrice' if present.
if (feeData.gasPrice) {
// Adjust the 'gasPrice' by the adjustment factor
let gasPrice;
if (this.gasPriceAdjustmentFactor != undefined) {
gasPrice = queriedGasPrice
feeData.gasPrice = feeData.gasPrice
* this.gasPriceAdjustmentFactor
/ DECIMAL_BASE_BIG_INT;
}

// Apply the max allowed 'gasPrice'
if (
gasPrice != undefined &&
this.maxAllowedGasPrice != undefined &&
this.maxAllowedGasPrice < gasPrice
this.maxAllowedGasPrice < feeData.gasPrice
) {
gasPrice = this.maxAllowedGasPrice;
feeData.gasPrice = this.maxAllowedGasPrice;
}
}

if (priority && gasPrice != undefined) {
gasPrice = gasPrice
// Apply the 'priority' adjustment factor
if (priority) {
if (feeData.maxFeePerGas != undefined) {
feeData.maxFeePerGas = feeData.maxFeePerGas
*this.priorityAdjustmentFactor
/ DECIMAL_BASE_BIG_INT;
}

if (feeData.maxPriorityFeePerGas != undefined) {
feeData.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas
*this.priorityAdjustmentFactor
/ DECIMAL_BASE_BIG_INT;
}

if (feeData.gasPrice != undefined) {
feeData.gasPrice = feeData.gasPrice
* this.priorityAdjustmentFactor
/ DECIMAL_BASE_BIG_INT;
}
}

return new FeeData(
feeData.gasPrice,
feeData.maxFeePerGas,
feeData.maxPriorityFeePerGas
);
}

getFeeDataForTransaction(priority?: boolean): GasFeeOverrides {
const adjustedFeeData = this.getAdjustedFeeData(priority);
if (adjustedFeeData == undefined) {
return {};
}

if (adjustedFeeData.maxPriorityFeePerGas != undefined) {
// Set fee data for EIP 1559 transactions
return {
maxFeePerGas: adjustedFeeData.maxFeePerGas ?? undefined,
maxPriorityFeePerGas: adjustedFeeData.maxPriorityFeePerGas,
};
} else {
return {
gasPrice,
gasPrice: adjustedFeeData.gasPrice ?? undefined,
};
}
}
Expand Down
79 changes: 68 additions & 11 deletions src/wallet/wallet.interface.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { TransactionReceipt, TransactionRequest, TransactionResponse } from 'ethers6';
import { FeeData, TransactionReceipt, TransactionRequest, TransactionResponse } from 'ethers6';
import { MessagePort } from 'worker_threads';
import { WalletTransactionOptions, WalletTransactionRequestMessage, WalletTransactionRequestResponse } from './wallet.types';
import { WALLET_WORKER_CRASHED_MESSAGE_ID } from './wallet.service';
import { WALLET_WORKER_CRASHED_MESSAGE_ID, WalletFeeDataMessage, WalletGetFeeDataMessage, WalletMessageType, WalletPortData, WalletTransactionOptions, WalletTransactionRequestMessage, WalletTransactionRequestResponseMessage } from './wallet.types';

export interface TransactionResult<T = any> {
txRequest: TransactionRequest;
Expand All @@ -22,6 +21,7 @@ export class WalletInterface {
}

async submitTransaction<T>(
chainId: string,
transaction: TransactionRequest,
metadata?: T,
options?: WalletTransactionOptions
Expand All @@ -30,22 +30,25 @@ export class WalletInterface {
const messageId = this.getNextPortMessageId();

const resultPromise = new Promise<TransactionResult<T>>(resolve => {
const listener = (data: any) => {
const listener = (data: WalletPortData) => {
if (data.messageId === messageId) {
this.port.off("message", listener);

const walletResponse = data as WalletTransactionRequestResponse<T>;
const walletResponse = data.message as WalletTransactionRequestResponseMessage<T>;

const result = {
txRequest: walletResponse.txRequest,
metadata: walletResponse.metadata,
tx: walletResponse.tx,
txReceipt: walletResponse.txReceipt,
submissionError: data.submissionError,
confirmationError: data.confirmationError
submissionError: walletResponse.submissionError,
confirmationError: walletResponse.confirmationError
};
resolve(result);
} else if (data.messageId === WALLET_WORKER_CRASHED_MESSAGE_ID) {
} else if (
data.messageId === WALLET_WORKER_CRASHED_MESSAGE_ID
&& data.chainId == chainId
) {
this.port.off("message", listener);

const result = {
Expand All @@ -59,13 +62,67 @@ export class WalletInterface {
};
this.port.on("message", listener);

const request: WalletTransactionRequestMessage = {
messageId,
const message: WalletTransactionRequestMessage = {
type: WalletMessageType.TransactionRequest,
txRequest: transaction,
metadata,
options
};
this.port.postMessage(request);

const portData: WalletPortData = {
chainId,
messageId,
message,
}
this.port.postMessage(portData);
});

return resultPromise;
}

async getFeeData(
chainId: string,
priority?: boolean,
): Promise<FeeData> {

const messageId = this.getNextPortMessageId();

const resultPromise = new Promise<FeeData>(resolve => {
const listener = (data: WalletPortData) => {
if (data.messageId === messageId) {
this.port.off("message", listener);

const walletResponse = data.message as WalletFeeDataMessage;

const result = {
gasPrice: walletResponse.gasPrice,
maxFeePerGas: walletResponse.maxFeePerGas,
maxPriorityFeePerGas: walletResponse.maxPriorityFeePerGas,
} as FeeData;
resolve(result);
} else if (
data.messageId === WALLET_WORKER_CRASHED_MESSAGE_ID
&& data.chainId == chainId
) {
this.port.off("message", listener);

const result = {} as FeeData;
resolve(result);
}
};
this.port.on("message", listener);

const message: WalletGetFeeDataMessage = {
type: WalletMessageType.GetFeeData,
priority: priority ?? false,
};

const portData: WalletPortData = {
chainId,
messageId,
message,
}
this.port.postMessage(portData);
});

return resultPromise;
Expand Down
Loading

0 comments on commit dc44835

Please sign in to comment.