@gear-js/api
Version:
A JavaScript library that provides functionality to connect GEAR Component APIs.
296 lines (292 loc) • 11.8 kB
JavaScript
;
var util = require('@polkadot/util');
const REPLY_CODE_LENGTH = 4;
function padTo4Bytes(input) {
const res = new Uint8Array(REPLY_CODE_LENGTH);
res.set(input, 0);
return res;
}
function checkAndGetCodeBytes(code, prevByteValue, prevBytePosition) {
if (code.length < REPLY_CODE_LENGTH) {
code = padTo4Bytes(code);
}
else if (code.length > REPLY_CODE_LENGTH) {
code = code.slice(0, REPLY_CODE_LENGTH);
}
if (prevByteValue != null && code[prevBytePosition] !== prevByteValue) {
throw new Error('Invalid byte sequence');
}
return code;
}
exports.EReplyCode = void 0;
(function (EReplyCode) {
EReplyCode[EReplyCode["Success"] = 0] = "Success";
EReplyCode[EReplyCode["Error"] = 1] = "Error";
})(exports.EReplyCode || (exports.EReplyCode = {}));
/**
* # Reply Code decoder
* @param codeBytes reply code
* @param _specVersion spec version of the Gear runtime
*/
class ReplyCode {
_specVersion;
_bytes;
constructor(codeBytes, _specVersion) {
this._specVersion = _specVersion;
this._bytes = checkAndGetCodeBytes(util.u8aToU8a(codeBytes));
if (this._bytes.length !== 4) {
throw new Error('Invalid message reply code length');
}
if (this._bytes[0] === 255) {
throw new Error('Unsupported message reply code');
}
}
get isSuccess() {
return this._bytes[0] === exports.EReplyCode.Success;
}
get isError() {
return this._bytes[0] === exports.EReplyCode.Error;
}
get successReason() {
return new SuccessReplyReason(this._bytes);
}
get errorReason() {
return new ErrorReplyReason(this._bytes, this._specVersion);
}
get asString() {
return this.isSuccess ? this.successReason.explanation : this.errorReason.explanation;
}
}
exports.ESuccessReply = void 0;
(function (ESuccessReply) {
ESuccessReply[ESuccessReply["Auto"] = 0] = "Auto";
ESuccessReply[ESuccessReply["Manual"] = 1] = "Manual";
})(exports.ESuccessReply || (exports.ESuccessReply = {}));
/**
* # Success reply reason.
*/
class SuccessReplyReason {
_bytes;
constructor(bytes) {
this._bytes = checkAndGetCodeBytes(bytes, exports.EReplyCode.Success, 0);
}
get explanation() {
switch (this._bytes[1]) {
case exports.ESuccessReply.Auto: {
return 'Success reply was created by system automatically.';
}
case exports.ESuccessReply.Manual: {
return 'Success reply was created by actor manually.';
}
default: {
throw new Error('Unsupported reason of success reply.');
}
}
}
get isAuto() {
return this._bytes[1] === exports.ESuccessReply.Auto;
}
get isManual() {
return this._bytes[1] === exports.ESuccessReply.Manual;
}
}
var EErrorReplyReason;
(function (EErrorReplyReason) {
EErrorReplyReason[EErrorReplyReason["Execution"] = 0] = "Execution";
EErrorReplyReason[EErrorReplyReason["FailedToCreateProgram"] = 1] = "FailedToCreateProgram";
EErrorReplyReason[EErrorReplyReason["UnavailableActor"] = 2] = "UnavailableActor";
EErrorReplyReason[EErrorReplyReason["RemovedFromWaitlist"] = 3] = "RemovedFromWaitlist";
EErrorReplyReason[EErrorReplyReason["ReinstrumentationFailure"] = 4] = "ReinstrumentationFailure";
})(EErrorReplyReason || (EErrorReplyReason = {}));
/**
* # Error reply reason
*/
class ErrorReplyReason {
_specVersion;
_bytes;
constructor(bytes, _specVersion) {
this._specVersion = _specVersion;
this._bytes = checkAndGetCodeBytes(bytes, exports.EReplyCode.Error, 0);
}
_throwUnsupported() {
throw new Error('Unsupported reason of error reply.');
}
get explanation() {
switch (this._bytes[1]) {
case EErrorReplyReason.Execution: {
return `Error reply was created due to underlying execution error. Reason: ${this.executionReason.explanation}`;
}
case EErrorReplyReason.FailedToCreateProgram: {
if (this._specVersion && this._specVersion < 1800) {
return 'Failed to create program.';
}
this._throwUnsupported();
break;
}
case EErrorReplyReason.UnavailableActor: {
return `Destination actor is unavailable, so it can't process the message. Reason: ${this.unavailableActorReason.explanation}`;
}
case EErrorReplyReason.RemovedFromWaitlist: {
return 'Message has died in Waitlist as out of rent one.';
}
case EErrorReplyReason.ReinstrumentationFailure: {
if (this._specVersion && this._specVersion < 1800) {
return 'Reinstrumentation failed.';
}
// falls through
}
default: {
this._throwUnsupported();
break;
}
}
// not reached — _throwUnsupported() always throws
return this._bytes[1].toString();
}
get isExecution() {
return this._bytes[1] === EErrorReplyReason.Execution;
}
get executionReason() {
return new ExecutionErrorReason(this._bytes);
}
/** This option is available only for spec versions before 1800 */
get isFailedToCreateProgram() {
return this._specVersion && this._specVersion < 1800 && this._bytes[1] === EErrorReplyReason.FailedToCreateProgram;
}
get isUnavailableActor() {
return this._bytes[1] === EErrorReplyReason.UnavailableActor;
}
get unavailableActorReason() {
return new UnavailableActorErrorReason(this._bytes);
}
get isRemovedFromWaitlist() {
return this._bytes[1] === EErrorReplyReason.RemovedFromWaitlist;
}
/** This option is available only for spec versions before 1800 */
get isReinstrumentationFailure() {
return (this._specVersion && this._specVersion < 1800 && this._bytes[1] === EErrorReplyReason.ReinstrumentationFailure);
}
}
exports.ESimpleExecutionError = void 0;
(function (ESimpleExecutionError) {
ESimpleExecutionError[ESimpleExecutionError["RanOutOfGas"] = 0] = "RanOutOfGas";
ESimpleExecutionError[ESimpleExecutionError["MemoryOverflow"] = 1] = "MemoryOverflow";
ESimpleExecutionError[ESimpleExecutionError["BackendError"] = 2] = "BackendError";
ESimpleExecutionError[ESimpleExecutionError["UserspacePanic"] = 3] = "UserspacePanic";
ESimpleExecutionError[ESimpleExecutionError["UnreachableInstruction"] = 4] = "UnreachableInstruction";
ESimpleExecutionError[ESimpleExecutionError["StackLimitExceeded"] = 5] = "StackLimitExceeded";
})(exports.ESimpleExecutionError || (exports.ESimpleExecutionError = {}));
/**
* # Execution error reason
*/
class ExecutionErrorReason {
_bytes;
constructor(bytes) {
this._bytes = checkAndGetCodeBytes(bytes, EErrorReplyReason.Execution, 1);
}
get explanation() {
switch (this._bytes[2]) {
case exports.ESimpleExecutionError.RanOutOfGas: {
return 'Message ran out of gas while executing.';
}
case exports.ESimpleExecutionError.MemoryOverflow: {
return 'Program has reached memory limit while executing.';
}
case exports.ESimpleExecutionError.BackendError: {
return "Execution failed with backend error that couldn't been caught.";
}
case exports.ESimpleExecutionError.UserspacePanic: {
return 'Execution failed with userspace panic.';
}
case exports.ESimpleExecutionError.UnreachableInstruction: {
return 'Execution failed with `unreachable` instruction call.';
}
case exports.ESimpleExecutionError.StackLimitExceeded: {
return 'Program reached stack limit.';
}
default: {
throw new Error('Unsupported reason of execution error');
}
}
}
get isRanOutOfGas() {
return this._bytes[2] === exports.ESimpleExecutionError.RanOutOfGas;
}
get isMemoryOverflow() {
return this._bytes[2] === exports.ESimpleExecutionError.MemoryOverflow;
}
get isBackendError() {
return this._bytes[2] === exports.ESimpleExecutionError.BackendError;
}
get isUserspacePanic() {
return this._bytes[2] === exports.ESimpleExecutionError.UserspacePanic;
}
get isUnreachableInstruction() {
return this._bytes[2] === exports.ESimpleExecutionError.UnreachableInstruction;
}
get isStackLimitExceeded() {
return this._bytes[2] === exports.ESimpleExecutionError.StackLimitExceeded;
}
}
exports.ESimpleUnavailableActorError = void 0;
(function (ESimpleUnavailableActorError) {
ESimpleUnavailableActorError[ESimpleUnavailableActorError["ProgramExited"] = 0] = "ProgramExited";
ESimpleUnavailableActorError[ESimpleUnavailableActorError["InitializationFailure"] = 1] = "InitializationFailure";
ESimpleUnavailableActorError[ESimpleUnavailableActorError["Uninitialized"] = 2] = "Uninitialized";
ESimpleUnavailableActorError[ESimpleUnavailableActorError["ProgramNotCreated"] = 3] = "ProgramNotCreated";
ESimpleUnavailableActorError[ESimpleUnavailableActorError["ReinstrumentationFailure"] = 4] = "ReinstrumentationFailure";
})(exports.ESimpleUnavailableActorError || (exports.ESimpleUnavailableActorError = {}));
class UnavailableActorErrorReason {
_bytes;
constructor(bytes) {
this._bytes = checkAndGetCodeBytes(bytes, EErrorReplyReason.UnavailableActor, 1);
}
_throwUnsupported() {
throw new Error('Unsupported reason of inactive actor error.');
}
get explanation() {
switch (this._bytes[2]) {
case exports.ESimpleUnavailableActorError.ProgramExited: {
return 'Program called `gr_exit` syscall.';
}
case exports.ESimpleUnavailableActorError.InitializationFailure: {
return 'Program was terminated due to failed initialization.';
}
case exports.ESimpleUnavailableActorError.Uninitialized: {
return 'Program is not initialized yet.';
}
case exports.ESimpleUnavailableActorError.ProgramNotCreated: {
return 'Program was not created.';
}
case exports.ESimpleUnavailableActorError.ReinstrumentationFailure: {
return 'Program re-instrumentation failed.';
}
default: {
this._throwUnsupported();
break;
}
}
// not reached — _throwUnsupported() always throws
return this._bytes[2].toString();
}
get isProgramExited() {
return this._bytes[2] === exports.ESimpleUnavailableActorError.ProgramExited;
}
get isInitializationFailure() {
return this._bytes[2] === exports.ESimpleUnavailableActorError.InitializationFailure;
}
get isUninitialized() {
return this._bytes[2] === exports.ESimpleUnavailableActorError.Uninitialized;
}
get isProgramNotCreated() {
return this._bytes[2] === exports.ESimpleUnavailableActorError.ProgramNotCreated;
}
get isReinstrumentationFailure() {
return this._bytes[2] === exports.ESimpleUnavailableActorError.ReinstrumentationFailure;
}
}
exports.ErrorReplyReason = ErrorReplyReason;
exports.ExecutionErrorReason = ExecutionErrorReason;
exports.ReplyCode = ReplyCode;
exports.SuccessReplyReason = SuccessReplyReason;
exports.UnavailableActorErrorReason = UnavailableActorErrorReason;