Skip to content

Commit

Permalink
fix: Added rateLimiter to fileCreate.
Browse files Browse the repository at this point in the history
Signed-off-by: ebadiere <ebadiere@gmail.com>
  • Loading branch information
ebadiere committed Jun 27, 2024
1 parent d7e315d commit c062b0b
Showing 1 changed file with 86 additions and 35 deletions.
121 changes: 86 additions & 35 deletions packages/relay/src/lib/clients/sdkClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ export class SDKClient {
fileId = await this.createFile(
ethereumTransactionData.callData,
this.clientMain,
requestId,
requestId ?? 'create-file-from-submit-ethereum-transaction',
callerName,
interactingEntity,
);
Expand Down Expand Up @@ -643,60 +643,111 @@ export class SDKClient {
private createFile = async (
callData: Uint8Array,
client: Client,
requestId?: string,
callerName?: string,
interactingEntity?: string,
requestId: string,
callerName: string,
interactingEntity: string,
) => {
const requestIdPrefix = formatRequestIdMessage(requestId);
const hexedCallData = Buffer.from(callData).toString('hex');
const currentDateNow = Date.now();
let createFileId;

const fileCreateTx = await new FileCreateTransaction()
.setContents(hexedCallData.substring(0, this.fileAppendChunkSize))
.setKeys(client.operatorPublicKey ? [client.operatorPublicKey] : []);
const fileCreateTxResponse = await fileCreateTx.execute(client);
const { fileId } = await fileCreateTxResponse.getReceipt(client);

const createFileRecord = await fileCreateTxResponse.getRecord(this.clientMain);
this.captureMetrics(
SDKClient.transactionMode,
fileCreateTx.constructor.name,
Status.Success,
createFileRecord.transactionFee.toTinybars().toNumber(),
createFileRecord?.contractFunctionResult?.gasUsed,
callerName,
interactingEntity,
);

if (fileId && callData.length > this.fileAppendChunkSize) {
const fileAppendTx = await new FileAppendTransaction()
.setFileId(fileId)
.setContents(hexedCallData.substring(this.fileAppendChunkSize, hexedCallData.length))
.setChunkSize(this.fileAppendChunkSize)
.setMaxChunks(this.maxChunks);
await fileAppendTx.execute(client);
try {
const shouldLimit = this.hbarLimiter.shouldLimit(currentDateNow, SDKClient.transactionMode, callerName);
if (shouldLimit) {
throw predefined.HBAR_RATE_LIMIT_EXCEEDED;
}
const fileCreateTxResponse = await fileCreateTx.execute(client);
const { fileId } = await fileCreateTxResponse.getReceipt(client);
createFileId = fileId;

const createFileRecord = await fileCreateTxResponse.getRecord(this.clientMain);
this.captureMetrics(
SDKClient.transactionMode,
fileAppendTx.constructor.name,
fileCreateTx.constructor.name,
Status.Success,
await this.calculateFileAppendTxTotalTinybarsCost(fileAppendTx),
0,
createFileRecord.transactionFee.toTinybars().toNumber(),
createFileRecord?.contractFunctionResult?.gasUsed,
callerName,
interactingEntity,
);
}

// Ensure that the calldata file is not empty
if (fileId) {
const fileSize = await (await new FileInfoQuery().setFileId(fileId).execute(client)).size;
if (fileId && callData.length > this.fileAppendChunkSize) {
const fileAppendTx = await new FileAppendTransaction()
.setFileId(fileId)
.setContents(hexedCallData.substring(this.fileAppendChunkSize, hexedCallData.length))
.setChunkSize(this.fileAppendChunkSize)
.setMaxChunks(this.maxChunks);
await fileAppendTx.execute(client);

this.captureMetrics(
SDKClient.transactionMode,
fileAppendTx.constructor.name,
Status.Success,
await this.calculateFileAppendTxTotalTinybarsCost(fileAppendTx),
0,
callerName,
interactingEntity,
);
}

// Ensure that the calldata file is not empty
if (fileId) {
const fileSize = await (await new FileInfoQuery().setFileId(fileId).execute(client)).size;

if (callData.length > 0 && fileSize.isZero()) {
throw new SDKClientError({}, `${requestIdPrefix} Created file is empty. `);
}
this.logger.trace(`${requestIdPrefix} Created file with fileId: ${fileId} and file size ${fileSize}`);
}
} catch (error: any) {
const sdkClientError = new SDKClientError(error, error.message);
let transactionFee: number | Hbar = 0;

// if valid network error utilize transaction id
if (sdkClientError.isValidNetworkError()) {
try {
const transactionRecord = await new TransactionRecordQuery()
.setTransactionId(fileCreateTx.transactionId!)
.setNodeAccountIds(fileCreateTx.nodeAccountIds!)
.setValidateReceiptStatus(false)
.execute(this.clientMain);
transactionFee = transactionRecord.transactionFee;

this.captureMetrics(
SDKClient.transactionMode,
fileCreateTx.constructor.name,
sdkClientError.status,
transactionFee.toTinybars().toNumber(),
transactionRecord?.contractFunctionResult?.gasUsed,
callerName,
interactingEntity,
);

this.hbarLimiter.addExpense(transactionFee.toTinybars().toNumber(), currentDateNow);
} catch (err: any) {
const recordQueryError = new SDKClientError(err, err.message);
this.logger.error(
recordQueryError,
`${requestIdPrefix} Error raised during TransactionRecordQuery for ${fileCreateTx.transactionId}`,
);
}
}

if (callData.length > 0 && fileSize.isZero()) {
throw new SDKClientError({}, `${requestIdPrefix} Created file is empty. `);
this.logger.trace(
`${requestIdPrefix} ${fileCreateTx.transactionId} ${callerName} ${fileCreateTx.constructor.name} status: ${sdkClientError.status} (${sdkClientError.status._code}), cost: ${transactionFee}`,
);
if (error instanceof JsonRpcError) {
throw predefined.HBAR_RATE_LIMIT_EXCEEDED;
}
this.logger.trace(`${requestIdPrefix} Created file with fileId: ${fileId} and file size ${fileSize}`);
throw sdkClientError;
}

return fileId;
return createFileId;
};

/**
Expand Down

0 comments on commit c062b0b

Please sign in to comment.