Skip to content

Commit

Permalink
feat(provider): pending response discrimination, pending type guards
Browse files Browse the repository at this point in the history
  • Loading branch information
tabaktoni committed Dec 13, 2023
1 parent 6b77f54 commit 013a22b
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 35 deletions.
34 changes: 12 additions & 22 deletions __tests__/defaultProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
} from './config/fixtures';
import { initializeMatcher } from './config/schema';

const { isPendingStateUpdate } = provider;

const testProvider = new Provider(getTestProvider());

describe('defaultProvider', () => {
Expand Down Expand Up @@ -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');
});
});

Expand Down
7 changes: 7 additions & 0 deletions src/provider/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ import {
Invocation,
InvocationsDetailsWithNonce,
PendingBlock,
PendingStateUpdate,
RPC,
RpcProviderOptions,
StateUpdate,
StateUpdateResponse,
TransactionType,
getContractVersionOptions,
getEstimateFeeBulkOptions,
Expand Down Expand Up @@ -94,6 +97,10 @@ export class RpcProvider implements ProviderInterface {

public getStateUpdate = this.getBlockStateUpdate;

public async getBlockStateUpdate(): Promise<PendingStateUpdate>;
public async getBlockStateUpdate(blockIdentifier: 'pending'): Promise<PendingStateUpdate>;
public async getBlockStateUpdate(blockIdentifier: 'latest'): Promise<StateUpdate>;
public async getBlockStateUpdate(blockIdentifier?: BlockIdentifier): Promise<StateUpdateResponse>;
public async getBlockStateUpdate(blockIdentifier?: BlockIdentifier) {
return this.channel.getBlockStateUpdate(blockIdentifier);
}
Expand Down
1 change: 1 addition & 0 deletions src/types/api/rpcspec_0_6/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
2 changes: 0 additions & 2 deletions src/types/provider/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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;
Expand Down
42 changes: 31 additions & 11 deletions src/utils/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

0 comments on commit 013a22b

Please sign in to comment.