diff --git a/__tests__/defaultProvider.test.ts b/__tests__/defaultProvider.test.ts index aae724900..0c85ca963 100644 --- a/__tests__/defaultProvider.test.ts +++ b/__tests__/defaultProvider.test.ts @@ -18,6 +18,8 @@ import { } from './config/fixtures'; import { initializeMatcher } from './config/schema'; +const { isPendingStateUpdate } = provider; + const testProvider = new Provider(getTestProvider()); describe('defaultProvider', () => { @@ -81,32 +83,20 @@ describe('defaultProvider', () => { test(`getStateUpdate(blockHash=${exampleBlockHash}, blockNumber=undefined)`, async () => { const stateUpdate = await testProvider.getStateUpdate(exampleBlockHash); - provider.defStateUpdate( - stateUpdate, - (state) => { - expect(state.block_hash).toBe(exampleBlockHash); - expect(state).toMatchSchemaRef('StateUpdateResponse'); - }, - (pending) => { - fail('exampleBlockHash is latest block, should not be pending'); - expect(pending).toMatchSchemaRef('PendingStateUpdateResponse'); - } - ); + if (!isPendingStateUpdate(stateUpdate)) { + fail('exampleBlockHash is latest block, should not be pending'); + } + expect(stateUpdate.block_hash).toBe(exampleBlockHash); + expect(stateUpdate).toMatchSchemaRef('StateUpdateResponse'); }); test(`getStateUpdate(blockHash=undefined, blockNumber=${exampleBlockNumber})`, async () => { const stateUpdate = await testProvider.getStateUpdate(exampleBlockNumber); - provider.defStateUpdate( - stateUpdate, - (state) => { - expect(state.block_hash).toBe(exampleBlockHash); - expect(state).toMatchSchemaRef('StateUpdateResponse'); - }, - (pending) => { - fail('exampleBlockHash is latest block, should not be pending'); - expect(pending).toMatchSchemaRef('PendingStateUpdateResponse'); - } - ); + if (isPendingStateUpdate(stateUpdate)) { + fail('exampleBlockHash is latest block, should not be pending'); + } + expect(stateUpdate.block_hash).toBe(exampleBlockHash); + expect(stateUpdate).toMatchSchemaRef('StateUpdateResponse'); }); }); diff --git a/src/provider/rpc.ts b/src/provider/rpc.ts index 44b5ae512..75757d005 100644 --- a/src/provider/rpc.ts +++ b/src/provider/rpc.ts @@ -13,8 +13,11 @@ import { Invocation, InvocationsDetailsWithNonce, PendingBlock, + PendingStateUpdate, RPC, RpcProviderOptions, + StateUpdate, + StateUpdateResponse, TransactionType, getContractVersionOptions, getEstimateFeeBulkOptions, @@ -94,6 +97,10 @@ export class RpcProvider implements ProviderInterface { public getStateUpdate = this.getBlockStateUpdate; + public async getBlockStateUpdate(): Promise; + public async getBlockStateUpdate(blockIdentifier: 'pending'): Promise; + public async getBlockStateUpdate(blockIdentifier: 'latest'): Promise; + public async getBlockStateUpdate(blockIdentifier?: BlockIdentifier): Promise; public async getBlockStateUpdate(blockIdentifier?: BlockIdentifier) { return this.channel.getBlockStateUpdate(blockIdentifier); } diff --git a/src/types/api/rpcspec_0_6/components.ts b/src/types/api/rpcspec_0_6/components.ts index c98f361b0..eadb87b24 100644 --- a/src/types/api/rpcspec_0_6/components.ts +++ b/src/types/api/rpcspec_0_6/components.ts @@ -134,6 +134,7 @@ export type STATE_DIFF = { export type PENDING_STATE_UPDATE = { old_root: FELT; state_diff: STATE_DIFF; + block_hash: never; // diverge: this make it distinct }; export type STATE_UPDATE = { diff --git a/src/types/provider/response.ts b/src/types/provider/response.ts index 43dad29d3..2ff3eded7 100644 --- a/src/types/provider/response.ts +++ b/src/types/provider/response.ts @@ -33,7 +33,6 @@ export type Block = { export type GetTransactionResponse = RPC.TransactionWithHash; -// TODO Check if can be pending discriminated export type GetTransactionReceiptResponse = RPC.Receipt | RPC.PendingReceipt; // Spread individual types for usage convenience export type InvokeTransactionReceiptResponse = @@ -80,7 +79,6 @@ export type SimulatedTransaction = RPC.SimulateTransaction & { export type SimulateTransactionResponse = SimulatedTransaction[]; -// TODO: Make discriminator key export type StateUpdateResponse = StateUpdate | PendingStateUpdate; export type StateUpdate = RPC.SPEC.STATE_UPDATE; export type PendingStateUpdate = RPC.SPEC.PENDING_STATE_UPDATE; diff --git a/src/utils/provider.ts b/src/utils/provider.ts index ddcb8db3d..aae71a90b 100644 --- a/src/utils/provider.ts +++ b/src/utils/provider.ts @@ -6,10 +6,15 @@ import { CompiledContract, CompiledSierra, ContractClass, + GetBlockResponse, + GetTransactionReceiptResponse, InvocationsDetailsWithNonce, LegacyContractClass, + PendingBlock, + PendingStateUpdate, RPC, SierraContractClass, + StateUpdateResponse, V3TransactionDetails, } from '../types'; import { ETransactionVersion } from '../types/api'; @@ -168,17 +173,6 @@ export class Block { } */ } -export function defStateUpdate( - state: RPC.SPEC.STATE_UPDATE | RPC.SPEC.PENDING_STATE_UPDATE, - accepted: (state: RPC.SPEC.STATE_UPDATE) => unknown, - pending: (state: RPC.SPEC.PENDING_STATE_UPDATE) => unknown -) { - if ('block_hash' in state) { - return accepted(state); - } - return pending(state); -} - export function isV3Tx(details: InvocationsDetailsWithNonce): details is V3TransactionDetails { const version = details.version ? toHex(details.version) : ETransactionVersion.V3; return version === ETransactionVersion.V3 || version === ETransactionVersion.F3; @@ -190,3 +184,29 @@ export function isVersion(version: '0.5' | '0.6', response: string) { return majorS === majorR && minorS === minorR; } + +/** + * Guard Pending Block + */ +export function isPendingBlock(response: GetBlockResponse): response is PendingBlock { + return response.status === 'PENDING'; +} + +/** + * Guard Pending Transaction + */ +export function isPendingTransaction( + response: GetTransactionReceiptResponse +): response is RPC.PendingReceipt { + return !('block_hash' in response); +} + +/** + * Guard Pending State Update + * ex. if(isPendingStateUpdate(stateUpdate)) throe Error('Update must be final') + */ +export function isPendingStateUpdate( + response: StateUpdateResponse +): response is PendingStateUpdate { + return !('block_hash' in response); +}