Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build(deps): upgrade to TS 4.4 test-plugin-ledger-connector-besu #1747

Closed
petermetz opened this issue Jan 10, 2022 · 3 comments
Closed

build(deps): upgrade to TS 4.4 test-plugin-ledger-connector-besu #1747

petermetz opened this issue Jan 10, 2022 · 3 comments
Assignees
Labels
dependencies Pull requests that update a dependency file Developer_Experience good-first-issue Good for newcomers good-first-issue-200-intermediate Hacktoberfest Hacktoberfest participants are welcome to take a stab at issues marked with this label. Nice-to-Have P4 Priority 4: Low
Milestone

Comments

@petermetz
Copy link
Member

No description provided.

@petermetz petermetz added good-first-issue Good for newcomers Nice-to-Have dependencies Pull requests that update a dependency file Developer_Experience Hacktoberfest Hacktoberfest participants are welcome to take a stab at issues marked with this label. good-first-issue-200-intermediate P4 Priority 4: Low labels Jan 10, 2022
Leeyoungone added a commit to Leeyoungone/cactus that referenced this issue Jan 11, 2022
Fixes hyperledger#1747

Signed-off-by: Youngone Lee <youngone.lee@accenture.com>
Leeyoungone added a commit to Leeyoungone/cactus that referenced this issue Jan 13, 2022
Fixes hyperledger#1747

Signed-off-by: Youngone Lee <youngone.lee@accenture.com>
Leeyoungone added a commit to Leeyoungone/cactus that referenced this issue Jan 14, 2022
Fixes hyperledger#1747

Signed-off-by: Youngone Lee <youngone.lee@accenture.com>
Leeyoungone added a commit to Leeyoungone/cactus that referenced this issue Jan 14, 2022
Fixes hyperledger#1747

Signed-off-by: Youngone Lee <youngone.lee@accenture.com>
@Leeyoungone Leeyoungone self-assigned this Jan 14, 2022
@arnabnandikgp
Copy link
Contributor

I am new to cacti and wanted to make some beginner level contributions to the project, but all these similar issues related to 'upgrading to ts 4.4' seem to be worked upon but stalled simultaneously for some reason, is their any problem related to these issues or is everything's just ok?

@petermetz
Copy link
Member Author

I am new to cacti and wanted to make some beginner level contributions to the project, but all these similar issues related to 'upgrading to ts 4.4' seem to be worked upon but stalled simultaneously for some reason, is their any problem related to these issues or is everything's just ok?

@arnabnandikgp Hi and sorry for the very slow response!
Yeah all of these were dependent on us having some utility functions available for convenient error handling patterns. Nowadays these are available so my plan is to solve one of these bugs just as an example on how the rest could be done as well (it's relatively straightforward once you see the patterns that need applying so please stay tuned for more if you are still interested in working on one of these)

@petermetz petermetz added this to the v2.0.0 milestone Oct 18, 2023
@petermetz petermetz self-assigned this Oct 18, 2023
petermetz added a commit to petermetz/cacti that referenced this issue Oct 18, 2023
WORK IN PROGRESS

Fixes hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
petermetz added a commit to petermetz/cacti that referenced this issue Oct 18, 2023
WORK IN PROGRESS

Fixes hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
petermetz added a commit to petermetz/cacti that referenced this issue Nov 6, 2023
WORK IN PROGRESS

Fixes hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
petermetz added a commit to petermetz/cacti that referenced this issue Nov 9, 2023
1. This is a function that is designed to be called by all the REST API
endpoint implementations to (more) correctly handle errors.
2. The problem right now is that we do not differentiate between invalid
request errors (e.g. expected exceptions) vs.
legitimate crashes (e.g. unexpected exceptions)
What the above means is that a lot of our endpoints will crash with an
HTTP 500 error code returned to the client even if the problem as user-
error (such as a missing parameter that is mandatory).
3. With the new utility function the REST endpoint code can easily
apply the decision logic at runtime in their own catch blocks' and
set the HTTP response status code based on the information (context)
provided by the callee (most often the connector plugin's underlying
method that was called)

An example usage of this utility method can be described as:
1. Add the necessary dependencies to your plugin (`http-errors`, `@types/http-errors`)
2. `yarn install` (which will update the lock file)
3. Choose the endpoint you wish to update to be using the new handleRestEndpointException
function internally when handling HTTP requests that involve the plugin.
For example this file:
```
packages/cactus-plugin-ledger-connector-besu/src/main/typescript/
web-services/deploy-contract-solidity-bytecode-endpoint.ts
```
4. Update the `catch() { ... }` block of the `handleRequest` method to
invoke the handleRestEndpointException method:

```typescript
public async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = `${this.className}#handleRequest()`;
const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`;
this.log.debug(reqTag);
const reqBody: DeployContractSolidityBytecodeV1Request = req.body;
try {
    const resBody = await this.options.connector.deployContract(reqBody);
    res.json(resBody);
} catch (ex) {
    const errorMsg = `${reqTag} ${fnTag} Failed to deploy contract:`;
    handleRestEndpointException({ errorMsg, log: this.log, error: ex, res });
}
}
```

Then proceed to also update the implementation of the method that is  being
called by the REST endpoint request handler such that it uses the HTTP
errors according to their intended status codes, e.g. 400 is user error
and 5xx is something that is a developer error (e.g. indicating that
a bug is in the code of the plugin and should be fixed)

```typescript
import createHttpError from "http-errors";

export class SomePluginImplementration {

  public async deployContract(
    req: DeployContractSolidityBytecodeV1Request,
  ): Promise<DeployContractSolidityBytecodeV1Response> {
    const fnTag = `${this.className}#deployContract()`;
    Checks.truthy(req, `${fnTag} req`);
    if (isWeb3SigningCredentialNone(req.web3SigningCredential)) {
      throw createHttpError[400](
        `${fnTag} Cannot deploy contract with pre-signed TX`,
      );
    }
    const { keychainId, contractName } = req;
    if (!keychainId || !req.contractName) {
      const errorMessage = `${fnTag} Cannot deploy contract without keychainId and the contractName.`;
      throw createHttpError[400](errorMessage);
    }

    const keychainPlugin = this.pluginRegistry.findOneByKeychainId(keychainId);

    if (!keychainPlugin) {
      const errorMessage =
        `${fnTag} The plugin registry does not contain` +
        ` a keychain plugin for ID:"${req.keychainId}"`;
      throw createHttpError[400](errorMessage);
    }

    if (!keychainPlugin.has(contractName)) {
      const errorMessage =
        `${fnTag} Cannot create an instance of the contract instance because` +
        `the contractName in the request does not exist on the keychain`;
      throw new createHttpError[400](errorMessage);
    }
    // rest of the implementation goes here
}
```

[skip ci]

Related to, but does NOT conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
petermetz added a commit to petermetz/cacti that referenced this issue Nov 9, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Related to but does not conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
petermetz added a commit to petermetz/cacti that referenced this issue Nov 9, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Depends on hyperledger#2868

Related to but does not conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
petermetz added a commit to petermetz/cacti that referenced this issue Nov 10, 2023
1. This is a function that is designed to be called by all the REST API
endpoint implementations to (more) correctly handle errors.
2. The problem right now is that we do not differentiate between invalid
request errors (e.g. expected exceptions) vs.
legitimate crashes (e.g. unexpected exceptions)
What the above means is that a lot of our endpoints will crash with an
HTTP 500 error code returned to the client even if the problem as user-
error (such as a missing parameter that is mandatory).
3. With the new utility function the REST endpoint code can easily
apply the decision logic at runtime in their own catch blocks' and
set the HTTP response status code based on the information (context)
provided by the callee (most often the connector plugin's underlying
method that was called)

An example usage of this utility method can be described as:
1. Add the necessary dependencies to your plugin (`http-errors`, `@types/http-errors`)
2. `yarn install` (which will update the lock file)
3. Choose the endpoint you wish to update to be using the new handleRestEndpointException
function internally when handling HTTP requests that involve the plugin.
For example this file:
```
packages/cactus-plugin-ledger-connector-besu/src/main/typescript/
web-services/deploy-contract-solidity-bytecode-endpoint.ts
```
4. Update the `catch() { ... }` block of the `handleRequest` method to
invoke the handleRestEndpointException method:

```typescript
public async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = `${this.className}#handleRequest()`;
const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`;
this.log.debug(reqTag);
const reqBody: DeployContractSolidityBytecodeV1Request = req.body;
try {
    const resBody = await this.options.connector.deployContract(reqBody);
    res.json(resBody);
} catch (ex) {
    const errorMsg = `${reqTag} ${fnTag} Failed to deploy contract:`;
    handleRestEndpointException({ errorMsg, log: this.log, error: ex, res });
}
}
```

Then proceed to also update the implementation of the method that is  being
called by the REST endpoint request handler such that it uses the HTTP
errors according to their intended status codes, e.g. 400 is user error
and 5xx is something that is a developer error (e.g. indicating that
a bug is in the code of the plugin and should be fixed)

```typescript
import createHttpError from "http-errors";

export class SomePluginImplementration {

  public async deployContract(
    req: DeployContractSolidityBytecodeV1Request,
  ): Promise<DeployContractSolidityBytecodeV1Response> {
    const fnTag = `${this.className}#deployContract()`;
    Checks.truthy(req, `${fnTag} req`);
    if (isWeb3SigningCredentialNone(req.web3SigningCredential)) {
      throw createHttpError[400](
        `${fnTag} Cannot deploy contract with pre-signed TX`,
      );
    }
    const { keychainId, contractName } = req;
    if (!keychainId || !req.contractName) {
      const errorMessage = `${fnTag} Cannot deploy contract without keychainId and the contractName.`;
      throw createHttpError[400](errorMessage);
    }

    const keychainPlugin = this.pluginRegistry.findOneByKeychainId(keychainId);

    if (!keychainPlugin) {
      const errorMessage =
        `${fnTag} The plugin registry does not contain` +
        ` a keychain plugin for ID:"${req.keychainId}"`;
      throw createHttpError[400](errorMessage);
    }

    if (!keychainPlugin.has(contractName)) {
      const errorMessage =
        `${fnTag} Cannot create an instance of the contract instance because` +
        `the contractName in the request does not exist on the keychain`;
      throw new createHttpError[400](errorMessage);
    }
    // rest of the implementation goes here
}
```

[skip ci]

Related to, but does NOT conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
(cherry picked from commit dfa6396)
petermetz added a commit to petermetz/cacti that referenced this issue Nov 10, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Depends on hyperledger#2868

Related to but does not conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
(cherry picked from commit 5816904)
petermetz added a commit to petermetz/cacti that referenced this issue Nov 10, 2023
1. This is a function that is designed to be called by all the REST API
endpoint implementations to (more) correctly handle errors.
2. The problem right now is that we do not differentiate between invalid
request errors (e.g. expected exceptions) vs.
legitimate crashes (e.g. unexpected exceptions)
What the above means is that a lot of our endpoints will crash with an
HTTP 500 error code returned to the client even if the problem as user-
error (such as a missing parameter that is mandatory).
3. With the new utility function the REST endpoint code can easily
apply the decision logic at runtime in their own catch blocks' and
set the HTTP response status code based on the information (context)
provided by the callee (most often the connector plugin's underlying
method that was called)

An example usage of this utility method can be described as:
1. Add the necessary dependencies to your plugin (`http-errors`, `@types/http-errors`)
2. `yarn install` (which will update the lock file)
3. Choose the endpoint you wish to update to be using the new handleRestEndpointException
function internally when handling HTTP requests that involve the plugin.
For example this file:
```
packages/cactus-plugin-ledger-connector-besu/src/main/typescript/
web-services/deploy-contract-solidity-bytecode-endpoint.ts
```
4. Update the `catch() { ... }` block of the `handleRequest` method to
invoke the handleRestEndpointException method:

```typescript
public async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = `${this.className}#handleRequest()`;
const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`;
this.log.debug(reqTag);
const reqBody: DeployContractSolidityBytecodeV1Request = req.body;
try {
    const resBody = await this.options.connector.deployContract(reqBody);
    res.json(resBody);
} catch (ex) {
    const errorMsg = `${reqTag} ${fnTag} Failed to deploy contract:`;
    handleRestEndpointException({ errorMsg, log: this.log, error: ex, res });
}
}
```

Then proceed to also update the implementation of the method that is  being
called by the REST endpoint request handler such that it uses the HTTP
errors according to their intended status codes, e.g. 400 is user error
and 5xx is something that is a developer error (e.g. indicating that
a bug is in the code of the plugin and should be fixed)

```typescript
import createHttpError from "http-errors";

export class SomePluginImplementration {

  public async deployContract(
    req: DeployContractSolidityBytecodeV1Request,
  ): Promise<DeployContractSolidityBytecodeV1Response> {
    const fnTag = `${this.className}#deployContract()`;
    Checks.truthy(req, `${fnTag} req`);
    if (isWeb3SigningCredentialNone(req.web3SigningCredential)) {
      throw createHttpError[400](
        `${fnTag} Cannot deploy contract with pre-signed TX`,
      );
    }
    const { keychainId, contractName } = req;
    if (!keychainId || !req.contractName) {
      const errorMessage = `${fnTag} Cannot deploy contract without keychainId and the contractName.`;
      throw createHttpError[400](errorMessage);
    }

    const keychainPlugin = this.pluginRegistry.findOneByKeychainId(keychainId);

    if (!keychainPlugin) {
      const errorMessage =
        `${fnTag} The plugin registry does not contain` +
        ` a keychain plugin for ID:"${req.keychainId}"`;
      throw createHttpError[400](errorMessage);
    }

    if (!keychainPlugin.has(contractName)) {
      const errorMessage =
        `${fnTag} Cannot create an instance of the contract instance because` +
        `the contractName in the request does not exist on the keychain`;
      throw new createHttpError[400](errorMessage);
    }
    // rest of the implementation goes here
}
```

[skip ci]

Related to, but does NOT conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
(cherry picked from commit dfa6396)
petermetz added a commit to petermetz/cacti that referenced this issue Nov 10, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Depends on hyperledger#2868

Related to but does not conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
(cherry picked from commit 5816904)
petermetz added a commit to petermetz/cacti that referenced this issue Nov 10, 2023
1. This is a function that is designed to be called by all the REST API
endpoint implementations to (more) correctly handle errors.
2. The problem right now is that we do not differentiate between invalid
request errors (e.g. expected exceptions) vs.
legitimate crashes (e.g. unexpected exceptions)
What the above means is that a lot of our endpoints will crash with an
HTTP 500 error code returned to the client even if the problem as user-
error (such as a missing parameter that is mandatory).
3. With the new utility function the REST endpoint code can easily
apply the decision logic at runtime in their own catch blocks' and
set the HTTP response status code based on the information (context)
provided by the callee (most often the connector plugin's underlying
method that was called)

An example usage of this utility method can be described as:
1. Add the necessary dependencies to your plugin (`http-errors`, `@types/http-errors`)
2. `yarn install` (which will update the lock file)
3. Choose the endpoint you wish to update to be using the new handleRestEndpointException
function internally when handling HTTP requests that involve the plugin.
For example this file:
```
packages/cactus-plugin-ledger-connector-besu/src/main/typescript/
web-services/deploy-contract-solidity-bytecode-endpoint.ts
```
4. Update the `catch() { ... }` block of the `handleRequest` method to
invoke the handleRestEndpointException method:

```typescript
public async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = `${this.className}#handleRequest()`;
const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`;
this.log.debug(reqTag);
const reqBody: DeployContractSolidityBytecodeV1Request = req.body;
try {
    const resBody = await this.options.connector.deployContract(reqBody);
    res.json(resBody);
} catch (ex) {
    const errorMsg = `${reqTag} ${fnTag} Failed to deploy contract:`;
    handleRestEndpointException({ errorMsg, log: this.log, error: ex, res });
}
}
```

Then proceed to also update the implementation of the method that is  being
called by the REST endpoint request handler such that it uses the HTTP
errors according to their intended status codes, e.g. 400 is user error
and 5xx is something that is a developer error (e.g. indicating that
a bug is in the code of the plugin and should be fixed)

```typescript
import createHttpError from "http-errors";

export class SomePluginImplementration {

  public async deployContract(
    req: DeployContractSolidityBytecodeV1Request,
  ): Promise<DeployContractSolidityBytecodeV1Response> {
    const fnTag = `${this.className}#deployContract()`;
    Checks.truthy(req, `${fnTag} req`);
    if (isWeb3SigningCredentialNone(req.web3SigningCredential)) {
      throw createHttpError[400](
        `${fnTag} Cannot deploy contract with pre-signed TX`,
      );
    }
    const { keychainId, contractName } = req;
    if (!keychainId || !req.contractName) {
      const errorMessage = `${fnTag} Cannot deploy contract without keychainId and the contractName.`;
      throw createHttpError[400](errorMessage);
    }

    const keychainPlugin = this.pluginRegistry.findOneByKeychainId(keychainId);

    if (!keychainPlugin) {
      const errorMessage =
        `${fnTag} The plugin registry does not contain` +
        ` a keychain plugin for ID:"${req.keychainId}"`;
      throw createHttpError[400](errorMessage);
    }

    if (!keychainPlugin.has(contractName)) {
      const errorMessage =
        `${fnTag} Cannot create an instance of the contract instance because` +
        `the contractName in the request does not exist on the keychain`;
      throw new createHttpError[400](errorMessage);
    }
    // rest of the implementation goes here
}
```

[skip ci]

Related to, but does NOT conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
(cherry picked from commit dfa6396)
petermetz added a commit to petermetz/cacti that referenced this issue Nov 10, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Depends on hyperledger#2868

Related to but does not conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
(cherry picked from commit 5816904)
petermetz added a commit to petermetz/cacti that referenced this issue Nov 14, 2023
1. This is a function that is designed to be called by all the REST API
endpoint implementations to (more) correctly handle errors.
2. The problem right now is that we do not differentiate between invalid
request errors (e.g. expected exceptions) vs.
legitimate crashes (e.g. unexpected exceptions)
What the above means is that a lot of our endpoints will crash with an
HTTP 500 error code returned to the client even if the problem as user-
error (such as a missing parameter that is mandatory).
3. With the new utility function the REST endpoint code can easily
apply the decision logic at runtime in their own catch blocks' and
set the HTTP response status code based on the information (context)
provided by the callee (most often the connector plugin's underlying
method that was called)

An example usage of this utility method can be described as:
1. Add the necessary dependencies to your plugin (`http-errors`, `@types/http-errors`)
2. `yarn install` (which will update the lock file)
3. Choose the endpoint you wish to update to be using the new handleRestEndpointException
function internally when handling HTTP requests that involve the plugin.
For example this file:
```
packages/cactus-plugin-ledger-connector-besu/src/main/typescript/
web-services/deploy-contract-solidity-bytecode-endpoint.ts
```
4. Update the `catch() { ... }` block of the `handleRequest` method to
invoke the handleRestEndpointException method:

```typescript
public async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = `${this.className}#handleRequest()`;
const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`;
this.log.debug(reqTag);
const reqBody: DeployContractSolidityBytecodeV1Request = req.body;
try {
    const resBody = await this.options.connector.deployContract(reqBody);
    res.json(resBody);
} catch (ex) {
    const errorMsg = `${reqTag} ${fnTag} Failed to deploy contract:`;
    handleRestEndpointException({ errorMsg, log: this.log, error: ex, res });
}
}
```

Then proceed to also update the implementation of the method that is  being
called by the REST endpoint request handler such that it uses the HTTP
errors according to their intended status codes, e.g. 400 is user error
and 5xx is something that is a developer error (e.g. indicating that
a bug is in the code of the plugin and should be fixed)

```typescript
import createHttpError from "http-errors";

export class SomePluginImplementration {

  public async deployContract(
    req: DeployContractSolidityBytecodeV1Request,
  ): Promise<DeployContractSolidityBytecodeV1Response> {
    const fnTag = `${this.className}#deployContract()`;
    Checks.truthy(req, `${fnTag} req`);
    if (isWeb3SigningCredentialNone(req.web3SigningCredential)) {
      throw createHttpError[400](
        `${fnTag} Cannot deploy contract with pre-signed TX`,
      );
    }
    const { keychainId, contractName } = req;
    if (!keychainId || !req.contractName) {
      const errorMessage = `${fnTag} Cannot deploy contract without keychainId and the contractName.`;
      throw createHttpError[400](errorMessage);
    }

    const keychainPlugin = this.pluginRegistry.findOneByKeychainId(keychainId);

    if (!keychainPlugin) {
      const errorMessage =
        `${fnTag} The plugin registry does not contain` +
        ` a keychain plugin for ID:"${req.keychainId}"`;
      throw createHttpError[400](errorMessage);
    }

    if (!keychainPlugin.has(contractName)) {
      const errorMessage =
        `${fnTag} Cannot create an instance of the contract instance because` +
        `the contractName in the request does not exist on the keychain`;
      throw new createHttpError[400](errorMessage);
    }
    // rest of the implementation goes here
}
```

[skip ci]

Related to, but does NOT conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
(cherry picked from commit dfa6396)
petermetz added a commit to petermetz/cacti that referenced this issue Nov 14, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Depends on hyperledger#2868

Related to but does not conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
(cherry picked from commit 5816904)
petermetz added a commit to petermetz/cacti that referenced this issue Nov 15, 2023
1. This is a function that is designed to be called by all the REST API
endpoint implementations to (more) correctly handle errors.
2. The problem right now is that we do not differentiate between invalid
request errors (e.g. expected exceptions) vs.
legitimate crashes (e.g. unexpected exceptions)
What the above means is that a lot of our endpoints will crash with an
HTTP 500 error code returned to the client even if the problem as user-
error (such as a missing parameter that is mandatory).
3. With the new utility function the REST endpoint code can easily
apply the decision logic at runtime in their own catch blocks' and
set the HTTP response status code based on the information (context)
provided by the callee (most often the connector plugin's underlying
method that was called)

An example usage of this utility method can be described as:
1. Add the necessary dependencies to your plugin (`http-errors`, `@types/http-errors`)
2. `yarn install` (which will update the lock file)
3. Choose the endpoint you wish to update to be using the new handleRestEndpointException
function internally when handling HTTP requests that involve the plugin.
For example this file:
```
packages/cactus-plugin-ledger-connector-besu/src/main/typescript/
web-services/deploy-contract-solidity-bytecode-endpoint.ts
```
4. Update the `catch() { ... }` block of the `handleRequest` method to
invoke the handleRestEndpointException method:

```typescript
public async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = `${this.className}#handleRequest()`;
const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`;
this.log.debug(reqTag);
const reqBody: DeployContractSolidityBytecodeV1Request = req.body;
try {
    const resBody = await this.options.connector.deployContract(reqBody);
    res.json(resBody);
} catch (ex) {
    const errorMsg = `${reqTag} ${fnTag} Failed to deploy contract:`;
    handleRestEndpointException({ errorMsg, log: this.log, error: ex, res });
}
}
```

Then proceed to also update the implementation of the method that is  being
called by the REST endpoint request handler such that it uses the HTTP
errors according to their intended status codes, e.g. 400 is user error
and 5xx is something that is a developer error (e.g. indicating that
a bug is in the code of the plugin and should be fixed)

```typescript
import createHttpError from "http-errors";

export class SomePluginImplementration {

  public async deployContract(
    req: DeployContractSolidityBytecodeV1Request,
  ): Promise<DeployContractSolidityBytecodeV1Response> {
    const fnTag = `${this.className}#deployContract()`;
    Checks.truthy(req, `${fnTag} req`);
    if (isWeb3SigningCredentialNone(req.web3SigningCredential)) {
      throw createHttpError[400](
        `${fnTag} Cannot deploy contract with pre-signed TX`,
      );
    }
    const { keychainId, contractName } = req;
    if (!keychainId || !req.contractName) {
      const errorMessage = `${fnTag} Cannot deploy contract without keychainId and the contractName.`;
      throw createHttpError[400](errorMessage);
    }

    const keychainPlugin = this.pluginRegistry.findOneByKeychainId(keychainId);

    if (!keychainPlugin) {
      const errorMessage =
        `${fnTag} The plugin registry does not contain` +
        ` a keychain plugin for ID:"${req.keychainId}"`;
      throw createHttpError[400](errorMessage);
    }

    if (!keychainPlugin.has(contractName)) {
      const errorMessage =
        `${fnTag} Cannot create an instance of the contract instance because` +
        `the contractName in the request does not exist on the keychain`;
      throw new createHttpError[400](errorMessage);
    }
    // rest of the implementation goes here
}
```

[skip ci]

Related to, but does NOT conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
petermetz added a commit that referenced this issue Nov 15, 2023
1. This is a function that is designed to be called by all the REST API
endpoint implementations to (more) correctly handle errors.
2. The problem right now is that we do not differentiate between invalid
request errors (e.g. expected exceptions) vs.
legitimate crashes (e.g. unexpected exceptions)
What the above means is that a lot of our endpoints will crash with an
HTTP 500 error code returned to the client even if the problem as user-
error (such as a missing parameter that is mandatory).
3. With the new utility function the REST endpoint code can easily
apply the decision logic at runtime in their own catch blocks' and
set the HTTP response status code based on the information (context)
provided by the callee (most often the connector plugin's underlying
method that was called)

An example usage of this utility method can be described as:
1. Add the necessary dependencies to your plugin (`http-errors`, `@types/http-errors`)
2. `yarn install` (which will update the lock file)
3. Choose the endpoint you wish to update to be using the new handleRestEndpointException
function internally when handling HTTP requests that involve the plugin.
For example this file:
```
packages/cactus-plugin-ledger-connector-besu/src/main/typescript/
web-services/deploy-contract-solidity-bytecode-endpoint.ts
```
4. Update the `catch() { ... }` block of the `handleRequest` method to
invoke the handleRestEndpointException method:

```typescript
public async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = `${this.className}#handleRequest()`;
const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`;
this.log.debug(reqTag);
const reqBody: DeployContractSolidityBytecodeV1Request = req.body;
try {
    const resBody = await this.options.connector.deployContract(reqBody);
    res.json(resBody);
} catch (ex) {
    const errorMsg = `${reqTag} ${fnTag} Failed to deploy contract:`;
    handleRestEndpointException({ errorMsg, log: this.log, error: ex, res });
}
}
```

Then proceed to also update the implementation of the method that is  being
called by the REST endpoint request handler such that it uses the HTTP
errors according to their intended status codes, e.g. 400 is user error
and 5xx is something that is a developer error (e.g. indicating that
a bug is in the code of the plugin and should be fixed)

```typescript
import createHttpError from "http-errors";

export class SomePluginImplementration {

  public async deployContract(
    req: DeployContractSolidityBytecodeV1Request,
  ): Promise<DeployContractSolidityBytecodeV1Response> {
    const fnTag = `${this.className}#deployContract()`;
    Checks.truthy(req, `${fnTag} req`);
    if (isWeb3SigningCredentialNone(req.web3SigningCredential)) {
      throw createHttpError[400](
        `${fnTag} Cannot deploy contract with pre-signed TX`,
      );
    }
    const { keychainId, contractName } = req;
    if (!keychainId || !req.contractName) {
      const errorMessage = `${fnTag} Cannot deploy contract without keychainId and the contractName.`;
      throw createHttpError[400](errorMessage);
    }

    const keychainPlugin = this.pluginRegistry.findOneByKeychainId(keychainId);

    if (!keychainPlugin) {
      const errorMessage =
        `${fnTag} The plugin registry does not contain` +
        ` a keychain plugin for ID:"${req.keychainId}"`;
      throw createHttpError[400](errorMessage);
    }

    if (!keychainPlugin.has(contractName)) {
      const errorMessage =
        `${fnTag} Cannot create an instance of the contract instance because` +
        `the contractName in the request does not exist on the keychain`;
      throw new createHttpError[400](errorMessage);
    }
    // rest of the implementation goes here
}
```

[skip ci]

Related to, but does NOT conclude: #1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
petermetz added a commit to petermetz/cacti that referenced this issue Nov 15, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Depends on hyperledger#2868

Related to but does not conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
(cherry picked from commit 5816904)
petermetz added a commit to petermetz/cacti that referenced this issue Nov 15, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Depends on hyperledger#2868

Related to but does not conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
(cherry picked from commit 5816904)
petermetz added a commit to petermetz/cacti that referenced this issue Nov 15, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Depends on hyperledger#2868

Related to but does not conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
petermetz added a commit that referenced this issue Nov 16, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Depends on #2868

Related to but does not conclude: #1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
sandeepnRES pushed a commit to sandeepnRES/cacti that referenced this issue Dec 21, 2023
1. This is a function that is designed to be called by all the REST API
endpoint implementations to (more) correctly handle errors.
2. The problem right now is that we do not differentiate between invalid
request errors (e.g. expected exceptions) vs.
legitimate crashes (e.g. unexpected exceptions)
What the above means is that a lot of our endpoints will crash with an
HTTP 500 error code returned to the client even if the problem as user-
error (such as a missing parameter that is mandatory).
3. With the new utility function the REST endpoint code can easily
apply the decision logic at runtime in their own catch blocks' and
set the HTTP response status code based on the information (context)
provided by the callee (most often the connector plugin's underlying
method that was called)

An example usage of this utility method can be described as:
1. Add the necessary dependencies to your plugin (`http-errors`, `@types/http-errors`)
2. `yarn install` (which will update the lock file)
3. Choose the endpoint you wish to update to be using the new handleRestEndpointException
function internally when handling HTTP requests that involve the plugin.
For example this file:
```
packages/cactus-plugin-ledger-connector-besu/src/main/typescript/
web-services/deploy-contract-solidity-bytecode-endpoint.ts
```
4. Update the `catch() { ... }` block of the `handleRequest` method to
invoke the handleRestEndpointException method:

```typescript
public async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = `${this.className}#handleRequest()`;
const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`;
this.log.debug(reqTag);
const reqBody: DeployContractSolidityBytecodeV1Request = req.body;
try {
    const resBody = await this.options.connector.deployContract(reqBody);
    res.json(resBody);
} catch (ex) {
    const errorMsg = `${reqTag} ${fnTag} Failed to deploy contract:`;
    handleRestEndpointException({ errorMsg, log: this.log, error: ex, res });
}
}
```

Then proceed to also update the implementation of the method that is  being
called by the REST endpoint request handler such that it uses the HTTP
errors according to their intended status codes, e.g. 400 is user error
and 5xx is something that is a developer error (e.g. indicating that
a bug is in the code of the plugin and should be fixed)

```typescript
import createHttpError from "http-errors";

export class SomePluginImplementration {

  public async deployContract(
    req: DeployContractSolidityBytecodeV1Request,
  ): Promise<DeployContractSolidityBytecodeV1Response> {
    const fnTag = `${this.className}#deployContract()`;
    Checks.truthy(req, `${fnTag} req`);
    if (isWeb3SigningCredentialNone(req.web3SigningCredential)) {
      throw createHttpError[400](
        `${fnTag} Cannot deploy contract with pre-signed TX`,
      );
    }
    const { keychainId, contractName } = req;
    if (!keychainId || !req.contractName) {
      const errorMessage = `${fnTag} Cannot deploy contract without keychainId and the contractName.`;
      throw createHttpError[400](errorMessage);
    }

    const keychainPlugin = this.pluginRegistry.findOneByKeychainId(keychainId);

    if (!keychainPlugin) {
      const errorMessage =
        `${fnTag} The plugin registry does not contain` +
        ` a keychain plugin for ID:"${req.keychainId}"`;
      throw createHttpError[400](errorMessage);
    }

    if (!keychainPlugin.has(contractName)) {
      const errorMessage =
        `${fnTag} Cannot create an instance of the contract instance because` +
        `the contractName in the request does not exist on the keychain`;
      throw new createHttpError[400](errorMessage);
    }
    // rest of the implementation goes here
}
```

[skip ci]

Related to, but does NOT conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
sandeepnRES pushed a commit to sandeepnRES/cacti that referenced this issue Dec 21, 2023
…Endpoint

1. Uses the new utility function from the core package in the catch block
so that HTTP `statusCode` is matching the intent of the thrower (e.g.
correctly differentiates between user-error and developer error)
2. Updates the `deployContract` method of the besu connector so that it
correctly specifies the intent of the errors thrown as either user error
or developer error via setting the `statusCode` property of the HTTP errors
to either 4xx or 5xx depending on the cause.
3. Provides a template for future similar changes (of which we'll need
dozens to update all the REST API endpoints)

Depends on hyperledger#2868

Related to but does not conclude: hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
@outSH
Copy link
Contributor

outSH commented Dec 28, 2023

TS 4.9.5 is used now

@outSH outSH closed this as completed Dec 28, 2023
petermetz added a commit to petermetz/cacti that referenced this issue Feb 8, 2024
WORK IN PROGRESS

Fixes hyperledger#1747

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file Developer_Experience good-first-issue Good for newcomers good-first-issue-200-intermediate Hacktoberfest Hacktoberfest participants are welcome to take a stab at issues marked with this label. Nice-to-Have P4 Priority 4: Low
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants