UNPKG

@hiero-ledger/sdk

Version:
366 lines (365 loc) 11.6 kB
export type ExecutionState = string; export namespace ExecutionState { let Finished: string; let Retry: string; let Error: string; } export const RST_STREAM: RegExp; export const DEFAULT_MAX_ATTEMPTS: 10; /** * @abstract * @internal * @template RequestT * @template ResponseT * @template OutputT */ export default class Executable<RequestT, ResponseT, OutputT> { /** * The number of times we can retry the grpc call * * @internal * @type {number} */ _maxAttempts: number; /** * List of node account IDs for each transaction that has been * built. * * @internal * @type {List<AccountId>} */ _nodeAccountIds: List<AccountId>; /** * List of the transaction node account IDs to check if * the node account ID of the request is in the list * * @protected * @type {Array<string>} */ protected transactionNodeIds: Array<string>; /** * @internal */ _signOnDemand: boolean; /** * This is the request's min backoff * * @internal * @type {number | null} */ _minBackoff: number | null; /** * This is the request's max backoff * * @internal * @type {number} */ _maxBackoff: number; /** * The operator that was used to execute this request. * The reason we save the operator in the request is because of the signing on * demand feature. This feature requires us to sign new request on each attempt * meaning if a client with an operator was used we'd need to sign with the operator * on each attempt. * * @internal * @type {ClientOperator | null} */ _operator: ClientOperator | null; /** * The complete timeout for running the `execute()` method * * @internal * @type {number | null} */ _requestTimeout: number | null; /** * The grpc request timeout aka deadline. * * The reason we have this is because there were times that consensus nodes held the grpc * connection, but didn't return anything; not error nor regular response. This resulted * in some weird behavior in the SDKs. To fix this we've added a grpc deadline to prevent * nodes from stalling the executing of a request. * * @internal * @type {number | null} */ _grpcDeadline: number | null; /** * Logger * * @protected * @type {Logger | null} */ protected _logger: Logger | null; /** * Get the list of node account IDs on the request. If no nodes are set, then null is returned. * The reasoning for this is simply "legacy behavior". * * @returns {?AccountId[]} */ get nodeAccountIds(): AccountId[] | null; /** * Set the node account IDs on the request * * @param {AccountId[]} nodeIds * @returns {this} */ setNodeAccountIds(nodeIds: AccountId[]): this; /** * @deprecated * @returns {number} */ get maxRetries(): number; /** * @param {number} maxRetries * @returns {this} */ setMaxRetries(maxRetries: number): this; /** * Get the max attempts on the request * * @returns {number} */ get maxAttempts(): number; /** * Set the max attempts on the request * * @param {number} maxAttempts * @returns {this} */ setMaxAttempts(maxAttempts: number): this; /** * Get the grpc deadline * * @returns {?number} */ get grpcDeadline(): number | null; /** * Set the grpc deadline * * @param {number} grpcDeadline * @returns {this} */ setGrpcDeadline(grpcDeadline: number): this; /** * Set the min backoff for the request * * @param {number} minBackoff * @returns {this} */ setMinBackoff(minBackoff: number): this; /** * Get the min backoff * * @returns {number | null} */ get minBackoff(): number | null; /** * Set the max backoff for the request * * @param {?number} maxBackoff * @returns {this} */ setMaxBackoff(maxBackoff: number | null): this; /** * Get the max backoff * * @returns {number} */ get maxBackoff(): number; /** * This method is responsible for doing any work before the executing process begins. * For paid queries this will result in executing a cost query, for transactions this * will make sure we save the operator and sign any requests that need to be signed * in case signing on demand is disabled. * * @abstract * @protected * @param {import("./client/Client.js").default<Channel, *>} client * @returns {Promise<void>} */ protected _beforeExecute(client: import("./client/Client.js").default<Channel, any>): Promise<void>; /** * Create a protobuf request which will be passed into the `_execute()` method * * @abstract * @protected * @returns {Promise<RequestT>} */ protected _makeRequestAsync(): Promise<RequestT>; /** * This name is a bit wrong now, but the purpose of this method is to map the * request and response into an error. This method will only be called when * `_shouldRetry` returned `ExecutionState.Error` * * @abstract * @internal * @param {RequestT} request * @param {ResponseT} response * @param {AccountId} nodeId * @returns {Error} */ _mapStatusError(request: RequestT, response: ResponseT, nodeId: AccountId): Error; /** * Map the request, response, and the node account ID used for this attempt into a response. * This method will only be called when `_shouldRetry` returned `ExecutionState.Finished` * * @abstract * @protected * @param {ResponseT} response * @param {AccountId} nodeAccountId * @param {RequestT} request * @returns {Promise<OutputT>} */ protected _mapResponse(response: ResponseT, nodeAccountId: AccountId, request: RequestT): Promise<OutputT>; /** * Perform a single grpc call with the given request. Each request has it's own * required service so we just pass in channel, and it'$ the request's responsiblity * to use the right service and call the right grpc method. * * @abstract * @internal * @param {Channel} channel * @param {RequestT} request * @returns {Promise<ResponseT>} */ _execute(channel: Channel, request: RequestT): Promise<ResponseT>; /** * Return the current transaction ID for the request. All requests which are * use the same transaction ID for each node, but the catch is that `Transaction` * implicitly supports chunked transactions. Meaning there could be multiple * transaction IDs stored in the request, and a different transaction ID will be used * on subsequent calls to `execute()` * * FIXME: This method can most likely be removed, although some further inspection * is required. * * @abstract * @protected * @returns {TransactionId} */ protected _getTransactionId(): TransactionId; /** * Return the log ID for this particular request * * Log IDs are simply a string constructed to make it easy to track each request's * execution even when mulitple requests are executing in parallel. Typically, this * method returns the format of `[<request type>.<timestamp of the transaction ID>]` * * Maybe we should deduplicate this using ${this.consturtor.name} * * @abstract * @internal * @returns {string} */ _getLogId(): string; /** * Serialize the request into bytes * * @abstract * @param {RequestT} request * @returns {Uint8Array} */ _requestToBytes(request: RequestT): Uint8Array; /** * Serialize the response into bytes * * @abstract * @param {ResponseT} response * @returns {Uint8Array} */ _responseToBytes(response: ResponseT): Uint8Array; /** * Determine if we should continue the execution process, error, or finish. * * FIXME: This method should really be called something else. Initially it returned * a boolean so `shouldRetry` made sense, but now it returns an enum, so the name * no longer makes sense. * * @abstract * @protected * @param {RequestT} request * @param {ResponseT} response * @returns {[Status, ExecutionState]} */ protected _shouldRetry(request: RequestT, response: ResponseT): [Status, ExecutionState]; /** * Determine if we should error based on the gRPC status * * Unlike `shouldRetry` this method does in fact still return a boolean * * @protected * @param {Error} error * @returns {boolean} */ protected _shouldRetryExceptionally(error: Error): boolean; /** * A helper method for setting the operator on the request * * @internal * @param {AccountId} accountId * @param {PublicKey} publicKey * @param {(message: Uint8Array) => Promise<Uint8Array>} transactionSigner * @returns {this} */ _setOperatorWith(accountId: AccountId, publicKey: PublicKey, transactionSigner: (message: Uint8Array) => Promise<Uint8Array>): this; /** * Execute this request using the signer * * This method is part of the signature providers feature * https://hips.hedera.com/hip/hip-338 * * @param {Signer} signer * @returns {Promise<OutputT>} */ executeWithSigner(signer: Signer): Promise<OutputT>; /** * @returns {boolean} * @abstract * @protected */ protected isBatchedAndNotBatchTransaction(): boolean; /** * Execute the request using a client and an optional request timeout * * @template {Channel} ChannelT * @template {MirrorChannel} MirrorChannelT * @param {import("./client/Client.js").default<ChannelT, MirrorChannelT>} client * @param {number=} requestTimeout * @returns {Promise<OutputT>} */ execute<ChannelT extends Channel, MirrorChannelT extends MirrorChannel>(client: import("./client/Client.js").default<ChannelT, MirrorChannelT>, requestTimeout?: number | undefined): Promise<OutputT>; /** * The current purpose of this method is to easily support signature providers since * signature providers need to serialize _any_ request into bytes. `Query` and `Transaction` * already implement `toBytes()` so it only made sense to make it available here too. * * @abstract * @returns {Uint8Array} */ toBytes(): Uint8Array; /** * Set logger * * @param {Logger} logger * @returns {this} */ setLogger(logger: Logger): this; /** * Get logger if set * * @returns {?Logger} */ get logger(): Logger | null; } export type AccountId = import("./account/AccountId.js").default; export type Channel = import("./channel/Channel.js").default; export type MirrorChannel = import("./channel/MirrorChannel.js").default; export type TransactionId = import("./transaction/TransactionId.js").default; export type ClientOperator = import("./client/Client.js").ClientOperator; export type Signer = import("./Signer.js").Signer; export type PublicKey = import("./PublicKey.js").default; export type Logger = import("./logger/Logger.js").default; import List from "./transaction/List.js"; import Status from "./Status.js";