|
|
@@ -7,20 +7,22 @@ import {
|
|
|
} from "../interface";
|
|
|
import { DurationInSeconds } from "../utils";
|
|
|
import {
|
|
|
+ Msgs,
|
|
|
+ Account,
|
|
|
+ TxResponse,
|
|
|
+ PrivateKey,
|
|
|
+ TxGrpcApi,
|
|
|
ChainGrpcAuthApi,
|
|
|
ChainGrpcWasmApi,
|
|
|
MsgExecuteContract,
|
|
|
- Msgs,
|
|
|
- PrivateKey,
|
|
|
- TxGrpcClient,
|
|
|
- TxResponse,
|
|
|
createTransactionFromMsg,
|
|
|
} from "@injectivelabs/sdk-ts";
|
|
|
+import { splitArrayToChunks } from "@injectivelabs/utils";
|
|
|
import { Logger } from "pino";
|
|
|
-import { Account } from "@injectivelabs/sdk-ts/dist/cjs/client/chain/types/auth";
|
|
|
|
|
|
const DEFAULT_GAS_PRICE = 160000000;
|
|
|
const DEFAULT_GAS_MULTIPLIER = 1.05;
|
|
|
+const DEFAULT_PRICE_IDS_PROCESS_CHUNK_SIZE = -1;
|
|
|
const INJECTIVE_TESTNET_CHAIN_ID = "injective-888";
|
|
|
|
|
|
type PriceQueryResponse = {
|
|
|
@@ -90,6 +92,7 @@ type InjectiveConfig = {
|
|
|
chainId: string;
|
|
|
gasMultiplier: number;
|
|
|
gasPrice: number;
|
|
|
+ priceIdsProcessChunkSize: number;
|
|
|
};
|
|
|
export class InjectivePricePusher implements IPricePusher {
|
|
|
private wallet: PrivateKey;
|
|
|
@@ -110,6 +113,9 @@ export class InjectivePricePusher implements IPricePusher {
|
|
|
chainId: chainConfig?.chainId ?? INJECTIVE_TESTNET_CHAIN_ID,
|
|
|
gasMultiplier: chainConfig?.gasMultiplier ?? DEFAULT_GAS_MULTIPLIER,
|
|
|
gasPrice: chainConfig?.gasPrice ?? DEFAULT_GAS_PRICE,
|
|
|
+ priceIdsProcessChunkSize:
|
|
|
+ chainConfig?.priceIdsProcessChunkSize ??
|
|
|
+ DEFAULT_PRICE_IDS_PROCESS_CHUNK_SIZE,
|
|
|
};
|
|
|
}
|
|
|
|
|
|
@@ -119,6 +125,7 @@ export class InjectivePricePusher implements IPricePusher {
|
|
|
|
|
|
private async signAndBroadcastMsg(msg: Msgs): Promise<TxResponse> {
|
|
|
const chainGrpcAuthApi = new ChainGrpcAuthApi(this.grpcEndpoint);
|
|
|
+
|
|
|
// Fetch the latest account details only if it's not stored.
|
|
|
this.account ??= await chainGrpcAuthApi.fetchAccount(
|
|
|
this.injectiveAddress(),
|
|
|
@@ -132,7 +139,7 @@ export class InjectivePricePusher implements IPricePusher {
|
|
|
pubKey: this.wallet.toPublicKey().toBase64(),
|
|
|
});
|
|
|
|
|
|
- const txService = new TxGrpcClient(this.grpcEndpoint);
|
|
|
+ const txService = new TxGrpcApi(this.grpcEndpoint);
|
|
|
// simulation
|
|
|
try {
|
|
|
const {
|
|
|
@@ -207,12 +214,33 @@ export class InjectivePricePusher implements IPricePusher {
|
|
|
if (priceIds.length !== pubTimesToPush.length)
|
|
|
throw new Error("Invalid arguments");
|
|
|
|
|
|
+ const priceIdChunks =
|
|
|
+ this.chainConfig.priceIdsProcessChunkSize === -1
|
|
|
+ ? [priceIds]
|
|
|
+ : splitArrayToChunks({
|
|
|
+ array: priceIds,
|
|
|
+ chunkSize: this.chainConfig.priceIdsProcessChunkSize,
|
|
|
+ });
|
|
|
+
|
|
|
+ for (const [chunkIndex, priceIdChunk] of priceIdChunks.entries()) {
|
|
|
+ await this.updatePriceFeedChunk(priceIdChunk, chunkIndex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private async updatePriceFeedChunk(
|
|
|
+ priceIds: string[],
|
|
|
+ chunkIndex: number,
|
|
|
+ ): Promise<void> {
|
|
|
let priceFeedUpdateObject;
|
|
|
+
|
|
|
try {
|
|
|
// get the latest VAAs for updatePriceFeed and then push them
|
|
|
priceFeedUpdateObject = await this.getPriceFeedUpdateObject(priceIds);
|
|
|
} catch (err) {
|
|
|
- this.logger.error(err, "Error fetching the latest vaas to push");
|
|
|
+ this.logger.error(
|
|
|
+ err,
|
|
|
+ `Error fetching the latest vaas to push for chunk ${chunkIndex}`,
|
|
|
+ );
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -233,7 +261,10 @@ export class InjectivePricePusher implements IPricePusher {
|
|
|
const json = Buffer.from(data).toString();
|
|
|
updateFeeQueryResponse = JSON.parse(json);
|
|
|
} catch (err) {
|
|
|
- this.logger.error(err, "Error fetching update fee");
|
|
|
+ this.logger.error(
|
|
|
+ err,
|
|
|
+ `Error fetching update fee for chunk ${chunkIndex}`,
|
|
|
+ );
|
|
|
// Throwing an error because it is likely an RPC issue
|
|
|
throw err;
|
|
|
}
|
|
|
@@ -247,10 +278,13 @@ export class InjectivePricePusher implements IPricePusher {
|
|
|
});
|
|
|
|
|
|
const rs = await this.signAndBroadcastMsg(executeMsg);
|
|
|
- this.logger.info({ hash: rs.txHash }, "Succesfully broadcasted txHash");
|
|
|
+ this.logger.info(
|
|
|
+ { hash: rs.txHash },
|
|
|
+ `Successfully broadcasted txHash for chunk ${chunkIndex}`,
|
|
|
+ );
|
|
|
} catch (err: any) {
|
|
|
if (err.message.match(/account inj[a-zA-Z0-9]+ not found/) !== null) {
|
|
|
- this.logger.error(err, "Account not found");
|
|
|
+ this.logger.error(err, `Account not found for chunk ${chunkIndex}`);
|
|
|
throw new Error("Please check the mnemonic");
|
|
|
}
|
|
|
|
|
|
@@ -258,10 +292,13 @@ export class InjectivePricePusher implements IPricePusher {
|
|
|
err.message.match(/insufficient/) !== null &&
|
|
|
err.message.match(/funds/) !== null
|
|
|
) {
|
|
|
- this.logger.error(err, "Insufficient funds");
|
|
|
+ this.logger.error(err, `Insufficient funds for chunk ${chunkIndex}`);
|
|
|
throw new Error("Insufficient funds");
|
|
|
}
|
|
|
- this.logger.error(err, "Error executing messages");
|
|
|
+ this.logger.error(
|
|
|
+ err,
|
|
|
+ `Error executing messages for chunk ${chunkIndex}`,
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
}
|