From 0fb328a3a5f1a08e236387b0493b860e1e2d6810 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Fri, 3 Nov 2023 14:14:33 +0100 Subject: [PATCH 01/26] chore: eslint no-warning-comments:warn --- .eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 45e744b46..8c56db1c8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -28,7 +28,7 @@ "@typescript-eslint/prefer-nullish-coalescing": "error", "@typescript-eslint/prefer-optional-chain": "error", "prettier/prettier": ["error", { "singleQuote": true, "trailingComma": "none", "tabWidth": 4 }], - "no-warning-comments": "error", + "no-warning-comments": "warn", "no-multi-str": "off" } } \ No newline at end of file From 741853fa921606acc0841d6f01a99a45f1b70f57 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Fri, 3 Nov 2023 14:16:50 +0100 Subject: [PATCH 02/26] feat: http client --- .../network/src/client/http/http-client.ts | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 packages/network/src/client/http/http-client.ts diff --git a/packages/network/src/client/http/http-client.ts b/packages/network/src/client/http/http-client.ts new file mode 100644 index 000000000..1e4c6a81e --- /dev/null +++ b/packages/network/src/client/http/http-client.ts @@ -0,0 +1,100 @@ +import Axios, { type AxiosInstance, type AxiosRequestConfig } from 'axios'; +import { Agent as HttpAgent } from 'http'; +import { Agent as HttpsAgent } from 'https'; +import { + type IHttpClient, + type HttpParams, + type HttpClientOptions +} from './types'; +import { convertError } from './helpers'; +import { DEFAULT_HTTP_TIMEOUT } from '../../utils'; + +/** + * Represents a concrete implementation of the `IHttpClient` interface, providing methods for making HTTP requests. + * + * This class leverages Axios for handling HTTP requests and allows for interaction with HTTP services. + * It is configured with a base URL and request timeout upon instantiation. + * + * @public + */ +class HttpClient implements IHttpClient { + protected readonly axios: AxiosInstance; + + /** + * Instantiates an `HttpClient` object with a specified base URL and HTTP request timeout. + * + * @param baseURL - The base URL for all network requests. + * @param options - (Optional) An object containing additional configuration options for the HTTP client, such as a custom Axios instance and a request timeout. + */ + constructor( + readonly baseURL: string, + options?: HttpClientOptions + ) { + this.axios = + options?.axiosInstance ?? + Axios.create({ + httpAgent: new HttpAgent({ keepAlive: true }), + httpsAgent: new HttpsAgent({ keepAlive: true }), + baseURL, + timeout: options?.timeout ?? DEFAULT_HTTP_TIMEOUT + }); + } + + /** + * Sends an HTTP request using the Axios library. + * + * @param method - The HTTP method to be used ('GET' or 'POST'). + * @param path - The path to access on the server relative to the base URL. + * @param params - (Optional) Additional request parameters such as query parameters, request body, and custom headers. + * @returns A promise that resolves to the response data from the HTTP request. + * @throws Will throw an error if the request fails, with more detailed information if the error is Axios-specific. + */ + public async http( + method: 'GET' | 'POST', + path: string, + params?: HttpParams + ): Promise { + const config: AxiosRequestConfig = { + method, + url: path, + data: params?.body, + headers: params?.headers, + params: params?.query + }; + + try { + const resp = await this.axios(config); + this.validateResponseHeader(params, resp.headers); + return resp.data as unknown; + } catch (err) { + if (Axios.isAxiosError(err)) { + throw convertError(err); + } + throw err; // If it's not an Axios error, re-throw the original error + } + } + + /** + * Validates the response headers if a validation function is provided. + * + * @param params - (Optional) The request parameters. + * @param headers - The response headers. + */ + private validateResponseHeader( + params?: HttpParams, + headers?: Record + ): void { + if (params?.validateResponseHeader != null && headers != null) { + const responseHeaders: Record = {}; + for (const key in headers) { + const value = headers[key]; + if (typeof value === 'string') { + responseHeaders[key] = value; + } + } + params.validateResponseHeader(responseHeaders); + } + } +} + +export { HttpClient }; From 9a1067734b18de4275ab4b809b165c7e51fbc376 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Fri, 3 Nov 2023 14:17:45 +0100 Subject: [PATCH 03/26] feat: http client types with additional options --- packages/network/src/client/http/types.d.ts | 80 +++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 packages/network/src/client/http/types.d.ts diff --git a/packages/network/src/client/http/types.d.ts b/packages/network/src/client/http/types.d.ts new file mode 100644 index 000000000..f03823f55 --- /dev/null +++ b/packages/network/src/client/http/types.d.ts @@ -0,0 +1,80 @@ +import { type AxiosInstance } from 'axios'; + +/** + * Represents the core networking interface for executing HTTP requests. + * + * This interface encapsulates methods for sending HTTP requests. It also outlines the structure for request parameters, + * making it a foundational networking API. + * + * @public + */ +interface IHttpClient { + /** + * The base URL for all network requests. + */ + readonly baseURL: string; + + /** + * Performs an HTTP request. + * + * @param method - Specifies the HTTP method to use, either 'GET' or 'POST'. + * @param path - Specifies the path to access on the server, relative to the baseURL. + * @param params - (Optional) Additional parameters for the request. + * @returns A promise resolving to the response body, JSON decoded. + */ + http: ( + method: 'GET' | 'POST', + path: string, + params?: NetParams + ) => Promise; +} + +/** + * Represents the parameters for making an HTTP request. + * + * This interface specifies options for configuring an HTTP request, including query parameters, + * request body, custom headers, and a function to validate response headers. + * + * @public + */ +interface HttpParams { + /** + * Query parameters to include in the request. + */ + query: Record; + + /** + * The request body, which can be of any type. + */ + body: unknown; + + /** + * Custom headers to be included in the request. + */ + headers: Record; + + /** + * A callback function to validate response headers. + * @param headers - The response headers to validate. + */ + validateResponseHeader: (headers: Record) => void; +} + +/** + * Represents the options for configuring an HTTP client. + * @public + */ +interface HttpClientOptions { + /** + * The timeout for an HTTP request, in milliseconds. + */ + timeout?: number; + + /** + * An Axios instance to use for sending HTTP requests. + * This is useful for customizing the HTTP client, such as adding a custom user agent. + */ + axiosInstance?: AxiosInstance; +} + +export type { IHttpClient, HttpParams, HttpClientOptions }; From 2672e0333b8b3db13fb5ed354e8ecece1871dd90 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Fri, 3 Nov 2023 14:18:13 +0100 Subject: [PATCH 04/26] refactor: errors in dedicated http client helpers path --- .../network/src/client/http/helpers/errors.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 packages/network/src/client/http/helpers/errors.ts diff --git a/packages/network/src/client/http/helpers/errors.ts b/packages/network/src/client/http/helpers/errors.ts new file mode 100644 index 000000000..89c75adaf --- /dev/null +++ b/packages/network/src/client/http/helpers/errors.ts @@ -0,0 +1,35 @@ +import { type AxiosError } from 'axios'; + +/** + * Converts an AxiosError into a standard Error. + * + * This function converts an AxiosError, which may contain HTTP response details, into a standard Error. + * It handles cases where the AxiosError has an HTTP response with status and data. + * + * @param error - The AxiosError to convert into an Error. + * @returns A standard Error with a descriptive message. + */ +const convertError = (error: AxiosError): Error => { + if (error.response != null) { + const resp = error.response; + if (typeof resp.data === 'string') { + let text = resp.data.trim(); + if (text.length > 50) { + text = text.slice(0, 50) + '...'; + } + return new Error( + `${resp.status} ${error.config?.method} ${error.config?.url}: ${text}` + ); + } else { + return new Error( + `${resp.status} ${error.config?.method} ${error.config?.url}` + ); + } + } else { + return new Error( + `${error.config?.method} ${error.config?.url}: ${error.message}` + ); + } +}; + +export { convertError }; From 7932d7b705632a8881823d01999198084e8fe01f Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Fri, 3 Nov 2023 14:18:45 +0100 Subject: [PATCH 05/26] test: testing non-axios error and minor refactors --- .../network/tests/driver/driver.solo.test.ts | 4 +-- .../tests/driver/driver.testnet.test.ts | 30 +++++++++++++++---- packages/network/tests/driver/fixture.ts | 26 ++++++++-------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/packages/network/tests/driver/driver.solo.test.ts b/packages/network/tests/driver/driver.solo.test.ts index e50d6a5df..ec8fd51e9 100644 --- a/packages/network/tests/driver/driver.solo.test.ts +++ b/packages/network/tests/driver/driver.solo.test.ts @@ -5,7 +5,7 @@ import { testAccount, zeroAddressAccountDetails } from './fixture'; -import { type NetParams } from '../../src'; +import { type HttpParams } from '../../src'; /** * SimpleNet class tests @@ -40,7 +40,7 @@ describe('Test SimpleNet class on Solo', () => { * Request params validation */ test('Should validate response headers', async () => { - const customParams: NetParams = { + const customParams: HttpParams = { query: {}, body: {}, headers: { diff --git a/packages/network/tests/driver/driver.testnet.test.ts b/packages/network/tests/driver/driver.testnet.test.ts index ac4c62fc5..ec2daf182 100644 --- a/packages/network/tests/driver/driver.testnet.test.ts +++ b/packages/network/tests/driver/driver.testnet.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from '@jest/globals'; -import { type NetParams } from '../../src'; -import { firstTestnetBlock, network, testAccount } from './fixture'; +import { type HttpParams } from '../../src'; +import { testnetGenesisBlock, network, testAccount } from './fixture'; /** * Timeout for each test. @@ -22,12 +22,12 @@ describe('Test SimpleNet class on Testnet', () => { // Perform an HTTP GET request using the SimpleNet instance const response = await network.http( 'GET', - '/blocks/1?expanded=false' + '/blocks/0?expanded=false' ); // Assert that the response matches the expected firstTestnetBlock expect(JSON.stringify(response)).toEqual( - JSON.stringify(firstTestnetBlock) + JSON.stringify(testnetGenesisBlock) ); }, TIMEOUT @@ -55,7 +55,7 @@ describe('Test SimpleNet class on Testnet', () => { test( 'Should validate response headers', async () => { - const customParams: NetParams = { + const customParams: HttpParams = { query: {}, body: {}, headers: { @@ -80,4 +80,24 @@ describe('Test SimpleNet class on Testnet', () => { }, TIMEOUT ); + + /** + * Request params validation rejecting with an error + */ + test('Should throw error for invalid header response', async () => { + const customParams: HttpParams = { + query: {}, + body: {}, + headers: { + 'X-Custom-Header': 'custom-value' + }, + validateResponseHeader: function (): void { + throw new Error(`Forcing error on header validation`); + } + }; + + await expect( + network.http('GET', '/accounts/' + testAccount, customParams) + ).rejects.toThrowError(`Forcing error on header validation`); + }); }); diff --git a/packages/network/tests/driver/fixture.ts b/packages/network/tests/driver/fixture.ts index 7f5c34b6e..54880f2f9 100644 --- a/packages/network/tests/driver/fixture.ts +++ b/packages/network/tests/driver/fixture.ts @@ -1,4 +1,4 @@ -import { SimpleNet } from '../../src'; +import { HttpClient } from '../../src'; /** * Url of the testnet fixture @@ -13,27 +13,27 @@ const _soloUrl = 'http://localhost:8669'; /** * Network instance fixture */ -const network = new SimpleNet(_testnetUrl); +const network = new HttpClient(_testnetUrl); /** * Solo network instance fixture */ -const soloNetwork = new SimpleNet(_soloUrl); +const soloNetwork = new HttpClient(_soloUrl); /** * First testnet block fixture */ -const firstTestnetBlock = { - number: 1, - id: '0x000000019015bbd98fc1c9088d793ba9add53896a29cd9aa3a4dcabd1f561c38', - size: 236, +const testnetGenesisBlock = { + number: 0, + id: '0x000000000b2bce3c70bc649a02749e8687721b09ed2e15997f466536b20bb127', + size: 170, parentID: - '0x000000000b2bce3c70bc649a02749e8687721b09ed2e15997f466536b20bb127', - timestamp: 1530014410, + '0xffffffff00000000000000000000000000000000000000000000000000000000', + timestamp: 1530014400, gasLimit: 10000000, - beneficiary: '0xb4094c25f86d628fdd571afc4077f0d0196afb48', + beneficiary: '0x0000000000000000000000000000000000000000', gasUsed: 0, - totalScore: 1, + totalScore: 0, txsRoot: '0x45b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0', txsFeatures: 0, @@ -42,7 +42,7 @@ const firstTestnetBlock = { receiptsRoot: '0x45b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0', com: false, - signer: '0x25ae0ef84da4a76d5a1dfe80d3789c2c46fee30a', + signer: '0x0000000000000000000000000000000000000000', isTrunk: true, isFinalized: true, transactions: [] @@ -70,7 +70,7 @@ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; export { network, soloNetwork, - firstTestnetBlock, + testnetGenesisBlock, testAccount, zeroAddressAccountDetails, ZERO_ADDRESS From e08fce51f239a8232c6d083c66034c82c30a3c0a Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Fri, 3 Nov 2023 14:19:28 +0100 Subject: [PATCH 06/26] feat: thor client & general network package structure --- .../network/src/client/http/helpers/index.ts | 1 + packages/network/src/client/http/index.ts | 3 + packages/network/src/client/index.ts | 1 + packages/network/src/client/thor/index.ts | 0 .../network/src/client/thor/thor-client.ts | 0 .../src/client/thor/thor-readonly-client.ts | 0 packages/network/src/client/thor/types.d.ts | 0 packages/network/src/driver/index.ts | 2 - packages/network/src/driver/interfaces.ts | 61 -------------- packages/network/src/driver/simple-net.ts | 83 ------------------- packages/network/src/network.ts | 3 +- .../src/utils/const/client/http-client.ts | 3 + .../network/src/utils/const/client/index.ts | 1 + packages/network/src/utils/const/index.ts | 1 + packages/network/src/utils/errors.ts | 35 -------- packages/network/src/utils/index.ts | 2 +- 16 files changed, 12 insertions(+), 184 deletions(-) create mode 100644 packages/network/src/client/http/helpers/index.ts create mode 100644 packages/network/src/client/http/index.ts create mode 100644 packages/network/src/client/index.ts create mode 100644 packages/network/src/client/thor/index.ts create mode 100644 packages/network/src/client/thor/thor-client.ts create mode 100644 packages/network/src/client/thor/thor-readonly-client.ts create mode 100644 packages/network/src/client/thor/types.d.ts delete mode 100644 packages/network/src/driver/index.ts delete mode 100644 packages/network/src/driver/interfaces.ts delete mode 100644 packages/network/src/driver/simple-net.ts create mode 100644 packages/network/src/utils/const/client/http-client.ts create mode 100644 packages/network/src/utils/const/client/index.ts create mode 100644 packages/network/src/utils/const/index.ts delete mode 100644 packages/network/src/utils/errors.ts diff --git a/packages/network/src/client/http/helpers/index.ts b/packages/network/src/client/http/helpers/index.ts new file mode 100644 index 000000000..f72bc43e2 --- /dev/null +++ b/packages/network/src/client/http/helpers/index.ts @@ -0,0 +1 @@ +export * from './errors'; diff --git a/packages/network/src/client/http/index.ts b/packages/network/src/client/http/index.ts new file mode 100644 index 000000000..b328aa87e --- /dev/null +++ b/packages/network/src/client/http/index.ts @@ -0,0 +1,3 @@ +export * from './types.d'; +export * from './http-client'; +export * from './helpers'; diff --git a/packages/network/src/client/index.ts b/packages/network/src/client/index.ts new file mode 100644 index 000000000..c202386ae --- /dev/null +++ b/packages/network/src/client/index.ts @@ -0,0 +1 @@ +export * from './http'; diff --git a/packages/network/src/client/thor/index.ts b/packages/network/src/client/thor/index.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/network/src/client/thor/thor-client.ts b/packages/network/src/client/thor/thor-client.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/network/src/client/thor/thor-readonly-client.ts b/packages/network/src/client/thor/thor-readonly-client.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/network/src/client/thor/types.d.ts b/packages/network/src/client/thor/types.d.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/network/src/driver/index.ts b/packages/network/src/driver/index.ts deleted file mode 100644 index c26dc940c..000000000 --- a/packages/network/src/driver/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './interfaces'; -export * from './simple-net'; diff --git a/packages/network/src/driver/interfaces.ts b/packages/network/src/driver/interfaces.ts deleted file mode 100644 index d366e8570..000000000 --- a/packages/network/src/driver/interfaces.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Represents the core networking interface for making HTTP requests and opening WebSocket readers. - * - * This interface defines methods for performing HTTP requests and opening WebSocket connections. - * It also includes parameters and types for request options, making it a versatile networking API. - * - * @public - */ -interface Net { - /** - * The base URL - */ - readonly baseURL: string; - - /** - * Perform http request - * - * @param method - 'GET' or 'POST' - * @param path - Path to access - * @param params - Additional params - * @returns The response body, JSON decoded - */ - http: ( - method: 'GET' | 'POST', - path: string, - params?: NetParams - ) => Promise; -} - -/** - * Interface representing parameters for making HTTP requests. - * - * This interface defines options for configuring an HTTP request, including query parameters, - * request body, custom headers, and a function to validate response headers. - * - * @public - */ -interface NetParams { - /** - * Query parameters to include in the request. - */ - query: Record; - - /** - * The request body, which can be of any type. - */ - body: unknown; - - /** - * Custom headers to be included in the request. - */ - headers: Record; - - /** - * A callback function to validate response headers. - * @param headers - The response headers to validate. - */ - validateResponseHeader: (headers: Record) => void; -} - -export type { Net, NetParams }; diff --git a/packages/network/src/driver/simple-net.ts b/packages/network/src/driver/simple-net.ts deleted file mode 100644 index 2ab54d046..000000000 --- a/packages/network/src/driver/simple-net.ts +++ /dev/null @@ -1,83 +0,0 @@ -import Axios, { type AxiosInstance, type AxiosError } from 'axios'; -import { Agent as HttpAgent } from 'http'; -import { Agent as HttpsAgent } from 'https'; -import { type Net, type NetParams } from './interfaces'; -import { convertError } from '../utils'; - -/** - * Represents a concrete implementation of the `Net` interface, providing methods for making HTTP requests and - * opening WebSocket readers. - * - * This class uses Axios for HTTP requests and allows interaction with both HTTP and WebSocket connections. - * - * @public - */ -class SimpleNet implements Net { - protected readonly axios: AxiosInstance; - - /** - * Creates a new `SimpleNet` instance with the specified base URL, HTTP timeout, and WebSocket timeout. - * - * @param baseURL - The base URL for all network requests. - * @param timeout - The HTTP request timeout in milliseconds (default: 30 seconds). - */ - constructor( - readonly baseURL: string, - timeout: number = 30 * 1000 - ) { - this.axios = Axios.create({ - httpAgent: new HttpAgent({ keepAlive: true }), - httpsAgent: new HttpsAgent({ keepAlive: true }), - baseURL, - timeout - }); - } - - /** - * Perform an HTTP request using the Axios library. - * - * @param method - The HTTP request method ('GET' or 'POST'). - * @param path - The path to access on the server. - * @param params - Additional request parameters, such as query parameters, request body, and custom headers. - * @returns A promise that resolves with the response data from the HTTP request. - * @throws An error if the request fails. - */ - public async http( - method: 'GET' | 'POST', - path: string, - params?: NetParams - ): Promise { - try { - const resp = await this.axios.request({ - method, - url: path, - data: params?.body, - headers: params?.headers, - params: params?.query - }); - - if (params?.validateResponseHeader != null) { - const responseHeaders: Record = {}; - - for (const key in resp.headers) { - const value: unknown = resp.headers[key]; - - if (typeof value === 'string') { - responseHeaders[key] = value; - } - } - - params.validateResponseHeader(responseHeaders); - } - - return resp.data as unknown; - } catch (err) { - const axiosError = err as AxiosError; - if (axiosError.isAxiosError) { - throw convertError(err as AxiosError); - } - } - } -} - -export { SimpleNet }; diff --git a/packages/network/src/network.ts b/packages/network/src/network.ts index 38ea03840..4f1cce44f 100644 --- a/packages/network/src/network.ts +++ b/packages/network/src/network.ts @@ -1,2 +1 @@ -export * from './driver'; -export * from './utils'; +export * from './client'; diff --git a/packages/network/src/utils/const/client/http-client.ts b/packages/network/src/utils/const/client/http-client.ts new file mode 100644 index 000000000..9c4913057 --- /dev/null +++ b/packages/network/src/utils/const/client/http-client.ts @@ -0,0 +1,3 @@ +const DEFAULT_HTTP_TIMEOUT = 30000; + +export { DEFAULT_HTTP_TIMEOUT }; diff --git a/packages/network/src/utils/const/client/index.ts b/packages/network/src/utils/const/client/index.ts new file mode 100644 index 000000000..29d4d49b6 --- /dev/null +++ b/packages/network/src/utils/const/client/index.ts @@ -0,0 +1 @@ +export * from './http-client'; diff --git a/packages/network/src/utils/const/index.ts b/packages/network/src/utils/const/index.ts new file mode 100644 index 000000000..4f1cce44f --- /dev/null +++ b/packages/network/src/utils/const/index.ts @@ -0,0 +1 @@ +export * from './client'; diff --git a/packages/network/src/utils/errors.ts b/packages/network/src/utils/errors.ts deleted file mode 100644 index 89c75adaf..000000000 --- a/packages/network/src/utils/errors.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { type AxiosError } from 'axios'; - -/** - * Converts an AxiosError into a standard Error. - * - * This function converts an AxiosError, which may contain HTTP response details, into a standard Error. - * It handles cases where the AxiosError has an HTTP response with status and data. - * - * @param error - The AxiosError to convert into an Error. - * @returns A standard Error with a descriptive message. - */ -const convertError = (error: AxiosError): Error => { - if (error.response != null) { - const resp = error.response; - if (typeof resp.data === 'string') { - let text = resp.data.trim(); - if (text.length > 50) { - text = text.slice(0, 50) + '...'; - } - return new Error( - `${resp.status} ${error.config?.method} ${error.config?.url}: ${text}` - ); - } else { - return new Error( - `${resp.status} ${error.config?.method} ${error.config?.url}` - ); - } - } else { - return new Error( - `${error.config?.method} ${error.config?.url}: ${error.message}` - ); - } -}; - -export { convertError }; diff --git a/packages/network/src/utils/index.ts b/packages/network/src/utils/index.ts index f72bc43e2..e47ea3a46 100644 --- a/packages/network/src/utils/index.ts +++ b/packages/network/src/utils/index.ts @@ -1 +1 @@ -export * from './errors'; +export * from './const'; From 8bb7c918f7dcd1ae7047a3802d9da9657be2e646 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Fri, 3 Nov 2023 14:30:32 +0100 Subject: [PATCH 07/26] chore: added error issue --- packages/network/src/client/http/helpers/errors.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/network/src/client/http/helpers/errors.ts b/packages/network/src/client/http/helpers/errors.ts index 89c75adaf..81fb6bc6e 100644 --- a/packages/network/src/client/http/helpers/errors.ts +++ b/packages/network/src/client/http/helpers/errors.ts @@ -8,6 +8,8 @@ import { type AxiosError } from 'axios'; * * @param error - The AxiosError to convert into an Error. * @returns A standard Error with a descriptive message. + * + * @TODO - Refactor using our error system (https://github.com/vechainfoundation/vechain-sdk/issues/192) */ const convertError = (error: AxiosError): Error => { if (error.response != null) { From d7af0d6795b9b790eb2ce8af180a1c431f609f30 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Fri, 3 Nov 2023 14:34:52 +0100 Subject: [PATCH 08/26] docs: default http timeout --- packages/network/src/utils/const/client/http-client.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/network/src/utils/const/client/http-client.ts b/packages/network/src/utils/const/client/http-client.ts index 9c4913057..4872ec112 100644 --- a/packages/network/src/utils/const/client/http-client.ts +++ b/packages/network/src/utils/const/client/http-client.ts @@ -1,3 +1,6 @@ +/** + * Default timeout for HTTP requests, in milliseconds. + */ const DEFAULT_HTTP_TIMEOUT = 30000; export { DEFAULT_HTTP_TIMEOUT }; From 1beeaa10cc5bfea12905adbccc2ab3665e61c72a Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Tue, 7 Nov 2023 10:54:14 +0100 Subject: [PATCH 09/26] feat: thor account client --- .../client/thor/accounts/account-client.ts | 129 ++++++++++++++++++ .../src/client/thor/accounts/types.d.ts | 86 ++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 packages/network/src/client/thor/accounts/account-client.ts create mode 100644 packages/network/src/client/thor/accounts/types.d.ts diff --git a/packages/network/src/client/thor/accounts/account-client.ts b/packages/network/src/client/thor/accounts/account-client.ts new file mode 100644 index 000000000..f5f8f3218 --- /dev/null +++ b/packages/network/src/client/thor/accounts/account-client.ts @@ -0,0 +1,129 @@ +import { DATA, buildError } from '@vechain-sdk/errors'; +import { blockUtils } from '../../../utils'; +import { type HttpClient } from '../../http'; +import { + GET_ACCOUNT_BYTECODE_ENDPOINT, + GET_ACCOUNT_DETAIL_ENDPOINT, + GET_STORAGE_AT_ENDPOINT +} from '../api'; +import { buildQuery } from '../helpers'; +import { + type ResponseBytecode, + type AccountDetail, + type IAccountClient, + type ResponseStorage +} from './types'; +import { dataUtils } from '@vechain-sdk/core'; + +/** + * The `AccountClient` class provides methods to interact with account-related endpoints + * of the VechainThor blockchain. It allows fetching details, bytecode, and storage data + * for a specific blockchain account. + */ +class AccountClient implements IAccountClient { + /** + * Initializes a new instance of the `AccountClient` class. + * @param httpClient - The HTTP client instance used for making HTTP requests. + */ + constructor(protected readonly httpClient: HttpClient) {} + + /** + * Retrieves account details such as balance of VET, VTHO, and if the address is a smart contract. + * + * @param address - The account address to query details for. + * @param revision - (Optional) The block number or ID to reference the state of the account. + * @returns A promise that resolves to an object containing the account details (balance, energy, hasCode). + * + * @throws {InvalidDataTypeError} - Will throw an error if the revision is not a valid block number or ID. + */ + public async getAccount( + address: string, + revision?: string + ): Promise { + if (revision != null && !blockUtils.isBlockRevision(revision)) + throw buildError( + DATA.INVALID_DATA_TYPE, + 'Invalid revision. The revision must be a string representing a block number or block id.' + ); + + return (await this.httpClient.http( + 'GET', + GET_ACCOUNT_DETAIL_ENDPOINT(address), + { + query: buildQuery({ revision }) + } + )) as AccountDetail; + } + + /** + * Fetches the bytecode of a contract at a given address. + * + * @param address - The contract address to get the bytecode for. + * @param revision - (Optional) The block number or ID to reference the bytecode version. + * @returns A promise that resolves to the contract bytecode as a string. + * + * @throws {InvalidDataTypeError} - Will throw an error if the revision is not a valid block number or ID. + */ + public async getBytecode( + address: string, + revision?: string + ): Promise { + if (revision != null && !blockUtils.isBlockRevision(revision)) + throw buildError( + DATA.INVALID_DATA_TYPE, + 'Invalid revision. The revision must be a string representing a block number or block id.' + ); + + const result = (await this.httpClient.http( + 'GET', + GET_ACCOUNT_BYTECODE_ENDPOINT(address), + { + query: buildQuery({ revision }) + } + )) as ResponseBytecode; + + return result.code; + } + + /** + * Retrieves the value from a smart contract's storage at a given position. + * + * @param address - The contract address to query storage from. + * @param position - The position in the storage to retrieve the value from. Must be a 32 bytes hex string (66 characters including `0x` prefix). + * @param revision - (Optional) The block number or ID to reference the storage state. + * @returns A promise that resolves to the storage value in hex string format. + * + * @throws {InvalidDataTypeError} - Will throw an error if the revision is not a valid block number or ID + * or if the position is not a 32 bytes hex string. + */ + public async getStorageAt( + address: string, + position: string, + revision?: string + ): Promise { + if (revision != null && !blockUtils.isBlockRevision(revision)) + throw buildError( + DATA.INVALID_DATA_TYPE, + 'Invalid `revision`. The revision must be a string representing a block number or block id.' + ); + + // The position represents a slot in the VM storage. Each slot is 32 bytes. + if (!dataUtils.isHexString(position) || position.length !== 66) + throw buildError( + DATA.INVALID_DATA_TYPE, + 'Invalid `position`. The position must be a hex string of 32 bytes (66 characters including `0x` prefix).' + ); + + const result = (await this.httpClient.http( + 'GET', + GET_STORAGE_AT_ENDPOINT(address, position), + { + query: buildQuery({ position, revision }) + } + )) as ResponseStorage; + + return result.value; + } +} + +export { AccountClient }; diff --git a/packages/network/src/client/thor/accounts/types.d.ts b/packages/network/src/client/thor/accounts/types.d.ts new file mode 100644 index 000000000..7b4f10fc7 --- /dev/null +++ b/packages/network/src/client/thor/accounts/types.d.ts @@ -0,0 +1,86 @@ +/** + * An account represents both an EOA and a smart contract on the VechainThor blockchain. + * + * This interface provides methods to interact with accounts on the VechainThor blockchain. + */ +interface IAccountClient { + /** + * Get the account details of the specified account. + * + * @param address - The address of the account. + * @param revision - The block revision as the desired block number o block id (default: best block). + * + * @returns an object containing the account's balance (VET), energy (VTHO) & whether it is a smart contract (hasCode). + */ + getAccount: (address: string, revision?: string) => Promise; + + /** + * Get the bytecode of the deployed smart contract. + * + * @param address - The address of the smart contract. + * @param revision - The block revision as the desired block number o block id (default: best block). + * Bytecode is immutable for a smart contract, thus the revision can be useful to check if the + * smart contract was deployed at the specified block. + * + * @returns the bytecode of the deployed smart contract in hex string. + */ + getBytecode: (address: string, revision?: string) => Promise; + + /** + * Get the storage data at the specified position of the smart contract. + * + * @param address - The address of the smart contract. + * @param position - The position of the storage data. + * @param revision - The block revision as the desired block number o block id (default: best block). + * + * @returns the storage data at the specified position of the smart contract in hex string. + */ + getStorageAt: ( + address: string, + position: string, + revision?: string + ) => Promise; +} + +/** + * The account details represent the balance, energy & whether the account is a smart contract. + */ +interface AccountDetail { + /** + * The balance of VET of the account. + */ + balance: string; + + /** + * The balance of VTHO of the account. + */ + energy: string; + + /** + * Whether the account is a smart contract (i.e., hasCode is true) + */ + hasCode: boolean; +} + +/** + * The bytecode of a smart contract. + * The bytecode is represented in hex string. + */ +interface ResponseBytecode { + code: string; +} + +/** + * The storage data of a smart contract at the specified position. + * The storage data is represented in hex string. + */ +interface ResponseStorage { + value: string; +} + +export type { + IAccountClient, + AccountDetail, + ResponseBytecode, + ResponseStorage +}; From c8ae1ab6cb75a119c30317ad53f20e5d4d29c220 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Tue, 7 Nov 2023 10:55:03 +0100 Subject: [PATCH 10/26] feat: thor client --- .../network/src/client/thor/thor-client.ts | 75 +++++++++++++++++++ packages/network/src/client/thor/types.d.ts | 9 +++ 2 files changed, 84 insertions(+) diff --git a/packages/network/src/client/thor/thor-client.ts b/packages/network/src/client/thor/thor-client.ts index e69de29bb..6ed0dbb43 100644 --- a/packages/network/src/client/thor/thor-client.ts +++ b/packages/network/src/client/thor/thor-client.ts @@ -0,0 +1,75 @@ +import { type HttpClient } from '../http'; +import { AccountClient, type AccountDetail } from './accounts'; +import { type IThorClient } from './types'; + +/** + * The `ThorClient` class serves as an interface to interact with the VeChain Thor blockchain. + * It provides methods for accessing account details, contract bytecode, and storage. + */ +class ThorClient implements IThorClient { + /** + * An instance of `AccountClient` to delegate account-related requests. + */ + private readonly accountClient: AccountClient; + + /** + * Constructs a new `ThorClient` instance with a given HTTP client. + * @param httpClient - The HTTP client instance used for making network requests. + */ + constructor(protected readonly httpClient: HttpClient) { + this.accountClient = new AccountClient(httpClient); + } + + /* --------------------------- Account (Externally Owned Accounts & Smart Contracts) --------------------------- */ + + /** + * Retrieves details for an account such as balance and nonce. + * This can be used for both externally owned accounts (EOAs) and smart contracts. + * + * @param address - The address of the account to query. + * @param revision - (Optional) A specific block number or ID to reference the state. + * @returns A promise resolved with the account details. + */ + public async getAccount( + address: string, + revision?: string | undefined + ): Promise { + return await this.accountClient.getAccount(address, revision); + } + + /** + * Fetches the bytecode of a smart contract at a specified address. + * + * @param address - The contract address to get the bytecode for. + * @param revision - (Optional) A specific block number or ID to reference the bytecode version. + * @returns A promise resolved with the contract bytecode as a string. + */ + public async getBytecode( + address: string, + revision?: string | undefined + ): Promise { + return await this.accountClient.getBytecode(address, revision); + } + + /** + * Retrieves the storage value from a specified position in a smart contract. + * + * @param address - The address of the contract to query storage from. + * @param position - The hex-encoded storage position to retrieve the value from. + * @param revision - (Optional) A specific block number or ID to reference the storage state. + * @returns A promise resolved with the storage value at the specified position. + */ + public async getStorageAt( + address: string, + position: string, + revision?: string | undefined + ): Promise { + return await this.accountClient.getStorageAt( + address, + position, + revision + ); + } +} + +export { ThorClient }; diff --git a/packages/network/src/client/thor/types.d.ts b/packages/network/src/client/thor/types.d.ts index e69de29bb..030ba37ff 100644 --- a/packages/network/src/client/thor/types.d.ts +++ b/packages/network/src/client/thor/types.d.ts @@ -0,0 +1,9 @@ +import { type IAccountClient } from './accounts'; + +/** + * The ThorClient interface contains all the methods for interacting with the VeChainThor blockchain. + * @extends IAccountClient + */ +interface IThorClient extends IAccountClient {} + +export type { IThorClient }; From 1132e916a8a73e9b0b04effe6e48b1baf52ba0a7 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Tue, 7 Nov 2023 10:55:49 +0100 Subject: [PATCH 11/26] test: thor client --- packages/network/tests/client/thor/fixture.ts | 148 ++++++++++++++++++ .../client/thor/thorclient.testnet.test.ts | 138 ++++++++++++++++ packages/network/tests/fixture.ts | 33 ++++ 3 files changed, 319 insertions(+) create mode 100644 packages/network/tests/client/thor/fixture.ts create mode 100644 packages/network/tests/client/thor/thorclient.testnet.test.ts create mode 100644 packages/network/tests/fixture.ts diff --git a/packages/network/tests/client/thor/fixture.ts b/packages/network/tests/client/thor/fixture.ts new file mode 100644 index 000000000..554ee6a89 --- /dev/null +++ b/packages/network/tests/client/thor/fixture.ts @@ -0,0 +1,148 @@ +import { InvalidDataTypeError } from '@vechain-sdk/errors'; +import { ThorClient } from '../../../src'; +import { testAccount, testNetwork } from '../../fixture'; + +/** + * Thor client instance fixture + */ +const thorClient = new ThorClient(testNetwork); + +/** + * VTHO contract address + */ +const VTHO_CONTRACT_ADDRESS = '0x0000000000000000000000000000456e65726779'; + +/** + * Bytecode of the VTHO deployed contract + */ +const VTHO_CONTRACT_BYTECODE = + '0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014457806318160ddd146101a957806323b872dd146101d4578063313ce5671461025957806370a082311461028a57806395d89b41146102e1578063a9059cbb14610371578063bb35783b146103d6578063d89135cd1461045b578063dd62ed3e14610486575b600080fd5b3480156100c057600080fd5b506100c96104fd565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101095780820151818401526020810190506100ee565b50505050905090810190601f1680156101365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015057600080fd5b5061018f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061053a565b604051808215151515815260200191505060405180910390f35b3480156101b557600080fd5b506101be61062b565b6040518082815260200191505060405180910390f35b3480156101e057600080fd5b5061023f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106d1565b604051808215151515815260200191505060405180910390f35b34801561026557600080fd5b5061026e610865565b604051808260ff1660ff16815260200191505060405180910390f35b34801561029657600080fd5b506102cb600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061086e565b6040518082815260200191505060405180910390f35b3480156102ed57600080fd5b506102f661094d565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561033657808201518184015260208101905061031b565b50505050905090810190601f1680156103635780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561037d57600080fd5b506103bc600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061098a565b604051808215151515815260200191505060405180910390f35b3480156103e257600080fd5b50610441600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506109a1565b604051808215151515815260200191505060405180910390f35b34801561046757600080fd5b50610470610b67565b6040518082815260200191505060405180910390f35b34801561049257600080fd5b506104e7600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c0d565b6040518082815260200191505060405180910390f35b60606040805190810160405280600681526020017f566554686f720000000000000000000000000000000000000000000000000000815250905090565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1663592b389c6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561069157600080fd5b505af11580156106a5573d6000803e3d6000fd5b505050506040513d60208110156106bb57600080fd5b8101908080519060200190929190505050905090565b6000816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156107c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6275696c74696e3a20696e73756666696369656e7420616c6c6f77616e63650081525060200191505060405180910390fd5b816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555061085a848484610c93565b600190509392505050565b60006012905090565b60003073ffffffffffffffffffffffffffffffffffffffff1663ee660480836040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561090b57600080fd5b505af115801561091f573d6000803e3d6000fd5b505050506040513d602081101561093557600080fd5b81019080805190602001909291905050509050919050565b60606040805190810160405280600481526020017f5654484f00000000000000000000000000000000000000000000000000000000815250905090565b6000610997338484610c93565b6001905092915050565b60003373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610add57503373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663059950e9866040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b158015610a8a57600080fd5b505af1158015610a9e573d6000803e3d6000fd5b505050506040513d6020811015610ab457600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff16145b1515610b51576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6275696c74696e3a2073656c66206f72206d617374657220726571756972656481525060200191505060405180910390fd5b610b5c848484610c93565b600190509392505050565b60003073ffffffffffffffffffffffffffffffffffffffff1663138d4d0c6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610bcd57600080fd5b505af1158015610be1573d6000803e3d6000fd5b505050506040513d6020811015610bf757600080fd5b8101908080519060200190929190505050905090565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000811115610eaa573073ffffffffffffffffffffffffffffffffffffffff166339ed08d584836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015610d3f57600080fd5b505af1158015610d53573d6000803e3d6000fd5b505050506040513d6020811015610d6957600080fd5b81019080805190602001909291905050501515610dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f6275696c74696e3a20696e73756666696369656e742062616c616e636500000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16631cedfac183836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015610e9157600080fd5b505af1158015610ea5573d6000803e3d6000fd5b505050505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050505600a165627a7a72305820bd55cb9aff347dc60fe8280ae6b08a6f6deacc85a4e1c89ba0a8ef31fbcaecc60029'; + +/** + * getAccount tests with revision block number or block id + */ +const getAccountWithRevisionTestCases = [ + { + description: 'get account with revision block number', + account: testAccount, + revision: '15000000', + expected: { + balance: '0x64fa270f17ef298000', + energy: '0x11bec42c96bc7bd45f', + hasCode: false + } + }, + { + description: 'get account with revision block id', + account: testAccount, + revision: + '0x00e4e1c0fbb78a30a5ae9549f8f5a0cf4ac4aab589803f2487b74261fffcbdf5', + expected: { + balance: '0x64fa270f17ef298000', + energy: '0x11bec42c96bc7bd45f', + hasCode: false + } + }, + { + description: 'get account with revision block number', + account: testAccount, + revision: '14000000', + expected: { + balance: '0x26a9f176f96e764a3d6', + energy: '0x5497801ddd36c434be', + hasCode: false + } + } +]; + +/** + * getBytecode tests with and without revision + */ +const getBytecodeTestCases = [ + { + description: 'get bytecode of VTHO contract without revision', + address: VTHO_CONTRACT_ADDRESS, + revision: undefined, + expected: VTHO_CONTRACT_BYTECODE + }, + { + description: 'get bytecode of VTHO contract with block number revision', + address: VTHO_CONTRACT_ADDRESS, + revision: '16000000', + expected: VTHO_CONTRACT_BYTECODE + }, + { + description: 'get bytecode of VTHO contract with block id revision', + address: VTHO_CONTRACT_ADDRESS, + revision: + '0x00e4e1c0fbb78a30a5ae9549f8f5a0cf4ac4aab589803f2487b74261fffcbdf5', + expected: VTHO_CONTRACT_BYTECODE + }, + { + description: 'get bytecode of contract before it was deployed', + address: '0x1c65362e12ecafaf2f37494886bb288c6d2ede28', + revision: '1', + expected: '0x' + }, + { + description: 'get bytecode of contract after it was deployed', + address: '0x1c65362e12ecafaf2f37494886bb288c6d2ede28', + revision: undefined, // best block + expected: + '0x608060405234801561001057600080fd5b50600436106101e55760003560e01c80636352211e1161010f578063a22cb465116100a2578063d539139311610071578063d5391393146105a0578063d547741f146105be578063e63ab1e9146105da578063e985e9c5146105f8576101e5565b8063a22cb46514610508578063b88d4fde14610524578063c87b56dd14610540578063ca15c87314610570576101e5565b80639010d07c116100de5780639010d07c1461046c57806391d148541461049c57806395d89b41146104cc578063a217fddf146104ea576101e5565b80636352211e146103e65780636a6278421461041657806370a08231146104325780638456cb5914610462576101e5565b80632f2ff15d1161018757806342842e0e1161015657806342842e0e1461036057806342966c681461037c5780634f6ccce7146103985780635c975abb146103c8576101e5565b80632f2ff15d146102ee5780632f745c591461030a57806336568abe1461033a5780633f4ba83a14610356576101e5565b8063095ea7b3116101c3578063095ea7b31461026857806318160ddd1461028457806323b872dd146102a2578063248a9ca3146102be576101e5565b806301ffc9a7146101ea57806306fdde031461021a578063081812fc14610238575b600080fd5b61020460048036038101906101ff91906130eb565b610628565b6040516102119190613133565b60405180910390f35b61022261063a565b60405161022f91906131de565b60405180910390f35b610252600480360381019061024d9190613236565b6106cc565b60405161025f91906132a4565b60405180910390f35b610282600480360381019061027d91906132eb565b610712565b005b61028c610829565b604051610299919061333a565b60405180910390f35b6102bc60048036038101906102b79190613355565b610836565b005b6102d860048036038101906102d391906133de565b610896565b6040516102e5919061341a565b60405180910390f35b61030860048036038101906103039190613435565b6108b5565b005b610324600480360381019061031f91906132eb565b6108d6565b604051610331919061333a565b60405180910390f35b610354600480360381019061034f9190613435565b61097b565b005b61035e6109fe565b005b61037a60048036038101906103759190613355565b610a78565b005b61039660048036038101906103919190613236565b610a98565b005b6103b260048036038101906103ad9190613236565b610af4565b6040516103bf919061333a565b60405180910390f35b6103d0610b65565b6040516103dd9190613133565b60405180910390f35b61040060048036038101906103fb9190613236565b610b7c565b60405161040d91906132a4565b60405180910390f35b610430600480360381019061042b9190613475565b610c02565b005b61044c60048036038101906104479190613475565b610c92565b604051610459919061333a565b60405180910390f35b61046a610d49565b005b610486600480360381019061048191906134a2565b610dc3565b60405161049391906132a4565b60405180910390f35b6104b660048036038101906104b19190613435565b610df2565b6040516104c39190613133565b60405180910390f35b6104d4610e5c565b6040516104e191906131de565b60405180910390f35b6104f2610eee565b6040516104ff919061341a565b60405180910390f35b610522600480360381019061051d919061350e565b610ef5565b005b61053e60048036038101906105399190613683565b610f0b565b005b61055a60048036038101906105559190613236565b610f6d565b60405161056791906131de565b60405180910390f35b61058a600480360381019061058591906133de565b610f9e565b604051610597919061333a565b60405180910390f35b6105a8610fc2565b6040516105b5919061341a565b60405180910390f35b6105d860048036038101906105d39190613435565b610fe6565b005b6105e2611007565b6040516105ef919061341a565b60405180910390f35b610612600480360381019061060d9190613706565b61102b565b60405161061f9190613133565b60405180910390f35b6000610633826111cf565b9050919050565b60606002805461064990613775565b80601f016020809104026020016040519081016040528092919081815260200182805461067590613775565b80156106c25780601f10610697576101008083540402835291602001916106c2565b820191906000526020600020905b8154815290600101906020018083116106a557829003601f168201915b5050505050905090565b60006106d782611249565b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061071d82610b7c565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361078d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078490613818565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166107ac611294565b73ffffffffffffffffffffffffffffffffffffffff1614806107db57506107da816107d5611294565b61102b565b5b61081a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610811906138aa565b60405180910390fd5b610824838361129c565b505050565b6000600a80549050905090565b610847610841611294565b82611355565b610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d9061393c565b60405180910390fd5b6108918383836113ea565b505050565b6000806000838152602001908152602001600020600101549050919050565b6108be82610896565b6108c7816116e3565b6108d183836116f7565b505050565b60006108e183610c92565b8210610922576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610919906139ce565b60405180910390fd5b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b610983611294565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109e790613a60565b60405180910390fd5b6109fa828261172b565b5050565b610a2f7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610a2a611294565b610df2565b610a6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6590613af2565b60405180910390fd5b610a7661175f565b565b610a9383838360405180602001604052806000815250610f0b565b505050565b610aa9610aa3611294565b82611355565b610ae8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610adf9061393c565b60405180910390fd5b610af1816117c2565b50565b6000610afe610829565b8210610b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3690613b84565b60405180910390fd5b600a8281548110610b5357610b52613ba4565b5b90600052602060002001549050919050565b6000600c60009054906101000a900460ff16905090565b600080610b8883611910565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bf9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf090613c1f565b60405180910390fd5b80915050919050565b610c337f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610c2e611294565b610df2565b610c72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6990613cb1565b60405180910390fd5b610c8581610c80600d61194d565b61195b565b610c8f600d611b78565b50565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cf990613d43565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610d7a7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610d75611294565b610df2565b610db9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db090613dd5565b60405180910390fd5b610dc1611b8e565b565b6000610dea8260016000868152602001908152602001600020611bf190919063ffffffff16565b905092915050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b606060038054610e6b90613775565b80601f0160208091040260200160405190810160405280929190818152602001828054610e9790613775565b8015610ee45780601f10610eb957610100808354040283529160200191610ee4565b820191906000526020600020905b815481529060010190602001808311610ec757829003601f168201915b5050505050905090565b6000801b81565b610f07610f00611294565b8383611c0b565b5050565b610f1c610f16611294565b83611355565b610f5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f529061393c565b60405180910390fd5b610f6784848484611d77565b50505050565b6060610f7882611dd3565b604051602001610f889190613e57565b6040516020818303038152906040529050919050565b6000610fbb60016000848152602001908152602001600020611e3b565b9050919050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610fef82610896565b610ff8816116e3565b611002838361172b565b505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6110c98282610df2565b61119b57600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611140611294565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006111c7836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611e50565b905092915050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611242575061124182611ec0565b5b9050919050565b61125281611fa2565b611291576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128890613c1f565b60405180910390fd5b50565b600033905090565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661130f83610b7c565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061136183610b7c565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806113a357506113a2818561102b565b5b806113e157508373ffffffffffffffffffffffffffffffffffffffff166113c9846106cc565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661140a82610b7c565b73ffffffffffffffffffffffffffffffffffffffff1614611460576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145790613eef565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036114cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114c690613f81565b60405180910390fd5b6114dc8383836001611fe3565b8273ffffffffffffffffffffffffffffffffffffffff166114fc82610b7c565b73ffffffffffffffffffffffffffffffffffffffff1614611552576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154990613eef565b60405180910390fd5b6006600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46116de8383836001611ff5565b505050565b6116f4816116ef611294565b611ffb565b50565b61170182826110bf565b611726816001600085815260200190815260200160002061119f90919063ffffffff16565b505050565b6117358282612080565b61175a816001600085815260200190815260200160002061216190919063ffffffff16565b505050565b611767612191565b6000600c60006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6117ab611294565b6040516117b891906132a4565b60405180910390a1565b60006117cd82610b7c565b90506117dd816000846001611fe3565b6117e682610b7c565b90506006600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461190c816000846001611ff5565b5050565b60006004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600081600001549050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036119ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c190613fed565b60405180910390fd5b6119d381611fa2565b15611a13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0a90614059565b60405180910390fd5b611a21600083836001611fe3565b611a2a81611fa2565b15611a6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6190614059565b60405180910390fd5b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611b74600083836001611ff5565b5050565b6001816000016000828254019250508190555050565b611b966121da565b6001600c60006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611bda611294565b604051611be791906132a4565b60405180910390a1565b6000611c008360000183612224565b60001c905092915050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611c79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c70906140c5565b60405180910390fd5b80600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611d6a9190613133565b60405180910390a3505050565b611d828484846113ea565b611d8e8484848461224f565b611dcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc490614157565b60405180910390fd5b50505050565b6060611dde82611249565b6000611de86123d6565b90506000815111611e085760405180602001604052806000815250611e33565b80611e1284612468565b604051602001611e23929190614177565b6040516020818303038152906040525b915050919050565b6000611e4982600001612536565b9050919050565b6000611e5c8383612547565b611eb5578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611eba565b600090505b92915050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611f8b57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611f9b5750611f9a8261256a565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16611fc483611910565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b611fef848484846125e4565b50505050565b50505050565b6120058282610df2565b61207c576120128161263e565b6120208360001c602061266b565b604051602001612031929190614233565b6040516020818303038152906040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207391906131de565b60405180910390fd5b5050565b61208a8282610df2565b1561215d57600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612102611294565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6000612189836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6128a7565b905092915050565b612199610b65565b6121d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cf906142b9565b60405180910390fd5b565b6121e2610b65565b15612222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161221990614325565b60405180910390fd5b565b600082600001828154811061223c5761223b613ba4565b5b9060005260206000200154905092915050565b60006122708473ffffffffffffffffffffffffffffffffffffffff166129bb565b156123c9578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612299611294565b8786866040518563ffffffff1660e01b81526004016122bb949392919061439a565b6020604051808303816000875af19250505080156122f757506040513d601f19601f820116820180604052508101906122f491906143fb565b60015b612379573d8060008114612327576040519150601f19603f3d011682016040523d82523d6000602084013e61232c565b606091505b506000815103612371576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161236890614157565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149150506123ce565b600190505b949350505050565b6060600e80546123e590613775565b80601f016020809104026020016040519081016040528092919081815260200182805461241190613775565b801561245e5780601f106124335761010080835404028352916020019161245e565b820191906000526020600020905b81548152906001019060200180831161244157829003601f168201915b5050505050905090565b606060006001612477846129de565b01905060008167ffffffffffffffff81111561249657612495613558565b5b6040519080825280601f01601f1916602001820160405280156124c85781602001600182028036833780820191505090505b509050600082602001820190505b60011561252b578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161251f5761251e614428565b5b049450600085036124d6575b819350505050919050565b600081600001805490509050919050565b600080836001016000848152602001908152602001600020541415905092915050565b60007f5a05180f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806125dd57506125dc82612b31565b5b9050919050565b6125f084848484612bab565b6125f8610b65565b15612638576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262f906144c9565b60405180910390fd5b50505050565b60606126648273ffffffffffffffffffffffffffffffffffffffff16601460ff1661266b565b9050919050565b60606000600283600261267e9190614518565b612688919061455a565b67ffffffffffffffff8111156126a1576126a0613558565b5b6040519080825280601f01601f1916602001820160405280156126d35781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061270b5761270a613ba4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061276f5761276e613ba4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026127af9190614518565b6127b9919061455a565b90505b6001811115612859577f3031323334353637383961626364656600000000000000000000000000000000600f8616601081106127fb576127fa613ba4565b5b1a60f81b82828151811061281257612811613ba4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806128529061458e565b90506127bc565b506000841461289d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289490614603565b60405180910390fd5b8091505092915050565b600080836001016000848152602001908152602001600020549050600081146129af5760006001826128d99190614623565b90506000600186600001805490506128f19190614623565b905081811461296057600086600001828154811061291257612911613ba4565b5b906000526020600020015490508087600001848154811061293657612935613ba4565b5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061297457612973614657565b5b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506129b5565b60009150505b92915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612a3c577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612a3257612a31614428565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612a79576d04ee2d6d415b85acef81000000008381612a6f57612a6e614428565b5b0492506020810190505b662386f26fc100008310612aa857662386f26fc100008381612a9e57612a9d614428565b5b0492506010810190505b6305f5e1008310612ad1576305f5e1008381612ac757612ac6614428565b5b0492506008810190505b6127108310612af6576127108381612aec57612aeb614428565b5b0492506004810190505b60648310612b195760648381612b0f57612b0e614428565b5b0492506002810190505b600a8310612b28576001810190505b80915050919050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612ba45750612ba382612d09565b5b9050919050565b612bb784848484612d73565b6001811115612bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bf2906146f8565b60405180910390fd5b6000829050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612c4257612c3d81612d79565b612c81565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612c8057612c7f8582612dc2565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612cc357612cbe81612f2f565b612d02565b8473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614612d0157612d008482613000565b5b5b5050505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b50505050565b600a80549050600b600083815260200190815260200160002081905550600a81908060018154018082558091505060019003906000526020600020016000909190919091505550565b60006001612dcf84610c92565b612dd99190614623565b9050600060096000848152602001908152602001600020549050818114612ebe576000600860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816009600083815260200190815260200160002081905550505b6009600084815260200190815260200160002060009055600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600a80549050612f439190614623565b90506000600b60008481526020019081526020016000205490506000600a8381548110612f7357612f72613ba4565b5b9060005260206000200154905080600a8381548110612f9557612f94613ba4565b5b906000526020600020018190555081600b600083815260200190815260200160002081905550600b600085815260200190815260200160002060009055600a805480612fe457612fe3614657565b5b6001900381819060005260206000200160009055905550505050565b600061300b83610c92565b905081600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806009600084815260200190815260200160002081905550505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6130c881613093565b81146130d357600080fd5b50565b6000813590506130e5816130bf565b92915050565b60006020828403121561310157613100613089565b5b600061310f848285016130d6565b91505092915050565b60008115159050919050565b61312d81613118565b82525050565b60006020820190506131486000830184613124565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561318857808201518184015260208101905061316d565b60008484015250505050565b6000601f19601f8301169050919050565b60006131b08261314e565b6131ba8185613159565b93506131ca81856020860161316a565b6131d381613194565b840191505092915050565b600060208201905081810360008301526131f881846131a5565b905092915050565b6000819050919050565b61321381613200565b811461321e57600080fd5b50565b6000813590506132308161320a565b92915050565b60006020828403121561324c5761324b613089565b5b600061325a84828501613221565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061328e82613263565b9050919050565b61329e81613283565b82525050565b60006020820190506132b96000830184613295565b92915050565b6132c881613283565b81146132d357600080fd5b50565b6000813590506132e5816132bf565b92915050565b6000806040838503121561330257613301613089565b5b6000613310858286016132d6565b925050602061332185828601613221565b9150509250929050565b61333481613200565b82525050565b600060208201905061334f600083018461332b565b92915050565b60008060006060848603121561336e5761336d613089565b5b600061337c868287016132d6565b935050602061338d868287016132d6565b925050604061339e86828701613221565b9150509250925092565b6000819050919050565b6133bb816133a8565b81146133c657600080fd5b50565b6000813590506133d8816133b2565b92915050565b6000602082840312156133f4576133f3613089565b5b6000613402848285016133c9565b91505092915050565b613414816133a8565b82525050565b600060208201905061342f600083018461340b565b92915050565b6000806040838503121561344c5761344b613089565b5b600061345a858286016133c9565b925050602061346b858286016132d6565b9150509250929050565b60006020828403121561348b5761348a613089565b5b6000613499848285016132d6565b91505092915050565b600080604083850312156134b9576134b8613089565b5b60006134c7858286016133c9565b92505060206134d885828601613221565b9150509250929050565b6134eb81613118565b81146134f657600080fd5b50565b600081359050613508816134e2565b92915050565b6000806040838503121561352557613524613089565b5b6000613533858286016132d6565b9250506020613544858286016134f9565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61359082613194565b810181811067ffffffffffffffff821117156135af576135ae613558565b5b80604052505050565b60006135c261307f565b90506135ce8282613587565b919050565b600067ffffffffffffffff8211156135ee576135ed613558565b5b6135f782613194565b9050602081019050919050565b82818337600083830152505050565b6000613626613621846135d3565b6135b8565b90508281526020810184848401111561364257613641613553565b5b61364d848285613604565b509392505050565b600082601f83011261366a5761366961354e565b5b813561367a848260208601613613565b91505092915050565b6000806000806080858703121561369d5761369c613089565b5b60006136ab878288016132d6565b94505060206136bc878288016132d6565b93505060406136cd87828801613221565b925050606085013567ffffffffffffffff8111156136ee576136ed61308e565b5b6136fa87828801613655565b91505092959194509250565b6000806040838503121561371d5761371c613089565b5b600061372b858286016132d6565b925050602061373c858286016132d6565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061378d57607f821691505b6020821081036137a05761379f613746565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613802602183613159565b915061380d826137a6565b604082019050919050565b60006020820190508181036000830152613831816137f5565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613894603d83613159565b915061389f82613838565b604082019050919050565b600060208201905081810360008301526138c381613887565b9050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613926602d83613159565b9150613931826138ca565b604082019050919050565b6000602082019050818103600083015261395581613919565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b60006139b8602b83613159565b91506139c38261395c565b604082019050919050565b600060208201905081810360008301526139e7816139ab565b9050919050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b6000613a4a602f83613159565b9150613a55826139ee565b604082019050919050565b60006020820190508181036000830152613a7981613a3d565b9050919050565b7f4552433732315072657365744d696e7465725061757365724175746f49643a2060008201527f6d75737420686176652070617573657220726f6c6520746f20756e7061757365602082015250565b6000613adc604083613159565b9150613ae782613a80565b604082019050919050565b60006020820190508181036000830152613b0b81613acf565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000613b6e602c83613159565b9150613b7982613b12565b604082019050919050565b60006020820190508181036000830152613b9d81613b61565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b6000613c09601883613159565b9150613c1482613bd3565b602082019050919050565b60006020820190508181036000830152613c3881613bfc565b9050919050565b7f4552433732315072657365744d696e7465725061757365724175746f49643a2060008201527f6d7573742068617665206d696e74657220726f6c6520746f206d696e74000000602082015250565b6000613c9b603d83613159565b9150613ca682613c3f565b604082019050919050565b60006020820190508181036000830152613cca81613c8e565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b6000613d2d602983613159565b9150613d3882613cd1565b604082019050919050565b60006020820190508181036000830152613d5c81613d20565b9050919050565b7f4552433732315072657365744d696e7465725061757365724175746f49643a2060008201527f6d75737420686176652070617573657220726f6c6520746f2070617573650000602082015250565b6000613dbf603e83613159565b9150613dca82613d63565b604082019050919050565b60006020820190508181036000830152613dee81613db2565b9050919050565b600081905092915050565b6000613e0b8261314e565b613e158185613df5565b9350613e2581856020860161316a565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000815250565b6000613e638284613e00565b9150613e6e82613e31565b60058201915081905092915050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b6000613ed9602583613159565b9150613ee482613e7d565b604082019050919050565b60006020820190508181036000830152613f0881613ecc565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000613f6b602483613159565b9150613f7682613f0f565b604082019050919050565b60006020820190508181036000830152613f9a81613f5e565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000613fd7602083613159565b9150613fe282613fa1565b602082019050919050565b6000602082019050818103600083015261400681613fca565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614043601c83613159565b915061404e8261400d565b602082019050919050565b6000602082019050818103600083015261407281614036565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006140af601983613159565b91506140ba82614079565b602082019050919050565b600060208201905081810360008301526140de816140a2565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614141603283613159565b915061414c826140e5565b604082019050919050565b6000602082019050818103600083015261417081614134565b9050919050565b60006141838285613e00565b915061418f8284613e00565b91508190509392505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b60006141d1601783613df5565b91506141dc8261419b565b601782019050919050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b600061421d601183613df5565b9150614228826141e7565b601182019050919050565b600061423e826141c4565b915061424a8285613e00565b915061425582614210565b91506142618284613e00565b91508190509392505050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b60006142a3601483613159565b91506142ae8261426d565b602082019050919050565b600060208201905081810360008301526142d281614296565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b600061430f601083613159565b915061431a826142d9565b602082019050919050565b6000602082019050818103600083015261433e81614302565b9050919050565b600081519050919050565b600082825260208201905092915050565b600061436c82614345565b6143768185614350565b935061438681856020860161316a565b61438f81613194565b840191505092915050565b60006080820190506143af6000830187613295565b6143bc6020830186613295565b6143c9604083018561332b565b81810360608301526143db8184614361565b905095945050505050565b6000815190506143f5816130bf565b92915050565b60006020828403121561441157614410613089565b5b600061441f848285016143e6565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4552433732315061757361626c653a20746f6b656e207472616e73666572207760008201527f68696c6520706175736564000000000000000000000000000000000000000000602082015250565b60006144b3602b83613159565b91506144be82614457565b604082019050919050565b600060208201905081810360008301526144e2816144a6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061452382613200565b915061452e83613200565b925082820261453c81613200565b91508282048414831517614553576145526144e9565b5b5092915050565b600061456582613200565b915061457083613200565b9250828201905080821115614588576145876144e9565b5b92915050565b600061459982613200565b9150600082036145ac576145ab6144e9565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b60006145ed602083613159565b91506145f8826145b7565b602082019050919050565b6000602082019050818103600083015261461c816145e0565b9050919050565b600061462e82613200565b915061463983613200565b9250828203905081811115614651576146506144e9565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f455243373231456e756d657261626c653a20636f6e736563757469766520747260008201527f616e7366657273206e6f7420737570706f727465640000000000000000000000602082015250565b60006146e2603583613159565b91506146ed82614686565b604082019050919050565b60006020820190508181036000830152614711816146d5565b905091905056fea2646970667358221220e972bbd276839058152a76991f80e14bc204d51ef1164ea5b20e88b88893b61164736f6c63430008110033' + } +]; + +/** + * Test smart contract address + */ +const testSmartContract = '0xa540a1924dff8db10bcb3aba3183c0385f2ad285'; + +/** + * Test storage position key + */ +const testStoragePositionKey = + '0x0000000000000000000000000000000000000000000000000000000000000001'; + +/** + * Empty storage slot + */ +const NULL_STORAGE_SLOT = + '0x0000000000000000000000000000000000000000000000000000000000000000'; + +/** + * Invalid getStorageAt test cases for invalid data types + */ +const invalidGetStorageAtTests = [ + { + description: 'Should throw error for invalid revision', + address: testSmartContract, + position: testStoragePositionKey, + revision: 'invalid-revision', + expectedError: InvalidDataTypeError + }, + { + description: 'Should throw error for invalid position', + address: testSmartContract, + position: 'invalid-position', + revision: '1', + expectedError: InvalidDataTypeError + }, + { + description: 'Should throw error for invalid address', + address: 'invalid-address', + position: '0x123', + revision: '1', + expectedError: InvalidDataTypeError + } +]; + +export { + thorClient, + getAccountWithRevisionTestCases, + getBytecodeTestCases, + testSmartContract, + testStoragePositionKey, + NULL_STORAGE_SLOT, + invalidGetStorageAtTests +}; diff --git a/packages/network/tests/client/thor/thorclient.testnet.test.ts b/packages/network/tests/client/thor/thorclient.testnet.test.ts new file mode 100644 index 000000000..13143bbb0 --- /dev/null +++ b/packages/network/tests/client/thor/thorclient.testnet.test.ts @@ -0,0 +1,138 @@ +import { describe, expect, test } from '@jest/globals'; +import { + NULL_STORAGE_SLOT, + getAccountWithRevisionTestCases, + getBytecodeTestCases, + invalidGetStorageAtTests, + testSmartContract, + testStoragePositionKey, + thorClient +} from './fixture'; +import { testAccount } from '../../fixture'; +import { InvalidDataTypeError } from '@vechain-sdk/errors'; + +/** + * ThorClient class tests + * + * @group integration/client/thor + */ +describe('ThorClient', () => { + /** + * getAccount tests + */ + describe('getAccount', () => { + /** + * getAccount tests with revision block number or block id + */ + getAccountWithRevisionTestCases.forEach( + ({ description, account, revision, expected }) => { + test(description, async () => { + const accountDetails = await thorClient.getAccount( + account, + revision + ); + expect(accountDetails).toEqual(expected); + }); + } + ); + + /** + * getAccount without revision (latest block) + */ + test('get account without revision', async () => { + const accountDetails = await thorClient.getAccount(testAccount); + expect(accountDetails).toBeDefined(); + expect(accountDetails.balance).toBeDefined(); + expect(accountDetails.energy).toBeDefined(); + expect(accountDetails.hasCode).toBeDefined(); + expect(accountDetails.hasCode).toEqual(false); + }); + + /** + * getAccount with invalid revision + */ + test('get account with invalid revision', async () => { + await expect( + thorClient.getAccount(testAccount, 'invalid-revision') + ).rejects.toThrowError(InvalidDataTypeError); + }); + }); + + /** + * getBytecode tests + */ + describe('getBytecode', () => { + /** + * Tests VTHO contract bytecode and revision + */ + getBytecodeTestCases.forEach( + ({ description, address, revision, expected }) => { + test(description, async () => { + const bytecode = await thorClient.getBytecode( + address, + revision + ); + expect(bytecode).toEqual(expected); + }); + } + ); + + /** + * Tests invalid revision + */ + test('invalid revision should throw an error', async () => { + await expect( + thorClient.getBytecode(testAccount, 'invalid-revision') + ).rejects.toThrowError(InvalidDataTypeError); + }); + }); + + /** + * getStorageAt tests + */ + describe('getStorageAt', () => { + /** + * Tests storage data at the specified position of the smart contract + */ + test('Should get the storage data at the specified position of the smart contract', async () => { + const storageData = await thorClient.getStorageAt( + testSmartContract, + testStoragePositionKey + ); + + expect(storageData).toBeDefined(); + expect(storageData).not.toEqual(NULL_STORAGE_SLOT); + }); + + /** + * Tests storage data at the specified position of the smart contract with revision + */ + test('Should get the storage data at the specified position of the smart contract with revision', async () => { + const storageData = await thorClient.getStorageAt( + testSmartContract, + testStoragePositionKey, + '1' + ); + + expect(storageData).toBeDefined(); + expect(storageData).toEqual(NULL_STORAGE_SLOT); + }); + + /** + * Tests invalid position & revisions + */ + invalidGetStorageAtTests.forEach( + ({ description, position, revision, expectedError }) => { + test(description, async () => { + await expect( + thorClient.getStorageAt( + testSmartContract, + position, + revision + ) + ).rejects.toThrowError(expectedError); + }); + } + ); + }); +}); diff --git a/packages/network/tests/fixture.ts b/packages/network/tests/fixture.ts new file mode 100644 index 000000000..0ffa549fd --- /dev/null +++ b/packages/network/tests/fixture.ts @@ -0,0 +1,33 @@ +import { HttpClient } from '../src'; + +/** + * Url of the testnet fixture + */ +const _testnetUrl = 'https://testnet.vechain.org'; + +/** + * Url of the solo network fixture + */ +const _soloUrl = 'http://localhost:8669'; + +/** + * Network instance fixture + */ +const testNetwork = new HttpClient(_testnetUrl); + +/** + * Solo network instance fixture + */ +const soloNetwork = new HttpClient(_soloUrl); + +/** + * Simple test account fixture + */ +const testAccount = '0xf077b491b355E64048cE21E3A6Fc4751eEeA77fa'; + +/** + * Zero address fixture + */ +const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; + +export { testNetwork, soloNetwork, ZERO_ADDRESS, testAccount }; From 640cd7accebd8a69ecb2fd65107b17d2cf977dc3 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Tue, 7 Nov 2023 10:56:06 +0100 Subject: [PATCH 12/26] feat: block utils --- packages/network/src/utils/block.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 packages/network/src/utils/block.ts diff --git a/packages/network/src/utils/block.ts b/packages/network/src/utils/block.ts new file mode 100644 index 000000000..01edebda9 --- /dev/null +++ b/packages/network/src/utils/block.ts @@ -0,0 +1,24 @@ +import { dataUtils } from '@vechain-sdk/core'; + +/** + * Determines whether the provided string is a valid block revision. + * A valid block revision is either a hex string for the block id or a decimal string for the block number. + * + * @param revision - The string to be validated as a block revision. + * @returns `true` if the string is a valid block revision, otherwise `false`. + */ +const isBlockRevision = (revision: string): boolean => { + if ( + !dataUtils.isHexString(revision) && + !dataUtils.isDecimalString(revision) + ) { + return false; + } + + return true; +}; + +/** + * A utility object for block-related utility operations. + */ +export const blockUtils = { isBlockRevision }; From 587ac50ddf049b400fcda9d6a2a4f9b72d81fb67 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Tue, 7 Nov 2023 10:56:24 +0100 Subject: [PATCH 13/26] chore: completed merge with main --- .github/workflows/typedoc.yml | 64 +++++++ .gitignore | 3 +- docs/encoding.md | 54 +++++- docs/examples/encoding/contract.ts | 43 +++++ docs/templates/encoding.md | 10 +- package.json | 4 +- packages/core/src/abi/contract.ts | 135 +++++++++++++++ packages/core/src/abi/fragment.ts | 7 +- packages/core/src/abi/index.ts | 1 + packages/core/src/certificate/types.d.ts | 2 +- packages/core/tests/abi/abi.test.ts | 11 +- packages/core/tests/abi/contract.test.ts | 156 ++++++++++++++++++ packages/core/tests/abi/fixture.ts | 90 +++++++++- packages/core/typedoc.json | 4 + packages/errors/src/model/base.ts | 8 +- packages/errors/src/model/{ => core}/abi.ts | 20 ++- .../errors/src/model/{ => core}/address.ts | 4 +- packages/errors/src/model/{ => core}/bloom.ts | 4 +- .../src/model/{ => core}/certificate.ts | 4 +- packages/errors/src/model/{ => core}/data.ts | 4 +- .../errors/src/model/{ => core}/hdnode.ts | 4 +- packages/errors/src/model/core/index.ts | 10 ++ .../errors/src/model/{ => core}/keystore.ts | 4 +- packages/errors/src/model/{ => core}/rlp.ts | 2 +- .../errors/src/model/{ => core}/secp256k1.ts | 4 +- .../src/model/{ => core}/transaction.ts | 4 +- packages/errors/src/model/index.ts | 12 +- .../errors/src/model/network/http-client.ts | 39 +++++ packages/errors/src/model/network/index.ts | 1 + packages/errors/src/types/errorTypes.ts | 72 ++++---- packages/errors/src/utils/errorBuilder.ts | 26 ++- packages/errors/tests/errorHandler.test.ts | 45 ++++- packages/errors/tests/fixture.ts | 18 +- packages/errors/typedoc.json | 4 + .../network/src/client/http/helpers/errors.ts | 37 ----- .../network/src/client/http/http-client.ts | 14 +- packages/network/src/client/http/index.ts | 1 - packages/network/src/client/http/types.d.ts | 8 +- packages/network/src/client/index.ts | 1 + .../network/src/client/thor/accounts/index.ts | 2 + packages/network/src/client/thor/api.ts | 34 ++++ .../network/src/client/thor/helpers/index.ts | 1 + .../src/client/thor/helpers/request.ts | 24 +++ packages/network/src/client/thor/index.ts | 1 + .../src/client/thor/thor-readonly-client.ts | 0 packages/network/src/utils/helpers/errors.ts | 48 ++++++ packages/network/src/utils/helpers/index.ts | 1 + packages/network/src/utils/index.ts | 2 + .../tests/{driver => client/http}/fixture.ts | 45 +---- .../http/http-client.solo.test.ts} | 18 +- .../http/http-client.testnet.test.ts} | 32 ++-- .../tests/utils/{ => helpers}/fixture.ts | 11 +- .../tests/utils/{ => helpers}/utils.test.ts | 14 +- packages/network/typedoc.json | 4 + typedoc.base.json | 15 ++ typedoc.json | 13 ++ yarn.lock | 57 +++++++ 57 files changed, 1051 insertions(+), 205 deletions(-) create mode 100644 .github/workflows/typedoc.yml create mode 100644 docs/examples/encoding/contract.ts create mode 100644 packages/core/src/abi/contract.ts create mode 100644 packages/core/tests/abi/contract.test.ts create mode 100644 packages/core/typedoc.json rename packages/errors/src/model/{ => core}/abi.ts (79%) rename packages/errors/src/model/{ => core}/address.ts (84%) rename packages/errors/src/model/{ => core}/bloom.ts (90%) rename packages/errors/src/model/{ => core}/certificate.ts (93%) rename packages/errors/src/model/{ => core}/data.ts (90%) rename packages/errors/src/model/{ => core}/hdnode.ts (96%) create mode 100644 packages/errors/src/model/core/index.ts rename packages/errors/src/model/{ => core}/keystore.ts (91%) rename packages/errors/src/model/{ => core}/rlp.ts (93%) rename packages/errors/src/model/{ => core}/secp256k1.ts (95%) rename packages/errors/src/model/{ => core}/transaction.ts (94%) create mode 100644 packages/errors/src/model/network/http-client.ts create mode 100644 packages/errors/src/model/network/index.ts create mode 100644 packages/errors/typedoc.json delete mode 100644 packages/network/src/client/http/helpers/errors.ts create mode 100644 packages/network/src/client/thor/accounts/index.ts create mode 100644 packages/network/src/client/thor/api.ts create mode 100644 packages/network/src/client/thor/helpers/index.ts create mode 100644 packages/network/src/client/thor/helpers/request.ts delete mode 100644 packages/network/src/client/thor/thor-readonly-client.ts create mode 100644 packages/network/src/utils/helpers/errors.ts create mode 100644 packages/network/src/utils/helpers/index.ts rename packages/network/tests/{driver => client/http}/fixture.ts (51%) rename packages/network/tests/{driver/driver.solo.test.ts => client/http/http-client.solo.test.ts} (81%) rename packages/network/tests/{driver/driver.testnet.test.ts => client/http/http-client.testnet.test.ts} (72%) rename packages/network/tests/utils/{ => helpers}/fixture.ts (86%) rename packages/network/tests/utils/{ => helpers}/utils.test.ts (65%) create mode 100644 packages/network/typedoc.json create mode 100644 typedoc.base.json create mode 100644 typedoc.json diff --git a/.github/workflows/typedoc.yml b/.github/workflows/typedoc.yml new file mode 100644 index 000000000..f69131eaa --- /dev/null +++ b/.github/workflows/typedoc.yml @@ -0,0 +1,64 @@ +name: Publish TypeDoc + +on: + push: + branches: + - 'githubpages' + workflow_dispatch: + + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one instance of wf to run at once +concurrency: + group: "pages" + cancel-in-progress: false + +env: + BUILD_PATH: "./api-docs/" + +jobs: + build-api-docs: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + + - name: Install packages + run: yarn install + + - name: Build + run: yarn build + + - name: Generate api docs + run: yarn generate:apidocs + + - name: Setup pages + uses: actions/configure-pages@v3 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v2 + with: + path: ${{ env.BUILD_PATH }} + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build-api-docs + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 diff --git a/.gitignore b/.gitignore index 8663d547e..5dbe7f155 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ junit.xml .turbo # docs -docs/build/*.md \ No newline at end of file +docs/build/*.md +api-docs/ \ No newline at end of file diff --git a/docs/encoding.md b/docs/encoding.md index 5dbf01629..edb51ee82 100644 --- a/docs/encoding.md +++ b/docs/encoding.md @@ -56,9 +56,60 @@ expect(data).toBe(expected); ``` +## Contract + +The contract interface is used to provide a higher level of abstraction to allow direct interaction with a smart contract. To create a contract interface is necessary to have a compatible smart contract ABI. Vechain SDK provides a full implementation of the Contract interface as well as some methods to encode directly a specific fragment of the smart contract (until now only functions and events fragments are supported). Encoding and decoding are based on the ABI one. + +```typescript { name=contract, category=example } +import { contract } from '@vechain-sdk/core'; +import { expect } from 'expect'; + +const contractABI = JSON.stringify([ + { + constant: false, + inputs: [ + { + name: 'value', + type: 'uint256' + } + ], + name: 'setValue', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function' + }, + { + constant: true, + inputs: [], + name: 'getValue', + outputs: [ + { + name: '', + type: 'uint256' + } + ], + payable: false, + stateMutability: 'view', + type: 'function' + } +]); + +const encodedData = contract.encodeFunctionInput(contractABI, 'setValue', [ + 123 +]); // encode the function input, ready to be used to send a tx + +const decodedData = String( + contract.decodeFunctionInput(contractABI, 'setValue', encodedData)[0] +); // decode the function input data + +expect(decodedData).toEqual('123'); + +``` + ## RLP Encoding -RLP is a serialisation technique used on the VechainThor blockchain. It is used to efficiently encode and decode data structures for storage and transmission on the blockchain. VeChain SDK includes dedicated methods for RLP encoding and decoding, enabling developers to handle data serialization and deserialization with ease. +RLP is a serialisation technique used on the VechainThor blockchain. It is used to efficiently encode and decode data structures for storage and transmission on the blockchain. VeChain SDK includes dedicated methods for RLP encoding and decoding, enabling developers to handle data serialization and deserialization with ease. By supporting ABI and RLP encoding handling, VeChain SDK equips developers with the necessary tools to interact with smart contracts and handle data efficiently on the VechainThor blockchain. This further enhances the library's capabilities and contributes to the seamless development of decentralised applications on the platform. @@ -96,3 +147,4 @@ const obj = rlp.decodeObject(data); expect(JSON.stringify(obj)).toBe(JSON.stringify(clause)); ``` + diff --git a/docs/examples/encoding/contract.ts b/docs/examples/encoding/contract.ts new file mode 100644 index 000000000..a021a4e16 --- /dev/null +++ b/docs/examples/encoding/contract.ts @@ -0,0 +1,43 @@ +import { contract } from '@vechain-sdk/core'; +import { expect } from 'expect'; + +const contractABI = JSON.stringify([ + { + constant: false, + inputs: [ + { + name: 'value', + type: 'uint256' + } + ], + name: 'setValue', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function' + }, + { + constant: true, + inputs: [], + name: 'getValue', + outputs: [ + { + name: '', + type: 'uint256' + } + ], + payable: false, + stateMutability: 'view', + type: 'function' + } +]); + +const encodedData = contract.encodeFunctionInput(contractABI, 'setValue', [ + 123 +]); // encode the function input, ready to be used to send a tx + +const decodedData = String( + contract.decodeFunctionInput(contractABI, 'setValue', encodedData)[0] +); // decode the function input data + +expect(decodedData).toEqual('123'); diff --git a/docs/templates/encoding.md b/docs/templates/encoding.md index 241ac2ae5..760c4c842 100644 --- a/docs/templates/encoding.md +++ b/docs/templates/encoding.md @@ -12,10 +12,16 @@ VeChain SDK provides functionality to interact with smart contracts on the Vecha [example](examples/encoding/abi.ts) +## Contract + +The contract interface is used to provide a higher level of abstraction to allow direct interaction with a smart contract. To create a contract interface is necessary to have a compatible smart contract ABI. Vechain SDK provides a full implementation of the Contract interface as well as some methods to encode directly a specific fragment of the smart contract (until now only functions and events fragments are supported). Encoding and decoding are based on the ABI one. + +[example](examples/encoding/contract.ts) + ## RLP Encoding -RLP is a serialisation technique used on the VechainThor blockchain. It is used to efficiently encode and decode data structures for storage and transmission on the blockchain. VeChain SDK includes dedicated methods for RLP encoding and decoding, enabling developers to handle data serialization and deserialization with ease. +RLP is a serialisation technique used on the VechainThor blockchain. It is used to efficiently encode and decode data structures for storage and transmission on the blockchain. VeChain SDK includes dedicated methods for RLP encoding and decoding, enabling developers to handle data serialization and deserialization with ease. By supporting ABI and RLP encoding handling, VeChain SDK equips developers with the necessary tools to interact with smart contracts and handle data efficiently on the VechainThor blockchain. This further enhances the library's capabilities and contributes to the seamless development of decentralised applications on the platform. -[example](examples/encoding/rlp.ts) \ No newline at end of file +[example](examples/encoding/rlp.ts) diff --git a/package.json b/package.json index d1158eb88..66188f151 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "format": "turbo format", "test:docs": "turbo test:docs", "test:examples": "turbo test:examples", - "merge-coverage": "ts-node scripts/merge-coverage.ts" + "merge-coverage": "ts-node scripts/merge-coverage.ts", + "generate:apidocs": "typedoc --options typedoc.json --logLevel Verbose" }, "private": true, "workspaces": [ @@ -49,6 +50,7 @@ "ts-jest": "^29.1.1", "tsup": "^7.2.0", "turbo": "^1.10.15", + "typedoc": "^0.25.3", "typescript": "*" } } diff --git a/packages/core/src/abi/contract.ts b/packages/core/src/abi/contract.ts new file mode 100644 index 000000000..d0a388f2c --- /dev/null +++ b/packages/core/src/abi/contract.ts @@ -0,0 +1,135 @@ +import { type InterfaceAbi, Interface as EthersInterface } from 'ethers'; +import type { BytesLike, Interface, Result } from './types'; +import { abi } from './coder'; +import { ERROR_CODES, buildError } from '@vechain-sdk/errors'; + +/** + * Creates a new Interface instance from an ABI fragment. + * @param abi - ABI in a compatible format + * @returns The Interface instance. + */ +function createInterface(abi: InterfaceAbi): Interface { + return new EthersInterface(abi); +} + +/** + * Encode function data that can be used to send a transaction. + * @param abi ABI in a compatible format + * @param functionName The name of the function defined in the ABI. + * @param functionData The data to pass to the function. + * @returns The encoded data that can be used to send a transaction. + * @throws {ContractInterfaceError} + */ +function encodeFunctionInput( + interfaceABI: InterfaceAbi, + functionName: string, + functionData?: unknown[] +): string { + try { + const contractInterface = createInterface(interfaceABI); + return new abi.Function( + contractInterface.getFunction(functionName) + ).encodeInput(functionData); + } catch (e) { + throw buildError( + ERROR_CODES.ABI.CONTRACT_INTERFACE_ERROR, + 'Cannot encode the input of the function', + { functionName, functionData }, + e + ); + } +} + +/** + * Decode the function data of an encoded function + * @param abi ABI in a compatible format + * @param functionName The name of the function defined in the ABI. + * @param encodedFunction The encoded function data. + * @returns an array of the decoded function data + * @throws {ContractInterfaceError} + */ +function decodeFunctionInput( + interfaceABI: InterfaceAbi, + functionName: string, + encodedFunction: BytesLike +): Result { + try { + const contractInterface = createInterface(interfaceABI); + return new abi.Function( + contractInterface.getFunction(functionName) + ).decodeInput(encodedFunction); + } catch (e) { + throw buildError( + ERROR_CODES.ABI.CONTRACT_INTERFACE_ERROR, + 'Cannot decode the input of the function', + { functionName }, + e + ); + } +} + +/** + * Encode event log data. + * @param abi ABI in a compatible format + * @param functionName The name of the function defined in the ABI. + * @param functionData The data to pass to the function. + * @returns The encoded data that can be used to send a transaction. + * @throws {ContractInterfaceError} + */ +function encodeEventLog( + interfaceABI: InterfaceAbi, + eventName: string, + dataToEncode: unknown[] +): { data: string; topics: string[] } { + try { + const contractInterface = createInterface(interfaceABI); + return new abi.Event( + contractInterface.getEvent(eventName) + ).encodeEventLog(dataToEncode); + } catch (e) { + throw buildError( + ERROR_CODES.ABI.CONTRACT_INTERFACE_ERROR, + 'Cannot encode the input of the event log', + { eventName }, + e + ); + } +} + +/** + * Decode event log data + * @param abi ABI in a compatible format + * @param functionName The name of the function defined in the ABI. + * @param encodedFunction The encoded function data. + * @returns an array of the decoded function data + * @throws {ContractInterfaceError} + */ +function decodeEventLog( + interfaceABI: InterfaceAbi, + eventName: string, + dataToDecode: { data: string; topics: string[] } +): Result { + try { + const contractInterface = createInterface(interfaceABI); + return new abi.Event( + contractInterface.getEvent(eventName) + ).decodeEventLog(dataToDecode); + } catch (e) { + throw buildError( + ERROR_CODES.ABI.CONTRACT_INTERFACE_ERROR, + 'Cannot decode the input of the event log', + { eventName }, + e + ); + } +} + +const contract = { + createInterface, + encodeFunctionInput, + decodeFunctionInput, + encodeEventLog, + decodeEventLog +}; + +export { contract }; diff --git a/packages/core/src/abi/fragment.ts b/packages/core/src/abi/fragment.ts index ef7364ef9..b4adce0a1 100644 --- a/packages/core/src/abi/fragment.ts +++ b/packages/core/src/abi/fragment.ts @@ -3,7 +3,8 @@ import { type Interface, type FunctionFragment, type Result, - type FormatType + type FormatType, + type BytesLike } from './types'; import { ABI, buildError } from '@vechain-sdk/errors'; @@ -99,7 +100,7 @@ class Function { * @param data - Data to decode. * @returns Decoding results. */ - public decodeOutput(data: string): Result { + public decodeInput(data: BytesLike): Result { try { return this.iface.decodeFunctionData(this.fragment, data); } catch { @@ -117,7 +118,7 @@ class Function { * @param dataToEncode - Data to encode. * @returns Encoded data. */ - public encodeInput(dataToEncode: TValue[]): string { + public encodeInput(dataToEncode?: TValue[]): string { try { return this.iface.encodeFunctionData(this.fragment, dataToEncode); } catch { diff --git a/packages/core/src/abi/index.ts b/packages/core/src/abi/index.ts index 218f1e1e6..f4d734b78 100644 --- a/packages/core/src/abi/index.ts +++ b/packages/core/src/abi/index.ts @@ -1,3 +1,4 @@ export * from './types.d'; export * from './fragment'; export * from './coder'; +export * from './contract'; diff --git a/packages/core/src/certificate/types.d.ts b/packages/core/src/certificate/types.d.ts index a8b62be66..6bdf4cb64 100644 --- a/packages/core/src/certificate/types.d.ts +++ b/packages/core/src/certificate/types.d.ts @@ -18,7 +18,7 @@ * @field signature - The signature field contains the cryptographic signature generated by the issuer's private key. * This signature ensures the integrity and authenticity of the certificate's content. */ -export interface Certificate { +interface Certificate { purpose: string; payload: { type: string; diff --git a/packages/core/tests/abi/abi.test.ts b/packages/core/tests/abi/abi.test.ts index b4ca8f2d4..85bec031b 100644 --- a/packages/core/tests/abi/abi.test.ts +++ b/packages/core/tests/abi/abi.test.ts @@ -127,7 +127,7 @@ describe('Abi - Function & Event', () => { * Encode and Decode. * Test with each function in each format. */ - test('Encode inputs AND Decode outputs', () => { + test('Encode AND Decode', () => { // Create a function from each format and compare between format (test if conversions are correct) functions .map((fixtureFunction) => { @@ -210,11 +210,10 @@ describe('Abi - Function & Event', () => { expect(encoded).toBeDefined(); - // Decode output - const decoded = - myFunction.decodeOutput(encoded); + // Decode input + const decoded = myFunction.decodeInput(encoded); - // Encoded input will be equal to decoded output + // Encoded input will be equal to decoded input expect(decoded).toStrictEqual(encodingInput); } ); @@ -243,7 +242,7 @@ describe('Abi - Function & Event', () => { ).toThrowError(InvalidAbiDataToEncodeError); // Decode - expect(() => myFunction.decodeOutput('INVALID')).toThrowError( + expect(() => myFunction.decodeInput('INVALID')).toThrowError( InvalidAbiDataToDecodeError ); }); diff --git a/packages/core/tests/abi/contract.test.ts b/packages/core/tests/abi/contract.test.ts new file mode 100644 index 000000000..60ec4db0b --- /dev/null +++ b/packages/core/tests/abi/contract.test.ts @@ -0,0 +1,156 @@ +import { describe, expect, test } from '@jest/globals'; +import { + ValueChangedEventData, + contractABI, + contractABIWithEvents +} from './fixture'; +import { contract } from '../../src/abi/contract'; +import { abi } from '../../src'; +import { ethers } from 'ethers'; +import { ContractInterfaceError } from '@vechain-sdk/errors'; + +/** + * Contract tests - encode & decode + * @group unit/encode-decode + */ +describe('Contract interface for ABI encoding/decoding', () => { + /** + * Test the creation of a contract interface. + */ + test('Create a contract interface from an ABI json', () => { + expect(contract.createInterface(contractABI)).toBeDefined(); + }); + + /** + * Test the encoding of a function fragment. + */ + test('get a function fragment and encode it', () => { + const contractInterface = contract.createInterface(contractABI); + + expect( + contractInterface.encodeFunctionData('setValue', [123]) + ).toBeDefined(); + expect(contractInterface.encodeFunctionData('getValue')).toBeDefined(); + }); + + /** + * Test the encoding of a function fragment with the custom encoding function data method. + */ + test('get a function fragment and encode it', () => { + const contractInterface = contract.createInterface(contractABI); + + expect( + contract.encodeFunctionInput(contractABI, 'setValue', [123]) + ).toEqual( + new abi.Function( + contractInterface.getFunction('setValue') + ).encodeInput([123]) + ); + + expect(contract.encodeFunctionInput(contractABI, 'getValue')).toEqual( + contractInterface.encodeFunctionData('getValue') + ); + }); + + /** + * Test the failed encoding of a function input. + */ + test('Fail to encode a contract function input', () => { + expect(() => + contract.encodeFunctionInput(contractABI, 'undefined', [123]) + ).toThrowError(ContractInterfaceError); + }); + + /** + * Test the decoding of a function fragment data with the custom decoding data method + */ + test('decode a function fragment data', () => { + const contractInterface = contract.createInterface(contractABI); + const encodedData = contractInterface.encodeFunctionData('setValue', [ + 123 + ]); + const decodedData = String( + contract.decodeFunctionInput( + contractABI, + 'setValue', + encodedData + )[0] + ); + expect(decodedData).toEqual('123'); + }); + + /** + * Test the failed decoding of a function input. + */ + test('Fail to decode a contract function input', () => { + expect(() => + contract.decodeFunctionInput(contractABI, 'setValue', '0x123') + ).toThrowError(ContractInterfaceError); + }); + + /** + * Test the encoding of an event fragment with the custom encoding method in contract. + */ + test('get an event fragment and encode it', () => { + const contractInterface = new ethers.Interface(contractABIWithEvents); + + expect( + contract.encodeEventLog(contractABIWithEvents, 'ValueChanged', [ + ValueChangedEventData.sender, + ValueChangedEventData.value + ]) + ).toEqual( + contractInterface.encodeEventLog('ValueChanged', [ + ValueChangedEventData.sender, + ValueChangedEventData.value + ]) + ); + }); + + /** + * Test the failed encoding of an event log. + */ + test('Fail to encode a contract event log', () => { + expect(() => + contract.encodeEventLog(contractABI, 'undefined', []) + ).toThrowError(ContractInterfaceError); + }); + + /** + * Test the decoding of an encoded event with the custom decoding method in contract. + */ + test('get an event fragment and decode it', () => { + const contractInterface = new ethers.Interface(contractABIWithEvents); + const encodedEventLog = contract.encodeEventLog( + contractABIWithEvents, + 'ValueChanged', + [ValueChangedEventData.sender, ValueChangedEventData.value] + ); + + expect( + contract.decodeEventLog( + contractABIWithEvents, + 'ValueChanged', + encodedEventLog + ) + ).toEqual( + contractInterface.decodeEventLog( + 'ValueChanged', + encodedEventLog.data, + encodedEventLog.topics + ) + ); + }); + + /** + * Test the failed decoding of an event log. + */ + test('Fail to decode a contract function input', () => { + expect(() => + contract.decodeEventLog(contractABI, 'ValueChanged', { + data: '0x123', + topics: [] + }) + ).toThrowError(ContractInterfaceError); + }); +}); diff --git a/packages/core/tests/abi/fixture.ts b/packages/core/tests/abi/fixture.ts index 7da3fa2c5..feaa91722 100644 --- a/packages/core/tests/abi/fixture.ts +++ b/packages/core/tests/abi/fixture.ts @@ -252,10 +252,98 @@ const encodedDecodedInvalidValues = [ } ]; +const contractABI = JSON.stringify([ + { + constant: false, + inputs: [ + { + name: 'value', + type: 'uint256' + } + ], + name: 'setValue', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function' + }, + { + constant: true, + inputs: [], + name: 'getValue', + outputs: [ + { + name: '', + type: 'uint256' + } + ], + payable: false, + stateMutability: 'view', + type: 'function' + } +]); + +const contractABIWithEvents = JSON.stringify([ + { + constant: false, + inputs: [ + { + name: 'value', + type: 'uint256' + } + ], + name: 'setValue', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function' + }, + { + constant: true, + inputs: [], + name: 'getValue', + outputs: [ + { + name: '', + type: 'uint256' + } + ], + payable: false, + stateMutability: 'view', + type: 'function' + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + name: 'sender', + type: 'address' + }, + { + indexed: false, + name: 'value', + type: 'uint256' + } + ], + name: 'ValueChanged', + type: 'event' + } +]); + +// Event data +const ValueChangedEventData = { + sender: '0x1234567890123456789012345678901234567890', // Replace with the actual address + value: 100 // Replace with the actual balance value +}; + export { events, functions, simpleParametersDataForFunction2, encodedDecodedValues, - encodedDecodedInvalidValues + encodedDecodedInvalidValues, + contractABI, + contractABIWithEvents, + ValueChangedEventData }; diff --git a/packages/core/typedoc.json b/packages/core/typedoc.json new file mode 100644 index 000000000..2e72d0e51 --- /dev/null +++ b/packages/core/typedoc.json @@ -0,0 +1,4 @@ +{ + "extends": ["../../typedoc.base.json"], + "entryPoints": ["src/core.ts"] + } \ No newline at end of file diff --git a/packages/errors/src/model/base.ts b/packages/errors/src/model/base.ts index b5e3c2ab9..67b799adc 100644 --- a/packages/errors/src/model/base.ts +++ b/packages/errors/src/model/base.ts @@ -1,4 +1,4 @@ -import type { ErrorCode } from '../types'; +import { type ErrorCode } from '../types'; /** * Base error class to construct all other errors from. @@ -13,19 +13,23 @@ class ErrorBase extends Error { code: ErrorCodeT; message: string; data?: DataTypeT; + innerError?: Error; constructor({ code, message, - data + data, + innerError }: { code: ErrorCodeT; message: string; data?: DataTypeT; + innerError?: Error; }) { super(); this.code = code; this.message = message; this.data = data; + this.innerError = innerError; } } diff --git a/packages/errors/src/model/abi.ts b/packages/errors/src/model/core/abi.ts similarity index 79% rename from packages/errors/src/model/abi.ts rename to packages/errors/src/model/core/abi.ts index 13c5a9401..49847a113 100644 --- a/packages/errors/src/model/abi.ts +++ b/packages/errors/src/model/core/abi.ts @@ -1,5 +1,5 @@ -import type { DefaultErrorData } from '../types'; -import { ErrorBase } from './base'; +import { type DefaultErrorData } from '../../types'; +import { ErrorBase } from '../base'; /** * Invalid data to decode error to be thrown when an invalid data is detected during decoding. @@ -61,6 +61,18 @@ class InvalidAbiFunctionError extends ErrorBase< DefaultErrorData > {} +/** + * Invalid function error to be thrown when an invalid function is detected. + * @param code - The error code from the error types enum. + * @param message - The error message. + * @param data - The error data. + * @returns The error object. + */ +class ContractInterfaceError extends ErrorBase< + ABI.CONTRACT_INTERFACE_ERROR, + DefaultErrorData +> {} + /** * Errors enum. * @@ -71,7 +83,8 @@ enum ABI { INVALID_EVENT = 'INVALID_EVENT', INVALID_DATA_TO_DECODE = 'INVALID_DATA_TO_DECODE', INVALID_DATA_TO_ENCODE = 'INVALID_DATA_TO_ENCODE', - INVALID_FORMAT_TYPE = 'INVALID_FORMAT_TYPE' + INVALID_FORMAT_TYPE = 'INVALID_FORMAT_TYPE', + CONTRACT_INTERFACE_ERROR = 'CONTRACT_INTERFACE_ERROR' } export { @@ -80,5 +93,6 @@ export { InvalidAbiEventError, InvalidAbiFormatTypeError, InvalidAbiFunctionError, + ContractInterfaceError, ABI }; diff --git a/packages/errors/src/model/address.ts b/packages/errors/src/model/core/address.ts similarity index 84% rename from packages/errors/src/model/address.ts rename to packages/errors/src/model/core/address.ts index 6ddcb8a20..3f3ec602f 100644 --- a/packages/errors/src/model/address.ts +++ b/packages/errors/src/model/core/address.ts @@ -1,5 +1,5 @@ -import type { DefaultErrorData } from '../types'; -import { ErrorBase } from './base'; +import { type DefaultErrorData } from '../../types'; +import { ErrorBase } from '../base'; /** * Invalid address error to be thrown when an invalid address is provided. diff --git a/packages/errors/src/model/bloom.ts b/packages/errors/src/model/core/bloom.ts similarity index 90% rename from packages/errors/src/model/bloom.ts rename to packages/errors/src/model/core/bloom.ts index e37ed4daa..444ef8ecf 100644 --- a/packages/errors/src/model/bloom.ts +++ b/packages/errors/src/model/core/bloom.ts @@ -1,5 +1,5 @@ -import type { DefaultErrorData } from '../types'; -import { ErrorBase } from './base'; +import { type DefaultErrorData } from '../../types'; +import { ErrorBase } from '../base'; /** * Invalid bloom error to be thrown when an invalid bloom is detected. diff --git a/packages/errors/src/model/certificate.ts b/packages/errors/src/model/core/certificate.ts similarity index 93% rename from packages/errors/src/model/certificate.ts rename to packages/errors/src/model/core/certificate.ts index 7fd7a28fe..d7cd7733b 100644 --- a/packages/errors/src/model/certificate.ts +++ b/packages/errors/src/model/core/certificate.ts @@ -1,5 +1,5 @@ -import type { DefaultErrorData } from '../types'; -import { ErrorBase } from './base'; +import { type DefaultErrorData } from '../../types'; +import { ErrorBase } from '../base'; /** * Certificate not signed. diff --git a/packages/errors/src/model/data.ts b/packages/errors/src/model/core/data.ts similarity index 90% rename from packages/errors/src/model/data.ts rename to packages/errors/src/model/core/data.ts index f15a89dd0..8be233942 100644 --- a/packages/errors/src/model/data.ts +++ b/packages/errors/src/model/core/data.ts @@ -1,5 +1,5 @@ -import type { DefaultErrorData } from '../types'; -import { ErrorBase } from './base'; +import { type DefaultErrorData } from '../../types'; +import { ErrorBase } from '../base'; /** * Invalid data error to be thrown when an invalid data is detected. diff --git a/packages/errors/src/model/hdnode.ts b/packages/errors/src/model/core/hdnode.ts similarity index 96% rename from packages/errors/src/model/hdnode.ts rename to packages/errors/src/model/core/hdnode.ts index 1fb6f4b27..ad866179b 100644 --- a/packages/errors/src/model/hdnode.ts +++ b/packages/errors/src/model/core/hdnode.ts @@ -1,5 +1,5 @@ -import type { DefaultErrorData } from '../types'; -import { ErrorBase } from './base'; +import { type DefaultErrorData } from '../../types'; +import { ErrorBase } from '../base'; /** * Invalid chaincode error to be thrown when an invalid chaincode is detected. diff --git a/packages/errors/src/model/core/index.ts b/packages/errors/src/model/core/index.ts new file mode 100644 index 000000000..9583ca72a --- /dev/null +++ b/packages/errors/src/model/core/index.ts @@ -0,0 +1,10 @@ +export * from './abi'; +export * from './address'; +export * from './bloom'; +export * from './certificate'; +export * from './data'; +export * from './hdnode'; +export * from './keystore'; +export * from './rlp'; +export * from './secp256k1'; +export * from './transaction'; diff --git a/packages/errors/src/model/keystore.ts b/packages/errors/src/model/core/keystore.ts similarity index 91% rename from packages/errors/src/model/keystore.ts rename to packages/errors/src/model/core/keystore.ts index 340a3e9ad..bdae71d60 100644 --- a/packages/errors/src/model/keystore.ts +++ b/packages/errors/src/model/core/keystore.ts @@ -1,5 +1,5 @@ -import type { DefaultErrorData } from '../types'; -import { ErrorBase } from './base'; +import { type DefaultErrorData } from '../../types'; +import { ErrorBase } from '../base'; /** * Invalid keystore error to be thrown when an invalid keystore is detected. diff --git a/packages/errors/src/model/rlp.ts b/packages/errors/src/model/core/rlp.ts similarity index 93% rename from packages/errors/src/model/rlp.ts rename to packages/errors/src/model/core/rlp.ts index 6840e6d05..9ed01f791 100644 --- a/packages/errors/src/model/rlp.ts +++ b/packages/errors/src/model/core/rlp.ts @@ -1,4 +1,4 @@ -import { ErrorBase } from './base'; +import { ErrorBase } from '../base'; /** * Invalid RLP error data interface. diff --git a/packages/errors/src/model/secp256k1.ts b/packages/errors/src/model/core/secp256k1.ts similarity index 95% rename from packages/errors/src/model/secp256k1.ts rename to packages/errors/src/model/core/secp256k1.ts index 7acb0ee09..3f93d7167 100644 --- a/packages/errors/src/model/secp256k1.ts +++ b/packages/errors/src/model/core/secp256k1.ts @@ -1,5 +1,5 @@ -import { ErrorBase } from '.'; -import type { DefaultErrorData } from '../types'; +import { type DefaultErrorData } from '../../types'; +import { ErrorBase } from '../base'; /** * Error to be thrown when the private key is invalid. diff --git a/packages/errors/src/model/transaction.ts b/packages/errors/src/model/core/transaction.ts similarity index 94% rename from packages/errors/src/model/transaction.ts rename to packages/errors/src/model/core/transaction.ts index b2b091237..0d41119e3 100644 --- a/packages/errors/src/model/transaction.ts +++ b/packages/errors/src/model/core/transaction.ts @@ -1,5 +1,5 @@ -import { ErrorBase } from './base'; -import { type DefaultErrorData } from '../types'; +import { type DefaultErrorData } from '../../types'; +import { ErrorBase } from '../base'; /** * Invalid Transaction to sign. It is already signed. diff --git a/packages/errors/src/model/index.ts b/packages/errors/src/model/index.ts index 161c59b12..40de47c69 100644 --- a/packages/errors/src/model/index.ts +++ b/packages/errors/src/model/index.ts @@ -1,11 +1,3 @@ -export * from './abi'; -export * from './address'; export * from './base'; -export * from './bloom'; -export * from './certificate'; -export * from './data'; -export * from './hdnode'; -export * from './keystore'; -export * from './rlp'; -export * from './secp256k1'; -export * from './transaction'; +export * from './core'; +export * from './network'; diff --git a/packages/errors/src/model/network/http-client.ts b/packages/errors/src/model/network/http-client.ts new file mode 100644 index 000000000..4abeace4f --- /dev/null +++ b/packages/errors/src/model/network/http-client.ts @@ -0,0 +1,39 @@ +import { ErrorBase } from '../base'; + +/** + * HTTP Client Error. + * + * @public + */ +interface HTTPClientErrorData { + status?: number; + method?: string; + url?: string; + text?: string; + message?: string; +} + +/** + * Client error to be thrown when an http request fails. + * + * @param code - The error code from the error types enum. + * @param message - The error message. + * @param data - The error data. + * + * @returns The error object. + */ +class HTTPClientError extends ErrorBase< + HTTP_CLIENT.INVALID_HTTP_REQUEST, + HTTPClientErrorData +> {} + +/** + * Errors enum. + * + * @public + */ +enum HTTP_CLIENT { + INVALID_HTTP_REQUEST = 'INVALID_HTTP_REQUEST' +} + +export { type HTTPClientErrorData, HTTPClientError, HTTP_CLIENT }; diff --git a/packages/errors/src/model/network/index.ts b/packages/errors/src/model/network/index.ts new file mode 100644 index 000000000..29d4d49b6 --- /dev/null +++ b/packages/errors/src/model/network/index.ts @@ -0,0 +1 @@ +export * from './http-client'; diff --git a/packages/errors/src/types/errorTypes.ts b/packages/errors/src/types/errorTypes.ts index 5881541b9..5291c817b 100644 --- a/packages/errors/src/types/errorTypes.ts +++ b/packages/errors/src/types/errorTypes.ts @@ -1,45 +1,49 @@ import { + ABI, + ADDRESS, + BLOOM, + CERTIFICATE, + CertificateInvalidSignatureFormatError, + CertificateInvalidSignerError, + CertificateNotSignedError, + ContractInterfaceError, + DATA, + type ErrorBase, + HDNODE, + HTTP_CLIENT, + HTTPClientError, + type HTTPClientErrorData, + InvalidAbiDataToDecodeError, + InvalidAbiDataToEncodeError, InvalidAbiEventError, InvalidAbiFormatTypeError, InvalidAbiFunctionError, - InvalidAbiDataToEncodeError, - InvalidAbiDataToDecodeError, InvalidAddressError, - InvalidSecp256k1MessageHashError, - InvalidHDNodePrivateKeyError, - InvalidSecp256k1SignatureError, - InvalidSecp256k1SignatureRecoveryError, InvalidBloomError, - InvalidKError, - CertificateNotSignedError, - CertificateInvalidSignatureFormatError, - CertificateInvalidSignerError, - InvalidDataTypeError, InvalidDataReturnTypeError, + InvalidDataTypeError, InvalidHDNodeChaincodeError, + InvalidHDNodeDerivationPathError, InvalidHDNodeMnemonicsError, + InvalidHDNodePrivateKeyError, InvalidHDNodePublicKeyError, - InvalidHDNodeDerivationPathError, + InvalidKError, InvalidKeystoreError, InvalidKeystorePasswordError, InvalidRLPError, - InvalidSecp256k1PrivateKeyError, - TransactionAlreadySignedError, - TransactionNotSignedError, - TransactionBodyError, - TransactionDelegationError, type InvalidRLPErrorData, - type ErrorBase, - ABI, - ADDRESS, - SECP256K1, + InvalidSecp256k1MessageHashError, + InvalidSecp256k1PrivateKeyError, + InvalidSecp256k1SignatureError, + InvalidSecp256k1SignatureRecoveryError, KEYSTORE, - HDNODE, - BLOOM, RLP, - DATA, + SECP256K1, TRANSACTION, - CERTIFICATE + TransactionAlreadySignedError, + TransactionBodyError, + TransactionDelegationError, + TransactionNotSignedError } from '../model'; /** @@ -51,7 +55,7 @@ import { * * @param ErrorCodeT - The error code type from the error types enum. */ -type DefaultErrorData = Record; +type DefaultErrorData = Record | { innerError: Error }; /** * Error code type. @@ -68,7 +72,8 @@ type ErrorCode = | ABI | RLP | DATA - | TRANSACTION; + | TRANSACTION + | HTTP_CLIENT; /** * Conditional type to get the error data type from the error code. @@ -80,6 +85,8 @@ type ErrorCode = */ type DataType = ErrorCodeT extends RLP.INVALID_RLP ? InvalidRLPErrorData + : ErrorCodeT extends HTTP_CLIENT.INVALID_HTTP_REQUEST + ? HTTPClientErrorData : DefaultErrorData; /** @@ -97,7 +104,8 @@ const ERROR_CODES = { ABI, RLP, DATA, - TRANSACTION + TRANSACTION, + HTTP_CLIENT }; /** @@ -155,6 +163,8 @@ type ErrorType = ? InvalidAbiFormatTypeError : ErrorCodeT extends ABI.INVALID_FUNCTION ? InvalidAbiFunctionError + : ErrorCodeT extends ABI.CONTRACT_INTERFACE_ERROR + ? ContractInterfaceError : ErrorCodeT extends RLP.INVALID_RLP ? InvalidRLPError : ErrorCodeT extends DATA.INVALID_DATA_TYPE @@ -169,6 +179,8 @@ type ErrorType = ? TransactionBodyError : ErrorCodeT extends TRANSACTION.INVALID_DELEGATION ? TransactionDelegationError + : ErrorCodeT extends HTTP_CLIENT.INVALID_HTTP_REQUEST + ? HTTPClientError : never; /** @@ -216,13 +228,15 @@ const ErrorClassMap = new Map< [ABI.INVALID_DATA_TO_ENCODE, InvalidAbiDataToEncodeError], [ABI.INVALID_FORMAT_TYPE, InvalidAbiFormatTypeError], [ABI.INVALID_FUNCTION, InvalidAbiFunctionError], + [ABI.CONTRACT_INTERFACE_ERROR, ContractInterfaceError], [RLP.INVALID_RLP, InvalidRLPError], [DATA.INVALID_DATA_TYPE, InvalidDataTypeError], [DATA.INVALID_DATA_RETURN_TYPE, InvalidDataReturnTypeError], [TRANSACTION.ALREADY_SIGNED, TransactionAlreadySignedError], [TRANSACTION.NOT_SIGNED, TransactionNotSignedError], [TRANSACTION.INVALID_TRANSACTION_BODY, TransactionBodyError], - [TRANSACTION.INVALID_DELEGATION, TransactionDelegationError] + [TRANSACTION.INVALID_DELEGATION, TransactionDelegationError], + [HTTP_CLIENT.INVALID_HTTP_REQUEST, HTTPClientError] ]); export { diff --git a/packages/errors/src/utils/errorBuilder.ts b/packages/errors/src/utils/errorBuilder.ts index 369f45605..e31f1f4d2 100644 --- a/packages/errors/src/utils/errorBuilder.ts +++ b/packages/errors/src/utils/errorBuilder.ts @@ -13,15 +13,35 @@ import { ErrorClassMap } from '../types'; function buildError< ErrorCodeT extends ErrorCode, DataTypeT extends DataType ->(code: ErrorCodeT, message: string, data?: DataTypeT): ErrorType { +>( + code: ErrorCodeT, + message: string, + data?: DataTypeT, + innerError?: unknown +): ErrorType { const ErrorClass = ErrorClassMap.get(code); if (ErrorClass === undefined || ErrorClass === null) { throw new Error('Invalid error code'); } - const error = new ErrorClass({ code, message, data }); + + const error = new ErrorClass({ + code, + message, + data, + innerError: + innerError === undefined ? undefined : assertInnerError(innerError) + }); return error as ErrorType; } -export { buildError }; +function assertInnerError(error: unknown): Error { + if (error instanceof Error) { + return error; + } + + throw new Error('Inner error is not an instance of Error'); +} + +export { buildError, assertInnerError }; diff --git a/packages/errors/tests/errorHandler.test.ts b/packages/errors/tests/errorHandler.test.ts index 62ec9bd0f..2baf2d48b 100644 --- a/packages/errors/tests/errorHandler.test.ts +++ b/packages/errors/tests/errorHandler.test.ts @@ -3,7 +3,8 @@ import { ERROR_CODES, buildError, InvalidKeystoreError, - InvalidRLPError + InvalidRLPError, + assertInnerError } from '../src'; import { ErrorsCodeAndClassesMapsFixture } from './fixture'; @@ -54,6 +55,48 @@ describe('Error handler test', () => { } }); + /** + * Verify that the object is an instance of error + */ + test('Assert valid error', () => { + expect(assertInnerError(new Error('test'))).toBeDefined(); + }); + + /** + * Verify that the object is not a valid instance of error + */ + test('Assert invalid error', () => { + expect(() => assertInnerError({})).toThrowError(); + }); + + /** + * Verify that the inner error is undefined when not provided + */ + test('Verify that the inner error is undefined', () => { + expect( + buildError( + ERROR_CODES.ABI.CONTRACT_INTERFACE_ERROR, + 'test', + undefined, + undefined + ).innerError + ).toBeUndefined(); + }); + + /** + * Verify that the inner error is defined when provided + */ + test('Verify that the inner error is defined', () => { + expect( + buildError( + ERROR_CODES.ABI.CONTRACT_INTERFACE_ERROR, + 'test', + undefined, + new Error('test') + ).innerError + ).toBeDefined(); + }); + /** * Verify all error codes and classes */ diff --git a/packages/errors/tests/fixture.ts b/packages/errors/tests/fixture.ts index 6f1b17d79..fa80c6d6d 100644 --- a/packages/errors/tests/fixture.ts +++ b/packages/errors/tests/fixture.ts @@ -37,7 +37,10 @@ import { InvalidHDNodeDerivationPathError, CertificateNotSignedError, CertificateInvalidSignatureFormatError, - CertificateInvalidSignerError + CertificateInvalidSignerError, + ContractInterfaceError, + HTTP_CLIENT, + HTTPClientError } from '../src'; /** @@ -166,6 +169,10 @@ const ErrorsCodeAndClassesMapsFixture = [ { errorCode: ABI.INVALID_FUNCTION, classExpected: InvalidAbiFunctionError + }, + { + errorCode: ABI.CONTRACT_INTERFACE_ERROR, + classExpected: ContractInterfaceError } ] }, @@ -211,6 +218,15 @@ const ErrorsCodeAndClassesMapsFixture = [ classExpected: TransactionDelegationError } ] + }, + { + name: 'HTTP Client', + elements: [ + { + errorCode: HTTP_CLIENT.INVALID_HTTP_REQUEST, + classExpected: HTTPClientError + } + ] } ]; export { ErrorsCodeAndClassesMapsFixture }; diff --git a/packages/errors/typedoc.json b/packages/errors/typedoc.json new file mode 100644 index 000000000..e6f120662 --- /dev/null +++ b/packages/errors/typedoc.json @@ -0,0 +1,4 @@ +{ + "extends": ["../../typedoc.base.json"], + "entryPoints": ["src/errors.ts"] + } \ No newline at end of file diff --git a/packages/network/src/client/http/helpers/errors.ts b/packages/network/src/client/http/helpers/errors.ts deleted file mode 100644 index 81fb6bc6e..000000000 --- a/packages/network/src/client/http/helpers/errors.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { type AxiosError } from 'axios'; - -/** - * Converts an AxiosError into a standard Error. - * - * This function converts an AxiosError, which may contain HTTP response details, into a standard Error. - * It handles cases where the AxiosError has an HTTP response with status and data. - * - * @param error - The AxiosError to convert into an Error. - * @returns A standard Error with a descriptive message. - * - * @TODO - Refactor using our error system (https://github.com/vechainfoundation/vechain-sdk/issues/192) - */ -const convertError = (error: AxiosError): Error => { - if (error.response != null) { - const resp = error.response; - if (typeof resp.data === 'string') { - let text = resp.data.trim(); - if (text.length > 50) { - text = text.slice(0, 50) + '...'; - } - return new Error( - `${resp.status} ${error.config?.method} ${error.config?.url}: ${text}` - ); - } else { - return new Error( - `${resp.status} ${error.config?.method} ${error.config?.url}` - ); - } - } else { - return new Error( - `${error.config?.method} ${error.config?.url}: ${error.message}` - ); - } -}; - -export { convertError }; diff --git a/packages/network/src/client/http/http-client.ts b/packages/network/src/client/http/http-client.ts index 1e4c6a81e..721144dc7 100644 --- a/packages/network/src/client/http/http-client.ts +++ b/packages/network/src/client/http/http-client.ts @@ -6,8 +6,8 @@ import { type HttpParams, type HttpClientOptions } from './types'; -import { convertError } from './helpers'; -import { DEFAULT_HTTP_TIMEOUT } from '../../utils'; +import { convertError, DEFAULT_HTTP_TIMEOUT } from '../../utils'; +import { buildError, HTTP_CLIENT } from '@vechain-sdk/errors'; /** * Represents a concrete implementation of the `IHttpClient` interface, providing methods for making HTTP requests. @@ -47,7 +47,7 @@ class HttpClient implements IHttpClient { * @param path - The path to access on the server relative to the base URL. * @param params - (Optional) Additional request parameters such as query parameters, request body, and custom headers. * @returns A promise that resolves to the response data from the HTTP request. - * @throws Will throw an error if the request fails, with more detailed information if the error is Axios-specific. + * @throws {HTTPClientError} Will throw an error if the request fails, with more detailed information if the error is Axios-specific. */ public async http( method: 'GET' | 'POST', @@ -70,7 +70,13 @@ class HttpClient implements IHttpClient { if (Axios.isAxiosError(err)) { throw convertError(err); } - throw err; // If it's not an Axios error, re-throw the original error + // If it's not an Axios error, re-throw the original error + throw buildError( + HTTP_CLIENT.INVALID_HTTP_REQUEST, + `An error occurred while performing http request ${JSON.stringify( + err + )}` + ); } } diff --git a/packages/network/src/client/http/index.ts b/packages/network/src/client/http/index.ts index b328aa87e..9f1dff55f 100644 --- a/packages/network/src/client/http/index.ts +++ b/packages/network/src/client/http/index.ts @@ -1,3 +1,2 @@ export * from './types.d'; export * from './http-client'; -export * from './helpers'; diff --git a/packages/network/src/client/http/types.d.ts b/packages/network/src/client/http/types.d.ts index f03823f55..e39fd3395 100644 --- a/packages/network/src/client/http/types.d.ts +++ b/packages/network/src/client/http/types.d.ts @@ -41,23 +41,23 @@ interface HttpParams { /** * Query parameters to include in the request. */ - query: Record; + query?: Record; /** * The request body, which can be of any type. */ - body: unknown; + body?: unknown; /** * Custom headers to be included in the request. */ - headers: Record; + headers?: Record; /** * A callback function to validate response headers. * @param headers - The response headers to validate. */ - validateResponseHeader: (headers: Record) => void; + validateResponseHeader?: (headers: Record) => void; } /** diff --git a/packages/network/src/client/index.ts b/packages/network/src/client/index.ts index c202386ae..9624102dd 100644 --- a/packages/network/src/client/index.ts +++ b/packages/network/src/client/index.ts @@ -1 +1,2 @@ export * from './http'; +export * from './thor'; diff --git a/packages/network/src/client/thor/accounts/index.ts b/packages/network/src/client/thor/accounts/index.ts new file mode 100644 index 000000000..538857985 --- /dev/null +++ b/packages/network/src/client/thor/accounts/index.ts @@ -0,0 +1,2 @@ +export * from './types.d'; +export * from './account-client'; diff --git a/packages/network/src/client/thor/api.ts b/packages/network/src/client/thor/api.ts new file mode 100644 index 000000000..bd41ccd83 --- /dev/null +++ b/packages/network/src/client/thor/api.ts @@ -0,0 +1,34 @@ +/** + * Constructs the endpoint URL for retrieving account details. + * + * @param address - The account address. + * @returns The URL endpoint to fetch account details. + */ +const GET_ACCOUNT_DETAIL_ENDPOINT = (address: string): string => + `/accounts/${address}`; + +/** + * Constructs the endpoint URL for retrieving the bytecode of a smart contract. + * + * @param address - The account address. + * @returns The URL endpoint to fetch the smart contract's bytecode. + */ +const GET_ACCOUNT_BYTECODE_ENDPOINT = (address: string): string => + `/accounts/${address}/code`; + +/** + * Constructs the endpoint URL for retrieving the storage at a specific position of a smart contract. + * This is usually used for querying the state of smart contracts. + * + * @param address - The account address. + * @param position - The specified position in the contract's storage. + * @returns The URL endpoint to fetch the storage data at the given position. + */ +const GET_STORAGE_AT_ENDPOINT = (address: string, position: string): string => + `/accounts/${address}/storage/${position}`; + +export { + GET_ACCOUNT_DETAIL_ENDPOINT, + GET_ACCOUNT_BYTECODE_ENDPOINT, + GET_STORAGE_AT_ENDPOINT +}; diff --git a/packages/network/src/client/thor/helpers/index.ts b/packages/network/src/client/thor/helpers/index.ts new file mode 100644 index 000000000..56e4b0555 --- /dev/null +++ b/packages/network/src/client/thor/helpers/index.ts @@ -0,0 +1 @@ +export * from './request'; diff --git a/packages/network/src/client/thor/helpers/request.ts b/packages/network/src/client/thor/helpers/request.ts new file mode 100644 index 000000000..7cc4204f4 --- /dev/null +++ b/packages/network/src/client/thor/helpers/request.ts @@ -0,0 +1,24 @@ +/** + * Constructs a query object for HTTP requests by filtering out undefined values. + * + * @param params - An object containing the query parameters with potential undefined values. + * @returns An object containing only the defined query parameters. + */ +const buildQuery = ( + params: Record +): Record => { + const definedParams: Record = {}; + + // Iterate over each property in the params object + for (const key in params) { + // Check if the value is not undefined + if (params[key] !== undefined) { + // If the value is defined, add it to the definedParams object + definedParams[key] = params[key] as string; + } + } + + return definedParams; +}; + +export { buildQuery }; diff --git a/packages/network/src/client/thor/index.ts b/packages/network/src/client/thor/index.ts index e69de29bb..321b608df 100644 --- a/packages/network/src/client/thor/index.ts +++ b/packages/network/src/client/thor/index.ts @@ -0,0 +1 @@ +export * from './thor-client'; diff --git a/packages/network/src/client/thor/thor-readonly-client.ts b/packages/network/src/client/thor/thor-readonly-client.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/network/src/utils/helpers/errors.ts b/packages/network/src/utils/helpers/errors.ts new file mode 100644 index 000000000..141a7d982 --- /dev/null +++ b/packages/network/src/utils/helpers/errors.ts @@ -0,0 +1,48 @@ +import { type AxiosError } from 'axios'; +import { + buildError, + HTTP_CLIENT, + type HTTPClientError +} from '@vechain-sdk/errors'; + +/** + * Converts an AxiosError into a standard Error. + * + * This function converts an AxiosError, which may contain HTTP response details, into a standard Error. + * It handles cases where the AxiosError has an HTTP response with status and data. + * + * @param error - The AxiosError to convert into an Error. + * @returns A standard Error with a descriptive message. + */ +const convertError = (error: AxiosError): HTTPClientError => { + // Error has a response + if (error.response != null) { + const resp = error.response; + + return buildError( + HTTP_CLIENT.INVALID_HTTP_REQUEST, + `An error occurred while performing http request ${error.config?.url}`, + { + status: resp.status, + method: error.config?.method, + url: error.config?.url, + text: + typeof resp.data === 'string' ? resp.data.trim() : undefined + } + ); + } + // Error does not have a response + else { + return buildError( + HTTP_CLIENT.INVALID_HTTP_REQUEST, + `An error occurred while performing http request ${error.config?.url}`, + { + method: error.config?.method, + url: error.config?.url, + message: error.message + } + ); + } +}; + +export { convertError }; diff --git a/packages/network/src/utils/helpers/index.ts b/packages/network/src/utils/helpers/index.ts new file mode 100644 index 000000000..f72bc43e2 --- /dev/null +++ b/packages/network/src/utils/helpers/index.ts @@ -0,0 +1 @@ +export * from './errors'; diff --git a/packages/network/src/utils/index.ts b/packages/network/src/utils/index.ts index e47ea3a46..c7683cf95 100644 --- a/packages/network/src/utils/index.ts +++ b/packages/network/src/utils/index.ts @@ -1 +1,3 @@ export * from './const'; +export * from './helpers'; +export * from './block'; diff --git a/packages/network/tests/driver/fixture.ts b/packages/network/tests/client/http/fixture.ts similarity index 51% rename from packages/network/tests/driver/fixture.ts rename to packages/network/tests/client/http/fixture.ts index 54880f2f9..1af5ce8d8 100644 --- a/packages/network/tests/driver/fixture.ts +++ b/packages/network/tests/client/http/fixture.ts @@ -1,24 +1,4 @@ -import { HttpClient } from '../../src'; - -/** - * Url of the testnet fixture - */ -const _testnetUrl = 'https://testnet.vechain.org'; - -/** - * Url of the solo network fixture - */ -const _soloUrl = 'http://localhost:8669'; - -/** - * Network instance fixture - */ -const network = new HttpClient(_testnetUrl); - -/** - * Solo network instance fixture - */ -const soloNetwork = new HttpClient(_soloUrl); +import { ZERO_ADDRESS } from '../../fixture'; /** * First testnet block fixture @@ -31,7 +11,7 @@ const testnetGenesisBlock = { '0xffffffff00000000000000000000000000000000000000000000000000000000', timestamp: 1530014400, gasLimit: 10000000, - beneficiary: '0x0000000000000000000000000000000000000000', + beneficiary: ZERO_ADDRESS, gasUsed: 0, totalScore: 0, txsRoot: @@ -42,7 +22,7 @@ const testnetGenesisBlock = { receiptsRoot: '0x45b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0', com: false, - signer: '0x0000000000000000000000000000000000000000', + signer: ZERO_ADDRESS, isTrunk: true, isFinalized: true, transactions: [] @@ -57,21 +37,4 @@ const zeroAddressAccountDetails = { hasCode: false }; -/** - * Simple test account fixture - */ -const testAccount = '0x5034aa590125b64023a0262112b98d72e3c8e40e'; - -/** - * Zero address fixture - */ -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - -export { - network, - soloNetwork, - testnetGenesisBlock, - testAccount, - zeroAddressAccountDetails, - ZERO_ADDRESS -}; +export { testnetGenesisBlock, zeroAddressAccountDetails, ZERO_ADDRESS }; diff --git a/packages/network/tests/driver/driver.solo.test.ts b/packages/network/tests/client/http/http-client.solo.test.ts similarity index 81% rename from packages/network/tests/driver/driver.solo.test.ts rename to packages/network/tests/client/http/http-client.solo.test.ts index ec8fd51e9..aedbdde3e 100644 --- a/packages/network/tests/driver/driver.solo.test.ts +++ b/packages/network/tests/client/http/http-client.solo.test.ts @@ -1,17 +1,15 @@ import { describe, expect, test } from '@jest/globals'; -import { - ZERO_ADDRESS, - soloNetwork, - testAccount, - zeroAddressAccountDetails -} from './fixture'; -import { type HttpParams } from '../../src'; +import { ZERO_ADDRESS, zeroAddressAccountDetails } from './fixture'; +import { type HttpParams } from '../../../src'; +import { soloNetwork, testAccount } from '../../fixture'; +import { HTTPClientError } from '@vechain-sdk/errors'; /** - * SimpleNet class tests + * HttpClient class tests. + * * @group integration/network */ -describe('Test SimpleNet class on Solo', () => { +describe('Test HttpClient class on Solo node', () => { /** * HTTP Request tests */ @@ -33,7 +31,7 @@ describe('Test SimpleNet class on Solo', () => { // Assert that the HTTP request fails with an error await expect( soloNetwork.http('GET', '/error-test-path') - ).rejects.toThrowError('404 get /error-test-path: 404 page not found'); + ).rejects.toThrowError(HTTPClientError); }); /** diff --git a/packages/network/tests/driver/driver.testnet.test.ts b/packages/network/tests/client/http/http-client.testnet.test.ts similarity index 72% rename from packages/network/tests/driver/driver.testnet.test.ts rename to packages/network/tests/client/http/http-client.testnet.test.ts index ec2daf182..bda43fae7 100644 --- a/packages/network/tests/driver/driver.testnet.test.ts +++ b/packages/network/tests/client/http/http-client.testnet.test.ts @@ -1,6 +1,8 @@ import { describe, expect, test } from '@jest/globals'; -import { type HttpParams } from '../../src'; -import { testnetGenesisBlock, network, testAccount } from './fixture'; +import { type HttpParams } from '../../../src'; +import { testnetGenesisBlock } from './fixture'; +import { testAccount, testNetwork } from '../../fixture'; +import { HTTPClientError, HTTP_CLIENT, buildError } from '@vechain-sdk/errors'; /** * Timeout for each test. @@ -9,18 +11,19 @@ import { testnetGenesisBlock, network, testAccount } from './fixture'; const TIMEOUT = 10000; /** - * SimpleNet class tests + * HttpClient class tests. + * * @group integration/network */ -describe('Test SimpleNet class on Testnet', () => { +describe('Test HttpClient class on Testnet', () => { /** * HTTP Request tests */ test( 'Should perform an HTTP GET request and resolve with response data', async () => { - // Perform an HTTP GET request using the SimpleNet instance - const response = await network.http( + // Perform an HTTP GET request using the HttpClient instance + const response = await testNetwork.http( 'GET', '/blocks/0?expanded=false' ); @@ -41,10 +44,8 @@ describe('Test SimpleNet class on Testnet', () => { async () => { // Assert that the HTTP request fails with an error await expect( - network.http('GET', '/error-test-path') - ).rejects.toThrowError( - '404 get /error-test-path: 404 page not found' - ); + testNetwork.http('GET', '/error-test-path') + ).rejects.toThrowError(HTTPClientError); }, TIMEOUT ); @@ -69,7 +70,7 @@ describe('Test SimpleNet class on Testnet', () => { }; // Make an actual HTTP GET request and pass the validateResponseHeaders function - const response = await network.http( + const response = await testNetwork.http( 'GET', '/accounts/' + testAccount, customParams @@ -92,12 +93,15 @@ describe('Test SimpleNet class on Testnet', () => { 'X-Custom-Header': 'custom-value' }, validateResponseHeader: function (): void { - throw new Error(`Forcing error on header validation`); + throw buildError( + HTTP_CLIENT.INVALID_HTTP_REQUEST, + `Forcing error on header validation` + ); } }; await expect( - network.http('GET', '/accounts/' + testAccount, customParams) - ).rejects.toThrowError(`Forcing error on header validation`); + testNetwork.http('GET', '/accounts/' + testAccount, customParams) + ).rejects.toThrowError(HTTPClientError); }); }); diff --git a/packages/network/tests/utils/fixture.ts b/packages/network/tests/utils/helpers/fixture.ts similarity index 86% rename from packages/network/tests/utils/fixture.ts rename to packages/network/tests/utils/helpers/fixture.ts index 739b1bd00..ad8188d5a 100644 --- a/packages/network/tests/utils/fixture.ts +++ b/packages/network/tests/utils/helpers/fixture.ts @@ -18,7 +18,7 @@ const config = { */ const convertErrors: Array<{ customAxiosError: AxiosError; - expected: string; + testName: string; }> = [ { @@ -36,7 +36,7 @@ const convertErrors: Array<{ name: 'AxiosError', message: 'AxiosError: Request failed with status code 200' }, - expected: '200 undefined http://localhost:3000', + testName: 'Should convert AxiosError with response data to Error with data' }, @@ -55,7 +55,7 @@ const convertErrors: Array<{ name: 'AxiosError', message: 'AxiosError: Request failed with status code 200' }, - expected: '200 undefined http://localhost:3000', + testName: 'Should convert AxiosError with response data to Error with data' }, @@ -67,8 +67,6 @@ const convertErrors: Array<{ name: 'AxiosError', message: 'AxiosError: Request failed with status code 404' }, - expected: - 'undefined http://localhost:3000: AxiosError: Request failed with status code 404', testName: 'Should convert AxiosError without response data to Error with a basic message' }, @@ -87,7 +85,6 @@ const convertErrors: Array<{ name: 'AxiosError', message: 'AxiosError: Request failed with no status code' }, - expected: '200 undefined http://localhost:3000: Not found', testName: 'Should convert AxiosError to Error with a basic message' }, { @@ -107,8 +104,6 @@ const convertErrors: Array<{ name: 'AxiosError', message: 'AxiosError: Request failed with status code 404' }, - expected: - '404 undefined http://localhost:3000: Lorem ipsum dolor sit amet, consectetur adipiscing...', testName: 'Should convert AxiosError with a long response data message' } ]; diff --git a/packages/network/tests/utils/utils.test.ts b/packages/network/tests/utils/helpers/utils.test.ts similarity index 65% rename from packages/network/tests/utils/utils.test.ts rename to packages/network/tests/utils/helpers/utils.test.ts index f75374fe5..360da51d1 100644 --- a/packages/network/tests/utils/utils.test.ts +++ b/packages/network/tests/utils/helpers/utils.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from '@jest/globals'; import { type AxiosError } from 'axios'; -import { convertError } from '../../src'; import { convertErrors } from './fixture'; +import { convertError } from '../../../src/utils'; /** * ConvertError function tests. - * Testing the conversion of our error from AxiosError. + * Testing the conversion of our error from AxiosError to our error system. * * @group unit/utils */ @@ -16,7 +16,6 @@ describe('Tests of convertError function', () => { convertErrors.forEach( (currentConvertError: { customAxiosError: AxiosError; - expected: string; testName: string; }) => { test(currentConvertError.testName, () => { @@ -31,7 +30,14 @@ describe('Tests of convertError function', () => { ).toStrictEqual({}); // Assert that the returned Error message matches the expected format - expect(error.message).toBe(currentConvertError.expected); + expect(error.message).toBe( + 'An error occurred while performing http request http://localhost:3000' + ); + expect(error.code).toBe('INVALID_HTTP_REQUEST'); + expect(error.data).toBeDefined(); + expect(error.data?.status).toBe( + currentConvertError.customAxiosError.response?.status + ); }); } ); diff --git a/packages/network/typedoc.json b/packages/network/typedoc.json new file mode 100644 index 000000000..4fc888931 --- /dev/null +++ b/packages/network/typedoc.json @@ -0,0 +1,4 @@ +{ + "extends": ["../../typedoc.base.json"], + "entryPoints": ["src/network.ts"] + } \ No newline at end of file diff --git a/typedoc.base.json b/typedoc.base.json new file mode 100644 index 000000000..5ac41dd95 --- /dev/null +++ b/typedoc.base.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "compilerOptions":{ + "strictNullChecks": false + }, + "skipErrorChecking": true, + "excludeExternals": true, + "exclude": [ "**/*+(index|.spec|.e2e|test).ts" ], + "externalPattern": [ + "**/node_modules/**" + ], + "readme": "none", + "excludeReferences": true, + "excludePrivate": true, +} \ No newline at end of file diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 000000000..849899497 --- /dev/null +++ b/typedoc.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "entryPoints": ["./packages/*"], + "entryPointStrategy": "packages", + "out": "./api-docs", + "readme": "README.md", + "name": "vechain-sdk", + "navigationLinks": { + "vechain": "https://www.vechain.org/", + "docs": "https://docs.vechain.org/", + "github": "https://github.com/vechainfoundation" + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index d050cbe54..578d1b52e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1380,6 +1380,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-sequence-parser@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" + integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -4083,6 +4088,11 @@ json5@^2.2.3: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonc-parser@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -4272,6 +4282,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + make-dir@^3.0.0, make-dir@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -4308,6 +4323,11 @@ map-obj@^4.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== +marked@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + meow@^12.0.1: version "12.1.1" resolved "https://registry.yarnpkg.com/meow/-/meow-12.1.1.tgz#e558dddbab12477b69b2e9a2728c327f191bace6" @@ -4399,6 +4419,13 @@ minimatch@^5.1.0: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -5207,6 +5234,16 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shiki@^0.14.1: + version "0.14.5" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.5.tgz#375dd214e57eccb04f0daf35a32aa615861deb93" + integrity sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw== + dependencies: + ansi-sequence-parser "^1.1.0" + jsonc-parser "^3.2.0" + vscode-oniguruma "^1.7.0" + vscode-textmate "^8.0.0" + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -5893,6 +5930,16 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typedoc@^0.25.3: + version "0.25.3" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.3.tgz#53c6d668e1001b3d488e9a750fcdfb05433554c0" + integrity sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw== + dependencies: + lunr "^2.3.9" + marked "^4.3.0" + minimatch "^9.0.3" + shiki "^0.14.1" + typescript@*, typescript@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" @@ -5991,6 +6038,16 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +vscode-oniguruma@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" + integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== + +vscode-textmate@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" + integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== + wait-on@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-7.0.1.tgz#5cff9f8427e94f4deacbc2762e6b0a489b19eae9" From 56b7260f7fb9224696da228aa506ea1147b46ca1 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Tue, 7 Nov 2023 11:10:04 +0100 Subject: [PATCH 14/26] fix: added core package missing after merge --- packages/network/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/network/package.json b/packages/network/package.json index 2caa25420..dc12f746f 100644 --- a/packages/network/package.json +++ b/packages/network/package.json @@ -14,6 +14,7 @@ }, "dependencies": { "@vechain-sdk/errors": "*", + "@vechain-sdk/core": "*", "axios": "^1.5.1", "testcontainers": "^10.2.2" } From 4ccadbdeb0a52f6eab9969e268273b1f5663f648 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Tue, 7 Nov 2023 11:15:17 +0100 Subject: [PATCH 15/26] chore: rename test file --- .../{thorclient.testnet.test.ts => thor-client.testnet.test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/network/tests/client/thor/{thorclient.testnet.test.ts => thor-client.testnet.test.ts} (100%) diff --git a/packages/network/tests/client/thor/thorclient.testnet.test.ts b/packages/network/tests/client/thor/thor-client.testnet.test.ts similarity index 100% rename from packages/network/tests/client/thor/thorclient.testnet.test.ts rename to packages/network/tests/client/thor/thor-client.testnet.test.ts From deaf9790d9fdc0d862e0445f3d0a892fe5d16cf6 Mon Sep 17 00:00:00 2001 From: rodolfopietro97 Date: Tue, 7 Nov 2023 11:47:38 +0100 Subject: [PATCH 16/26] fix: mv block in block folder --- packages/network/src/utils/{ => block}/block.ts | 0 packages/network/src/utils/block/index.ts | 1 + packages/network/src/utils/index.ts | 1 + 3 files changed, 2 insertions(+) rename packages/network/src/utils/{ => block}/block.ts (100%) create mode 100644 packages/network/src/utils/block/index.ts diff --git a/packages/network/src/utils/block.ts b/packages/network/src/utils/block/block.ts similarity index 100% rename from packages/network/src/utils/block.ts rename to packages/network/src/utils/block/block.ts diff --git a/packages/network/src/utils/block/index.ts b/packages/network/src/utils/block/index.ts new file mode 100644 index 000000000..d814a5a7c --- /dev/null +++ b/packages/network/src/utils/block/index.ts @@ -0,0 +1 @@ +export * from './block'; diff --git a/packages/network/src/utils/index.ts b/packages/network/src/utils/index.ts index c7683cf95..945019aca 100644 --- a/packages/network/src/utils/index.ts +++ b/packages/network/src/utils/index.ts @@ -1,3 +1,4 @@ +export * from './block'; export * from './const'; export * from './helpers'; export * from './block'; From 3df5d0fbcca1c533c166e7921b597ad65be7e241 Mon Sep 17 00:00:00 2001 From: rodolfopietro97 Date: Tue, 7 Nov 2023 11:48:09 +0100 Subject: [PATCH 17/26] fix: remove unuseful --- packages/network/src/client/http/helpers/index.ts | 1 - 1 file changed, 1 deletion(-) delete mode 100644 packages/network/src/client/http/helpers/index.ts diff --git a/packages/network/src/client/http/helpers/index.ts b/packages/network/src/client/http/helpers/index.ts deleted file mode 100644 index f72bc43e2..000000000 --- a/packages/network/src/client/http/helpers/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './errors'; From 1de47b61e4b18908adab81353536c23f32172082 Mon Sep 17 00:00:00 2001 From: rodolfopietro97 Date: Tue, 7 Nov 2023 11:54:40 +0100 Subject: [PATCH 18/26] fix: move buildQUery in helper --- packages/network/src/client/thor/accounts/account-client.ts | 3 +-- packages/network/src/client/thor/helpers/index.ts | 1 - packages/network/src/utils/helpers/index.ts | 1 + packages/network/src/{client/thor => utils}/helpers/request.ts | 0 4 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 packages/network/src/client/thor/helpers/index.ts rename packages/network/src/{client/thor => utils}/helpers/request.ts (100%) diff --git a/packages/network/src/client/thor/accounts/account-client.ts b/packages/network/src/client/thor/accounts/account-client.ts index f5f8f3218..46958de98 100644 --- a/packages/network/src/client/thor/accounts/account-client.ts +++ b/packages/network/src/client/thor/accounts/account-client.ts @@ -1,12 +1,11 @@ import { DATA, buildError } from '@vechain-sdk/errors'; -import { blockUtils } from '../../../utils'; +import { blockUtils, buildQuery } from '../../../utils'; import { type HttpClient } from '../../http'; import { GET_ACCOUNT_BYTECODE_ENDPOINT, GET_ACCOUNT_DETAIL_ENDPOINT, GET_STORAGE_AT_ENDPOINT } from '../api'; -import { buildQuery } from '../helpers'; import { type ResponseBytecode, type AccountDetail, diff --git a/packages/network/src/client/thor/helpers/index.ts b/packages/network/src/client/thor/helpers/index.ts deleted file mode 100644 index 56e4b0555..000000000 --- a/packages/network/src/client/thor/helpers/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './request'; diff --git a/packages/network/src/utils/helpers/index.ts b/packages/network/src/utils/helpers/index.ts index f72bc43e2..efaf8a803 100644 --- a/packages/network/src/utils/helpers/index.ts +++ b/packages/network/src/utils/helpers/index.ts @@ -1 +1,2 @@ export * from './errors'; +export * from './request'; diff --git a/packages/network/src/client/thor/helpers/request.ts b/packages/network/src/utils/helpers/request.ts similarity index 100% rename from packages/network/src/client/thor/helpers/request.ts rename to packages/network/src/utils/helpers/request.ts From 7c0576e6d87e38e22744fc96a974dbaf90c55885 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Tue, 7 Nov 2023 11:55:16 +0100 Subject: [PATCH 19/26] feat: address validation --- docs/certificates.md | 4 +- docs/cryptography.md | 4 +- docs/examples/certificates/sign_verify.ts | 4 +- docs/examples/cryptography/secp256k1.ts | 4 +- packages/core/src/address/address.ts | 2 +- packages/core/src/certificate/certificate.ts | 4 +- packages/core/src/hdnode/hdnode.ts | 4 +- packages/core/src/keystore/keystore.ts | 4 +- .../core/src/transaction/handlers/sign.ts | 4 +- packages/core/src/transaction/transaction.ts | 8 ++-- packages/core/src/utils/bloom/bloom.ts | 4 +- .../core/src/utils/transaction/transaction.ts | 4 +- packages/core/tests/abi/fixture.ts | 10 ++--- packages/core/tests/address/address.test.ts | 24 ++++++----- packages/core/tests/certificate/fixture.ts | 4 +- packages/core/tests/hdnode/hdnode.test.ts | 22 +++++----- packages/core/tests/keystore/keystore.test.ts | 8 ++-- packages/core/tests/mnemonic/mnemonic.test.ts | 4 +- packages/core/tests/transaction/fixture.ts | 8 ++-- .../client/thor/accounts/account-client.ts | 31 +++++++++++-- packages/network/tests/client/thor/fixture.ts | 37 +++++++++++++++- .../client/thor/thor-client.testnet.test.ts | 43 +++++++++++-------- 22 files changed, 156 insertions(+), 85 deletions(-) diff --git a/docs/certificates.md b/docs/certificates.md index 6b742d5a8..307eec04e 100644 --- a/docs/certificates.md +++ b/docs/certificates.md @@ -39,7 +39,7 @@ import { certificate, secp256k1, blake2b256, - address + addressUtils } from '@vechain-sdk/core'; // In this example we create a certificate and @@ -48,7 +48,7 @@ import { // Generate a private key and address for the signer const privateKey = secp256k1.generatePrivateKey(); const publicKey = secp256k1.derivePublicKey(privateKey); -const signerAddress = address.fromPublicKey(publicKey); +const signerAddress = addressUtils.fromPublicKey(publicKey); // Create a certificate const cert: Certificate = { diff --git a/docs/cryptography.md b/docs/cryptography.md index e43491e0b..edfde5fd2 100644 --- a/docs/cryptography.md +++ b/docs/cryptography.md @@ -58,7 +58,7 @@ Secp256k1 is mainly used for generating public and private key pairs in cryptogr import { keccak256, secp256k1, - address, + addressUtils, type HashInput } from '@vechain-sdk/core'; import { expect } from 'expect'; @@ -70,7 +70,7 @@ console.log('Private key:', privateKey.toString('hex')); // Public key and address from private key const publicKey = secp256k1.derivePublicKey(privateKey); -const userAddress = address.fromPublicKey(publicKey); +const userAddress = addressUtils.fromPublicKey(publicKey); console.log('User address:', userAddress); // User address: 0x...SOME_ADDRESS... diff --git a/docs/examples/certificates/sign_verify.ts b/docs/examples/certificates/sign_verify.ts index d456a1663..8c58d26b9 100644 --- a/docs/examples/certificates/sign_verify.ts +++ b/docs/examples/certificates/sign_verify.ts @@ -3,7 +3,7 @@ import { certificate, secp256k1, blake2b256, - address + addressUtils } from '@vechain-sdk/core'; // In this example we create a certificate and @@ -12,7 +12,7 @@ import { // Generate a private key and address for the signer const privateKey = secp256k1.generatePrivateKey(); const publicKey = secp256k1.derivePublicKey(privateKey); -const signerAddress = address.fromPublicKey(publicKey); +const signerAddress = addressUtils.fromPublicKey(publicKey); // Create a certificate const cert: Certificate = { diff --git a/docs/examples/cryptography/secp256k1.ts b/docs/examples/cryptography/secp256k1.ts index 636d026c7..4beb0364e 100644 --- a/docs/examples/cryptography/secp256k1.ts +++ b/docs/examples/cryptography/secp256k1.ts @@ -1,7 +1,7 @@ import { keccak256, secp256k1, - address, + addressUtils, type HashInput } from '@vechain-sdk/core'; import { expect } from 'expect'; @@ -13,7 +13,7 @@ console.log('Private key:', privateKey.toString('hex')); // Public key and address from private key const publicKey = secp256k1.derivePublicKey(privateKey); -const userAddress = address.fromPublicKey(publicKey); +const userAddress = addressUtils.fromPublicKey(publicKey); console.log('User address:', userAddress); // User address: 0x...SOME_ADDRESS... diff --git a/packages/core/src/address/address.ts b/packages/core/src/address/address.ts index e5c94bee8..30ac2abbd 100644 --- a/packages/core/src/address/address.ts +++ b/packages/core/src/address/address.ts @@ -50,4 +50,4 @@ function toChecksumed(address: string): string { return ethers.getAddress(address); } -export const address = { fromPublicKey, isAddress, toChecksumed }; +export const addressUtils = { fromPublicKey, isAddress, toChecksumed }; diff --git a/packages/core/src/certificate/certificate.ts b/packages/core/src/certificate/certificate.ts index 7d2aa5da8..e0fb49f96 100644 --- a/packages/core/src/certificate/certificate.ts +++ b/packages/core/src/certificate/certificate.ts @@ -1,4 +1,4 @@ -import { address } from '../address'; +import { addressUtils } from '../address'; import { blake2b256 } from '../hash'; import { secp256k1 } from '../secp256k1'; import fastJsonStableStringify from 'fast-json-stable-stringify'; @@ -55,7 +55,7 @@ function verify(cert: Certificate): void { ); // Signature does not match with the signer's public key - if (address.fromPublicKey(pubKey) !== cert.signer) { + if (addressUtils.fromPublicKey(pubKey) !== cert.signer) { throw buildError( CERTIFICATE.CERTIFICATE_INVALID_SIGNER, "Signature does not match with the signer's public key." diff --git a/packages/core/src/hdnode/hdnode.ts b/packages/core/src/hdnode/hdnode.ts index 4ff5f64e4..db1d90424 100644 --- a/packages/core/src/hdnode/hdnode.ts +++ b/packages/core/src/hdnode/hdnode.ts @@ -7,7 +7,7 @@ import { X_PUB_PREFIX } from '../utils'; import { type IHDNode } from './types'; -import { address } from '../address'; +import { addressUtils } from '../address'; import { sha256 } from '../hash'; import { secp256k1 } from '../secp256k1'; import { type WordlistSizeType } from '../mnemonic'; @@ -142,7 +142,7 @@ function ethersNodeToOurHDNode(ethersNode: ethers.HDNodeWallet): IHDNode { ) ); const cc = Buffer.from(ethersNode.chainCode.slice(2), 'hex'); - const addr = address.fromPublicKey(pub); + const addr = addressUtils.fromPublicKey(pub); return { get publicKey() { diff --git a/packages/core/src/keystore/keystore.ts b/packages/core/src/keystore/keystore.ts index e02830d81..dc7a480a7 100644 --- a/packages/core/src/keystore/keystore.ts +++ b/packages/core/src/keystore/keystore.ts @@ -1,7 +1,7 @@ /** * Implements the JSON Keystore v3 Wallet encryption, decryption, and validation functionality. */ -import { address } from '../address'; +import { addressUtils } from '../address'; import { secp256k1 } from '../secp256k1'; import { ethers } from 'ethers'; import { SCRYPT_PARAMS } from '../utils'; @@ -21,7 +21,7 @@ async function encrypt( ): Promise { // Public and Address are derived from private key const derivePublicKey = secp256k1.derivePublicKey(privateKey); - const deriveAddress = address.fromPublicKey(derivePublicKey); + const deriveAddress = addressUtils.fromPublicKey(derivePublicKey); // Create keystore account compatible with ethers const keystoreAccount: ethers.KeystoreAccount = { diff --git a/packages/core/src/transaction/handlers/sign.ts b/packages/core/src/transaction/handlers/sign.ts index 8ee3d5b8d..47055f5c5 100644 --- a/packages/core/src/transaction/handlers/sign.ts +++ b/packages/core/src/transaction/handlers/sign.ts @@ -1,4 +1,4 @@ -import { address } from '../../address'; +import { addressUtils } from '../../address'; import { secp256k1 } from '../../secp256k1'; import { Transaction } from '../transaction'; import { buildError, SECP256K1, TRANSACTION } from '@vechain-sdk/errors'; @@ -88,7 +88,7 @@ function signWithDelegator( const transactionHash = transactionToSign.getSignatureHash(); const delegatedHash = transactionToSign.getSignatureHash( - address.fromPublicKey(secp256k1.derivePublicKey(signerPrivateKey)) + addressUtils.fromPublicKey(secp256k1.derivePublicKey(signerPrivateKey)) ); const signature = Buffer.concat([ secp256k1.sign(transactionHash, signerPrivateKey), diff --git a/packages/core/src/transaction/transaction.ts b/packages/core/src/transaction/transaction.ts index 092ae15f8..2a367f205 100644 --- a/packages/core/src/transaction/transaction.ts +++ b/packages/core/src/transaction/transaction.ts @@ -1,4 +1,4 @@ -import { address } from '../address'; +import { addressUtils } from '../address'; import { type RLPValidObject } from '../encoding'; import { blake2b256 } from '../hash'; import { secp256k1 } from '../secp256k1'; @@ -126,7 +126,7 @@ class Transaction { ); // Address from public key - return address.fromPublicKey(delegatorPublicKey); + return addressUtils.fromPublicKey(delegatorPublicKey); } /** @@ -188,7 +188,7 @@ class Transaction { */ public getSignatureHash(delegateFor?: string): Buffer { // Correct delegateFor address - if (delegateFor !== undefined && !address.isAddress(delegateFor)) + if (delegateFor !== undefined && !addressUtils.isAddress(delegateFor)) throw buildError( ADDRESS.INVALID_ADDRESS, 'Invalid address given as input as delegateFor parameter.' @@ -244,7 +244,7 @@ class Transaction { ); // Address from public key - return address.fromPublicKey(originPublicKey); + return addressUtils.fromPublicKey(originPublicKey); } /** diff --git a/packages/core/src/utils/bloom/bloom.ts b/packages/core/src/utils/bloom/bloom.ts index 604ad179b..aa538f545 100644 --- a/packages/core/src/utils/bloom/bloom.ts +++ b/packages/core/src/utils/bloom/bloom.ts @@ -1,7 +1,7 @@ import { bloom as bloomInstance } from '../../bloom'; import { dataUtils } from '../data'; import { type HexString } from '../types'; -import { address } from '../../address'; +import { addressUtils } from '../../address'; import { BLOOM_REGEX_LOWERCASE, BLOOM_REGEX_UPPERCASE } from '../const'; import { ADDRESS, BLOOM, buildError, DATA } from '@vechain-sdk/errors'; @@ -108,7 +108,7 @@ const isAddressInBloom = ( k: number, addressToCheck: HexString ): boolean => { - if (!address.isAddress(addressToCheck)) { + if (!addressUtils.isAddress(addressToCheck)) { throw buildError( ADDRESS.INVALID_ADDRESS, 'Invalid address given as input in Bloom filter.' diff --git a/packages/core/src/utils/transaction/transaction.ts b/packages/core/src/utils/transaction/transaction.ts index 687920fbf..d38483bc7 100644 --- a/packages/core/src/utils/transaction/transaction.ts +++ b/packages/core/src/utils/transaction/transaction.ts @@ -1,4 +1,4 @@ -import { address } from '../../address'; +import { addressUtils } from '../../address'; import { type TransactionClause } from '../../transaction'; import { TRANSACTIONS_GAS_CONSTANTS } from '../const'; import { dataUtils } from '../data'; @@ -26,7 +26,7 @@ function intrinsicGas(clauses: TransactionClause[]): number { return clauses.reduce((sum, clause: TransactionClause) => { if (clause.to !== null) { // Invalid address - if (!address.isAddress(clause.to)) { + if (!addressUtils.isAddress(clause.to)) { throw buildError( DATA.INVALID_DATA_TYPE, 'Invalid data type. Data should be an address.' diff --git a/packages/core/tests/abi/fixture.ts b/packages/core/tests/abi/fixture.ts index feaa91722..a0e843461 100644 --- a/packages/core/tests/abi/fixture.ts +++ b/packages/core/tests/abi/fixture.ts @@ -1,4 +1,4 @@ -import { address } from '../../src'; +import { addressUtils } from '../../src'; /** * Simple functions fixtures @@ -97,10 +97,10 @@ const functions = [ */ const simpleParametersDataForFunction2 = [ { - master: address.toChecksumed( + master: addressUtils.toChecksumed( '0x0e8fd586e022f825a109848832d7e552132bc332' ), - endorsor: address.toChecksumed( + endorsor: addressUtils.toChecksumed( '0x224626926a7a12225a60e127cec119c939db4a5c' ), identity: @@ -108,10 +108,10 @@ const simpleParametersDataForFunction2 = [ active: false }, { - master: address.toChecksumed( + master: addressUtils.toChecksumed( '0x4977d68df97bb313b23238520580d8d3a59939bf' ), - endorsor: address.toChecksumed( + endorsor: addressUtils.toChecksumed( '0x7ad1d568b3fe5bad3fc264aca70bc7bcd5e4a6ff' ), identity: diff --git a/packages/core/tests/address/address.test.ts b/packages/core/tests/address/address.test.ts index 392eef268..1cade1acc 100644 --- a/packages/core/tests/address/address.test.ts +++ b/packages/core/tests/address/address.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from '@jest/globals'; -import { address, secp256k1 } from '../../src'; +import { addressUtils, secp256k1 } from '../../src'; import { checksumedAndUnchecksumedAddresses, invalidPrivateKey, @@ -25,12 +25,16 @@ describe('Address', () => { * Valid and invalid address check */ test('validate address', () => { - expect(address.isAddress('not an address')).toEqual(false); + expect(addressUtils.isAddress('not an address')).toEqual(false); expect( - address.isAddress('52908400098527886E0F7030069857D2E4169EE7') + addressUtils.isAddress( + '52908400098527886E0F7030069857D2E4169EE7' + ) ).toEqual(false); expect( - address.isAddress('0x52908400098527886E0F7030069857D2E4169EE7') + addressUtils.isAddress( + '0x52908400098527886E0F7030069857D2E4169EE7' + ) ).toEqual(true); }); }); @@ -47,7 +51,7 @@ describe('Address', () => { expect(secp256k1.derivePublicKey(simplePrivateKey)).toEqual( simplePublicKey ); - expect(address.fromPublicKey(simplePublicKey)).toEqual( + expect(addressUtils.fromPublicKey(simplePublicKey)).toEqual( simpleAddress ); @@ -67,10 +71,10 @@ describe('Address', () => { */ test('invalid input should throw error', () => { expect(() => { - address.toChecksumed('invalid data'); + addressUtils.toChecksumed('invalid data'); }).toThrowError(InvalidAddressError); expect(() => { - address.toChecksumed( + addressUtils.toChecksumed( '52908400098527886E0F7030069857D2E4169EE7' ); }).toThrowError(InvalidAddressError); @@ -81,9 +85,9 @@ describe('Address', () => { */ test('valid input', () => { checksumedAndUnchecksumedAddresses.forEach((addressPair) => { - expect(address.toChecksumed(addressPair.unchecksumed)).toEqual( - addressPair.checksumed - ); + expect( + addressUtils.toChecksumed(addressPair.unchecksumed) + ).toEqual(addressPair.checksumed); }); }); }); diff --git a/packages/core/tests/certificate/fixture.ts b/packages/core/tests/certificate/fixture.ts index c0344edee..c70c7d6e8 100644 --- a/packages/core/tests/certificate/fixture.ts +++ b/packages/core/tests/certificate/fixture.ts @@ -1,4 +1,4 @@ -import { secp256k1, address, blake2b256, certificate } from '../../src'; +import { secp256k1, addressUtils, blake2b256, certificate } from '../../src'; /** * Private Key used for digital signature during certificate creation @@ -19,7 +19,7 @@ const cert = { }, domain: 'localhost', timestamp: 1545035330, - signer: address.fromPublicKey(secp256k1.derivePublicKey(privKey)) + signer: addressUtils.fromPublicKey(secp256k1.derivePublicKey(privKey)) }; /** diff --git a/packages/core/tests/hdnode/hdnode.test.ts b/packages/core/tests/hdnode/hdnode.test.ts index 05f0f93af..ed3b56c23 100644 --- a/packages/core/tests/hdnode/hdnode.test.ts +++ b/packages/core/tests/hdnode/hdnode.test.ts @@ -3,7 +3,7 @@ import { HDNode, type WordlistSizeType, ZERO_BUFFER, - address, + addressUtils, mnemonic, secp256k1 } from '../../src'; @@ -32,9 +32,9 @@ describe('Hdnode', () => { const child = node.derive(i); // Correct address - expect(address.fromPublicKey(child.publicKey).slice(2)).toEqual( - addresses[i] - ); + expect( + addressUtils.fromPublicKey(child.publicKey).slice(2) + ).toEqual(addresses[i]); expect(child.address).toEqual('0x' + addresses[i]); // Correct public key @@ -53,9 +53,9 @@ describe('Hdnode', () => { for (let i = 0; i < 5; i++) { const child = xprivNode.derive(i); // Correct address - expect(address.fromPublicKey(child.publicKey).slice(2)).toEqual( - addresses[i] - ); + expect( + addressUtils.fromPublicKey(child.publicKey).slice(2) + ).toEqual(addresses[i]); expect(child.address).toEqual('0x' + addresses[i]); // Correct public key @@ -71,9 +71,9 @@ describe('Hdnode', () => { for (let i = 0; i < 5; i++) { const child = xpubNode.derive(i); // Correct address - expect(address.fromPublicKey(child.publicKey).slice(2)).toEqual( - addresses[i] - ); + expect( + addressUtils.fromPublicKey(child.publicKey).slice(2) + ).toEqual(addresses[i]); expect(child.address).toEqual('0x' + addresses[i]); // Null private key @@ -113,7 +113,7 @@ describe('Hdnode', () => { // Address expect(currentHdnode.address).toBeDefined(); - address.isAddress(currentHdnode.address); + addressUtils.isAddress(currentHdnode.address); } ); }); diff --git a/packages/core/tests/keystore/keystore.test.ts b/packages/core/tests/keystore/keystore.test.ts index 63191787d..aacc38595 100644 --- a/packages/core/tests/keystore/keystore.test.ts +++ b/packages/core/tests/keystore/keystore.test.ts @@ -1,5 +1,5 @@ import { describe, test, expect } from '@jest/globals'; -import { secp256k1, address, keystore } from '../../src'; +import { secp256k1, addressUtils, keystore } from '../../src'; import { type Keystore } from '../../src'; import { encryptionPassword } from './fixture'; import { @@ -28,8 +28,10 @@ describe('Keystore', () => { // Verify keystore expect(myKeystore.version).toBe(3); - const keyStoreAddress = address.toChecksumed(`0x` + myKeystore.address); - const addressFromPrivateKey = address.fromPublicKey( + const keyStoreAddress = addressUtils.toChecksumed( + `0x` + myKeystore.address + ); + const addressFromPrivateKey = addressUtils.fromPublicKey( secp256k1.derivePublicKey(privateKey) ); expect(keyStoreAddress).toEqual(addressFromPrivateKey); diff --git a/packages/core/tests/mnemonic/mnemonic.test.ts b/packages/core/tests/mnemonic/mnemonic.test.ts index a47cf853a..80250687f 100644 --- a/packages/core/tests/mnemonic/mnemonic.test.ts +++ b/packages/core/tests/mnemonic/mnemonic.test.ts @@ -7,7 +7,7 @@ import { wrongDerivationPath } from './fixture'; import { - address, + addressUtils, MNEMONIC_WORDLIST_ALLOWED_SIZES, secp256k1, type WordlistSizeType @@ -66,7 +66,7 @@ describe('Mnemonic', () => { expect(mnemonic.deriveAddress(words)).toBeDefined(); expect(mnemonic.deriveAddress(words).length).toEqual(42); expect( - address.isAddress(mnemonic.deriveAddress(words)) + addressUtils.isAddress(mnemonic.deriveAddress(words)) ).toBe(true); } ); diff --git a/packages/core/tests/transaction/fixture.ts b/packages/core/tests/transaction/fixture.ts index 7b383bcc6..bcae7db08 100644 --- a/packages/core/tests/transaction/fixture.ts +++ b/packages/core/tests/transaction/fixture.ts @@ -1,4 +1,4 @@ -import { address, secp256k1, type TransactionBody } from '../../src'; +import { addressUtils, secp256k1, type TransactionBody } from '../../src'; /** * Simple correct transaction body fixture @@ -103,7 +103,9 @@ const _signerPrivateKey = Buffer.from( ); const signer = { privateKey: _signerPrivateKey, - address: address.fromPublicKey(secp256k1.derivePublicKey(_signerPrivateKey)) + address: addressUtils.fromPublicKey( + secp256k1.derivePublicKey(_signerPrivateKey) + ) }; /** @@ -115,7 +117,7 @@ const _delegatorPrivateKey = Buffer.from( ); const delegator = { privateKey: _delegatorPrivateKey, - address: address.fromPublicKey( + address: addressUtils.fromPublicKey( secp256k1.derivePublicKey(_delegatorPrivateKey) ) }; diff --git a/packages/network/src/client/thor/accounts/account-client.ts b/packages/network/src/client/thor/accounts/account-client.ts index f5f8f3218..101df2a64 100644 --- a/packages/network/src/client/thor/accounts/account-client.ts +++ b/packages/network/src/client/thor/accounts/account-client.ts @@ -13,7 +13,7 @@ import { type IAccountClient, type ResponseStorage } from './types'; -import { dataUtils } from '@vechain-sdk/core'; +import { dataUtils, addressUtils } from '@vechain-sdk/core'; /** * The `AccountClient` class provides methods to interact with account-related endpoints @@ -34,12 +34,20 @@ class AccountClient implements IAccountClient { * @param revision - (Optional) The block number or ID to reference the state of the account. * @returns A promise that resolves to an object containing the account details (balance, energy, hasCode). * - * @throws {InvalidDataTypeError} - Will throw an error if the revision is not a valid block number or ID. + * @throws {InvalidDataTypeError} - Will throw an error if the revision is not a valid block number or ID + * or if the address is not a valid address. */ public async getAccount( address: string, revision?: string ): Promise { + if (!addressUtils.isAddress(address)) { + throw buildError( + DATA.INVALID_DATA_TYPE, + 'Invalid address. The address must be 20 bytes (a 42 characters hex string with a `0x` prefix.)' + ); + } + if (revision != null && !blockUtils.isBlockRevision(revision)) throw buildError( DATA.INVALID_DATA_TYPE, @@ -62,12 +70,20 @@ class AccountClient implements IAccountClient { * @param revision - (Optional) The block number or ID to reference the bytecode version. * @returns A promise that resolves to the contract bytecode as a string. * - * @throws {InvalidDataTypeError} - Will throw an error if the revision is not a valid block number or ID. + * @throws {InvalidDataTypeError} - Will throw an error if the revision is not a valid block number or ID + * or if the address is not a valid address. */ public async getBytecode( address: string, revision?: string ): Promise { + if (!addressUtils.isAddress(address)) { + throw buildError( + DATA.INVALID_DATA_TYPE, + 'Invalid address. The address must be 20 bytes (a 42 characters hex string with a `0x` prefix.)' + ); + } + if (revision != null && !blockUtils.isBlockRevision(revision)) throw buildError( DATA.INVALID_DATA_TYPE, @@ -94,13 +110,20 @@ class AccountClient implements IAccountClient { * @returns A promise that resolves to the storage value in hex string format. * * @throws {InvalidDataTypeError} - Will throw an error if the revision is not a valid block number or ID - * or if the position is not a 32 bytes hex string. + * or if the position is not a 32 bytes hex string or if the address is not a valid address. */ public async getStorageAt( address: string, position: string, revision?: string ): Promise { + if (!addressUtils.isAddress(address)) { + throw buildError( + DATA.INVALID_DATA_TYPE, + 'Invalid address. The address must be 20 bytes (a 42 characters hex string with a `0x` prefix.)' + ); + } + if (revision != null && !blockUtils.isBlockRevision(revision)) throw buildError( DATA.INVALID_DATA_TYPE, diff --git a/packages/network/tests/client/thor/fixture.ts b/packages/network/tests/client/thor/fixture.ts index 554ee6a89..05000b0c0 100644 --- a/packages/network/tests/client/thor/fixture.ts +++ b/packages/network/tests/client/thor/fixture.ts @@ -137,6 +137,39 @@ const invalidGetStorageAtTests = [ } ]; +/** + * Invalid getAccount test cases for invalid data types + */ +const invalidGetAccountTests = [ + { + description: 'Should throw error for invalid revision', + address: testAccount, + revision: 'invalid-revision', + expectedError: InvalidDataTypeError + }, + { + description: 'Should throw error for invalid address', + address: 'invalid-address', + revision: '1', + expectedError: InvalidDataTypeError + } +]; + +const invalidGetBytecodeTests = [ + { + description: 'Should throw error for invalid revision', + address: testSmartContract, + revision: 'invalid-revision', + expectedError: InvalidDataTypeError + }, + { + description: 'Should throw error for invalid address', + address: 'invalid-address', + revision: '1', + expectedError: InvalidDataTypeError + } +]; + export { thorClient, getAccountWithRevisionTestCases, @@ -144,5 +177,7 @@ export { testSmartContract, testStoragePositionKey, NULL_STORAGE_SLOT, - invalidGetStorageAtTests + invalidGetStorageAtTests, + invalidGetAccountTests, + invalidGetBytecodeTests }; diff --git a/packages/network/tests/client/thor/thor-client.testnet.test.ts b/packages/network/tests/client/thor/thor-client.testnet.test.ts index 13143bbb0..a04ef0282 100644 --- a/packages/network/tests/client/thor/thor-client.testnet.test.ts +++ b/packages/network/tests/client/thor/thor-client.testnet.test.ts @@ -3,13 +3,14 @@ import { NULL_STORAGE_SLOT, getAccountWithRevisionTestCases, getBytecodeTestCases, + invalidGetAccountTests, + invalidGetBytecodeTests, invalidGetStorageAtTests, testSmartContract, testStoragePositionKey, thorClient } from './fixture'; import { testAccount } from '../../fixture'; -import { InvalidDataTypeError } from '@vechain-sdk/errors'; /** * ThorClient class tests @@ -49,13 +50,17 @@ describe('ThorClient', () => { }); /** - * getAccount with invalid revision + * getAccount with invalid revision & address */ - test('get account with invalid revision', async () => { - await expect( - thorClient.getAccount(testAccount, 'invalid-revision') - ).rejects.toThrowError(InvalidDataTypeError); - }); + invalidGetAccountTests.forEach( + ({ description, address, revision, expectedError }) => { + test(description, async () => { + await expect( + thorClient.getAccount(address, revision) + ).rejects.toThrowError(expectedError); + }); + } + ); }); /** @@ -78,13 +83,17 @@ describe('ThorClient', () => { ); /** - * Tests invalid revision + * Tests invalid revision & address */ - test('invalid revision should throw an error', async () => { - await expect( - thorClient.getBytecode(testAccount, 'invalid-revision') - ).rejects.toThrowError(InvalidDataTypeError); - }); + invalidGetBytecodeTests.forEach( + ({ description, address, revision, expectedError }) => { + test(description, async () => { + await expect( + thorClient.getBytecode(address, revision) + ).rejects.toThrowError(expectedError); + }); + } + ); }); /** @@ -122,14 +131,10 @@ describe('ThorClient', () => { * Tests invalid position & revisions */ invalidGetStorageAtTests.forEach( - ({ description, position, revision, expectedError }) => { + ({ description, address, position, revision, expectedError }) => { test(description, async () => { await expect( - thorClient.getStorageAt( - testSmartContract, - position, - revision - ) + thorClient.getStorageAt(address, position, revision) ).rejects.toThrowError(expectedError); }); } From f111199c53be372825c73b850cc268f8ea6f0f06 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Tue, 7 Nov 2023 12:12:32 +0100 Subject: [PATCH 20/26] refactor: hierarchy of thor-client & removing interfaces --- .../client/thor/accounts/account-client.ts | 16 ++--- .../src/client/thor/accounts/types.d.ts | 51 +-------------- .../network/src/client/thor/thor-client.ts | 63 +------------------ packages/network/src/client/thor/types.d.ts | 9 --- packages/network/src/utils/index.ts | 1 + .../thor/api.ts => utils/thorest/account.ts} | 15 +++-- packages/network/src/utils/thorest/index.ts | 5 ++ 7 files changed, 22 insertions(+), 138 deletions(-) rename packages/network/src/{client/thor/api.ts => utils/thorest/account.ts} (70%) create mode 100644 packages/network/src/utils/thorest/index.ts diff --git a/packages/network/src/client/thor/accounts/account-client.ts b/packages/network/src/client/thor/accounts/account-client.ts index 822426e8b..db005708f 100644 --- a/packages/network/src/client/thor/accounts/account-client.ts +++ b/packages/network/src/client/thor/accounts/account-client.ts @@ -1,15 +1,9 @@ import { DATA, buildError } from '@vechain-sdk/errors'; -import { blockUtils, buildQuery } from '../../../utils'; +import { blockUtils, buildQuery, thorest } from '../../../utils'; import { type HttpClient } from '../../http'; -import { - GET_ACCOUNT_BYTECODE_ENDPOINT, - GET_ACCOUNT_DETAIL_ENDPOINT, - GET_STORAGE_AT_ENDPOINT -} from '../api'; import { type ResponseBytecode, type AccountDetail, - type IAccountClient, type ResponseStorage } from './types'; import { dataUtils, addressUtils } from '@vechain-sdk/core'; @@ -19,7 +13,7 @@ import { dataUtils, addressUtils } from '@vechain-sdk/core'; * of the VechainThor blockchain. It allows fetching details, bytecode, and storage data * for a specific blockchain account. */ -class AccountClient implements IAccountClient { +class AccountClient { /** * Initializes a new instance of the `AccountClient` class. * @param httpClient - The HTTP client instance used for making HTTP requests. @@ -55,7 +49,7 @@ class AccountClient implements IAccountClient { return (await this.httpClient.http( 'GET', - GET_ACCOUNT_DETAIL_ENDPOINT(address), + thorest.account.ACCOUNT_DETAIL(address), { query: buildQuery({ revision }) } @@ -91,7 +85,7 @@ class AccountClient implements IAccountClient { const result = (await this.httpClient.http( 'GET', - GET_ACCOUNT_BYTECODE_ENDPOINT(address), + thorest.account.ACCOUNT_BYTECODE(address), { query: buildQuery({ revision }) } @@ -138,7 +132,7 @@ class AccountClient implements IAccountClient { const result = (await this.httpClient.http( 'GET', - GET_STORAGE_AT_ENDPOINT(address, position), + thorest.account.STORAGE_AT(address, position), { query: buildQuery({ position, revision }) } diff --git a/packages/network/src/client/thor/accounts/types.d.ts b/packages/network/src/client/thor/accounts/types.d.ts index 7b4f10fc7..3ac827d1c 100644 --- a/packages/network/src/client/thor/accounts/types.d.ts +++ b/packages/network/src/client/thor/accounts/types.d.ts @@ -1,47 +1,3 @@ -/** - * An account represents both an EOA and a smart contract on the VechainThor blockchain. - * - * This interface provides methods to interact with accounts on the VechainThor blockchain. - */ -interface IAccountClient { - /** - * Get the account details of the specified account. - * - * @param address - The address of the account. - * @param revision - The block revision as the desired block number o block id (default: best block). - * - * @returns an object containing the account's balance (VET), energy (VTHO) & whether it is a smart contract (hasCode). - */ - getAccount: (address: string, revision?: string) => Promise; - - /** - * Get the bytecode of the deployed smart contract. - * - * @param address - The address of the smart contract. - * @param revision - The block revision as the desired block number o block id (default: best block). - * Bytecode is immutable for a smart contract, thus the revision can be useful to check if the - * smart contract was deployed at the specified block. - * - * @returns the bytecode of the deployed smart contract in hex string. - */ - getBytecode: (address: string, revision?: string) => Promise; - - /** - * Get the storage data at the specified position of the smart contract. - * - * @param address - The address of the smart contract. - * @param position - The position of the storage data. - * @param revision - The block revision as the desired block number o block id (default: best block). - * - * @returns the storage data at the specified position of the smart contract in hex string. - */ - getStorageAt: ( - address: string, - position: string, - revision?: string - ) => Promise; -} - /** * The account details represent the balance, energy & whether the account is a smart contract. */ @@ -78,9 +34,4 @@ interface ResponseStorage { value: string; } -export type { - IAccountClient, - AccountDetail, - ResponseBytecode, - ResponseStorage -}; +export type { AccountDetail, ResponseBytecode, ResponseStorage }; diff --git a/packages/network/src/client/thor/thor-client.ts b/packages/network/src/client/thor/thor-client.ts index 6ed0dbb43..82353ef86 100644 --- a/packages/network/src/client/thor/thor-client.ts +++ b/packages/network/src/client/thor/thor-client.ts @@ -1,74 +1,17 @@ import { type HttpClient } from '../http'; -import { AccountClient, type AccountDetail } from './accounts'; -import { type IThorClient } from './types'; +import { AccountClient } from './accounts'; /** * The `ThorClient` class serves as an interface to interact with the VeChain Thor blockchain. * It provides methods for accessing account details, contract bytecode, and storage. */ -class ThorClient implements IThorClient { - /** - * An instance of `AccountClient` to delegate account-related requests. - */ - private readonly accountClient: AccountClient; - +class ThorClient extends AccountClient { /** * Constructs a new `ThorClient` instance with a given HTTP client. * @param httpClient - The HTTP client instance used for making network requests. */ constructor(protected readonly httpClient: HttpClient) { - this.accountClient = new AccountClient(httpClient); - } - - /* --------------------------- Account (Externally Owned Accounts & Smart Contracts) --------------------------- */ - - /** - * Retrieves details for an account such as balance and nonce. - * This can be used for both externally owned accounts (EOAs) and smart contracts. - * - * @param address - The address of the account to query. - * @param revision - (Optional) A specific block number or ID to reference the state. - * @returns A promise resolved with the account details. - */ - public async getAccount( - address: string, - revision?: string | undefined - ): Promise { - return await this.accountClient.getAccount(address, revision); - } - - /** - * Fetches the bytecode of a smart contract at a specified address. - * - * @param address - The contract address to get the bytecode for. - * @param revision - (Optional) A specific block number or ID to reference the bytecode version. - * @returns A promise resolved with the contract bytecode as a string. - */ - public async getBytecode( - address: string, - revision?: string | undefined - ): Promise { - return await this.accountClient.getBytecode(address, revision); - } - - /** - * Retrieves the storage value from a specified position in a smart contract. - * - * @param address - The address of the contract to query storage from. - * @param position - The hex-encoded storage position to retrieve the value from. - * @param revision - (Optional) A specific block number or ID to reference the storage state. - * @returns A promise resolved with the storage value at the specified position. - */ - public async getStorageAt( - address: string, - position: string, - revision?: string | undefined - ): Promise { - return await this.accountClient.getStorageAt( - address, - position, - revision - ); + super(httpClient); } } diff --git a/packages/network/src/client/thor/types.d.ts b/packages/network/src/client/thor/types.d.ts index 030ba37ff..e69de29bb 100644 --- a/packages/network/src/client/thor/types.d.ts +++ b/packages/network/src/client/thor/types.d.ts @@ -1,9 +0,0 @@ -import { type IAccountClient } from './accounts'; - -/** - * The ThorClient interface contains all the methods for interacting with the VeChainThor blockchain. - * @extends IAccountClient - */ -interface IThorClient extends IAccountClient {} - -export type { IThorClient }; diff --git a/packages/network/src/utils/index.ts b/packages/network/src/utils/index.ts index 945019aca..1c60dd602 100644 --- a/packages/network/src/utils/index.ts +++ b/packages/network/src/utils/index.ts @@ -2,3 +2,4 @@ export * from './block'; export * from './const'; export * from './helpers'; export * from './block'; +export * from './thorest'; diff --git a/packages/network/src/client/thor/api.ts b/packages/network/src/utils/thorest/account.ts similarity index 70% rename from packages/network/src/client/thor/api.ts rename to packages/network/src/utils/thorest/account.ts index bd41ccd83..56f80bd75 100644 --- a/packages/network/src/client/thor/api.ts +++ b/packages/network/src/utils/thorest/account.ts @@ -4,8 +4,7 @@ * @param address - The account address. * @returns The URL endpoint to fetch account details. */ -const GET_ACCOUNT_DETAIL_ENDPOINT = (address: string): string => - `/accounts/${address}`; +const ACCOUNT_DETAIL = (address: string): string => `/accounts/${address}`; /** * Constructs the endpoint URL for retrieving the bytecode of a smart contract. @@ -13,7 +12,7 @@ const GET_ACCOUNT_DETAIL_ENDPOINT = (address: string): string => * @param address - The account address. * @returns The URL endpoint to fetch the smart contract's bytecode. */ -const GET_ACCOUNT_BYTECODE_ENDPOINT = (address: string): string => +const ACCOUNT_BYTECODE = (address: string): string => `/accounts/${address}/code`; /** @@ -24,11 +23,11 @@ const GET_ACCOUNT_BYTECODE_ENDPOINT = (address: string): string => * @param position - The specified position in the contract's storage. * @returns The URL endpoint to fetch the storage data at the given position. */ -const GET_STORAGE_AT_ENDPOINT = (address: string, position: string): string => +const STORAGE_AT = (address: string, position: string): string => `/accounts/${address}/storage/${position}`; -export { - GET_ACCOUNT_DETAIL_ENDPOINT, - GET_ACCOUNT_BYTECODE_ENDPOINT, - GET_STORAGE_AT_ENDPOINT +export const account = { + ACCOUNT_DETAIL, + ACCOUNT_BYTECODE, + STORAGE_AT }; diff --git a/packages/network/src/utils/thorest/index.ts b/packages/network/src/utils/thorest/index.ts new file mode 100644 index 000000000..57e0eace4 --- /dev/null +++ b/packages/network/src/utils/thorest/index.ts @@ -0,0 +1,5 @@ +import { account } from './account'; + +export const thorest = { + account +}; From 8927d397b4bb54e826374eff1323889b6ec473d9 Mon Sep 17 00:00:00 2001 From: Piero Bassa Date: Tue, 7 Nov 2023 12:17:17 +0100 Subject: [PATCH 21/26] feat: check if revision is 'best' too --- packages/network/src/utils/block/block.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/network/src/utils/block/block.ts b/packages/network/src/utils/block/block.ts index 01edebda9..3c332c415 100644 --- a/packages/network/src/utils/block/block.ts +++ b/packages/network/src/utils/block/block.ts @@ -10,7 +10,8 @@ import { dataUtils } from '@vechain-sdk/core'; const isBlockRevision = (revision: string): boolean => { if ( !dataUtils.isHexString(revision) && - !dataUtils.isDecimalString(revision) + !dataUtils.isDecimalString(revision) && + revision !== 'best' ) { return false; } From 97ecdd8085a1a0f8bed148e1c78786ff6a6b12e8 Mon Sep 17 00:00:00 2001 From: rodolfopietro97 Date: Tue, 7 Nov 2023 12:24:21 +0100 Subject: [PATCH 22/26] fix: remove redundant interface --- .../network/src/client/http/http-client.ts | 8 ++--- packages/network/src/client/http/types.d.ts | 31 +------------------ 2 files changed, 3 insertions(+), 36 deletions(-) diff --git a/packages/network/src/client/http/http-client.ts b/packages/network/src/client/http/http-client.ts index 721144dc7..2540fa116 100644 --- a/packages/network/src/client/http/http-client.ts +++ b/packages/network/src/client/http/http-client.ts @@ -1,11 +1,7 @@ import Axios, { type AxiosInstance, type AxiosRequestConfig } from 'axios'; import { Agent as HttpAgent } from 'http'; import { Agent as HttpsAgent } from 'https'; -import { - type IHttpClient, - type HttpParams, - type HttpClientOptions -} from './types'; +import { type HttpParams, type HttpClientOptions } from './types'; import { convertError, DEFAULT_HTTP_TIMEOUT } from '../../utils'; import { buildError, HTTP_CLIENT } from '@vechain-sdk/errors'; @@ -17,7 +13,7 @@ import { buildError, HTTP_CLIENT } from '@vechain-sdk/errors'; * * @public */ -class HttpClient implements IHttpClient { +class HttpClient { protected readonly axios: AxiosInstance; /** diff --git a/packages/network/src/client/http/types.d.ts b/packages/network/src/client/http/types.d.ts index e39fd3395..2190c62d8 100644 --- a/packages/network/src/client/http/types.d.ts +++ b/packages/network/src/client/http/types.d.ts @@ -1,34 +1,5 @@ import { type AxiosInstance } from 'axios'; -/** - * Represents the core networking interface for executing HTTP requests. - * - * This interface encapsulates methods for sending HTTP requests. It also outlines the structure for request parameters, - * making it a foundational networking API. - * - * @public - */ -interface IHttpClient { - /** - * The base URL for all network requests. - */ - readonly baseURL: string; - - /** - * Performs an HTTP request. - * - * @param method - Specifies the HTTP method to use, either 'GET' or 'POST'. - * @param path - Specifies the path to access on the server, relative to the baseURL. - * @param params - (Optional) Additional parameters for the request. - * @returns A promise resolving to the response body, JSON decoded. - */ - http: ( - method: 'GET' | 'POST', - path: string, - params?: NetParams - ) => Promise; -} - /** * Represents the parameters for making an HTTP request. * @@ -77,4 +48,4 @@ interface HttpClientOptions { axiosInstance?: AxiosInstance; } -export type { IHttpClient, HttpParams, HttpClientOptions }; +export type { HttpParams, HttpClientOptions }; From 034fe90180a20b84e742294d648a7ced7921b623 Mon Sep 17 00:00:00 2001 From: rodolfopietro97 Date: Tue, 7 Nov 2023 12:48:33 +0100 Subject: [PATCH 23/26] fix: missing export --- packages/network/src/client/thor/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/network/src/client/thor/index.ts b/packages/network/src/client/thor/index.ts index 321b608df..826b79337 100644 --- a/packages/network/src/client/thor/index.ts +++ b/packages/network/src/client/thor/index.ts @@ -1 +1,2 @@ +export * from './accounts'; export * from './thor-client'; From 517bdd2f06df28cdb3099d898e5e65c89c1a8423 Mon Sep 17 00:00:00 2001 From: rodolfopietro97 Date: Tue, 7 Nov 2023 12:48:57 +0100 Subject: [PATCH 24/26] fix: composition better wrt inerithance --- .../network/src/client/thor/thor-client.ts | 9 ++++++-- .../client/thor/thor-client.testnet.test.ts | 21 ++++++++++++------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/network/src/client/thor/thor-client.ts b/packages/network/src/client/thor/thor-client.ts index 82353ef86..f82d526f2 100644 --- a/packages/network/src/client/thor/thor-client.ts +++ b/packages/network/src/client/thor/thor-client.ts @@ -5,13 +5,18 @@ import { AccountClient } from './accounts'; * The `ThorClient` class serves as an interface to interact with the VeChain Thor blockchain. * It provides methods for accessing account details, contract bytecode, and storage. */ -class ThorClient extends AccountClient { +class ThorClient { + /** + * The `AccountClient` instance used for interacting with account-related endpoints. + */ + public readonly accounts: AccountClient; + /** * Constructs a new `ThorClient` instance with a given HTTP client. * @param httpClient - The HTTP client instance used for making network requests. */ constructor(protected readonly httpClient: HttpClient) { - super(httpClient); + this.accounts = new AccountClient(httpClient); } } diff --git a/packages/network/tests/client/thor/thor-client.testnet.test.ts b/packages/network/tests/client/thor/thor-client.testnet.test.ts index a04ef0282..4957ffe61 100644 --- a/packages/network/tests/client/thor/thor-client.testnet.test.ts +++ b/packages/network/tests/client/thor/thor-client.testnet.test.ts @@ -28,7 +28,7 @@ describe('ThorClient', () => { getAccountWithRevisionTestCases.forEach( ({ description, account, revision, expected }) => { test(description, async () => { - const accountDetails = await thorClient.getAccount( + const accountDetails = await thorClient.accounts.getAccount( account, revision ); @@ -41,7 +41,8 @@ describe('ThorClient', () => { * getAccount without revision (latest block) */ test('get account without revision', async () => { - const accountDetails = await thorClient.getAccount(testAccount); + const accountDetails = + await thorClient.accounts.getAccount(testAccount); expect(accountDetails).toBeDefined(); expect(accountDetails.balance).toBeDefined(); expect(accountDetails.energy).toBeDefined(); @@ -56,7 +57,7 @@ describe('ThorClient', () => { ({ description, address, revision, expectedError }) => { test(description, async () => { await expect( - thorClient.getAccount(address, revision) + thorClient.accounts.getAccount(address, revision) ).rejects.toThrowError(expectedError); }); } @@ -73,7 +74,7 @@ describe('ThorClient', () => { getBytecodeTestCases.forEach( ({ description, address, revision, expected }) => { test(description, async () => { - const bytecode = await thorClient.getBytecode( + const bytecode = await thorClient.accounts.getBytecode( address, revision ); @@ -89,7 +90,7 @@ describe('ThorClient', () => { ({ description, address, revision, expectedError }) => { test(description, async () => { await expect( - thorClient.getBytecode(address, revision) + thorClient.accounts.getBytecode(address, revision) ).rejects.toThrowError(expectedError); }); } @@ -104,7 +105,7 @@ describe('ThorClient', () => { * Tests storage data at the specified position of the smart contract */ test('Should get the storage data at the specified position of the smart contract', async () => { - const storageData = await thorClient.getStorageAt( + const storageData = await thorClient.accounts.getStorageAt( testSmartContract, testStoragePositionKey ); @@ -117,7 +118,7 @@ describe('ThorClient', () => { * Tests storage data at the specified position of the smart contract with revision */ test('Should get the storage data at the specified position of the smart contract with revision', async () => { - const storageData = await thorClient.getStorageAt( + const storageData = await thorClient.accounts.getStorageAt( testSmartContract, testStoragePositionKey, '1' @@ -134,7 +135,11 @@ describe('ThorClient', () => { ({ description, address, position, revision, expectedError }) => { test(description, async () => { await expect( - thorClient.getStorageAt(address, position, revision) + thorClient.accounts.getStorageAt( + address, + position, + revision + ) ).rejects.toThrowError(expectedError); }); } From 4336da8e461afb4b4869496fa72ca331b4256f08 Mon Sep 17 00:00:00 2001 From: rodolfopietro97 Date: Tue, 7 Nov 2023 13:14:57 +0100 Subject: [PATCH 25/26] fix: refactor test structure --- .../accounts/accounts-testnet.test.ts} | 7 +- packages/network/tests/client/thor/fixture.ts | 183 ------------------ packages/network/tests/fixture.ts | 9 +- 3 files changed, 10 insertions(+), 189 deletions(-) rename packages/network/tests/client/{thor/thor-client.testnet.test.ts => thor-client/accounts/accounts-testnet.test.ts} (97%) delete mode 100644 packages/network/tests/client/thor/fixture.ts diff --git a/packages/network/tests/client/thor/thor-client.testnet.test.ts b/packages/network/tests/client/thor-client/accounts/accounts-testnet.test.ts similarity index 97% rename from packages/network/tests/client/thor/thor-client.testnet.test.ts rename to packages/network/tests/client/thor-client/accounts/accounts-testnet.test.ts index 4957ffe61..274bdf0d3 100644 --- a/packages/network/tests/client/thor/thor-client.testnet.test.ts +++ b/packages/network/tests/client/thor-client/accounts/accounts-testnet.test.ts @@ -7,17 +7,16 @@ import { invalidGetBytecodeTests, invalidGetStorageAtTests, testSmartContract, - testStoragePositionKey, - thorClient + testStoragePositionKey } from './fixture'; -import { testAccount } from '../../fixture'; +import { testAccount, thorClient } from '../../../fixture'; /** * ThorClient class tests * * @group integration/client/thor */ -describe('ThorClient', () => { +describe('ThorClient - Acounts', () => { /** * getAccount tests */ diff --git a/packages/network/tests/client/thor/fixture.ts b/packages/network/tests/client/thor/fixture.ts deleted file mode 100644 index 05000b0c0..000000000 --- a/packages/network/tests/client/thor/fixture.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { InvalidDataTypeError } from '@vechain-sdk/errors'; -import { ThorClient } from '../../../src'; -import { testAccount, testNetwork } from '../../fixture'; - -/** - * Thor client instance fixture - */ -const thorClient = new ThorClient(testNetwork); - -/** - * VTHO contract address - */ -const VTHO_CONTRACT_ADDRESS = '0x0000000000000000000000000000456e65726779'; - -/** - * Bytecode of the VTHO deployed contract - */ -const VTHO_CONTRACT_BYTECODE = - '0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014457806318160ddd146101a957806323b872dd146101d4578063313ce5671461025957806370a082311461028a57806395d89b41146102e1578063a9059cbb14610371578063bb35783b146103d6578063d89135cd1461045b578063dd62ed3e14610486575b600080fd5b3480156100c057600080fd5b506100c96104fd565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101095780820151818401526020810190506100ee565b50505050905090810190601f1680156101365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015057600080fd5b5061018f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061053a565b604051808215151515815260200191505060405180910390f35b3480156101b557600080fd5b506101be61062b565b6040518082815260200191505060405180910390f35b3480156101e057600080fd5b5061023f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106d1565b604051808215151515815260200191505060405180910390f35b34801561026557600080fd5b5061026e610865565b604051808260ff1660ff16815260200191505060405180910390f35b34801561029657600080fd5b506102cb600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061086e565b6040518082815260200191505060405180910390f35b3480156102ed57600080fd5b506102f661094d565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561033657808201518184015260208101905061031b565b50505050905090810190601f1680156103635780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561037d57600080fd5b506103bc600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061098a565b604051808215151515815260200191505060405180910390f35b3480156103e257600080fd5b50610441600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506109a1565b604051808215151515815260200191505060405180910390f35b34801561046757600080fd5b50610470610b67565b6040518082815260200191505060405180910390f35b34801561049257600080fd5b506104e7600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c0d565b6040518082815260200191505060405180910390f35b60606040805190810160405280600681526020017f566554686f720000000000000000000000000000000000000000000000000000815250905090565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1663592b389c6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561069157600080fd5b505af11580156106a5573d6000803e3d6000fd5b505050506040513d60208110156106bb57600080fd5b8101908080519060200190929190505050905090565b6000816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156107c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6275696c74696e3a20696e73756666696369656e7420616c6c6f77616e63650081525060200191505060405180910390fd5b816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555061085a848484610c93565b600190509392505050565b60006012905090565b60003073ffffffffffffffffffffffffffffffffffffffff1663ee660480836040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561090b57600080fd5b505af115801561091f573d6000803e3d6000fd5b505050506040513d602081101561093557600080fd5b81019080805190602001909291905050509050919050565b60606040805190810160405280600481526020017f5654484f00000000000000000000000000000000000000000000000000000000815250905090565b6000610997338484610c93565b6001905092915050565b60003373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610add57503373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663059950e9866040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b158015610a8a57600080fd5b505af1158015610a9e573d6000803e3d6000fd5b505050506040513d6020811015610ab457600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff16145b1515610b51576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6275696c74696e3a2073656c66206f72206d617374657220726571756972656481525060200191505060405180910390fd5b610b5c848484610c93565b600190509392505050565b60003073ffffffffffffffffffffffffffffffffffffffff1663138d4d0c6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610bcd57600080fd5b505af1158015610be1573d6000803e3d6000fd5b505050506040513d6020811015610bf757600080fd5b8101908080519060200190929190505050905090565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000811115610eaa573073ffffffffffffffffffffffffffffffffffffffff166339ed08d584836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015610d3f57600080fd5b505af1158015610d53573d6000803e3d6000fd5b505050506040513d6020811015610d6957600080fd5b81019080805190602001909291905050501515610dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f6275696c74696e3a20696e73756666696369656e742062616c616e636500000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16631cedfac183836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015610e9157600080fd5b505af1158015610ea5573d6000803e3d6000fd5b505050505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050505600a165627a7a72305820bd55cb9aff347dc60fe8280ae6b08a6f6deacc85a4e1c89ba0a8ef31fbcaecc60029'; - -/** - * getAccount tests with revision block number or block id - */ -const getAccountWithRevisionTestCases = [ - { - description: 'get account with revision block number', - account: testAccount, - revision: '15000000', - expected: { - balance: '0x64fa270f17ef298000', - energy: '0x11bec42c96bc7bd45f', - hasCode: false - } - }, - { - description: 'get account with revision block id', - account: testAccount, - revision: - '0x00e4e1c0fbb78a30a5ae9549f8f5a0cf4ac4aab589803f2487b74261fffcbdf5', - expected: { - balance: '0x64fa270f17ef298000', - energy: '0x11bec42c96bc7bd45f', - hasCode: false - } - }, - { - description: 'get account with revision block number', - account: testAccount, - revision: '14000000', - expected: { - balance: '0x26a9f176f96e764a3d6', - energy: '0x5497801ddd36c434be', - hasCode: false - } - } -]; - -/** - * getBytecode tests with and without revision - */ -const getBytecodeTestCases = [ - { - description: 'get bytecode of VTHO contract without revision', - address: VTHO_CONTRACT_ADDRESS, - revision: undefined, - expected: VTHO_CONTRACT_BYTECODE - }, - { - description: 'get bytecode of VTHO contract with block number revision', - address: VTHO_CONTRACT_ADDRESS, - revision: '16000000', - expected: VTHO_CONTRACT_BYTECODE - }, - { - description: 'get bytecode of VTHO contract with block id revision', - address: VTHO_CONTRACT_ADDRESS, - revision: - '0x00e4e1c0fbb78a30a5ae9549f8f5a0cf4ac4aab589803f2487b74261fffcbdf5', - expected: VTHO_CONTRACT_BYTECODE - }, - { - description: 'get bytecode of contract before it was deployed', - address: '0x1c65362e12ecafaf2f37494886bb288c6d2ede28', - revision: '1', - expected: '0x' - }, - { - description: 'get bytecode of contract after it was deployed', - address: '0x1c65362e12ecafaf2f37494886bb288c6d2ede28', - revision: undefined, // best block - expected: - '0x608060405234801561001057600080fd5b50600436106101e55760003560e01c80636352211e1161010f578063a22cb465116100a2578063d539139311610071578063d5391393146105a0578063d547741f146105be578063e63ab1e9146105da578063e985e9c5146105f8576101e5565b8063a22cb46514610508578063b88d4fde14610524578063c87b56dd14610540578063ca15c87314610570576101e5565b80639010d07c116100de5780639010d07c1461046c57806391d148541461049c57806395d89b41146104cc578063a217fddf146104ea576101e5565b80636352211e146103e65780636a6278421461041657806370a08231146104325780638456cb5914610462576101e5565b80632f2ff15d1161018757806342842e0e1161015657806342842e0e1461036057806342966c681461037c5780634f6ccce7146103985780635c975abb146103c8576101e5565b80632f2ff15d146102ee5780632f745c591461030a57806336568abe1461033a5780633f4ba83a14610356576101e5565b8063095ea7b3116101c3578063095ea7b31461026857806318160ddd1461028457806323b872dd146102a2578063248a9ca3146102be576101e5565b806301ffc9a7146101ea57806306fdde031461021a578063081812fc14610238575b600080fd5b61020460048036038101906101ff91906130eb565b610628565b6040516102119190613133565b60405180910390f35b61022261063a565b60405161022f91906131de565b60405180910390f35b610252600480360381019061024d9190613236565b6106cc565b60405161025f91906132a4565b60405180910390f35b610282600480360381019061027d91906132eb565b610712565b005b61028c610829565b604051610299919061333a565b60405180910390f35b6102bc60048036038101906102b79190613355565b610836565b005b6102d860048036038101906102d391906133de565b610896565b6040516102e5919061341a565b60405180910390f35b61030860048036038101906103039190613435565b6108b5565b005b610324600480360381019061031f91906132eb565b6108d6565b604051610331919061333a565b60405180910390f35b610354600480360381019061034f9190613435565b61097b565b005b61035e6109fe565b005b61037a60048036038101906103759190613355565b610a78565b005b61039660048036038101906103919190613236565b610a98565b005b6103b260048036038101906103ad9190613236565b610af4565b6040516103bf919061333a565b60405180910390f35b6103d0610b65565b6040516103dd9190613133565b60405180910390f35b61040060048036038101906103fb9190613236565b610b7c565b60405161040d91906132a4565b60405180910390f35b610430600480360381019061042b9190613475565b610c02565b005b61044c60048036038101906104479190613475565b610c92565b604051610459919061333a565b60405180910390f35b61046a610d49565b005b610486600480360381019061048191906134a2565b610dc3565b60405161049391906132a4565b60405180910390f35b6104b660048036038101906104b19190613435565b610df2565b6040516104c39190613133565b60405180910390f35b6104d4610e5c565b6040516104e191906131de565b60405180910390f35b6104f2610eee565b6040516104ff919061341a565b60405180910390f35b610522600480360381019061051d919061350e565b610ef5565b005b61053e60048036038101906105399190613683565b610f0b565b005b61055a60048036038101906105559190613236565b610f6d565b60405161056791906131de565b60405180910390f35b61058a600480360381019061058591906133de565b610f9e565b604051610597919061333a565b60405180910390f35b6105a8610fc2565b6040516105b5919061341a565b60405180910390f35b6105d860048036038101906105d39190613435565b610fe6565b005b6105e2611007565b6040516105ef919061341a565b60405180910390f35b610612600480360381019061060d9190613706565b61102b565b60405161061f9190613133565b60405180910390f35b6000610633826111cf565b9050919050565b60606002805461064990613775565b80601f016020809104026020016040519081016040528092919081815260200182805461067590613775565b80156106c25780601f10610697576101008083540402835291602001916106c2565b820191906000526020600020905b8154815290600101906020018083116106a557829003601f168201915b5050505050905090565b60006106d782611249565b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061071d82610b7c565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361078d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078490613818565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166107ac611294565b73ffffffffffffffffffffffffffffffffffffffff1614806107db57506107da816107d5611294565b61102b565b5b61081a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610811906138aa565b60405180910390fd5b610824838361129c565b505050565b6000600a80549050905090565b610847610841611294565b82611355565b610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d9061393c565b60405180910390fd5b6108918383836113ea565b505050565b6000806000838152602001908152602001600020600101549050919050565b6108be82610896565b6108c7816116e3565b6108d183836116f7565b505050565b60006108e183610c92565b8210610922576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610919906139ce565b60405180910390fd5b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b610983611294565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109e790613a60565b60405180910390fd5b6109fa828261172b565b5050565b610a2f7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610a2a611294565b610df2565b610a6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6590613af2565b60405180910390fd5b610a7661175f565b565b610a9383838360405180602001604052806000815250610f0b565b505050565b610aa9610aa3611294565b82611355565b610ae8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610adf9061393c565b60405180910390fd5b610af1816117c2565b50565b6000610afe610829565b8210610b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3690613b84565b60405180910390fd5b600a8281548110610b5357610b52613ba4565b5b90600052602060002001549050919050565b6000600c60009054906101000a900460ff16905090565b600080610b8883611910565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bf9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf090613c1f565b60405180910390fd5b80915050919050565b610c337f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610c2e611294565b610df2565b610c72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6990613cb1565b60405180910390fd5b610c8581610c80600d61194d565b61195b565b610c8f600d611b78565b50565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cf990613d43565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610d7a7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610d75611294565b610df2565b610db9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db090613dd5565b60405180910390fd5b610dc1611b8e565b565b6000610dea8260016000868152602001908152602001600020611bf190919063ffffffff16565b905092915050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b606060038054610e6b90613775565b80601f0160208091040260200160405190810160405280929190818152602001828054610e9790613775565b8015610ee45780601f10610eb957610100808354040283529160200191610ee4565b820191906000526020600020905b815481529060010190602001808311610ec757829003601f168201915b5050505050905090565b6000801b81565b610f07610f00611294565b8383611c0b565b5050565b610f1c610f16611294565b83611355565b610f5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f529061393c565b60405180910390fd5b610f6784848484611d77565b50505050565b6060610f7882611dd3565b604051602001610f889190613e57565b6040516020818303038152906040529050919050565b6000610fbb60016000848152602001908152602001600020611e3b565b9050919050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610fef82610896565b610ff8816116e3565b611002838361172b565b505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6110c98282610df2565b61119b57600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611140611294565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006111c7836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611e50565b905092915050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611242575061124182611ec0565b5b9050919050565b61125281611fa2565b611291576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128890613c1f565b60405180910390fd5b50565b600033905090565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661130f83610b7c565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061136183610b7c565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806113a357506113a2818561102b565b5b806113e157508373ffffffffffffffffffffffffffffffffffffffff166113c9846106cc565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661140a82610b7c565b73ffffffffffffffffffffffffffffffffffffffff1614611460576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145790613eef565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036114cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114c690613f81565b60405180910390fd5b6114dc8383836001611fe3565b8273ffffffffffffffffffffffffffffffffffffffff166114fc82610b7c565b73ffffffffffffffffffffffffffffffffffffffff1614611552576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154990613eef565b60405180910390fd5b6006600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46116de8383836001611ff5565b505050565b6116f4816116ef611294565b611ffb565b50565b61170182826110bf565b611726816001600085815260200190815260200160002061119f90919063ffffffff16565b505050565b6117358282612080565b61175a816001600085815260200190815260200160002061216190919063ffffffff16565b505050565b611767612191565b6000600c60006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6117ab611294565b6040516117b891906132a4565b60405180910390a1565b60006117cd82610b7c565b90506117dd816000846001611fe3565b6117e682610b7c565b90506006600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461190c816000846001611ff5565b5050565b60006004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600081600001549050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036119ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c190613fed565b60405180910390fd5b6119d381611fa2565b15611a13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0a90614059565b60405180910390fd5b611a21600083836001611fe3565b611a2a81611fa2565b15611a6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6190614059565b60405180910390fd5b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611b74600083836001611ff5565b5050565b6001816000016000828254019250508190555050565b611b966121da565b6001600c60006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611bda611294565b604051611be791906132a4565b60405180910390a1565b6000611c008360000183612224565b60001c905092915050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611c79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c70906140c5565b60405180910390fd5b80600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611d6a9190613133565b60405180910390a3505050565b611d828484846113ea565b611d8e8484848461224f565b611dcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc490614157565b60405180910390fd5b50505050565b6060611dde82611249565b6000611de86123d6565b90506000815111611e085760405180602001604052806000815250611e33565b80611e1284612468565b604051602001611e23929190614177565b6040516020818303038152906040525b915050919050565b6000611e4982600001612536565b9050919050565b6000611e5c8383612547565b611eb5578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611eba565b600090505b92915050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611f8b57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611f9b5750611f9a8261256a565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16611fc483611910565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b611fef848484846125e4565b50505050565b50505050565b6120058282610df2565b61207c576120128161263e565b6120208360001c602061266b565b604051602001612031929190614233565b6040516020818303038152906040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207391906131de565b60405180910390fd5b5050565b61208a8282610df2565b1561215d57600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612102611294565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6000612189836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6128a7565b905092915050565b612199610b65565b6121d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cf906142b9565b60405180910390fd5b565b6121e2610b65565b15612222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161221990614325565b60405180910390fd5b565b600082600001828154811061223c5761223b613ba4565b5b9060005260206000200154905092915050565b60006122708473ffffffffffffffffffffffffffffffffffffffff166129bb565b156123c9578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612299611294565b8786866040518563ffffffff1660e01b81526004016122bb949392919061439a565b6020604051808303816000875af19250505080156122f757506040513d601f19601f820116820180604052508101906122f491906143fb565b60015b612379573d8060008114612327576040519150601f19603f3d011682016040523d82523d6000602084013e61232c565b606091505b506000815103612371576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161236890614157565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149150506123ce565b600190505b949350505050565b6060600e80546123e590613775565b80601f016020809104026020016040519081016040528092919081815260200182805461241190613775565b801561245e5780601f106124335761010080835404028352916020019161245e565b820191906000526020600020905b81548152906001019060200180831161244157829003601f168201915b5050505050905090565b606060006001612477846129de565b01905060008167ffffffffffffffff81111561249657612495613558565b5b6040519080825280601f01601f1916602001820160405280156124c85781602001600182028036833780820191505090505b509050600082602001820190505b60011561252b578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161251f5761251e614428565b5b049450600085036124d6575b819350505050919050565b600081600001805490509050919050565b600080836001016000848152602001908152602001600020541415905092915050565b60007f5a05180f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806125dd57506125dc82612b31565b5b9050919050565b6125f084848484612bab565b6125f8610b65565b15612638576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262f906144c9565b60405180910390fd5b50505050565b60606126648273ffffffffffffffffffffffffffffffffffffffff16601460ff1661266b565b9050919050565b60606000600283600261267e9190614518565b612688919061455a565b67ffffffffffffffff8111156126a1576126a0613558565b5b6040519080825280601f01601f1916602001820160405280156126d35781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061270b5761270a613ba4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061276f5761276e613ba4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026127af9190614518565b6127b9919061455a565b90505b6001811115612859577f3031323334353637383961626364656600000000000000000000000000000000600f8616601081106127fb576127fa613ba4565b5b1a60f81b82828151811061281257612811613ba4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806128529061458e565b90506127bc565b506000841461289d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289490614603565b60405180910390fd5b8091505092915050565b600080836001016000848152602001908152602001600020549050600081146129af5760006001826128d99190614623565b90506000600186600001805490506128f19190614623565b905081811461296057600086600001828154811061291257612911613ba4565b5b906000526020600020015490508087600001848154811061293657612935613ba4565b5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061297457612973614657565b5b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506129b5565b60009150505b92915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612a3c577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612a3257612a31614428565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612a79576d04ee2d6d415b85acef81000000008381612a6f57612a6e614428565b5b0492506020810190505b662386f26fc100008310612aa857662386f26fc100008381612a9e57612a9d614428565b5b0492506010810190505b6305f5e1008310612ad1576305f5e1008381612ac757612ac6614428565b5b0492506008810190505b6127108310612af6576127108381612aec57612aeb614428565b5b0492506004810190505b60648310612b195760648381612b0f57612b0e614428565b5b0492506002810190505b600a8310612b28576001810190505b80915050919050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612ba45750612ba382612d09565b5b9050919050565b612bb784848484612d73565b6001811115612bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bf2906146f8565b60405180910390fd5b6000829050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612c4257612c3d81612d79565b612c81565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612c8057612c7f8582612dc2565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612cc357612cbe81612f2f565b612d02565b8473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614612d0157612d008482613000565b5b5b5050505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b50505050565b600a80549050600b600083815260200190815260200160002081905550600a81908060018154018082558091505060019003906000526020600020016000909190919091505550565b60006001612dcf84610c92565b612dd99190614623565b9050600060096000848152602001908152602001600020549050818114612ebe576000600860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816009600083815260200190815260200160002081905550505b6009600084815260200190815260200160002060009055600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600a80549050612f439190614623565b90506000600b60008481526020019081526020016000205490506000600a8381548110612f7357612f72613ba4565b5b9060005260206000200154905080600a8381548110612f9557612f94613ba4565b5b906000526020600020018190555081600b600083815260200190815260200160002081905550600b600085815260200190815260200160002060009055600a805480612fe457612fe3614657565b5b6001900381819060005260206000200160009055905550505050565b600061300b83610c92565b905081600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806009600084815260200190815260200160002081905550505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6130c881613093565b81146130d357600080fd5b50565b6000813590506130e5816130bf565b92915050565b60006020828403121561310157613100613089565b5b600061310f848285016130d6565b91505092915050565b60008115159050919050565b61312d81613118565b82525050565b60006020820190506131486000830184613124565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561318857808201518184015260208101905061316d565b60008484015250505050565b6000601f19601f8301169050919050565b60006131b08261314e565b6131ba8185613159565b93506131ca81856020860161316a565b6131d381613194565b840191505092915050565b600060208201905081810360008301526131f881846131a5565b905092915050565b6000819050919050565b61321381613200565b811461321e57600080fd5b50565b6000813590506132308161320a565b92915050565b60006020828403121561324c5761324b613089565b5b600061325a84828501613221565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061328e82613263565b9050919050565b61329e81613283565b82525050565b60006020820190506132b96000830184613295565b92915050565b6132c881613283565b81146132d357600080fd5b50565b6000813590506132e5816132bf565b92915050565b6000806040838503121561330257613301613089565b5b6000613310858286016132d6565b925050602061332185828601613221565b9150509250929050565b61333481613200565b82525050565b600060208201905061334f600083018461332b565b92915050565b60008060006060848603121561336e5761336d613089565b5b600061337c868287016132d6565b935050602061338d868287016132d6565b925050604061339e86828701613221565b9150509250925092565b6000819050919050565b6133bb816133a8565b81146133c657600080fd5b50565b6000813590506133d8816133b2565b92915050565b6000602082840312156133f4576133f3613089565b5b6000613402848285016133c9565b91505092915050565b613414816133a8565b82525050565b600060208201905061342f600083018461340b565b92915050565b6000806040838503121561344c5761344b613089565b5b600061345a858286016133c9565b925050602061346b858286016132d6565b9150509250929050565b60006020828403121561348b5761348a613089565b5b6000613499848285016132d6565b91505092915050565b600080604083850312156134b9576134b8613089565b5b60006134c7858286016133c9565b92505060206134d885828601613221565b9150509250929050565b6134eb81613118565b81146134f657600080fd5b50565b600081359050613508816134e2565b92915050565b6000806040838503121561352557613524613089565b5b6000613533858286016132d6565b9250506020613544858286016134f9565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61359082613194565b810181811067ffffffffffffffff821117156135af576135ae613558565b5b80604052505050565b60006135c261307f565b90506135ce8282613587565b919050565b600067ffffffffffffffff8211156135ee576135ed613558565b5b6135f782613194565b9050602081019050919050565b82818337600083830152505050565b6000613626613621846135d3565b6135b8565b90508281526020810184848401111561364257613641613553565b5b61364d848285613604565b509392505050565b600082601f83011261366a5761366961354e565b5b813561367a848260208601613613565b91505092915050565b6000806000806080858703121561369d5761369c613089565b5b60006136ab878288016132d6565b94505060206136bc878288016132d6565b93505060406136cd87828801613221565b925050606085013567ffffffffffffffff8111156136ee576136ed61308e565b5b6136fa87828801613655565b91505092959194509250565b6000806040838503121561371d5761371c613089565b5b600061372b858286016132d6565b925050602061373c858286016132d6565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061378d57607f821691505b6020821081036137a05761379f613746565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613802602183613159565b915061380d826137a6565b604082019050919050565b60006020820190508181036000830152613831816137f5565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613894603d83613159565b915061389f82613838565b604082019050919050565b600060208201905081810360008301526138c381613887565b9050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613926602d83613159565b9150613931826138ca565b604082019050919050565b6000602082019050818103600083015261395581613919565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b60006139b8602b83613159565b91506139c38261395c565b604082019050919050565b600060208201905081810360008301526139e7816139ab565b9050919050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b6000613a4a602f83613159565b9150613a55826139ee565b604082019050919050565b60006020820190508181036000830152613a7981613a3d565b9050919050565b7f4552433732315072657365744d696e7465725061757365724175746f49643a2060008201527f6d75737420686176652070617573657220726f6c6520746f20756e7061757365602082015250565b6000613adc604083613159565b9150613ae782613a80565b604082019050919050565b60006020820190508181036000830152613b0b81613acf565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000613b6e602c83613159565b9150613b7982613b12565b604082019050919050565b60006020820190508181036000830152613b9d81613b61565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b6000613c09601883613159565b9150613c1482613bd3565b602082019050919050565b60006020820190508181036000830152613c3881613bfc565b9050919050565b7f4552433732315072657365744d696e7465725061757365724175746f49643a2060008201527f6d7573742068617665206d696e74657220726f6c6520746f206d696e74000000602082015250565b6000613c9b603d83613159565b9150613ca682613c3f565b604082019050919050565b60006020820190508181036000830152613cca81613c8e565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b6000613d2d602983613159565b9150613d3882613cd1565b604082019050919050565b60006020820190508181036000830152613d5c81613d20565b9050919050565b7f4552433732315072657365744d696e7465725061757365724175746f49643a2060008201527f6d75737420686176652070617573657220726f6c6520746f2070617573650000602082015250565b6000613dbf603e83613159565b9150613dca82613d63565b604082019050919050565b60006020820190508181036000830152613dee81613db2565b9050919050565b600081905092915050565b6000613e0b8261314e565b613e158185613df5565b9350613e2581856020860161316a565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000815250565b6000613e638284613e00565b9150613e6e82613e31565b60058201915081905092915050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b6000613ed9602583613159565b9150613ee482613e7d565b604082019050919050565b60006020820190508181036000830152613f0881613ecc565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000613f6b602483613159565b9150613f7682613f0f565b604082019050919050565b60006020820190508181036000830152613f9a81613f5e565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000613fd7602083613159565b9150613fe282613fa1565b602082019050919050565b6000602082019050818103600083015261400681613fca565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614043601c83613159565b915061404e8261400d565b602082019050919050565b6000602082019050818103600083015261407281614036565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006140af601983613159565b91506140ba82614079565b602082019050919050565b600060208201905081810360008301526140de816140a2565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614141603283613159565b915061414c826140e5565b604082019050919050565b6000602082019050818103600083015261417081614134565b9050919050565b60006141838285613e00565b915061418f8284613e00565b91508190509392505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b60006141d1601783613df5565b91506141dc8261419b565b601782019050919050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b600061421d601183613df5565b9150614228826141e7565b601182019050919050565b600061423e826141c4565b915061424a8285613e00565b915061425582614210565b91506142618284613e00565b91508190509392505050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b60006142a3601483613159565b91506142ae8261426d565b602082019050919050565b600060208201905081810360008301526142d281614296565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b600061430f601083613159565b915061431a826142d9565b602082019050919050565b6000602082019050818103600083015261433e81614302565b9050919050565b600081519050919050565b600082825260208201905092915050565b600061436c82614345565b6143768185614350565b935061438681856020860161316a565b61438f81613194565b840191505092915050565b60006080820190506143af6000830187613295565b6143bc6020830186613295565b6143c9604083018561332b565b81810360608301526143db8184614361565b905095945050505050565b6000815190506143f5816130bf565b92915050565b60006020828403121561441157614410613089565b5b600061441f848285016143e6565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4552433732315061757361626c653a20746f6b656e207472616e73666572207760008201527f68696c6520706175736564000000000000000000000000000000000000000000602082015250565b60006144b3602b83613159565b91506144be82614457565b604082019050919050565b600060208201905081810360008301526144e2816144a6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061452382613200565b915061452e83613200565b925082820261453c81613200565b91508282048414831517614553576145526144e9565b5b5092915050565b600061456582613200565b915061457083613200565b9250828201905080821115614588576145876144e9565b5b92915050565b600061459982613200565b9150600082036145ac576145ab6144e9565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b60006145ed602083613159565b91506145f8826145b7565b602082019050919050565b6000602082019050818103600083015261461c816145e0565b9050919050565b600061462e82613200565b915061463983613200565b9250828203905081811115614651576146506144e9565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f455243373231456e756d657261626c653a20636f6e736563757469766520747260008201527f616e7366657273206e6f7420737570706f727465640000000000000000000000602082015250565b60006146e2603583613159565b91506146ed82614686565b604082019050919050565b60006020820190508181036000830152614711816146d5565b905091905056fea2646970667358221220e972bbd276839058152a76991f80e14bc204d51ef1164ea5b20e88b88893b61164736f6c63430008110033' - } -]; - -/** - * Test smart contract address - */ -const testSmartContract = '0xa540a1924dff8db10bcb3aba3183c0385f2ad285'; - -/** - * Test storage position key - */ -const testStoragePositionKey = - '0x0000000000000000000000000000000000000000000000000000000000000001'; - -/** - * Empty storage slot - */ -const NULL_STORAGE_SLOT = - '0x0000000000000000000000000000000000000000000000000000000000000000'; - -/** - * Invalid getStorageAt test cases for invalid data types - */ -const invalidGetStorageAtTests = [ - { - description: 'Should throw error for invalid revision', - address: testSmartContract, - position: testStoragePositionKey, - revision: 'invalid-revision', - expectedError: InvalidDataTypeError - }, - { - description: 'Should throw error for invalid position', - address: testSmartContract, - position: 'invalid-position', - revision: '1', - expectedError: InvalidDataTypeError - }, - { - description: 'Should throw error for invalid address', - address: 'invalid-address', - position: '0x123', - revision: '1', - expectedError: InvalidDataTypeError - } -]; - -/** - * Invalid getAccount test cases for invalid data types - */ -const invalidGetAccountTests = [ - { - description: 'Should throw error for invalid revision', - address: testAccount, - revision: 'invalid-revision', - expectedError: InvalidDataTypeError - }, - { - description: 'Should throw error for invalid address', - address: 'invalid-address', - revision: '1', - expectedError: InvalidDataTypeError - } -]; - -const invalidGetBytecodeTests = [ - { - description: 'Should throw error for invalid revision', - address: testSmartContract, - revision: 'invalid-revision', - expectedError: InvalidDataTypeError - }, - { - description: 'Should throw error for invalid address', - address: 'invalid-address', - revision: '1', - expectedError: InvalidDataTypeError - } -]; - -export { - thorClient, - getAccountWithRevisionTestCases, - getBytecodeTestCases, - testSmartContract, - testStoragePositionKey, - NULL_STORAGE_SLOT, - invalidGetStorageAtTests, - invalidGetAccountTests, - invalidGetBytecodeTests -}; diff --git a/packages/network/tests/fixture.ts b/packages/network/tests/fixture.ts index 0ffa549fd..14727a65b 100644 --- a/packages/network/tests/fixture.ts +++ b/packages/network/tests/fixture.ts @@ -1,4 +1,4 @@ -import { HttpClient } from '../src'; +import { HttpClient, ThorClient } from '../src'; /** * Url of the testnet fixture @@ -30,4 +30,9 @@ const testAccount = '0xf077b491b355E64048cE21E3A6Fc4751eEeA77fa'; */ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; -export { testNetwork, soloNetwork, ZERO_ADDRESS, testAccount }; +/** + * Thor client instance fixture + */ +const thorClient = new ThorClient(testNetwork); + +export { testNetwork, soloNetwork, ZERO_ADDRESS, testAccount, thorClient }; From e431e7a3cb1147b153104e1f16d49b718e57f037 Mon Sep 17 00:00:00 2001 From: rodolfopietro97 Date: Tue, 7 Nov 2023 13:15:22 +0100 Subject: [PATCH 26/26] fix: missing fixture in commit --- .../client/thor-client/accounts/fixture.ts | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 packages/network/tests/client/thor-client/accounts/fixture.ts diff --git a/packages/network/tests/client/thor-client/accounts/fixture.ts b/packages/network/tests/client/thor-client/accounts/fixture.ts new file mode 100644 index 000000000..bd7eef090 --- /dev/null +++ b/packages/network/tests/client/thor-client/accounts/fixture.ts @@ -0,0 +1,176 @@ +import { InvalidDataTypeError } from '@vechain-sdk/errors'; +import { testAccount } from '../../../fixture'; + +/** + * VTHO contract address + */ +const VTHO_CONTRACT_ADDRESS = '0x0000000000000000000000000000456e65726779'; + +/** + * Bytecode of the VTHO deployed contract + */ +const VTHO_CONTRACT_BYTECODE = + '0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014457806318160ddd146101a957806323b872dd146101d4578063313ce5671461025957806370a082311461028a57806395d89b41146102e1578063a9059cbb14610371578063bb35783b146103d6578063d89135cd1461045b578063dd62ed3e14610486575b600080fd5b3480156100c057600080fd5b506100c96104fd565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101095780820151818401526020810190506100ee565b50505050905090810190601f1680156101365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015057600080fd5b5061018f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061053a565b604051808215151515815260200191505060405180910390f35b3480156101b557600080fd5b506101be61062b565b6040518082815260200191505060405180910390f35b3480156101e057600080fd5b5061023f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106d1565b604051808215151515815260200191505060405180910390f35b34801561026557600080fd5b5061026e610865565b604051808260ff1660ff16815260200191505060405180910390f35b34801561029657600080fd5b506102cb600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061086e565b6040518082815260200191505060405180910390f35b3480156102ed57600080fd5b506102f661094d565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561033657808201518184015260208101905061031b565b50505050905090810190601f1680156103635780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561037d57600080fd5b506103bc600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061098a565b604051808215151515815260200191505060405180910390f35b3480156103e257600080fd5b50610441600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506109a1565b604051808215151515815260200191505060405180910390f35b34801561046757600080fd5b50610470610b67565b6040518082815260200191505060405180910390f35b34801561049257600080fd5b506104e7600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c0d565b6040518082815260200191505060405180910390f35b60606040805190810160405280600681526020017f566554686f720000000000000000000000000000000000000000000000000000815250905090565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1663592b389c6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561069157600080fd5b505af11580156106a5573d6000803e3d6000fd5b505050506040513d60208110156106bb57600080fd5b8101908080519060200190929190505050905090565b6000816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156107c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6275696c74696e3a20696e73756666696369656e7420616c6c6f77616e63650081525060200191505060405180910390fd5b816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555061085a848484610c93565b600190509392505050565b60006012905090565b60003073ffffffffffffffffffffffffffffffffffffffff1663ee660480836040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561090b57600080fd5b505af115801561091f573d6000803e3d6000fd5b505050506040513d602081101561093557600080fd5b81019080805190602001909291905050509050919050565b60606040805190810160405280600481526020017f5654484f00000000000000000000000000000000000000000000000000000000815250905090565b6000610997338484610c93565b6001905092915050565b60003373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610add57503373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663059950e9866040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b158015610a8a57600080fd5b505af1158015610a9e573d6000803e3d6000fd5b505050506040513d6020811015610ab457600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff16145b1515610b51576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6275696c74696e3a2073656c66206f72206d617374657220726571756972656481525060200191505060405180910390fd5b610b5c848484610c93565b600190509392505050565b60003073ffffffffffffffffffffffffffffffffffffffff1663138d4d0c6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610bcd57600080fd5b505af1158015610be1573d6000803e3d6000fd5b505050506040513d6020811015610bf757600080fd5b8101908080519060200190929190505050905090565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000811115610eaa573073ffffffffffffffffffffffffffffffffffffffff166339ed08d584836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015610d3f57600080fd5b505af1158015610d53573d6000803e3d6000fd5b505050506040513d6020811015610d6957600080fd5b81019080805190602001909291905050501515610dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f6275696c74696e3a20696e73756666696369656e742062616c616e636500000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16631cedfac183836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015610e9157600080fd5b505af1158015610ea5573d6000803e3d6000fd5b505050505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050505600a165627a7a72305820bd55cb9aff347dc60fe8280ae6b08a6f6deacc85a4e1c89ba0a8ef31fbcaecc60029'; + +/** + * getAccount tests with revision block number or block id + */ +const getAccountWithRevisionTestCases = [ + { + description: 'get account with revision block number', + account: testAccount, + revision: '15000000', + expected: { + balance: '0x64fa270f17ef298000', + energy: '0x11bec42c96bc7bd45f', + hasCode: false + } + }, + { + description: 'get account with revision block id', + account: testAccount, + revision: + '0x00e4e1c0fbb78a30a5ae9549f8f5a0cf4ac4aab589803f2487b74261fffcbdf5', + expected: { + balance: '0x64fa270f17ef298000', + energy: '0x11bec42c96bc7bd45f', + hasCode: false + } + }, + { + description: 'get account with revision block number', + account: testAccount, + revision: '14000000', + expected: { + balance: '0x26a9f176f96e764a3d6', + energy: '0x5497801ddd36c434be', + hasCode: false + } + } +]; + +/** + * getBytecode tests with and without revision + */ +const getBytecodeTestCases = [ + { + description: 'get bytecode of VTHO contract without revision', + address: VTHO_CONTRACT_ADDRESS, + revision: undefined, + expected: VTHO_CONTRACT_BYTECODE + }, + { + description: 'get bytecode of VTHO contract with block number revision', + address: VTHO_CONTRACT_ADDRESS, + revision: '16000000', + expected: VTHO_CONTRACT_BYTECODE + }, + { + description: 'get bytecode of VTHO contract with block id revision', + address: VTHO_CONTRACT_ADDRESS, + revision: + '0x00e4e1c0fbb78a30a5ae9549f8f5a0cf4ac4aab589803f2487b74261fffcbdf5', + expected: VTHO_CONTRACT_BYTECODE + }, + { + description: 'get bytecode of contract before it was deployed', + address: '0x1c65362e12ecafaf2f37494886bb288c6d2ede28', + revision: '1', + expected: '0x' + }, + { + description: 'get bytecode of contract after it was deployed', + address: '0x1c65362e12ecafaf2f37494886bb288c6d2ede28', + revision: undefined, // best block + expected: + '0x608060405234801561001057600080fd5b50600436106101e55760003560e01c80636352211e1161010f578063a22cb465116100a2578063d539139311610071578063d5391393146105a0578063d547741f146105be578063e63ab1e9146105da578063e985e9c5146105f8576101e5565b8063a22cb46514610508578063b88d4fde14610524578063c87b56dd14610540578063ca15c87314610570576101e5565b80639010d07c116100de5780639010d07c1461046c57806391d148541461049c57806395d89b41146104cc578063a217fddf146104ea576101e5565b80636352211e146103e65780636a6278421461041657806370a08231146104325780638456cb5914610462576101e5565b80632f2ff15d1161018757806342842e0e1161015657806342842e0e1461036057806342966c681461037c5780634f6ccce7146103985780635c975abb146103c8576101e5565b80632f2ff15d146102ee5780632f745c591461030a57806336568abe1461033a5780633f4ba83a14610356576101e5565b8063095ea7b3116101c3578063095ea7b31461026857806318160ddd1461028457806323b872dd146102a2578063248a9ca3146102be576101e5565b806301ffc9a7146101ea57806306fdde031461021a578063081812fc14610238575b600080fd5b61020460048036038101906101ff91906130eb565b610628565b6040516102119190613133565b60405180910390f35b61022261063a565b60405161022f91906131de565b60405180910390f35b610252600480360381019061024d9190613236565b6106cc565b60405161025f91906132a4565b60405180910390f35b610282600480360381019061027d91906132eb565b610712565b005b61028c610829565b604051610299919061333a565b60405180910390f35b6102bc60048036038101906102b79190613355565b610836565b005b6102d860048036038101906102d391906133de565b610896565b6040516102e5919061341a565b60405180910390f35b61030860048036038101906103039190613435565b6108b5565b005b610324600480360381019061031f91906132eb565b6108d6565b604051610331919061333a565b60405180910390f35b610354600480360381019061034f9190613435565b61097b565b005b61035e6109fe565b005b61037a60048036038101906103759190613355565b610a78565b005b61039660048036038101906103919190613236565b610a98565b005b6103b260048036038101906103ad9190613236565b610af4565b6040516103bf919061333a565b60405180910390f35b6103d0610b65565b6040516103dd9190613133565b60405180910390f35b61040060048036038101906103fb9190613236565b610b7c565b60405161040d91906132a4565b60405180910390f35b610430600480360381019061042b9190613475565b610c02565b005b61044c60048036038101906104479190613475565b610c92565b604051610459919061333a565b60405180910390f35b61046a610d49565b005b610486600480360381019061048191906134a2565b610dc3565b60405161049391906132a4565b60405180910390f35b6104b660048036038101906104b19190613435565b610df2565b6040516104c39190613133565b60405180910390f35b6104d4610e5c565b6040516104e191906131de565b60405180910390f35b6104f2610eee565b6040516104ff919061341a565b60405180910390f35b610522600480360381019061051d919061350e565b610ef5565b005b61053e60048036038101906105399190613683565b610f0b565b005b61055a60048036038101906105559190613236565b610f6d565b60405161056791906131de565b60405180910390f35b61058a600480360381019061058591906133de565b610f9e565b604051610597919061333a565b60405180910390f35b6105a8610fc2565b6040516105b5919061341a565b60405180910390f35b6105d860048036038101906105d39190613435565b610fe6565b005b6105e2611007565b6040516105ef919061341a565b60405180910390f35b610612600480360381019061060d9190613706565b61102b565b60405161061f9190613133565b60405180910390f35b6000610633826111cf565b9050919050565b60606002805461064990613775565b80601f016020809104026020016040519081016040528092919081815260200182805461067590613775565b80156106c25780601f10610697576101008083540402835291602001916106c2565b820191906000526020600020905b8154815290600101906020018083116106a557829003601f168201915b5050505050905090565b60006106d782611249565b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061071d82610b7c565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361078d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078490613818565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166107ac611294565b73ffffffffffffffffffffffffffffffffffffffff1614806107db57506107da816107d5611294565b61102b565b5b61081a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610811906138aa565b60405180910390fd5b610824838361129c565b505050565b6000600a80549050905090565b610847610841611294565b82611355565b610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d9061393c565b60405180910390fd5b6108918383836113ea565b505050565b6000806000838152602001908152602001600020600101549050919050565b6108be82610896565b6108c7816116e3565b6108d183836116f7565b505050565b60006108e183610c92565b8210610922576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610919906139ce565b60405180910390fd5b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b610983611294565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109e790613a60565b60405180910390fd5b6109fa828261172b565b5050565b610a2f7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610a2a611294565b610df2565b610a6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6590613af2565b60405180910390fd5b610a7661175f565b565b610a9383838360405180602001604052806000815250610f0b565b505050565b610aa9610aa3611294565b82611355565b610ae8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610adf9061393c565b60405180910390fd5b610af1816117c2565b50565b6000610afe610829565b8210610b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3690613b84565b60405180910390fd5b600a8281548110610b5357610b52613ba4565b5b90600052602060002001549050919050565b6000600c60009054906101000a900460ff16905090565b600080610b8883611910565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bf9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf090613c1f565b60405180910390fd5b80915050919050565b610c337f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610c2e611294565b610df2565b610c72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6990613cb1565b60405180910390fd5b610c8581610c80600d61194d565b61195b565b610c8f600d611b78565b50565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cf990613d43565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610d7a7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610d75611294565b610df2565b610db9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db090613dd5565b60405180910390fd5b610dc1611b8e565b565b6000610dea8260016000868152602001908152602001600020611bf190919063ffffffff16565b905092915050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b606060038054610e6b90613775565b80601f0160208091040260200160405190810160405280929190818152602001828054610e9790613775565b8015610ee45780601f10610eb957610100808354040283529160200191610ee4565b820191906000526020600020905b815481529060010190602001808311610ec757829003601f168201915b5050505050905090565b6000801b81565b610f07610f00611294565b8383611c0b565b5050565b610f1c610f16611294565b83611355565b610f5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f529061393c565b60405180910390fd5b610f6784848484611d77565b50505050565b6060610f7882611dd3565b604051602001610f889190613e57565b6040516020818303038152906040529050919050565b6000610fbb60016000848152602001908152602001600020611e3b565b9050919050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610fef82610896565b610ff8816116e3565b611002838361172b565b505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6110c98282610df2565b61119b57600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611140611294565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006111c7836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611e50565b905092915050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611242575061124182611ec0565b5b9050919050565b61125281611fa2565b611291576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128890613c1f565b60405180910390fd5b50565b600033905090565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661130f83610b7c565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061136183610b7c565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806113a357506113a2818561102b565b5b806113e157508373ffffffffffffffffffffffffffffffffffffffff166113c9846106cc565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661140a82610b7c565b73ffffffffffffffffffffffffffffffffffffffff1614611460576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145790613eef565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036114cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114c690613f81565b60405180910390fd5b6114dc8383836001611fe3565b8273ffffffffffffffffffffffffffffffffffffffff166114fc82610b7c565b73ffffffffffffffffffffffffffffffffffffffff1614611552576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154990613eef565b60405180910390fd5b6006600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46116de8383836001611ff5565b505050565b6116f4816116ef611294565b611ffb565b50565b61170182826110bf565b611726816001600085815260200190815260200160002061119f90919063ffffffff16565b505050565b6117358282612080565b61175a816001600085815260200190815260200160002061216190919063ffffffff16565b505050565b611767612191565b6000600c60006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6117ab611294565b6040516117b891906132a4565b60405180910390a1565b60006117cd82610b7c565b90506117dd816000846001611fe3565b6117e682610b7c565b90506006600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461190c816000846001611ff5565b5050565b60006004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600081600001549050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036119ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c190613fed565b60405180910390fd5b6119d381611fa2565b15611a13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0a90614059565b60405180910390fd5b611a21600083836001611fe3565b611a2a81611fa2565b15611a6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6190614059565b60405180910390fd5b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611b74600083836001611ff5565b5050565b6001816000016000828254019250508190555050565b611b966121da565b6001600c60006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611bda611294565b604051611be791906132a4565b60405180910390a1565b6000611c008360000183612224565b60001c905092915050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611c79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c70906140c5565b60405180910390fd5b80600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611d6a9190613133565b60405180910390a3505050565b611d828484846113ea565b611d8e8484848461224f565b611dcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc490614157565b60405180910390fd5b50505050565b6060611dde82611249565b6000611de86123d6565b90506000815111611e085760405180602001604052806000815250611e33565b80611e1284612468565b604051602001611e23929190614177565b6040516020818303038152906040525b915050919050565b6000611e4982600001612536565b9050919050565b6000611e5c8383612547565b611eb5578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611eba565b600090505b92915050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611f8b57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611f9b5750611f9a8261256a565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16611fc483611910565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b611fef848484846125e4565b50505050565b50505050565b6120058282610df2565b61207c576120128161263e565b6120208360001c602061266b565b604051602001612031929190614233565b6040516020818303038152906040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207391906131de565b60405180910390fd5b5050565b61208a8282610df2565b1561215d57600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612102611294565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6000612189836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6128a7565b905092915050565b612199610b65565b6121d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cf906142b9565b60405180910390fd5b565b6121e2610b65565b15612222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161221990614325565b60405180910390fd5b565b600082600001828154811061223c5761223b613ba4565b5b9060005260206000200154905092915050565b60006122708473ffffffffffffffffffffffffffffffffffffffff166129bb565b156123c9578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612299611294565b8786866040518563ffffffff1660e01b81526004016122bb949392919061439a565b6020604051808303816000875af19250505080156122f757506040513d601f19601f820116820180604052508101906122f491906143fb565b60015b612379573d8060008114612327576040519150601f19603f3d011682016040523d82523d6000602084013e61232c565b606091505b506000815103612371576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161236890614157565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149150506123ce565b600190505b949350505050565b6060600e80546123e590613775565b80601f016020809104026020016040519081016040528092919081815260200182805461241190613775565b801561245e5780601f106124335761010080835404028352916020019161245e565b820191906000526020600020905b81548152906001019060200180831161244157829003601f168201915b5050505050905090565b606060006001612477846129de565b01905060008167ffffffffffffffff81111561249657612495613558565b5b6040519080825280601f01601f1916602001820160405280156124c85781602001600182028036833780820191505090505b509050600082602001820190505b60011561252b578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161251f5761251e614428565b5b049450600085036124d6575b819350505050919050565b600081600001805490509050919050565b600080836001016000848152602001908152602001600020541415905092915050565b60007f5a05180f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806125dd57506125dc82612b31565b5b9050919050565b6125f084848484612bab565b6125f8610b65565b15612638576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262f906144c9565b60405180910390fd5b50505050565b60606126648273ffffffffffffffffffffffffffffffffffffffff16601460ff1661266b565b9050919050565b60606000600283600261267e9190614518565b612688919061455a565b67ffffffffffffffff8111156126a1576126a0613558565b5b6040519080825280601f01601f1916602001820160405280156126d35781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061270b5761270a613ba4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061276f5761276e613ba4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026127af9190614518565b6127b9919061455a565b90505b6001811115612859577f3031323334353637383961626364656600000000000000000000000000000000600f8616601081106127fb576127fa613ba4565b5b1a60f81b82828151811061281257612811613ba4565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806128529061458e565b90506127bc565b506000841461289d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289490614603565b60405180910390fd5b8091505092915050565b600080836001016000848152602001908152602001600020549050600081146129af5760006001826128d99190614623565b90506000600186600001805490506128f19190614623565b905081811461296057600086600001828154811061291257612911613ba4565b5b906000526020600020015490508087600001848154811061293657612935613ba4565b5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061297457612973614657565b5b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506129b5565b60009150505b92915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612a3c577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612a3257612a31614428565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612a79576d04ee2d6d415b85acef81000000008381612a6f57612a6e614428565b5b0492506020810190505b662386f26fc100008310612aa857662386f26fc100008381612a9e57612a9d614428565b5b0492506010810190505b6305f5e1008310612ad1576305f5e1008381612ac757612ac6614428565b5b0492506008810190505b6127108310612af6576127108381612aec57612aeb614428565b5b0492506004810190505b60648310612b195760648381612b0f57612b0e614428565b5b0492506002810190505b600a8310612b28576001810190505b80915050919050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612ba45750612ba382612d09565b5b9050919050565b612bb784848484612d73565b6001811115612bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bf2906146f8565b60405180910390fd5b6000829050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612c4257612c3d81612d79565b612c81565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612c8057612c7f8582612dc2565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612cc357612cbe81612f2f565b612d02565b8473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614612d0157612d008482613000565b5b5b5050505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b50505050565b600a80549050600b600083815260200190815260200160002081905550600a81908060018154018082558091505060019003906000526020600020016000909190919091505550565b60006001612dcf84610c92565b612dd99190614623565b9050600060096000848152602001908152602001600020549050818114612ebe576000600860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816009600083815260200190815260200160002081905550505b6009600084815260200190815260200160002060009055600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600a80549050612f439190614623565b90506000600b60008481526020019081526020016000205490506000600a8381548110612f7357612f72613ba4565b5b9060005260206000200154905080600a8381548110612f9557612f94613ba4565b5b906000526020600020018190555081600b600083815260200190815260200160002081905550600b600085815260200190815260200160002060009055600a805480612fe457612fe3614657565b5b6001900381819060005260206000200160009055905550505050565b600061300b83610c92565b905081600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806009600084815260200190815260200160002081905550505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6130c881613093565b81146130d357600080fd5b50565b6000813590506130e5816130bf565b92915050565b60006020828403121561310157613100613089565b5b600061310f848285016130d6565b91505092915050565b60008115159050919050565b61312d81613118565b82525050565b60006020820190506131486000830184613124565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561318857808201518184015260208101905061316d565b60008484015250505050565b6000601f19601f8301169050919050565b60006131b08261314e565b6131ba8185613159565b93506131ca81856020860161316a565b6131d381613194565b840191505092915050565b600060208201905081810360008301526131f881846131a5565b905092915050565b6000819050919050565b61321381613200565b811461321e57600080fd5b50565b6000813590506132308161320a565b92915050565b60006020828403121561324c5761324b613089565b5b600061325a84828501613221565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061328e82613263565b9050919050565b61329e81613283565b82525050565b60006020820190506132b96000830184613295565b92915050565b6132c881613283565b81146132d357600080fd5b50565b6000813590506132e5816132bf565b92915050565b6000806040838503121561330257613301613089565b5b6000613310858286016132d6565b925050602061332185828601613221565b9150509250929050565b61333481613200565b82525050565b600060208201905061334f600083018461332b565b92915050565b60008060006060848603121561336e5761336d613089565b5b600061337c868287016132d6565b935050602061338d868287016132d6565b925050604061339e86828701613221565b9150509250925092565b6000819050919050565b6133bb816133a8565b81146133c657600080fd5b50565b6000813590506133d8816133b2565b92915050565b6000602082840312156133f4576133f3613089565b5b6000613402848285016133c9565b91505092915050565b613414816133a8565b82525050565b600060208201905061342f600083018461340b565b92915050565b6000806040838503121561344c5761344b613089565b5b600061345a858286016133c9565b925050602061346b858286016132d6565b9150509250929050565b60006020828403121561348b5761348a613089565b5b6000613499848285016132d6565b91505092915050565b600080604083850312156134b9576134b8613089565b5b60006134c7858286016133c9565b92505060206134d885828601613221565b9150509250929050565b6134eb81613118565b81146134f657600080fd5b50565b600081359050613508816134e2565b92915050565b6000806040838503121561352557613524613089565b5b6000613533858286016132d6565b9250506020613544858286016134f9565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61359082613194565b810181811067ffffffffffffffff821117156135af576135ae613558565b5b80604052505050565b60006135c261307f565b90506135ce8282613587565b919050565b600067ffffffffffffffff8211156135ee576135ed613558565b5b6135f782613194565b9050602081019050919050565b82818337600083830152505050565b6000613626613621846135d3565b6135b8565b90508281526020810184848401111561364257613641613553565b5b61364d848285613604565b509392505050565b600082601f83011261366a5761366961354e565b5b813561367a848260208601613613565b91505092915050565b6000806000806080858703121561369d5761369c613089565b5b60006136ab878288016132d6565b94505060206136bc878288016132d6565b93505060406136cd87828801613221565b925050606085013567ffffffffffffffff8111156136ee576136ed61308e565b5b6136fa87828801613655565b91505092959194509250565b6000806040838503121561371d5761371c613089565b5b600061372b858286016132d6565b925050602061373c858286016132d6565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061378d57607f821691505b6020821081036137a05761379f613746565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613802602183613159565b915061380d826137a6565b604082019050919050565b60006020820190508181036000830152613831816137f5565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613894603d83613159565b915061389f82613838565b604082019050919050565b600060208201905081810360008301526138c381613887565b9050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613926602d83613159565b9150613931826138ca565b604082019050919050565b6000602082019050818103600083015261395581613919565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b60006139b8602b83613159565b91506139c38261395c565b604082019050919050565b600060208201905081810360008301526139e7816139ab565b9050919050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b6000613a4a602f83613159565b9150613a55826139ee565b604082019050919050565b60006020820190508181036000830152613a7981613a3d565b9050919050565b7f4552433732315072657365744d696e7465725061757365724175746f49643a2060008201527f6d75737420686176652070617573657220726f6c6520746f20756e7061757365602082015250565b6000613adc604083613159565b9150613ae782613a80565b604082019050919050565b60006020820190508181036000830152613b0b81613acf565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000613b6e602c83613159565b9150613b7982613b12565b604082019050919050565b60006020820190508181036000830152613b9d81613b61565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b6000613c09601883613159565b9150613c1482613bd3565b602082019050919050565b60006020820190508181036000830152613c3881613bfc565b9050919050565b7f4552433732315072657365744d696e7465725061757365724175746f49643a2060008201527f6d7573742068617665206d696e74657220726f6c6520746f206d696e74000000602082015250565b6000613c9b603d83613159565b9150613ca682613c3f565b604082019050919050565b60006020820190508181036000830152613cca81613c8e565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b6000613d2d602983613159565b9150613d3882613cd1565b604082019050919050565b60006020820190508181036000830152613d5c81613d20565b9050919050565b7f4552433732315072657365744d696e7465725061757365724175746f49643a2060008201527f6d75737420686176652070617573657220726f6c6520746f2070617573650000602082015250565b6000613dbf603e83613159565b9150613dca82613d63565b604082019050919050565b60006020820190508181036000830152613dee81613db2565b9050919050565b600081905092915050565b6000613e0b8261314e565b613e158185613df5565b9350613e2581856020860161316a565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000815250565b6000613e638284613e00565b9150613e6e82613e31565b60058201915081905092915050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b6000613ed9602583613159565b9150613ee482613e7d565b604082019050919050565b60006020820190508181036000830152613f0881613ecc565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000613f6b602483613159565b9150613f7682613f0f565b604082019050919050565b60006020820190508181036000830152613f9a81613f5e565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000613fd7602083613159565b9150613fe282613fa1565b602082019050919050565b6000602082019050818103600083015261400681613fca565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614043601c83613159565b915061404e8261400d565b602082019050919050565b6000602082019050818103600083015261407281614036565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006140af601983613159565b91506140ba82614079565b602082019050919050565b600060208201905081810360008301526140de816140a2565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614141603283613159565b915061414c826140e5565b604082019050919050565b6000602082019050818103600083015261417081614134565b9050919050565b60006141838285613e00565b915061418f8284613e00565b91508190509392505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b60006141d1601783613df5565b91506141dc8261419b565b601782019050919050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b600061421d601183613df5565b9150614228826141e7565b601182019050919050565b600061423e826141c4565b915061424a8285613e00565b915061425582614210565b91506142618284613e00565b91508190509392505050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b60006142a3601483613159565b91506142ae8261426d565b602082019050919050565b600060208201905081810360008301526142d281614296565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b600061430f601083613159565b915061431a826142d9565b602082019050919050565b6000602082019050818103600083015261433e81614302565b9050919050565b600081519050919050565b600082825260208201905092915050565b600061436c82614345565b6143768185614350565b935061438681856020860161316a565b61438f81613194565b840191505092915050565b60006080820190506143af6000830187613295565b6143bc6020830186613295565b6143c9604083018561332b565b81810360608301526143db8184614361565b905095945050505050565b6000815190506143f5816130bf565b92915050565b60006020828403121561441157614410613089565b5b600061441f848285016143e6565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4552433732315061757361626c653a20746f6b656e207472616e73666572207760008201527f68696c6520706175736564000000000000000000000000000000000000000000602082015250565b60006144b3602b83613159565b91506144be82614457565b604082019050919050565b600060208201905081810360008301526144e2816144a6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061452382613200565b915061452e83613200565b925082820261453c81613200565b91508282048414831517614553576145526144e9565b5b5092915050565b600061456582613200565b915061457083613200565b9250828201905080821115614588576145876144e9565b5b92915050565b600061459982613200565b9150600082036145ac576145ab6144e9565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b60006145ed602083613159565b91506145f8826145b7565b602082019050919050565b6000602082019050818103600083015261461c816145e0565b9050919050565b600061462e82613200565b915061463983613200565b9250828203905081811115614651576146506144e9565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f455243373231456e756d657261626c653a20636f6e736563757469766520747260008201527f616e7366657273206e6f7420737570706f727465640000000000000000000000602082015250565b60006146e2603583613159565b91506146ed82614686565b604082019050919050565b60006020820190508181036000830152614711816146d5565b905091905056fea2646970667358221220e972bbd276839058152a76991f80e14bc204d51ef1164ea5b20e88b88893b61164736f6c63430008110033' + } +]; + +/** + * Test smart contract address + */ +const testSmartContract = '0xa540a1924dff8db10bcb3aba3183c0385f2ad285'; + +/** + * Test storage position key + */ +const testStoragePositionKey = + '0x0000000000000000000000000000000000000000000000000000000000000001'; + +/** + * Empty storage slot + */ +const NULL_STORAGE_SLOT = + '0x0000000000000000000000000000000000000000000000000000000000000000'; + +/** + * Invalid getStorageAt test cases for invalid data types + */ +const invalidGetStorageAtTests = [ + { + description: 'Should throw error for invalid revision', + address: testSmartContract, + position: testStoragePositionKey, + revision: 'invalid-revision', + expectedError: InvalidDataTypeError + }, + { + description: 'Should throw error for invalid position', + address: testSmartContract, + position: 'invalid-position', + revision: '1', + expectedError: InvalidDataTypeError + }, + { + description: 'Should throw error for invalid address', + address: 'invalid-address', + position: '0x123', + revision: '1', + expectedError: InvalidDataTypeError + } +]; + +/** + * Invalid getAccount test cases for invalid data types + */ +const invalidGetAccountTests = [ + { + description: 'Should throw error for invalid revision', + address: testAccount, + revision: 'invalid-revision', + expectedError: InvalidDataTypeError + }, + { + description: 'Should throw error for invalid address', + address: 'invalid-address', + revision: '1', + expectedError: InvalidDataTypeError + } +]; + +const invalidGetBytecodeTests = [ + { + description: 'Should throw error for invalid revision', + address: testSmartContract, + revision: 'invalid-revision', + expectedError: InvalidDataTypeError + }, + { + description: 'Should throw error for invalid address', + address: 'invalid-address', + revision: '1', + expectedError: InvalidDataTypeError + } +]; + +export { + getAccountWithRevisionTestCases, + getBytecodeTestCases, + testSmartContract, + testStoragePositionKey, + NULL_STORAGE_SLOT, + invalidGetStorageAtTests, + invalidGetAccountTests, + invalidGetBytecodeTests +};