Skip to content
This repository has been archived by the owner on Jul 12, 2022. It is now read-only.

feat!: convenient broadcast errors #266

Merged
merged 5 commits into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DRIVE_BRANCH=feat/grpc-error-codes
DAPI_BRANCH=error-codes
DASHMATE_BRANCH=error-codes
TEST_SUITE_BRANCH=error-codes
DRIVE_BRANCH=bring-back-drive-errors
DAPI_BRANCH=send-metadata-buffer
DASHMATE_BRANCH=convenient-errors
TEST_SUITE_BRANCH=convenient-errors
219 changes: 102 additions & 117 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@
},
"homepage": "https://github.com/dashevo/DashJS#readme",
"dependencies": {
"@dashevo/dapi-client": "~0.21.0-dev.7",
"@dashevo/dapi-client": "~0.21.0-dev.9",
"@dashevo/dashcore-lib": "~0.19.25",
"@dashevo/dpp": "~0.21.0-dev.4",
"@dashevo/wallet-lib": "~7.21.0-dev.6",
"@dashevo/grpc-common": "~0.5.0",
"@dashevo/wallet-lib": "~7.21.0-dev.7",
"bs58": "^4.0.1",
"node-inspect-extracted": "1.0.7"
},
Expand Down
4 changes: 0 additions & 4 deletions src/SDK/Client/Client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ describe('Dash - Client', function suite() {
expect(error).to.be.an.instanceOf(StateTransitionBroadcastError);
expect(error.getCode()).to.be.equal(errorResponse.error.code);
expect(error.getMessage()).to.be.equal(errorResponse.error.message);
expect(error.getData()).to.be.equal(errorResponse.error.data);

const importedIdentityIds = account.identities.getIdentityIds();
// Check that no identities were imported
Expand Down Expand Up @@ -226,7 +225,6 @@ describe('Dash - Client', function suite() {
expect(error).to.be.an.instanceOf(StateTransitionBroadcastError);
expect(error.getCode()).to.be.equal(errorResponse.error.code);
expect(error.getMessage()).to.be.equal(errorResponse.error.message);
expect(error.getData()).to.be.equal(errorResponse.error.data);
});
});

Expand Down Expand Up @@ -254,7 +252,6 @@ describe('Dash - Client', function suite() {
expect(error).to.be.an.instanceOf(StateTransitionBroadcastError);
expect(error.getCode()).to.be.equal(errorResponse.error.code);
expect(error.getMessage()).to.be.equal(errorResponse.error.message);
expect(error.getData()).to.be.equal(errorResponse.error.data);
});

it('should broadcast documents', async () => {
Expand Down Expand Up @@ -303,7 +300,6 @@ describe('Dash - Client', function suite() {
expect(error).to.be.an.instanceOf(StateTransitionBroadcastError);
expect(error.getCode()).to.be.equal(errorResponse.error.code);
expect(error.getMessage()).to.be.equal(errorResponse.error.message);
expect(error.getData()).to.be.equal(errorResponse.error.data);
});

it('should broadcast data contract', async () => {
Expand Down
76 changes: 44 additions & 32 deletions src/SDK/Client/Platform/broadcastStateTransition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import { StateTransitionBroadcastError } from "../../../errors/StateTransitionBr
import { IStateTransitionResult } from "./IStateTransitionResult";
import { IPlatformStateProof } from "./IPlatformStateProof";

const ResponseError = require('@dashevo/dapi-client/lib/transport/errors/response/ResponseError');
const InvalidRequestDPPError = require('@dashevo/dapi-client/lib/transport/errors/response/InvalidRequestDPPError');

const createGrpcTransportError = require('@dashevo/dapi-client/lib/transport/GrpcTransport/createGrpcTransportError');

const GrpcError = require('@dashevo/grpc-common/lib/server/error/GrpcError');

/**
* @param {Platform} platform
* @param stateTransition
Expand All @@ -14,7 +21,13 @@ export default async function broadcastStateTransition(platform: Platform, state
const result = await dpp.stateTransition.validateBasic(stateTransition);

if (!result.isValid()) {
throw new Error(`StateTransition is invalid - ${JSON.stringify(result.getErrors())}`);
const consensusError = result.getFirstError();

throw new StateTransitionBroadcastError(
consensusError.getCode(),
consensusError.message,
consensusError,
);
}

// Subscribing to future result
Expand All @@ -26,40 +39,24 @@ export default async function broadcastStateTransition(platform: Platform, state

try {
await client.getDAPIClient().platform.broadcastStateTransition(serializedStateTransition);
} catch (e) {
let data;
let message;

if (e.data) {
data = e.data;
} else if (e.metadata) {
// Due to an unknown bug in the minifier, `get` method of the metadata can be stripped off.
// See the comment in the 'else' branch for more details
if (typeof e.metadata.get === 'function') {
const errors = e.metadata.get('errors');
data = {};
data.errors = errors && errors.length > 0 ? JSON.parse(errors) : errors;
} else {
// This code can be executed only if deserialization failed and no errors
// were provided in the metadata, so we can deserialize here again
// and see the details locally
try {
await dpp.stateTransition.createFromBuffer(serializedStateTransition);
} catch (deserializationError) {
data = {};
data.errors = deserializationError.errors;
data.rawStateTransition = deserializationError.rawStateTransition;
}
} catch (error) {
if (error instanceof ResponseError) {
let cause = error;

// Pass DPP consensus error directly to avoid
// additional wrappers
if (cause instanceof InvalidRequestDPPError) {
cause = cause.getConsensusError();
}
}

if (e.details) {
message = e.details;
} else {
message = e.message;
throw new StateTransitionBroadcastError(
cause.getCode(),
cause.message,
cause,
);
}

throw new StateTransitionBroadcastError(e.code, message, data);
throw error;
}

// Waiting for result to return
Expand All @@ -68,7 +65,22 @@ export default async function broadcastStateTransition(platform: Platform, state
let { error } = stateTransitionResult;

if (error) {
throw new StateTransitionBroadcastError(error.code, error.message, error.data);
// Create DAPI response error from gRPC error passed as gRPC response
const grpcError = new GrpcError(error.code, error.message, error.data);

let cause = createGrpcTransportError(grpcError);

// Pass DPP consensus error directly to avoid
// additional wrappers
if (cause instanceof InvalidRequestDPPError) {
cause = cause.getConsensusError();
}

throw new StateTransitionBroadcastError(
cause.getCode(),
cause.message,
cause,
);
}

return stateTransitionResult.proof;
Expand Down
2 changes: 1 addition & 1 deletion src/SDK/Client/Platform/methods/contracts/get.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Identifier from "@dashevo/dpp/lib/Identifier";
import 'mocha';
import { ClientApps } from "../../../ClientApps";
const GetDataContractResponse = require("@dashevo/dapi-client/lib/methods/platform/getDataContract/GetDataContractResponse");
const NotFoundError = require('@dashevo/dapi-client/lib/errors/response/NotFoundError');
const NotFoundError = require('@dashevo/dapi-client/lib/transport/GrpcTransport/errors/NotFoundError');

const factory = new DataContractFactory(
undefined,
Expand Down
2 changes: 1 addition & 1 deletion src/SDK/Client/Platform/methods/contracts/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Platform} from "../../Platform";
// @ts-ignore
import Identifier from "@dashevo/dpp/lib/Identifier";
import Metadata from "@dashevo/dpp/lib/Metadata";
const NotFoundError = require('@dashevo/dapi-client/lib/errors/response/NotFoundError');
const NotFoundError = require('@dashevo/dapi-client/lib/transport/GrpcTransport/errors/NotFoundError');

declare type ContractIdentifier = string | Identifier;

Expand Down
2 changes: 1 addition & 1 deletion src/SDK/Client/Platform/methods/identities/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {Platform} from "../../Platform";
// @ts-ignore
import Identifier from "@dashevo/dpp/lib/Identifier";
import Metadata from "@dashevo/dpp/lib/Metadata";
const NotFoundError = require('@dashevo/dapi-client/lib/errors/response/NotFoundError');
const NotFoundError = require('@dashevo/dapi-client/lib/transport/GrpcTransport/errors/NotFoundError');

/**
* Get an identity from the platform
Expand Down
33 changes: 10 additions & 23 deletions src/errors/StateTransitionBroadcastError.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,19 @@
export class StateTransitionBroadcastError extends Error {
code: number;
message: string;
data: any;
cause: Error;

/**
*
* @param {number} code
* @param {string} message
* @param {*} data
* @param {Error} cause
*/
constructor(code: number, message: string, data: any) {
let detailedMessage = message;

if (data && data.errors && data.errors.length > 0) {
const [firstError] = data.errors;

detailedMessage += `: ${firstError.name}: ${firstError.message}`;

if (data.errors.length > 1) {
detailedMessage += ` and ${data.errors.length} more`;
}
}

super(detailedMessage);
constructor(code: number, message: string, cause: Error) {
super(message);

this.code = code;
this.message = detailedMessage;
this.data = data;
this.message = message;
this.cause = cause;

if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
Expand Down Expand Up @@ -54,11 +41,11 @@ export class StateTransitionBroadcastError extends Error {
}

/**
* Get error data
* Get error that was a cause
*
* @return {*}
* @return {Error}
*/
getData(): any {
return this.data;
getCause(): any {
return this.cause;
}
}