@hiero-ledger/sdk
Version:
366 lines (365 loc) • 11.6 kB
TypeScript
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";