diff --git a/docs/contracts.md b/docs/contracts.md index 37b3b3736..8f4d639c2 100644 --- a/docs/contracts.md +++ b/docs/contracts.md @@ -149,10 +149,34 @@ const multipleClausesResult = contract.clause.decimals() ]); -expect(multipleClausesResult[0]).toEqual([expectedBalance]); -expect(multipleClausesResult[1]).toEqual(['SampleToken']); -expect(multipleClausesResult[2]).toEqual(['ST']); -expect(multipleClausesResult[3]).toEqual([18]); +expect(multipleClausesResult[0]).toEqual({ + success: true, + result: { + plain: expectedBalance, + array: [expectedBalance] + } +}); +expect(multipleClausesResult[1]).toEqual({ + success: true, + result: { + plain: 'SampleToken', + array: ['SampleToken'] + } +}); +expect(multipleClausesResult[2]).toEqual({ + success: true, + result: { + plain: 'ST', + array: ['ST'] + } +}); +expect(multipleClausesResult[3]).toEqual({ + success: true, + result: { + plain: 18, + array: [18] + } +}); ``` > ⚠️ **Warning:** diff --git a/docs/examples/contracts/contract-create-ERC20-token.ts b/docs/examples/contracts/contract-create-ERC20-token.ts index 9370e90e7..602b5e65b 100644 --- a/docs/examples/contracts/contract-create-ERC20-token.ts +++ b/docs/examples/contracts/contract-create-ERC20-token.ts @@ -70,9 +70,33 @@ const multipleClausesResult = contract.clause.decimals() ]); -expect(multipleClausesResult[0]).toEqual([expectedBalance]); -expect(multipleClausesResult[1]).toEqual(['SampleToken']); -expect(multipleClausesResult[2]).toEqual(['ST']); -expect(multipleClausesResult[3]).toEqual([18]); +expect(multipleClausesResult[0]).toEqual({ + success: true, + result: { + plain: expectedBalance, + array: [expectedBalance] + } +}); +expect(multipleClausesResult[1]).toEqual({ + success: true, + result: { + plain: 'SampleToken', + array: ['SampleToken'] + } +}); +expect(multipleClausesResult[2]).toEqual({ + success: true, + result: { + plain: 'ST', + array: ['ST'] + } +}); +expect(multipleClausesResult[3]).toEqual({ + success: true, + result: { + plain: 18, + array: [18] + } +}); // END_SNIPPET: ERC20MultiClausesReadSnippet diff --git a/docs/examples/evm-extension/evm-extension.ts b/docs/examples/evm-extension/evm-extension.ts index cbe8c5422..f4c9ca13d 100644 --- a/docs/examples/evm-extension/evm-extension.ts +++ b/docs/examples/evm-extension/evm-extension.ts @@ -791,4 +791,10 @@ const totalSupply = await thorSoloClient.contracts.executeCall( // END_SNIPPET: EVMExtensionSnippet // Check the result -expect(totalSupply).toStrictEqual([10000000000000000000000000000n]); +expect(totalSupply).toStrictEqual({ + result: { + array: [10000000000000000000000000000n], + plain: 10000000000000000000000000000n + }, + success: true +}); diff --git a/packages/core/package.json b/packages/core/package.json index c4f185f59..3bac0fd54 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -49,6 +49,7 @@ }, "devDependencies": { "bignumber.js": "^9.1.2", - "thor-devkit": "^2.0.9" + "thor-devkit": "^2.0.9", + "tsd": "^0.31.2" } } \ No newline at end of file diff --git a/packages/core/src/transaction/Clause.ts b/packages/core/src/transaction/Clause.ts index 23a5674da..e1ded5f89 100644 --- a/packages/core/src/transaction/Clause.ts +++ b/packages/core/src/transaction/Clause.ts @@ -1,3 +1,4 @@ +import { InvalidDataType } from '@vechain/sdk-errors'; import { ERC721_ABI, VIP180_ABI } from '../utils'; import { ABI, @@ -11,10 +12,9 @@ import { } from '../vcdm'; import { Hex } from '../vcdm/Hex'; import { HexInt } from '../vcdm/HexInt'; -import { InvalidDataType } from '@vechain/sdk-errors'; +import type { ClauseOptions } from './ClauseOptions'; import type { DeployParams } from './DeployParams'; import type { TransactionClause } from './TransactionClause'; -import type { ClauseOptions } from './ClauseOptions'; /** * This class represent a transaction clause. diff --git a/packages/core/src/vcdm/abi/ABIContract.ts b/packages/core/src/vcdm/abi/ABIContract.ts index a00082c2e..f8cca4df7 100644 --- a/packages/core/src/vcdm/abi/ABIContract.ts +++ b/packages/core/src/vcdm/abi/ABIContract.ts @@ -6,6 +6,8 @@ import { getAbiItem, type AbiEvent, type AbiFunction, + type ContractEventName, + type ContractFunctionName, type DecodeEventLogReturnType, type DecodeFunctionDataReturnType, type DecodeFunctionResultReturnType, @@ -16,12 +18,12 @@ import { ABI } from './ABI'; import { ABIEvent, type ABIEventData } from './ABIEvent'; import { ABIFunction } from './ABIFunction'; -class ABIContract extends ABI { - private readonly abi: ViemABI; +class ABIContract extends ABI { + private readonly viemABI: ViemABI; - constructor(abi: ViemABI) { + constructor(readonly abi: TAbi) { super(); - this.abi = abi; + this.viemABI = abi as ViemABI; } /** @@ -29,7 +31,7 @@ class ABIContract extends ABI { * @param {ViemABI} abi representation of the contract. * @returns New instance of ABIContract. */ - public static ofAbi(abi: ViemABI): ABIContract { + public static ofAbi(abi: TAbi): ABIContract { return new ABIContract(abi); } @@ -39,10 +41,12 @@ class ABIContract extends ABI { * @returns {ABIFunction} The function with the given name. * @throws {InvalidAbiItem} */ - public getFunction(name: string): ABIFunction { + public getFunction>( + name: TFunctionName | string + ): ABIFunction { const functionAbiItem = getAbiItem({ - abi: this.abi, - name + abi: this.viemABI, + name: name as string }); if (functionAbiItem === null || functionAbiItem === undefined) { throw new InvalidAbiItem( @@ -54,7 +58,9 @@ class ABIContract extends ABI { } ); } - return new ABIFunction(functionAbiItem as AbiFunction); + return new ABIFunction( + functionAbiItem as AbiFunction + ); } /** @@ -63,10 +69,12 @@ class ABIContract extends ABI { * @returns {ABIEvent} The event with the given name. * @throws {InvalidAbiItem} */ - public getEvent(name: string): ABIEvent { + public getEvent>( + name: TEventName | string + ): ABIEvent { const eventAbiItem = getAbiItem({ - abi: this.abi, - name + abi: this.viemABI, + name: name as string }); if (eventAbiItem === null || eventAbiItem === undefined) { throw new InvalidAbiItem( @@ -78,7 +86,7 @@ class ABIContract extends ABI { } ); } - return new ABIEvent(eventAbiItem as AbiEvent); + return new ABIEvent(eventAbiItem as AbiEvent); } /** @@ -88,16 +96,17 @@ class ABIContract extends ABI { * @returns {Hex} The encoded data in hexadecimal that can be used to send a transaction. * @throws {InvalidAbiDataToEncodeOrDecode} */ - public encodeFunctionInput( - functionName: string, - functionData?: unknown[] - ): Hex { + public encodeFunctionInput< + TFunctionName extends ContractFunctionName + >(functionName: TFunctionName | string, functionData?: unknown[]): Hex { try { const functionAbiItem = getAbiItem({ - abi: this.abi, - name: functionName + abi: this.viemABI, + name: functionName as string }); - const functionAbi = new ABIFunction(functionAbiItem as AbiFunction); + const functionAbi = new ABIFunction( + functionAbiItem as AbiFunction + ); return functionAbi.encodeData(functionData); } catch (error) { @@ -117,16 +126,20 @@ class ABIContract extends ABI { * @returns {DecodeFunctionDataReturnType} an array of the decoded function data * @throws {InvalidAbiDataToEncodeOrDecode} */ - public decodeFunctionInput( - functionName: string, + public decodeFunctionInput< + TFunctionName extends ContractFunctionName + >( + functionName: TFunctionName | string, encodedFunctionInput: Hex - ): DecodeFunctionDataReturnType { + ): DecodeFunctionDataReturnType { try { const functionAbiItem = getAbiItem({ - abi: this.abi, - name: functionName + abi: this.viemABI, + name: functionName as string }); - const functionAbi = new ABIFunction(functionAbiItem as AbiFunction); + const functionAbi = new ABIFunction( + functionAbiItem as AbiFunction + ); return functionAbi.decodeData(encodedFunctionInput); } catch (error) { @@ -154,16 +167,20 @@ class ABIContract extends ABI { * const decodedOutput = decodeFunctionOutput('getValue', encodedValue); * */ - public decodeFunctionOutput( - functionName: string, + public decodeFunctionOutput< + TFunctionName extends ContractFunctionName + >( + functionName: TFunctionName | string, encodedFunctionOutput: Hex - ): DecodeFunctionResultReturnType { + ): DecodeFunctionResultReturnType { try { const functionAbiItem = getAbiItem({ - abi: this.abi, - name: functionName + abi: this.viemABI, + name: functionName as string }); - const functionAbi = new ABIFunction(functionAbiItem as AbiFunction); + const functionAbi = new ABIFunction( + functionAbiItem as AbiFunction + ); return functionAbi.decodeResult(encodedFunctionOutput); } catch (error) { @@ -183,16 +200,18 @@ class ABIContract extends ABI { * @returns {ABIEventData} An object containing the encoded data and topics. * @throws {InvalidAbiDataToEncodeOrDecode} */ - public encodeEventLog( - eventName: string, + public encodeEventLog>( + eventName: TEventName | string, eventArgs: unknown[] ): ABIEventData { try { const eventAbiItem = getAbiItem({ - abi: this.abi, - name: eventName + abi: this.viemABI, + name: eventName as string }); - const eventAbi = new ABIEvent(eventAbiItem as AbiEvent); + const eventAbi = new ABIEvent( + eventAbiItem as AbiEvent + ); return eventAbi.encodeEventLog(eventArgs); } catch (error) { throw new InvalidAbiDataToEncodeOrDecode( @@ -211,16 +230,18 @@ class ABIContract extends ABI { * @returns {DecodeEventLogReturnType} The decoded data of the event log. * @throws {InvalidAbiDataToEncodeOrDecode} */ - public decodeEventLog( - eventName: string, + public decodeEventLog>( + eventName: TEventName | string, eventToDecode: ABIEventData - ): DecodeEventLogReturnType { + ): DecodeEventLogReturnType { try { const eventAbiItem = getAbiItem({ - abi: this.abi, - name: eventName + abi: this.viemABI, + name: eventName as string }); - const eventAbi = new ABIEvent(eventAbiItem as AbiEvent); + const eventAbi = new ABIEvent( + eventAbiItem as AbiEvent + ); return eventAbi.decodeEventLog(eventToDecode); } catch (error) { throw new InvalidAbiDataToEncodeOrDecode( @@ -245,9 +266,15 @@ class ABIContract extends ABI { * @returns {DecodeEventLogReturnType} - A log object representing the decoded log or null if decoding fails. * @throws {InvalidAbiDataToEncodeOrDecode} */ - public parseLog(data: Hex, topics: Hex[]): DecodeEventLogReturnType { + public parseLog>( + data: Hex, + topics: Hex[] + ): DecodeEventLogReturnType { try { - return ABIEvent.parseLog(this.abi, { data, topics }); + return ABIEvent.parseLog(this.abi, { + data, + topics + }); } catch (e) { throw new InvalidAbiDataToEncodeOrDecode( 'ABIContract.parseLog()', @@ -272,7 +299,9 @@ class ABIContract extends ABI { return []; } - return this.parseObjectValues(eventLogDecoded.args); + return this.parseObjectValues( + eventLogDecoded.args as unknown as object + ); } } diff --git a/packages/core/src/vcdm/abi/ABIEvent.ts b/packages/core/src/vcdm/abi/ABIEvent.ts index af221f80d..47c9c42ec 100644 --- a/packages/core/src/vcdm/abi/ABIEvent.ts +++ b/packages/core/src/vcdm/abi/ABIEvent.ts @@ -5,6 +5,7 @@ import { import { type AbiEventParameter } from 'abitype'; import { type AbiEvent, + type ContractEventName, type DecodeEventLogReturnType, encodeEventTopics, type EncodeEventTopicsReturnType, @@ -27,7 +28,10 @@ interface ABIEventData { * Represents a function call in the Event ABI. * @extends ABIItem */ -class ABIEvent extends ABIItem { +class ABIEvent< + TAbi extends ViemABI = ViemABI, + TEventName extends ContractEventName = ContractEventName +> extends ABIItem { private readonly abiEvent: AbiEvent; public constructor(signature: string); public constructor(signature: AbiEvent); @@ -55,10 +59,13 @@ class ABIEvent extends ABIItem { * @returns Decoding results. * @throws {InvalidAbiDataToEncodeOrDecode} */ - public static parseLog( - abi: ViemABI, + public static parseLog< + TAbi extends ViemABI, + TEventName extends ContractEventName + >( + abi: TAbi, eventData: ABIEventData - ): DecodeEventLogReturnType { + ): DecodeEventLogReturnType { try { return viemDecodeEventLog({ abi, @@ -95,9 +102,11 @@ class ABIEvent extends ABIItem { * @returns Decoding results. * @throws {InvalidAbiDataToEncodeOrDecode} */ - public decodeEventLog(event: ABIEventData): DecodeEventLogReturnType { + public decodeEventLog( + event: ABIEventData + ): DecodeEventLogReturnType { try { - return ABIEvent.parseLog([this.abiEvent], event); + return ABIEvent.parseLog([this.abiEvent] as ViemABI, event); } catch (error) { throw new InvalidAbiDataToEncodeOrDecode( 'ABIEvent.decodeEventLog', @@ -120,7 +129,7 @@ class ABIEvent extends ABIItem { return []; } - return this.parseObjectValues(rawDecodedData.args); + return this.parseObjectValues(rawDecodedData.args as unknown as object); } /** diff --git a/packages/core/src/vcdm/abi/ABIFunction.ts b/packages/core/src/vcdm/abi/ABIFunction.ts index 913a6c2a8..ed198f828 100644 --- a/packages/core/src/vcdm/abi/ABIFunction.ts +++ b/packages/core/src/vcdm/abi/ABIFunction.ts @@ -4,11 +4,13 @@ import { } from '@vechain/sdk-errors'; import { type AbiFunction, + type ContractFunctionName, decodeFunctionData, type DecodeFunctionDataReturnType, decodeFunctionResult, type DecodeFunctionResultReturnType, encodeFunctionData, + type Abi as ViemABI, type Hex as ViemHex } from 'viem'; import { Hex } from '../Hex'; @@ -18,7 +20,11 @@ import { ABIItem } from './ABIItem'; * Represents a function call in the Function ABI. * @extends ABIItem */ -class ABIFunction extends ABIItem { +class ABIFunction< + TAbi extends ViemABI = ViemABI, + TFunctionName extends + ContractFunctionName = ContractFunctionName +> extends ABIItem { private readonly abiFunction: AbiFunction; public constructor(signature: string); public constructor(signature: AbiFunction); @@ -55,7 +61,9 @@ class ABIFunction extends ABIItem { * @returns Decoding results. * @throws {InvalidAbiDataToEncodeOrDecode} */ - public decodeData(data: Hex): DecodeFunctionDataReturnType { + public decodeData( + data: Hex + ): DecodeFunctionDataReturnType { try { return decodeFunctionData({ abi: [this.abiFunction], @@ -110,12 +118,19 @@ class ABIFunction extends ABIItem { * console.log('Decoded Output:', decoded); * ``` */ - public decodeResult(data: Hex): DecodeFunctionResultReturnType { + public decodeResult( + data: Hex + ): DecodeFunctionResultReturnType { try { - return decodeFunctionResult({ + const result = decodeFunctionResult({ abi: [this.abiFunction], data: data.toString() as ViemHex }); + + return result as DecodeFunctionResultReturnType< + TAbi, + TFunctionName + >; } catch (error) { throw new InvalidAbiDataToEncodeOrDecode( 'ABIFunction.decodeResult', diff --git a/packages/core/tests/vcdm/abi/contract.unit.test.ts b/packages/core/tests/vcdm/abi/contract.unit.test.ts index 8ac4d68c7..01abd54fe 100644 --- a/packages/core/tests/vcdm/abi/contract.unit.test.ts +++ b/packages/core/tests/vcdm/abi/contract.unit.test.ts @@ -5,12 +5,15 @@ import { InvalidDataType } from '@vechain/sdk-errors'; import { fail } from 'assert'; +import { expectType } from 'tsd'; import { type AbiEvent, encodeFunctionResult } from 'viem'; import { ABIContract, ABIEvent, ABIItem, ERC721_ABI, Hex } from '../../../src'; import { contractABI, contractABIWithEvents, contractStorageABI, + type ExpectedCustomFunctionType, + type ExpectedERC721TransferEventType, ValueChangedEventData } from './fixture'; @@ -19,10 +22,10 @@ import { * @group unit/encode-decode */ describe('Contract interface for ABI encoding/decoding', () => { - let contractAbi: ABIContract; - let contractAbiWithEvents: ABIContract; - let erc721Abi: ABIContract; - let contractStorageAbi: ABIContract; + let contractAbi: ABIContract; + let contractAbiWithEvents: ABIContract; + let erc721Abi: ABIContract; + let contractStorageAbi: ABIContract; beforeAll(() => { contractAbi = ABIContract.ofAbi(contractABI); contractAbiWithEvents = ABIContract.ofAbi(contractABIWithEvents); @@ -63,9 +66,9 @@ describe('Contract interface for ABI encoding/decoding', () => { * Test the error when getting a function ABI. */ test('get a function ABI and throw an error', () => { - expect(() => contractAbi.getFunction('undefined')).toThrowError( - InvalidAbiItem - ); + expect(() => + contractAbi.getFunction('undefined' as unknown as 'setValue') + ).toThrowError(InvalidAbiItem); }); /** @@ -73,7 +76,10 @@ describe('Contract interface for ABI encoding/decoding', () => { */ test('Fail to encode a contract function input', () => { expect(() => - contractAbi.encodeFunctionInput('undefined', [123]) + contractAbi.encodeFunctionInput( + 'undefined' as unknown as 'setValue', + [123] + ) ).toThrowError(InvalidAbiDataToEncodeOrDecode); }); @@ -86,12 +92,19 @@ describe('Contract interface for ABI encoding/decoding', () => { 'setValue', encodedData ); + expectType(functionInputDecoded); const decodedData = functionInputDecoded.args !== null && functionInputDecoded.args !== undefined ? String(functionInputDecoded.args[0]) : ''; expect(decodedData).toEqual('123'); + + const fuctionDataDecoded = contractAbi + .getFunction('setValue') + .decodeData(encodedData); + + expectType(fuctionDataDecoded); }); /** @@ -166,7 +179,7 @@ describe('Contract interface for ABI encoding/decoding', () => { * Test the decoding of an encoded event log from a contract transaction. */ test('parse an event log and return decoded data', () => { - const decodedEventLog = erc721Abi.parseLog(Hex.of('0x'), [ + const decodedEventLog = erc721Abi.parseLog<'Transfer'>(Hex.of('0x'), [ Hex.of( '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' ), @@ -181,20 +194,20 @@ describe('Contract interface for ABI encoding/decoding', () => { ) ]); + expectType(decodedEventLog); expect(decodedEventLog).toBeDefined(); expect(decodedEventLog.eventName).toEqual('Transfer'); expect(decodedEventLog.args).toBeDefined(); if (decodedEventLog.args === undefined) { fail('Decoded event log args are undefined'); } - const argsValues = Object.values(decodedEventLog.args); - expect(argsValues[0]).toEqual( + expect(decodedEventLog.args.from).toEqual( '0x0000000000000000000000000000000000000000' ); - expect(argsValues[1]).toEqual( + expect(decodedEventLog.args.to).toEqual( '0xF02f557c753edf5fcdCbfE4c1c3a448B3cC84D54' ); - expect(argsValues[2]).toEqual(1n); + expect(decodedEventLog.args.tokenId).toEqual(1n); }); /** @@ -296,6 +309,9 @@ describe('Contract interface for ABI encoding/decoding', () => { functionName, Hex.of(encodedFunctionOutput) ); + + expectType(decodedOutput); + expect(decodedOutput).toBeDefined(); expect(decodedOutput).toEqual(mockReturnValue); @@ -321,7 +337,7 @@ describe('Contract interface for ABI encoding/decoding', () => { expect(() => contractStorageAbi.decodeFunctionOutput( - 'invalidFunctionName', + 'invalidFunctionName' as unknown as 'getValue', Hex.of(encodedFunctionOutput) ) ).toThrowError(InvalidAbiDataToEncodeOrDecode); diff --git a/packages/core/tests/vcdm/abi/fixture.ts b/packages/core/tests/vcdm/abi/fixture.ts index c1af8bfa2..ab553fd71 100644 --- a/packages/core/tests/vcdm/abi/fixture.ts +++ b/packages/core/tests/vcdm/abi/fixture.ts @@ -552,6 +552,20 @@ const ValueChangedEventData = { value: 100 // Replace with the actual balance value }; +interface ExpectedERC721TransferEventType { + eventName: 'Transfer'; + args: { + from: `0x${string}`; + to: `0x${string}`; + tokenId: bigint; + }; +} + +interface ExpectedCustomFunctionType { + args: readonly [bigint]; + functionName: 'setValue'; +} + export { contractABI, contractABIWithEvents, @@ -563,5 +577,7 @@ export { invalidTopicsEventTestCases, simpleParametersDataForFunction2, topicsEventTestCases, - ValueChangedEventData + ValueChangedEventData, + type ExpectedCustomFunctionType, + type ExpectedERC721TransferEventType }; diff --git a/packages/errors/src/available-errors/contract/contract.ts b/packages/errors/src/available-errors/contract/contract.ts index 199e5d449..ae9f482eb 100644 --- a/packages/errors/src/available-errors/contract/contract.ts +++ b/packages/errors/src/available-errors/contract/contract.ts @@ -9,4 +9,12 @@ import { type ObjectErrorData } from '../types'; */ class ContractDeploymentFailed extends VechainSDKError {} -export { ContractDeploymentFailed }; +/** + * Error when calling a read function on a contract. + * + * WHEN TO USE: + * * Error will be thrown when a read (call) operation fails. + */ +class ContractCallError extends VechainSDKError {} + +export { ContractCallError, ContractDeploymentFailed }; diff --git a/packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts b/packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts index 597d747b9..15e196c12 100644 --- a/packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts +++ b/packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts @@ -6,13 +6,11 @@ import { type ThorClient } from '../../../../../thor-client'; * @returns The current gas price in Wei unit considering that 1 VTHO equals 1e18 Wei. */ const ethGasPrice = async (thorClient: ThorClient): Promise => { - const result = BigInt( - (await Promise.resolve( - thorClient.contracts.getBaseGasPrice() - )) as string - ); + const { + result: { plain } + } = await thorClient.contracts.getBaseGasPrice(); - return '0x' + result.toString(16); + return '0x' + BigInt(plain as bigint).toString(16); }; export { ethGasPrice }; diff --git a/packages/network/src/thor-client/contracts/contracts-module.ts b/packages/network/src/thor-client/contracts/contracts-module.ts index f89578aeb..0772012f7 100644 --- a/packages/network/src/thor-client/contracts/contracts-module.ts +++ b/packages/network/src/thor-client/contracts/contracts-module.ts @@ -1,11 +1,11 @@ import { ABIContract, + Address, + Clause, dataUtils, Hex, - Address, - VET, Units, - Clause, + VET, type ABIFunction } from '@vechain/sdk-core'; import { type Abi } from 'abitype'; @@ -68,6 +68,41 @@ class ContractsModule { return new Contract(address, abi, this.thor, signer); } + /** + * Extracts the decoded contract call result from the response of a simulated transaction. + * @param {string} encodedData Data returned from the simulated transaction. + * @param {ABIFunction} functionAbi Function ABI of the contract function. + * @param {boolean} reverted Whether the transaction was reverted. + * @returns {ContractCallResult} An object containing the decoded contract call result. + */ + private getContractCallResult( + encodedData: string, + functionAbi: ABIFunction, + reverted: boolean + ): ContractCallResult { + if (reverted) { + const errorMessage = decodeRevertReason(encodedData) ?? ''; + return { + success: false, + result: { + errorMessage + } + }; + } + + // Returning the decoded result both as plain and array. + const encodedResult = Hex.of(encodedData); + const plain = functionAbi.decodeResult(encodedResult); + const array = functionAbi.decodeOutputAsArray(encodedResult); + return { + success: true, + result: { + plain, + array + } + }; + } + /** * Executes a read-only call to a smart contract function, simulating the transaction to obtain the result. * @@ -84,7 +119,7 @@ class ContractsModule { functionAbi: ABIFunction, functionData: unknown[], contractCallOptions?: ContractCallOptions - ): Promise { + ): Promise { // Simulate the transaction to get the result of the contract call const response = await this.thor.transactions.simulateTransaction( [ @@ -97,39 +132,35 @@ class ContractsModule { contractCallOptions ); - if (response[0].reverted) { - /** - * The decoded revert reason of the transaction. - * Solidity may revert with Error(string) or Panic(uint256). - * - * @link see [Error handling: Assert, Require, Revert and Exceptions](https://docs.soliditylang.org/en/latest/control-structures.html#error-handling-assert-require-revert-and-exceptions) - */ - return decodeRevertReason(response[0].data) ?? ''; - } else { - // Returning an array of values. - // The viem format is a single value/JSON object (ABIFunction#decodeResult) - return functionAbi.decodeOutputAsArray(Hex.of(response[0].data)); - } + return this.getContractCallResult( + response[0].data, + functionAbi, + response[0].reverted + ); } /** * Executes a read-only call to multiple smart contract functions, simulating the transaction to obtain the results. * @param clauses - An array of contract clauses to interact with the contract functions. * @param options - (Optional) Additional options for the contract call, such as the sender's address, gas limit, and gas price, which can affect the simulation's context. + * @returns A promise that resolves to an array of decoded outputs of the smart contract function calls, the format of which depends on the functions' return types. */ public async executeMultipleClausesCall( clauses: ContractClause[], options?: SimulateTransactionOptions - ): Promise> { + ): Promise { // Simulate the transaction to get the result of the contract call const response = await this.thor.transactions.simulateTransaction( clauses.map((clause) => clause.clause), options ); - // Returning an array of values. - // The viem format is a single value/JSON object (ABIFunction#decodeResult) + // Returning the decoded results both as plain and array. return response.map((res, index) => - clauses[index].functionAbi.decodeOutputAsArray(Hex.of(res.data)) + this.getContractCallResult( + res.data, + clauses[index].functionAbi, + res.reverted + ) ); } @@ -226,7 +257,7 @@ class ContractsModule { * * @returns The base gas price in wei. */ - public async getBaseGasPrice(): Promise { + public async getBaseGasPrice(): Promise { return await this.executeCall( BUILT_IN_CONTRACTS.PARAMS_ADDRESS, ABIContract.ofAbi(BUILT_IN_CONTRACTS.PARAMS_ABI).getFunction('get'), diff --git a/packages/network/src/thor-client/contracts/model/contract-proxy.ts b/packages/network/src/thor-client/contracts/model/contract-proxy.ts index 747b67f21..e45339415 100644 --- a/packages/network/src/thor-client/contracts/model/contract-proxy.ts +++ b/packages/network/src/thor-client/contracts/model/contract-proxy.ts @@ -5,7 +5,10 @@ import { Units, VET } from '@vechain/sdk-core'; -import { InvalidTransactionField } from '@vechain/sdk-errors'; +import { + ContractCallError, + InvalidTransactionField +} from '@vechain/sdk-errors'; import type { Abi, AbiEvent, @@ -17,7 +20,7 @@ import type { import { type VeChainSigner } from '../../../signer'; import { type FilterCriteria } from '../../logs'; import { type SendTransactionResult } from '../../transactions/types'; -import { type ContractCallResult, type ContractClause } from '../types'; +import { type ContractClause } from '../types'; import { type Contract } from './contract'; import { ContractFilter } from './contract-filter'; import { @@ -48,7 +51,7 @@ function getReadProxy( ExtractAbiFunction['inputs'], 'inputs' > - ): Promise => { + ): Promise => { // check if the clause comment is provided as an argument const extractOptionsResult = extractAndRemoveAdditionalOptions( @@ -61,21 +64,35 @@ function getReadProxy( const revisionValue = extractOptionsResult.clauseAdditionalOptions?.revision; - return (await contract.thor.contracts.executeCall( - contract.address, - contract.getFunctionAbi(prop), - extractOptionsResult.args, - { - caller: - contract.getSigner() !== undefined - ? await contract.getSigner()?.getAddress() - : undefined, - ...contract.getContractReadOptions(), - comment: clauseComment, - revision: revisionValue, - includeABI: true - } - )) as ContractCallResult; + const functionAbi = contract.getFunctionAbi(prop); + + const executeCallResult = + await contract.thor.contracts.executeCall( + contract.address, + functionAbi, + extractOptionsResult.args, + { + caller: + contract.getSigner() !== undefined + ? await contract.getSigner()?.getAddress() + : undefined, + ...contract.getContractReadOptions(), + comment: clauseComment, + revision: revisionValue, + includeABI: true + } + ); + + if (!executeCallResult.success) { + throw new ContractCallError( + functionAbi.stringSignature, + executeCallResult.result.errorMessage as string, + { + contractAddress: contract.address + } + ); + } + return executeCallResult.result.array as unknown[]; }; } }); diff --git a/packages/network/src/thor-client/contracts/types.d.ts b/packages/network/src/thor-client/contracts/types.d.ts index 2caf0ea81..bc25d82c6 100644 --- a/packages/network/src/thor-client/contracts/types.d.ts +++ b/packages/network/src/thor-client/contracts/types.d.ts @@ -43,7 +43,14 @@ type ContractCallOptions = SimulateTransactionOptions & ClauseOptions; /** * Represents the result of a contract call operation, encapsulating the output of the call. */ -type ContractCallResult = unknown[]; +interface ContractCallResult { + success: boolean; + result: { + plain?: unknown; // Success result as a plain value (might be literal or object). + array?: unknown[]; // Success result as an array (values are the same as in plain). + errorMessage?: string; + }; +} /** * Represents a contract clause, which includes the clause and the corresponding function ABI. diff --git a/packages/network/src/utils/vns/index.ts b/packages/network/src/utils/vns/index.ts index e01aac93b..a688e2dcf 100644 --- a/packages/network/src/utils/vns/index.ts +++ b/packages/network/src/utils/vns/index.ts @@ -42,14 +42,16 @@ const resolveNames = async ( const resolveUtilsAddress = NetworkContracts[genesisBlock.id].resolveUtils; // use the resolveUtils to lookup names - const [addresses] = (await thorClient.contracts.executeCall( + const callGetAddresses = await thorClient.contracts.executeCall( resolveUtilsAddress, ABIItem.ofSignature( ABIFunction, 'function getAddresses(string[] names) returns (address[] addresses)' ), [names] - )) as string[][]; + ); + + const [addresses] = callGetAddresses.result.array as string[][]; return addresses.map((address) => { // zero addresses are missing configuration entries @@ -101,14 +103,16 @@ const lookupAddresses = async ( const resolveUtilsAddress = NetworkContracts[genesisBlock.id].resolveUtils; // use the resolveUtils to lookup names - const [names] = (await thorClient.contracts.executeCall( + const callGetNames = await thorClient.contracts.executeCall( resolveUtilsAddress, ABIItem.ofSignature( ABIFunction, 'function getNames(address[] addresses) returns (string[] names)' ), [addresses] - )) as string[][]; + ); + + const [names] = callGetNames.result.array as string[][]; return names.map((name) => { // empty strings indicate a missing entry diff --git a/packages/network/tests/thor-client/contracts/contract.erc20.solo.test.ts b/packages/network/tests/thor-client/contracts/contract.erc20.solo.test.ts index 50eea22e2..8dce9b158 100644 --- a/packages/network/tests/thor-client/contracts/contract.erc20.solo.test.ts +++ b/packages/network/tests/thor-client/contracts/contract.erc20.solo.test.ts @@ -1,4 +1,5 @@ import { beforeEach, describe, expect, test } from '@jest/globals'; +import { Address, ERC20_ABI, HexUInt } from '@vechain/sdk-core'; import { ProviderInternalBaseWallet, THOR_SOLO_URL, @@ -10,7 +11,6 @@ import { } from '../../../src'; import { TEST_ACCOUNTS } from '../../fixture'; import { erc20ContractBytecode } from './fixture'; -import { Address, ERC20_ABI, HexUInt } from '@vechain/sdk-core'; /** * Tests for the ThorClient class, specifically focusing on ERC20 contract-related functionality. @@ -131,7 +131,7 @@ describe('ThorClient - ERC20 Contracts', () => { // Ensure that the transfer transaction was successful and the balance is as expected expect(transactionReceiptTransfer.reverted).toBe(false); - expect(balanceOfResult).toEqual([BigInt(1000)]); + expect(balanceOfResult).toEqual([1000n]); }, 10000); // Set a timeout of 10000ms for this test test('Execute ERC20 contract operations with comments', async () => { @@ -168,7 +168,7 @@ describe('ThorClient - ERC20 Contracts', () => { // Ensure that the transfer transaction was successful and the balance is as expected expect(transactionReceiptTransfer.reverted).toBe(false); - expect(balanceOfResult).toEqual([BigInt(1000)]); + expect(balanceOfResult).toEqual([1000n]); }, 10000); // Set a timeout of 10000ms for this test test('Execute ERC20 contract operations with revision', async () => { @@ -205,7 +205,7 @@ describe('ThorClient - ERC20 Contracts', () => { // Ensure that the transfer transaction was successful and the balance is as expected expect(transactionReceiptTransfer.reverted).toBe(false); - expect(balanceOfResult).toEqual([BigInt(1000)]); + expect(balanceOfResult).toEqual([1000n]); }, 10000); /** @@ -269,7 +269,7 @@ describe('ThorClient - ERC20 Contracts', () => { await contract.read.balanceOf( TEST_ACCOUNTS.TRANSACTION.DELEGATOR.address ) - ).toEqual([BigInt(1000)]); + ).toEqual([1000n]); }, 10000); /** @@ -294,9 +294,27 @@ describe('ThorClient - ERC20 Contracts', () => { contract.clause.decimals() ]); - expect(contractRead[0]).toEqual(['SampleToken']); - expect(contractRead[1]).toEqual(['ST']); - expect(contractRead[2]).toEqual([18]); + expect(contractRead[0]).toEqual({ + success: true, + result: { + plain: 'SampleToken', + array: ['SampleToken'] + } + }); + expect(contractRead[1]).toEqual({ + success: true, + result: { + plain: 'ST', + array: ['ST'] + } + }); + expect(contractRead[2]).toEqual({ + success: true, + result: { + plain: 18, + array: [18] + } + }); }, 10000); /** @@ -321,9 +339,27 @@ describe('ThorClient - ERC20 Contracts', () => { contract.clause.decimals() ]); - expect(contractRead[0]).toEqual(['SampleToken']); - expect(contractRead[1]).toEqual(['ST']); - expect(contractRead[2]).toEqual([18]); + expect(contractRead[0]).toEqual({ + success: true, + result: { + plain: 'SampleToken', + array: ['SampleToken'] + } + }); + expect(contractRead[1]).toEqual({ + success: true, + result: { + plain: 'ST', + array: ['ST'] + } + }); + expect(contractRead[2]).toEqual({ + success: true, + result: { + plain: 18, + array: [18] + } + }); }, 10000); /** @@ -377,9 +413,21 @@ describe('ThorClient - ERC20 Contracts', () => { ] ); - expect(reads[0]).toEqual([BigInt(1000)]); + expect(reads[0]).toEqual({ + success: true, + result: { + plain: 1000n, + array: [1000n] + } + }); - expect(reads[1]).toEqual([BigInt(4000)]); + expect(reads[1]).toEqual({ + success: true, + result: { + plain: 4000n, + array: [4000n] + } + }); }, 10000); /** @@ -412,6 +460,6 @@ describe('ThorClient - ERC20 Contracts', () => { await contract.read.balanceOf( TEST_ACCOUNTS.TRANSACTION.DELEGATOR.address ) - ).toEqual([BigInt(1000)]); + ).toEqual([1000n]); }, 30000); }); diff --git a/packages/network/tests/thor-client/contracts/contract.solo.test.ts b/packages/network/tests/thor-client/contracts/contract.solo.test.ts index d02a9b151..a2a55a8d1 100644 --- a/packages/network/tests/thor-client/contracts/contract.solo.test.ts +++ b/packages/network/tests/thor-client/contracts/contract.solo.test.ts @@ -1,12 +1,13 @@ /* eslint-disable */ import { beforeEach, describe, expect, test } from '@jest/globals'; -import { ABIContract, Address, HexUInt, type DeployParams } from '@vechain/sdk-core'; +import { ABIContract, Address, type DeployParams, HexUInt } from '@vechain/sdk-core'; import { CannotFindTransaction, ContractDeploymentFailed, InvalidTransactionField } from '@vechain/sdk-errors'; +import { fail } from 'assert'; import { Contract, type ContractFactory, @@ -227,7 +228,7 @@ describe('ThorClient - Contracts', () => { const callFunctionGetResult = await contract.read.get(); - expect(callFunctionGetResult).toEqual([BigInt(123)]); + expect(callFunctionGetResult).toEqual([123n]); }, 10000); /** @@ -241,7 +242,7 @@ describe('ThorClient - Contracts', () => { const contract = await factory.waitForDeployment(); await (await contract.transact.set(123n)).wait(); - expect(await contract.read.get()).toEqual([BigInt(123)]); + expect(await contract.read.get()).toEqual([123n]); contract.setContractReadOptions({ caller: 'invalid address' }); @@ -258,7 +259,7 @@ describe('ThorClient - Contracts', () => { contract.clearContractTransactOptions(); await (await contract.transact.set(22323n)).wait(); - expect(await contract.read.get()).toEqual([BigInt(22323)]); + expect(await contract.read.get()).toEqual([22323n]); }, 15000); /** @@ -290,7 +291,7 @@ describe('ThorClient - Contracts', () => { const callFunctionGetResult = await contract.read.get(); - expect(callFunctionGetResult).toEqual([BigInt(123)]); + expect(callFunctionGetResult).toEqual([123n]); }, 10000); /** @@ -312,7 +313,7 @@ describe('ThorClient - Contracts', () => { // Call the get function of the loaded contract to verify that the stored value is 100 let callFunctionGetResult = await loadedContract.read.get(); - expect(callFunctionGetResult).toEqual([BigInt(100)]); + expect(callFunctionGetResult).toEqual([100n]); // Set the private key of the caller for signing transactions loadedContract.setSigner(contract.getSigner() as VeChainSigner); @@ -329,7 +330,7 @@ describe('ThorClient - Contracts', () => { callFunctionGetResult = await loadedContract.read.get(); // Assertion: The value should be 123 - expect(callFunctionGetResult).toEqual([BigInt(123)]); + expect(callFunctionGetResult).toEqual([123n]); }, 10000); /** @@ -429,7 +430,7 @@ describe('ThorClient - Contracts', () => { await deployedDepositContract.read.getBalance( TEST_ACCOUNTS.TRANSACTION.TRANSACTION_SENDER.address ) - ).toEqual([BigInt(1000)]); + ).toEqual([1000n]); }, 10000); test('Deploy a contract that returns two values', async () => { @@ -469,17 +470,28 @@ describe('ThorClient - Contracts', () => { const deployedContract = await factory.waitForDeployment(); - const secretData = await deployedContract.read.getSecretData(); + const [secretData] = await deployedContract.read.getSecretData(); - expect(secretData[0]).toEqual(42n); + expect(secretData).toEqual(42n); const loadedContract = thorSoloClient.contracts.load( deployedContract.address, OWNER_RESTRICTION_ABI, receiverSigner ); - const secretDataNotOwner = await loadedContract.read.getSecretData(); - expect(secretDataNotOwner).toEqual('Not the contract owner'); + try { + await loadedContract.read.getSecretData(); + fail('Should fail'); + } catch (error) { + if (error instanceof Error) { + expect(error.message).toEqual( + `Method 'getSecretData()' failed.` + + `\n-Reason: 'Not the contract owner'` + + `\n-Parameters: \n\t` + + `{\n "contractAddress": "${deployedContract.address}"\n}` + ); + } + } }); /** @@ -599,7 +611,7 @@ describe('ThorClient - Contracts', () => { ), params ); - expect(response).toBe(expected); + expect(response).toStrictEqual(expected); }); } ); @@ -797,8 +809,14 @@ describe('ThorClient - Contracts', () => { test('Should return the base gas price of the Solo network', async () => { const baseGasPrice = await thorSoloClient.contracts.getBaseGasPrice(); - expect(baseGasPrice).toEqual([1000000000000000n]); - expect(baseGasPrice).toEqual([BigInt(10 ** 15)]); // 10^13 wei + expect(baseGasPrice).toEqual( { + success: true, + result: { plain: 1000000000000000n, array: [1000000000000000n] } + }); + expect(baseGasPrice).toEqual( { + success: true, + result: { plain: BigInt(10 ** 15), array: [BigInt(10 ** 15)] } + }); // 10^13 wei }); }); }); diff --git a/packages/network/tests/thor-client/contracts/contract.testnet.test.ts b/packages/network/tests/thor-client/contracts/contract.testnet.test.ts index 2cabce075..2d0b7f4f7 100644 --- a/packages/network/tests/thor-client/contracts/contract.testnet.test.ts +++ b/packages/network/tests/thor-client/contracts/contract.testnet.test.ts @@ -19,7 +19,20 @@ describe('ThorClient - Gas Module', () => { */ test('Should return the base gas price of the Testnet', async () => { const baseGasPrice = await thorClient.contracts.getBaseGasPrice(); - expect(baseGasPrice).toEqual([10000000000000n]); - expect(baseGasPrice).toEqual([BigInt(10 ** 13)]); // 10^13 wei + const expected = { + success: true, + result: { + plain: 10000000000000n, + array: [10000000000000n] + } + }; + expect(baseGasPrice).toEqual(expected); + expect(baseGasPrice).toEqual({ + ...expected, + result: { + plain: BigInt(10 ** 13), + array: [BigInt(10 ** 13)] + } + }); // 10^13 wei }); }); diff --git a/packages/network/tests/thor-client/contracts/fixture.ts b/packages/network/tests/thor-client/contracts/fixture.ts index 4afc2a280..cdd428f60 100644 --- a/packages/network/tests/thor-client/contracts/fixture.ts +++ b/packages/network/tests/thor-client/contracts/fixture.ts @@ -322,7 +322,13 @@ const erc721ContractTestCases: TestCase[] = [ 'should get the current NFT balance of the CONTRACT_MANAGER address', functionName: 'balanceOf', params: [TEST_ACCOUNTS.TRANSACTION.CONTRACT_MANAGER.address], - expected: [2n], + expected: { + success: true, + result: { + plain: 2n, + array: [2n] + } + }, reverted: false, isReadOnly: true }, @@ -331,7 +337,13 @@ const erc721ContractTestCases: TestCase[] = [ 'should get the current NFT balance of the DELEGATOR address', functionName: 'balanceOf', params: [TEST_ACCOUNTS.TRANSACTION.DELEGATOR.address], - expected: [1n], + expected: { + success: true, + result: { + plain: 1n, + array: [1n] + } + }, reverted: false, isReadOnly: true }, @@ -360,7 +372,13 @@ const erc721ContractTestCases: TestCase[] = [ 'should get the current NFT balance of the CONTRACT_MANAGER address', functionName: 'balanceOf', params: [TEST_ACCOUNTS.TRANSACTION.CONTRACT_MANAGER.address], - expected: [1n], + expected: { + success: true, + result: { + plain: 1n, + array: [1n] + } + }, reverted: false, isReadOnly: true }, @@ -369,7 +387,13 @@ const erc721ContractTestCases: TestCase[] = [ 'should get the current NFT balance of the DELEGATOR address', functionName: 'balanceOf', params: [TEST_ACCOUNTS.TRANSACTION.DELEGATOR.address], - expected: [2n], + expected: { + success: true, + result: { + plain: 2n, + array: [2n] + } + }, reverted: false, isReadOnly: true } @@ -380,7 +404,7 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the bool value false', functionName: 'boolData', params: [false], - expected: [false], + expected: { result: { array: [false], plain: false }, success: true }, reverted: false, isReadOnly: true }, @@ -388,7 +412,7 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the bool value true', functionName: 'boolData', params: [true], - expected: [true], + expected: { result: { array: [true], plain: true }, success: true }, reverted: false, isReadOnly: true }, @@ -396,7 +420,7 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the int value 1', functionName: 'intData', params: [1], - expected: [1n], + expected: { result: { array: [1n], plain: 1n }, success: true }, reverted: false, isReadOnly: true }, @@ -404,7 +428,7 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the int value -1', functionName: 'intData', params: [-1], - expected: [-1n], + expected: { result: { array: [-1n], plain: -1n }, success: true }, reverted: false, isReadOnly: true }, @@ -412,7 +436,7 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the int value 0', functionName: 'intData', params: [0], - expected: [0n], + expected: { result: { array: [0n], plain: 0n }, success: true }, reverted: false, isReadOnly: true }, @@ -420,7 +444,7 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the uint value 0', functionName: 'uintData', params: [0], - expected: [0n], + expected: { result: { array: [0n], plain: 0n }, success: true }, reverted: false, isReadOnly: true }, @@ -428,7 +452,7 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the uint value 1', functionName: 'uintData', params: [1], - expected: [1n], + expected: { result: { array: [1n], plain: 1n }, success: true }, reverted: false, isReadOnly: true }, @@ -437,7 +461,13 @@ const testingContractTestCases: TestCase[] = [ 'should return the address value 0x0000000000000000000000000000000000000000', functionName: 'addressData', params: ['0x0000000000000000000000000000000000000000'], - expected: ['0x0000000000000000000000000000000000000000'], + expected: { + result: { + array: ['0x0000000000000000000000000000000000000000'], + plain: '0x0000000000000000000000000000000000000000' + }, + success: true + }, reverted: false, isReadOnly: true }, @@ -448,9 +478,15 @@ const testingContractTestCases: TestCase[] = [ params: [ '0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0' ], - expected: [ - '0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0' - ], + expected: { + result: { + array: [ + '0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0' + ], + plain: '0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0' + }, + success: true + }, reverted: false, isReadOnly: true }, @@ -458,7 +494,7 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the string value "a"', functionName: 'stringData', params: ['a'], - expected: ['a'], + expected: { result: { array: ['a'], plain: 'a' }, success: true }, reverted: false, isReadOnly: true }, @@ -466,7 +502,10 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the passed fixed array', functionName: 'fixedArrayData', params: [[123, 456, 789]], - expected: [[123n, 456n, 789n]], + expected: { + result: { array: [[123n, 456n, 789n]], plain: [123n, 456n, 789n] }, + success: true + }, reverted: false, isReadOnly: true }, @@ -474,7 +513,13 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the passed dynamic array', functionName: 'dynamicArrayData', params: [[123, 456, 789, 323, 123]], - expected: [[123n, 456n, 789n, 323n, 123n]], + expected: { + result: { + array: [[123n, 456n, 789n, 323n, 123n]], + plain: [123n, 456n, 789n, 323n, 123n] + }, + success: true + }, reverted: false, isReadOnly: true }, @@ -482,7 +527,13 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the passed struct', functionName: 'structData', params: [{ id: 10, name: 'test' }], - expected: [[10n, 'test']], + expected: { + result: { + array: [[10n, 'test']], + plain: { id: 10n, name: 'test' } + }, + success: true + }, reverted: false, isReadOnly: true }, @@ -490,7 +541,10 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the passed enum', functionName: 'enumData', params: [ExampleEnum.SMALL], - expected: [ExampleEnum.SMALL], + expected: { + result: { array: [ExampleEnum.SMALL], plain: ExampleEnum.SMALL }, + success: true + }, reverted: false, isReadOnly: true }, @@ -507,16 +561,31 @@ const testingContractTestCases: TestCase[] = [ { id: 10, name: 'test' }, ExampleEnum.SMALL ], - expected: [ - 1n, - '0x0000000000000000000000000000000000000000', - '0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0', - 'a', - [123n, 456n, 789n], - [123n, 456n, 789n, 323n, 123n], - [10n, 'test'], - ExampleEnum.SMALL - ], + expected: { + result: { + array: [ + 1n, + '0x0000000000000000000000000000000000000000', + '0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0', + 'a', + [123n, 456n, 789n], + [123n, 456n, 789n, 323n, 123n], + [10n, 'test'], + ExampleEnum.SMALL + ], + plain: [ + 1n, + '0x0000000000000000000000000000000000000000', + '0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0', + 'a', + [123n, 456n, 789n], + [123n, 456n, 789n, 323n, 123n], + { id: 10n, name: 'test' }, + 0 + ] + }, + success: true + }, reverted: false, isReadOnly: true }, @@ -524,7 +593,13 @@ const testingContractTestCases: TestCase[] = [ description: 'should return the passed multiple int values', functionName: 'multipleIntData', params: [1, 222, 333, 287274, 390343843, 123223663], - expected: [1, 222, 333, 287274n, 390343843n, 123223663n], + expected: { + result: { + array: [1, 222, 333, 287274n, 390343843n, 123223663n], + plain: [1, 222, 333, 287274n, 390343843n, 123223663n] + }, + success: true + }, reverted: false, isReadOnly: true } @@ -535,7 +610,10 @@ const testingContractNegativeTestCases: TestCase[] = [ description: 'testRequireError() test', functionName: 'testRequireError', params: [8], - expected: 'Value must be greater than 10', + expected: { + result: { errorMessage: 'Value must be greater than 10' }, + success: false + }, reverted: true, isReadOnly: true }, @@ -543,7 +621,7 @@ const testingContractNegativeTestCases: TestCase[] = [ description: 'testAssertError() test', functionName: 'testAssertError', params: [1], - expected: 'Panic(0x01)', + expected: { result: { errorMessage: 'Panic(0x01)' }, success: false }, reverted: true, isReadOnly: true }, @@ -551,7 +629,10 @@ const testingContractNegativeTestCases: TestCase[] = [ description: 'testRevertError() test', functionName: 'testRevertError', params: [4], - expected: 'Value must be at least 5', + expected: { + result: { errorMessage: 'Value must be at least 5' }, + success: false + }, reverted: true, isReadOnly: true }, @@ -559,7 +640,7 @@ const testingContractNegativeTestCases: TestCase[] = [ description: 'testOverflowError() test', functionName: 'testOverflowError', params: [255], - expected: 'Panic(0x11)', + expected: { result: { errorMessage: 'Panic(0x11)' }, success: false }, reverted: true, isReadOnly: true }, @@ -567,7 +648,7 @@ const testingContractNegativeTestCases: TestCase[] = [ description: 'testInvalidOpcodeError() test', functionName: 'testInvalidOpcodeError', params: [], - expected: '', + expected: { result: { errorMessage: '' }, success: false }, reverted: true, isReadOnly: true } @@ -578,9 +659,15 @@ const testingContractEVMExtensionTestCases: TestCase[] = [ description: 'should return the blockID of the given block number', functionName: 'getBlockID', params: [1], - expected: [ - '0x00000001fb5387f59d35a8e76dcce151cb229a3910ac5f4731ff55f7ca36a809' - ], + expected: { + result: { + array: [ + '0x00000001fb5387f59d35a8e76dcce151cb229a3910ac5f4731ff55f7ca36a809' + ], + plain: '0x00000001fb5387f59d35a8e76dcce151cb229a3910ac5f4731ff55f7ca36a809' + }, + success: true + }, reverted: false, isReadOnly: true }, @@ -589,7 +676,7 @@ const testingContractEVMExtensionTestCases: TestCase[] = [ 'should return the block total score of the given block defined by the block number', functionName: 'getBlockTotalScore', params: [1], - expected: [1n], + expected: { result: { array: [1n], plain: 1n }, success: true }, reverted: false, isReadOnly: true }, @@ -597,7 +684,10 @@ const testingContractEVMExtensionTestCases: TestCase[] = [ description: 'should return the block time of the given block number', functionName: 'getBlockTime', params: [1], - expected: [1702231120n], + expected: { + result: { array: [1702231120n], plain: 1702231120n }, + success: true + }, reverted: false, isReadOnly: true }, @@ -605,7 +695,13 @@ const testingContractEVMExtensionTestCases: TestCase[] = [ description: 'should return the block signer of the given block number', functionName: 'getBlockSigner', params: [1], - expected: ['0xf077b491b355E64048cE21E3A6Fc4751eEeA77fa'], + expected: { + result: { + array: ['0xf077b491b355E64048cE21E3A6Fc4751eEeA77fa'], + plain: '0xf077b491b355E64048cE21E3A6Fc4751eEeA77fa' + }, + success: true + }, reverted: false, isReadOnly: true }, @@ -613,7 +709,13 @@ const testingContractEVMExtensionTestCases: TestCase[] = [ description: 'should return the total supply of VET', functionName: 'getTotalSupply', params: [], - expected: [10000000000000000000000000000n], + expected: { + result: { + array: [10000000000000000000000000000n], + plain: 10000000000000000000000000000n + }, + success: true + }, reverted: false, isReadOnly: true }, @@ -622,7 +724,7 @@ const testingContractEVMExtensionTestCases: TestCase[] = [ 'should return the `provedWork` of the current transaction', functionName: 'getTxProvedWork', params: [], - expected: [0n], + expected: { result: { array: [0n], plain: 0n }, success: true }, reverted: false, isReadOnly: true }, @@ -631,9 +733,15 @@ const testingContractEVMExtensionTestCases: TestCase[] = [ 'should return the transaction ID of the current transaction', functionName: 'getTxID', params: [], - expected: [ - '0x0000000000000000000000000000000000000000000000000000000000000000' - ], + expected: { + result: { + array: [ + '0x0000000000000000000000000000000000000000000000000000000000000000' + ], + plain: '0x0000000000000000000000000000000000000000000000000000000000000000' + }, + success: true + }, reverted: false, isReadOnly: true }, @@ -641,7 +749,13 @@ const testingContractEVMExtensionTestCases: TestCase[] = [ description: 'should return the `blockRef` of the current transaction', functionName: 'getTxBlockRef', params: [], - expected: ['0x0000000000000000'], + expected: { + result: { + array: ['0x0000000000000000'], + plain: '0x0000000000000000' + }, + success: true + }, reverted: false, isReadOnly: true }, @@ -650,7 +764,7 @@ const testingContractEVMExtensionTestCases: TestCase[] = [ 'should return the `expiration` of the current transaction', functionName: 'getTxExpiration', params: [], - expected: [0n], + expected: { result: { array: [0n], plain: 0n }, success: true }, reverted: false, isReadOnly: true }, @@ -658,9 +772,15 @@ const testingContractEVMExtensionTestCases: TestCase[] = [ description: 'should return the data hashed using Blake2b256', functionName: 'calculateBlake2b256', params: ['0x'], - expected: [ - '0x0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' - ], + expected: { + result: { + array: [ + '0x0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + ], + plain: '0x0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + }, + success: true + }, reverted: false, isReadOnly: true } @@ -3700,12 +3820,12 @@ export { multipleClausesTestCases, OWNER_RESTRICTION_ABI, OWNER_RESTRICTION_BYTECODE, + sampleTwoValuesReturnAbi, + sampleTwoValuesReturnBytecode, testingContractEVMExtensionTestCases, testingContractNegativeTestCases, testingContractTestCases, TESTNET_DELEGATE_URL, xAllocationAddress, - xAllocationVotingGovernorABI, - sampleTwoValuesReturnAbi, - sampleTwoValuesReturnBytecode + xAllocationVotingGovernorABI }; diff --git a/packages/network/tests/utils/subscriptions/subscriptions.solo.test.ts b/packages/network/tests/utils/subscriptions/subscriptions.solo.test.ts index 8ce59a5af..134071569 100644 --- a/packages/network/tests/utils/subscriptions/subscriptions.solo.test.ts +++ b/packages/network/tests/utils/subscriptions/subscriptions.solo.test.ts @@ -6,8 +6,8 @@ import { Hex, HexUInt, Transaction, - Units, - type TransactionClause + type TransactionClause, + Units } from '@vechain/sdk-core'; import { type AbiEvent } from 'abitype'; import { @@ -29,6 +29,7 @@ import { } from '../../fixture'; // eslint-disable-next-line import/no-named-default import { default as NodeWebSocket } from 'isomorphic-ws'; +import { expectType } from 'tsd'; const TIMEOUT = 15000; // 15-second timeout @@ -173,12 +174,18 @@ describe('Subscriptions Solo network tests', () => { ) } ); - const decodedLogValues = Object.values( - decodedLog.args as unknown[] - ); - expect(decodedLogValues.length).toBe(4); - expect(decodedLogValues[2]).toBe( + expectType<{ + eventName: 'StateChanged'; + args: { + newValue: bigint; + oldValue: bigint; + sender: string; + timestamp: bigint; + }; + }>(decodedLog); + expect(Object.keys(decodedLog.args).length).toBe(4); + expect(decodedLog.args.sender).toBe( Address.checksum( HexUInt.of( TEST_ACCOUNTS.SUBSCRIPTION diff --git a/yarn.lock b/yarn.lock index 9374a301c..77abf5f68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3332,6 +3332,11 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@tsd/typescript@~5.4.3": + version "5.4.5" + resolved "https://registry.yarnpkg.com/@tsd/typescript/-/typescript-5.4.5.tgz#a7c11d3a97ddfa201f831f4e4270a169a87f7655" + integrity sha512-saiCxzHRhUrRxQV2JhH580aQUZiKQUXI38FcAcikcfOomAil4G4lxT0RfrrKywoAYP/rqAdYXYmNRLppcd+hQQ== + "@typechain/ethers-v6@^0.5.0": version "0.5.1" resolved "https://registry.yarnpkg.com/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz#42fe214a19a8b687086c93189b301e2b878797ea" @@ -3469,7 +3474,15 @@ "@types/node" "*" "@types/ssh2" "*" -"@types/estree@1.0.6", "@types/estree@^1.0.0": +"@types/eslint@^7.2.13": + version "7.29.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78" + integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@1.0.6", "@types/estree@^1.0.0": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== @@ -3572,6 +3585,11 @@ "@types/tough-cookie" "*" parse5 "^7.0.0" +"@types/json-schema@*": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" @@ -3606,6 +3624,11 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== +"@types/minimist@^1.2.0": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" + integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== + "@types/mocha@>=9.1.0": version "10.0.8" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.8.tgz#a7eff5816e070c3b4d803f1d3cd780c4e42934a1" @@ -3654,6 +3677,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== +"@types/normalize-package-data@^2.4.0": + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" + integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== + "@types/pbkdf2@^3.0.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc" @@ -4389,6 +4417,11 @@ arraybuffer.prototype.slice@^1.0.3: is-array-buffer "^3.0.4" is-shared-array-buffer "^1.0.2" +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + as-table@^1.0.36: version "1.0.55" resolved "https://registry.yarnpkg.com/as-table/-/as-table-1.0.55.tgz#dc984da3937745de902cea1d45843c01bdbbec4f" @@ -4921,6 +4954,15 @@ camelcase-css@^2.0.1: resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== +camelcase-keys@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -5605,7 +5647,15 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -decamelize@^1.2.0: +decamelize-keys@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" + integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== @@ -6276,6 +6326,20 @@ eslint-config-standard@17.1.0: resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz#40ffb8595d47a6b242e07cbfd49dc211ed128975" integrity sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q== +eslint-formatter-pretty@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/eslint-formatter-pretty/-/eslint-formatter-pretty-4.1.0.tgz#7a6877c14ffe2672066c853587d89603e97c7708" + integrity sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ== + dependencies: + "@types/eslint" "^7.2.13" + ansi-escapes "^4.2.1" + chalk "^4.1.0" + eslint-rule-docs "^1.1.5" + log-symbols "^4.0.0" + plur "^4.0.0" + string-width "^4.2.0" + supports-hyperlinks "^2.0.0" + eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: version "0.3.9" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" @@ -6426,6 +6490,11 @@ eslint-plugin-react@^7.33.2: string.prototype.matchall "^4.0.11" string.prototype.repeat "^1.0.0" +eslint-rule-docs@^1.1.5: + version "1.1.235" + resolved "https://registry.yarnpkg.com/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz#be6ef1fc3525f17b3c859ae2997fedadc89bfb9b" + integrity sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A== + eslint-scope@^7.2.2: version "7.2.2" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" @@ -7387,7 +7456,7 @@ globby@^10.0.1: merge2 "^1.2.3" slash "^3.0.0" -globby@^11.0.0, globby@^11.1.0: +globby@^11.0.0, globby@^11.0.1, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -7428,6 +7497,11 @@ handlebars@^4.0.1: optionalDependencies: uglify-js "^3.1.4" +hard-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + hardhat-gas-reporter@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz#ebe5bda5334b5def312747580cd923c2b09aef1b" @@ -7614,6 +7688,18 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +hosted-git-info@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== + dependencies: + lru-cache "^6.0.0" + html-encoding-sniffer@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" @@ -7805,6 +7891,11 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +irregular-plurals@^3.2.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-3.5.0.tgz#0835e6639aa8425bdc8b0d33d0dc4e89d9c01d2b" + integrity sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ== + is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -7874,7 +7965,7 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.12.1, is-core-module@^2.13.0, is-core-module@^2.15.1: +is-core-module@^2.12.1, is-core-module@^2.13.0, is-core-module@^2.15.1, is-core-module@^2.5.0: version "2.15.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== @@ -7973,6 +8064,11 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + is-plain-obj@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" @@ -8299,7 +8395,7 @@ jest-config@^29.7.0: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@^29.7.0: +jest-diff@^29.0.3, jest-diff@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== @@ -8785,7 +8881,7 @@ keyv@^4.5.3: dependencies: json-buffer "3.0.1" -kind-of@^6.0.2: +kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -8971,7 +9067,7 @@ lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@^4.1.0: +log-symbols@^4.0.0, log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -9018,6 +9114,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + lru_map@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" @@ -9073,6 +9176,16 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== + +map-obj@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== + markdown-it@^14.1.0: version "14.1.0" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45" @@ -9134,6 +9247,24 @@ meow@^12.0.1: resolved "https://registry.yarnpkg.com/meow/-/meow-12.1.1.tgz#e558dddbab12477b69b2e9a2728c327f191bace6" integrity sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw== +meow@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize "^1.2.0" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + merge-descriptors@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" @@ -9287,6 +9418,15 @@ minimatch@^9.0.1, minimatch@^9.0.4, minimatch@^9.0.5: 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" + integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + kind-of "^6.0.3" + minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -9487,6 +9627,26 @@ nopt@3.x: dependencies: abbrev "1" +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-package-data@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" + integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== + dependencies: + hosted-git-info "^4.0.1" + is-core-module "^2.5.0" + semver "^7.3.4" + validate-npm-package-license "^3.0.1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -9826,7 +9986,7 @@ parse-cache-control@^1.0.1: resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" integrity sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg== -parse-json@^5.2.0: +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -9964,6 +10124,13 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +plur@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/plur/-/plur-4.0.0.tgz#729aedb08f452645fe8c58ef115bf16b0a73ef84" + integrity sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg== + dependencies: + irregular-plurals "^3.2.0" + possible-typed-array-names@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" @@ -10235,6 +10402,11 @@ queue-tick@^1.0.1: resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag== +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -10294,6 +10466,25 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" +read-pkg-up@^7.0.0, read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + read-yaml-file@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-yaml-file/-/read-yaml-file-1.1.0.tgz#9362bbcbdc77007cc8ea4519fe1c0b821a7ce0d8" @@ -10501,7 +10692,7 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.20.0, resolve@^1.22.2, resolve@^1.22.4, resolve@^1.22.8: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.2, resolve@^1.22.4, resolve@^1.22.8: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -10701,7 +10892,7 @@ selfsigned@^2.0.1: "@types/node-forge" "^1.3.0" node-forge "^1" -semver@^5.5.0: +"semver@2 || 3 || 4 || 5", semver@^5.5.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== @@ -11007,6 +11198,32 @@ spawndamnit@^2.0.0: cross-spawn "^5.1.0" signal-exit "^3.0.2" +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.20" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz#e44ed19ed318dd1e5888f93325cee800f0f51b89" + integrity sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw== + split-ca@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" @@ -11119,7 +11336,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -11136,15 +11353,6 @@ string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -11238,7 +11446,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -11252,13 +11460,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -11339,7 +11540,7 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: +supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== @@ -11353,6 +11554,14 @@ supports-color@^8.0.0, supports-color@^8.1.1: dependencies: has-flag "^4.0.0" +supports-hyperlinks@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -11689,6 +11898,11 @@ trim-lines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== +trim-newlines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" + integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== + ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" @@ -11766,6 +11980,19 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" +tsd@^0.31.2: + version "0.31.2" + resolved "https://registry.yarnpkg.com/tsd/-/tsd-0.31.2.tgz#9bfef86f43517e6e4b66973402daf17d094ae6d4" + integrity sha512-VplBAQwvYrHzVihtzXiUVXu5bGcr7uH1juQZ1lmKgkuGNGT+FechUCqmx9/zk7wibcqR2xaNEwCkDyKh+VVZnQ== + dependencies: + "@tsd/typescript" "~5.4.3" + eslint-formatter-pretty "^4.1.0" + globby "^11.0.1" + jest-diff "^29.0.3" + meow "^9.0.0" + path-exists "^4.0.0" + read-pkg-up "^7.0.0" + tslib@2.7.0, tslib@^2.2.0, tslib@^2.4.0, tslib@^2.6.2: version "2.7.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" @@ -11889,6 +12116,11 @@ type-detect@^4.0.0, type-detect@^4.1.0: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== +type-fest@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" + integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -11899,12 +12131,17 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + type-fest@^0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== -type-fest@^0.8.0: +type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== @@ -12202,6 +12439,14 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^2.0.0" +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -12523,7 +12768,7 @@ wrangler@3.82.0, wrangler@^3.72.3: optionalDependencies: fsevents "~2.3.2" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -12541,15 +12786,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -12647,6 +12883,11 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yaml@^2.2.2, yaml@^2.3.4, yaml@^2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.1.tgz#c9772aacf62cb7494a95b0c4f1fb065b563db130" @@ -12660,7 +12901,7 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^20.2.2, yargs-parser@^20.2.9: +yargs-parser@^20.2.2, yargs-parser@^20.2.3, yargs-parser@^20.2.9: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==