Repository: 0xs34n/starknet.js
Pull request #329 (2022-09-12 17:54:31)

RPC Improvements
## Motivation and Resolution
fix https://github.com/0xs34n/starknet.js/issues/306
fix https://github.com/0xs34n/starknet.js/issues/305
This is still work in progress branch but as it contains missing RPC endpoints it should be good to implement now and subsequential completion done later.

### RPC version (if applicable)
0.1.0

## Usage related changes

### Added missing RPC methods
- getBlockHashAndNumber
- getClassHashAt
- getPendingTransactions
- getProtocolVersion (with throw error as pathfinder didn't implement it)
- getStateUpdate
- getClass
- traceTransaction (without throw but expect not imeplelemned method resposen)
- traceBlockTransactions (without throw but expect not imeplelemned method resposen)

## Development related changes

### Utils Clenup

- BlockIdentifierClass, getIdentifier, getBlockIdentifier and getFormattedBlockIdentifier replaced with single Block Class. It is used both for RPC body identifier params and Sequencer query identifier params.

- Utils test block identifier

```
const block = new Block(blockIdentifier)
rpcparams = block.identifier
sequencerparams = block.queryIdentifier
```

### OpenRPC specification

- [X] Complete OpenRPC 0.1.0 specification
- [X] Complete mapping OpenRpc to RPC
- [X] Refactor current RPC fetch error handling
- [X] Expose RPC fetch as public for custom usage
- [ ] Refactor RPC Methods to OpenRPC method and implementation
- [ ] Refactor RPC fetch and methods to use an object instead of the sorted array.
- [ ] Merge RPC and OpenRPC 
- [X] Add missing test for RPC-specific endpoints
- [ ] Extend Fetch with expected and unexpected error response ex: "{message, code}" vs "1" in some cases
- [ ] Check valid types on all prev. implemented RPC methods (mostly for 'any')
- [ ] Refactor common interface response parser
- [ ] Update documentation

## Checklist:

- [x] Performed a self-review of the code
- [x] Rebased to the last commit of the target branch (or merged it into my branch)
- [x] Linked the issues which this PR resolves
- [ ] Documented the changes
- [ ] Updated the docs (www)
- [x] Updated the tests
- [x] All tests are passing



Patch:
diff --git a/src/provider/rpc.ts b/src/provider/rpc.ts
index 31d0dc38..34603285 100644
--- a/src/provider/rpc.ts
+++ b/src/provider/rpc.ts
@@ -29,13 +29,14 @@ import { parseCalldata, parseContract, wait } from '../utils/provider';
 import { RPCResponseParser } from '../utils/responseParser/rpc';
 import { randomAddress } from '../utils/stark';
 import { ProviderInterface } from './interface';
-import { BlockIdentifier, BlockIdentifierClass } from './utils';
+import { Block, BlockIdentifier } from './utils';
 
 export type RpcProviderOptions = { nodeUrl: string };
 
 export class RpcProvider implements ProviderInterface {
   public nodeUrl: string;
 
+  // from interface
   public chainId!: StarknetChainId;
 
   private responseParser = new RPCResponseParser();
@@ -49,87 +50,106 @@ export class RpcProvider implements ProviderInterface {
     });
   }
 
+  public fetch(method: any, params: any): Promise<any> {
+    return fetch(this.nodeUrl, {
+      method: 'POST',
+      body: stringify({ method, jsonrpc: '2.0', params, id: 0 }),
+      headers: { 'Content-Type': 'application/json' },
+    });
+  }
+
+  protected errorHandler(error: any) {
+    if (error) {
+      const { code, message } = error;
+      throw new Error(`${code}: ${message}`);
+    }
+  }
+
   protected async fetchEndpoint<T extends keyof RPC.Methods>(
     method: T,
     request?: RPC.Methods[T]['REQUEST']
   ): Promise<RPC.Methods[T]['RESPONSE']> {
-    const requestData = {
-      method,
-      jsonrpc: '2.0',
-      params: request,
-      id: 0,
-    };
-
     try {
-      const rawResult = await fetch(this.nodeUrl, {
-        method: 'POST',
-        body: stringify(requestData),
-        headers: {
-          'Content-Type': 'application/json',
-        },
-      });
+      const rawResult = await this.fetch(method, request);
       const { error, result } = await rawResult.json();
-      if (error) {
-        const { code, message } = error;
-        throw new Error(`${code}: ${message}`);
-      } else {
-        return result as RPC.Methods[T]['RESPONSE'];
-      }
+      this.errorHandler(error);
+      return result as RPC.Methods[T]['RESPONSE'];
     } catch (error: any) {
-      const data = error?.response?.data;
-      if (data?.message) {
-        throw new Error(`${data.code}: ${data.message}`);
-      }
+      this.errorHandler(error?.response?.data);
       throw error;
     }
   }
 
-  public async getChainId(): Promise<StarknetChainId> {
+  // Methods from Interface
+  public async getChainId(): Promise<any> {
     return this.fetchEndpoint('starknet_chainId');
   }
 
-  // Common Interface
+  // Methods from Interface
   public async getBlock(blockIdentifier: BlockIdentifier = 'pending'): Promise<GetBlockResponse> {
     return this.getBlockWithTxHashes(blockIdentifier).then(
       this.responseParser.parseGetBlockResponse
     );
   }
 
+  public async getBlockHashAndNumber(): Promise<RPC.BlockHashAndNumber> {
+    return this.fetchEndpoint('starknet_blockHashAndNumber');
+  }
+
   public async getBlockWithTxHashes(
     blockIdentifier: BlockIdentifier = 'pending'
   ): Promise<RPC.GetBlockWithTxHashesResponse> {
-    const blockIdentifierGetter = new BlockIdentifierClass(blockIdentifier);
-    return this.fetchEndpoint('starknet_getBlockWithTxHashes', [
-      blockIdentifierGetter.getIdentifier(),
-    ]);
+    const block = new Block(blockIdentifier);
+    return this.fetchEndpoint('starknet_getBlockWithTxHashes', [block.identifier]);
   }
 
   public async getBlockWithTxs(
     blockIdentifier: BlockIdentifier = 'pending'
   ): Promise<RPC.GetBlockWithTxs> {
-    const blockIdentifierGetter = new BlockIdentifierClass(blockIdentifier);
-    return this.fetchEndpoint('starknet_getBlockWithTxs', [blockIdentifierGetter.getIdentifier()]);
+    const block = new Block(blockIdentifier);
+    return this.fetchEndpoint('starknet_getBlockWithTxs', [block.identifier]);
+  }
+
+  public async getClassHashAt(
+    blockIdentifier: BlockIdentifier,
+    contractAddress: RPC.ContractAddress
+  ): Promise<RPC.Felt> {
+    const block = new Block(blockIdentifier);
+    return this.fetchEndpoint('starknet_getClassHashAt', [block.identifier, contractAddress]);
   }
 
   public async getNonce(contractAddress: string): Promise<any> {
     return this.fetchEndpoint('starknet_getNonce', [contractAddress]);
   }
 
+  public async getPendingTransactions(): Promise<RPC.PendingTransactions> {
+    return this.fetchEndpoint('starknet_pendingTransactions');
+  }
+
+  public async getProtocolVersion(): Promise<Error> {
+    throw new Error('Pathfinder does not implement this rpc 0.1.0 method');
+  }
+
+  public async getStateUpdate(blockIdentifier: BlockIdentifier): Promise<RPC.StateUpdate> {
+    const block = new Block(blockIdentifier);
+    return this.fetchEndpoint('starknet_getStateUpdate', [block.identifier]);
+  }
+
   public async getStorageAt(
     contractAddress: string,
     key: BigNumberish,
     blockIdentifier: BlockIdentifier = 'pending'
   ): Promise<BigNumberish> {
     const parsedKey = toHex(toBN(key));
-    const blockIdentifierGetter = new BlockIdentifierClass(blockIdentifier);
+    const block = new Block(blockIdentifier);
     return this.fetchEndpoint('starknet_getStorageAt', [
       contractAddress,
       parsedKey,
-      blockIdentifierGetter.getIdentifier(),
+      block.identifier,
     ]);
   }
 
-  // common interface
+  // Methods from Interface
   public async getTransaction(txHash: BigNumberish): Promise<GetTransactionResponse> {
     return this.getTransactionByHash(txHash).then(this.responseParser.parseGetTransactionResponse);
   }
@@ -144,7 +164,11 @@ export class RpcProvider implements ProviderInterface {
     blockIdentifier: BlockIdentifier,
     index: number
   ): Promise<RPC.GetTransactionByBlockIdAndIndex> {
-    return this.fetchEndpoint('starknet_getTransactionByHash', [blockIdentifier, index]);
+    const block = new Block(blockIdentifier);
+    return this.fetchEndpoint('starknet_getTransactionByBlockIdAndIndex', [
+      block.identifier,
+      index,
+    ]);
   }
 
   public async getTransactionReceipt(txHash: BigNumberish): Promise<GetTransactionReceiptResponse> {
@@ -153,12 +177,20 @@ export class RpcProvider implements ProviderInterface {
     );
   }
 
+  public async getClass(classHash: RPC.Felt): Promise<RPC.ContractClass> {
+    return this.fetchEndpoint('starknet_getClass', [classHash]);
+  }
+
   public async getClassAt(contractAddress: string, blockIdentifier: BlockIdentifier): Promise<any> {
-    const blockIdentifierGetter = new BlockIdentifierClass(blockIdentifier);
-    return this.fetchEndpoint('starknet_getClassAt', [
-      blockIdentifierGetter.getIdentifier(),
-      contractAddress,
-    ]);
+    const block = new Block(blockIdentifier);
+    return this.fetchEndpoint('starknet_getClassAt', [block.identifier, contractAddress]);
+  }
+
+  public async getCode(
+    _contractAddress: string,
+    _blockIdentifier?: BlockIdentifier
+  ): Promise<GetCodeResponse> {
+    throw new Error('RPC 0.1.0 does not implement getCode function');
   }
 
   public async getEstimateFee(
@@ -228,6 +260,7 @@ export class RpcProvider implements ProviderInterface {
     ]).then(this.responseParser.parseInvokeFunctionResponse);
   }
 
+  // Methods from Interface
   public async callContract(
     call: Call,
     blockIdentifier: BlockIdentifier = 'pending'
@@ -244,11 +277,12 @@ export class RpcProvider implements ProviderInterface {
     return this.responseParser.parseCallContractResponse(result);
   }
 
-  public async getCode(
-    _contractAddress: string,
-    _blockIdentifier?: BlockIdentifier
-  ): Promise<GetCodeResponse> {
-    throw new Error('RPC 0.1.0 does not implement getCode function');
+  public async traceTransaction(transactionHash: RPC.TransactionHash): Promise<RPC.Trace> {
+    return this.fetchEndpoint('starknet_traceTransaction', [transactionHash]);
+  }
+
+  public async traceBlockTransactions(blockHash: RPC.BlockHash): Promise<RPC.Traces> {
+    return this.fetchEndpoint('starknet_traceBlockTransactions', [blockHash]);
   }
 
   public async waitForTransaction(txHash: BigNumberish, retryInterval: number = 8000) {
@@ -299,10 +333,8 @@ export class RpcProvider implements ProviderInterface {
   public async getTransactionCount(
     blockIdentifier: BlockIdentifier
   ): Promise<RPC.GetTransactionCountResponse> {
-    const blockIdentifierGetter = new BlockIdentifierClass(blockIdentifier);
-    return this.fetchEndpoint('starknet_getBlockTransactionCount', [
-      blockIdentifierGetter.getIdentifier(),
-    ]);
+    const block = new Block(blockIdentifier);
+    return this.fetchEndpoint('starknet_getBlockTransactionCount', [block.identifier]);
   }
 
   /**
diff --git a/src/provider/sequencer.ts b/src/provider/sequencer.ts
index d7b0bda4..51a209fa 100644
--- a/src/provider/sequencer.ts
+++ b/src/provider/sequencer.ts
@@ -33,7 +33,7 @@ import { randomAddress } from '../utils/stark';
 import { buildUrl } from '../utils/url';
 import { GatewayError, HttpError } from './errors';
 import { ProviderInterface } from './interface';
-import { BlockIdentifier, getFormattedBlockIdentifier } from './utils';
+import { Block, BlockIdentifier } from './utils';
 
 type NetworkName = 'mainnet-alpha' | 'goerli-alpha';
 
@@ -129,7 +129,8 @@ export class SequencerProvider implements ProviderInterface {
     const queryString = Object.entries(query)
       .map(([key, value]) => {
         if (key === 'blockIdentifier') {
-          return `${getFormattedBlockIdentifier(value)}`;
+          const block = new Block(value);
+          return `${block.queryIdentifier}`;
         }
         return `${key}=${value}`;
       })
diff --git a/src/provider/utils.ts b/src/provider/utils.ts
index 7884e734..17ebb8f8 100644
--- a/src/provider/utils.ts
+++ b/src/provider/utils.ts
@@ -1,3 +1,4 @@
+/* eslint-disable max-classes-per-file */
 import type { BlockNumber } from '../types';
 import { BigNumberish, isHex, toBN, toHex } from '../utils/number';
 
@@ -33,73 +34,59 @@ export function txIdentifier(txHash?: BigNumberish, txId?: BigNumberish): string
 // null appends nothing to the request url
 
 export type BlockIdentifier = BlockNumber | BigNumberish;
-type BlockIdentifierObject =
-  | { type: 'BLOCK_NUMBER'; data: BlockNumber }
-  | { type: 'BLOCK_HASH'; data: BigNumberish };
 
-export class BlockIdentifierClass {
-  blockIdentifier: BlockIdentifier;
+export class Block {
+  hash: BlockIdentifier = null;
 
-  constructor(blockIdentifier: BlockIdentifier) {
-    this.blockIdentifier = blockIdentifier;
+  number: BlockIdentifier = null;
+
+  tag: BlockIdentifier = null;
+
+  private setIdentifier: (_identifier: BlockIdentifier) => void;
+
+  constructor(_identifier: BlockIdentifier) {
+    this.setIdentifier = function (__identifier: BlockIdentifier) {
+      if (typeof __identifier === 'string' && isHex(__identifier)) {
+        this.hash = __identifier;
+      } else if (typeof __identifier === 'number') {
+        this.number = __identifier;
+      } else {
+        this.tag = __identifier;
+      }
+    };
+
+    this.setIdentifier(_identifier);
   }
 
-  getIdentifier() {
-    if (typeof this.blockIdentifier === 'string' && isHex(this.blockIdentifier)) {
-      return { block_hash: this.blockIdentifier };
+  get queryIdentifier(): any {
+    if (this.number !== null) {
+      return `blockNumber=${this.number}`;
     }
 
-    if (typeof this.blockIdentifier === 'number') {
-      return { block_number: this.blockIdentifier };
+    if (this.hash !== null) {
+      return `blockHash=${this.hash}`;
     }
 
-    return this.blockIdentifier;
+    return `blockNumber=${this.tag}`;
   }
-}
 
-/**
- * Identifies the block to be queried.
- *
- * @param blockIdentifier - block identifier
- * @returns block identifier object
- */
-export function getBlockIdentifier(blockIdentifier: BlockIdentifier): BlockIdentifierObject {
-  if (blockIdentifier === null || blockIdentifier === 'latest') {
-    return { type: 'BLOCK_NUMBER', data: 'latest' }; // default to latest block
-  }
-  if (blockIdentifier === 'pending') {
-    return { type: 'BLOCK_NUMBER', data: 'pending' };
-  }
-  if (typeof blockIdentifier === 'number' || typeof blockIdentifier === 'bigint') {
-    return { type: 'BLOCK_NUMBER', data: blockIdentifier };
-  }
-  if (typeof blockIdentifier === 'string' && blockIdentifier.startsWith('0x')) {
-    return { type: 'BLOCK_HASH', data: blockIdentifier };
-  }
-  if (typeof blockIdentifier === 'string' && !Number.isNaN(parseInt(blockIdentifier, 10))) {
-    return { type: 'BLOCK_NUMBER', data: parseInt(blockIdentifier, 10) };
-  }
-  if (typeof blockIdentifier === 'string') {
-    throw new Error(`Invalid block identifier: ${blockIdentifier}`);
-  }
-  return { type: 'BLOCK_HASH', data: blockIdentifier };
-}
+  get identifier(): any {
+    if (this.number !== null) {
+      return { block_number: this.number };
+    }
 
-/**
- * Gets the block identifier for API request
- *
- * [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L164-L173)
- *
- * @param blockIdentifier
- * @returns block identifier for API request
- */
-export function getFormattedBlockIdentifier(blockIdentifier: BlockIdentifier = null): string {
-  const blockIdentifierObject = getBlockIdentifier(blockIdentifier);
-  if (blockIdentifierObject.type === 'BLOCK_NUMBER' && blockIdentifierObject.data === null) {
-    return '';
+    if (this.hash !== null) {
+      return { block_hash: this.hash };
+    }
+
+    return this.tag;
   }
-  if (blockIdentifierObject.type === 'BLOCK_NUMBER') {
-    return `blockNumber=${blockIdentifierObject.data}`;
+
+  set identifier(_identifier: BlockIdentifier) {
+    this.setIdentifier(_identifier);
   }
-  return `blockHash=${toHex(toBN(blockIdentifierObject.data))}`;
+
+  valueOf = () => this.number;
+
+  toString = () => this.hash;
 }
diff --git a/src/types/api/openrpc.ts b/src/types/api/openrpc.ts
index 0c13adaf..22d7e150 100644
--- a/src/types/api/openrpc.ts
+++ b/src/types/api/openrpc.ts
@@ -1,9 +1,11 @@
 /**
  * Starknet RPC version 0.1.0
- * starknet_api_openrpc version 0.31.0
  *
- * TypeScript Representation of OpenRpc protocol types | results
- * errors are not implemented here only results
+ * StarkNet Node API 0.31.0
+ * StarkNet Node Write API 0.3.0
+ * StarkNet Trace API 0.3.0
+ *
+ * TypeScript Representation of OpenRpc protocol types
  */
 
 /**
@@ -13,12 +15,28 @@
  * "description": "A field element. Represented as up to 63 hex digits and leading 4 bits zeroed.",
  * "pattern": "^0x0[a-fA-F0-9]{1,63}$"
  */
-type FELT = string;
+export type FELT = string;
+export type ADDRESS = FELT;
+/**
+ * "title": "An integer number in hex format (0x...)",
+ * "pattern": "^0x[a-fA-F0-9]+$"
+ */
+type NUM_AS_HEX = string;
+type SIGNATURE = Array<FELT>;
+type ETH_ADDRESS = string;
 type BLOCK_NUMBER = number;
 type BLOCK_HASH = FELT;
 type TXN_HASH = FELT;
+type CHAIN_ID = string;
+type PROTOCOL_VERSION = string;
 type TXN_STATUS = 'PENDING' | 'ACCEPTED_ON_L2' | 'ACCEPTED_ON_L1' | 'REJECTED';
 type TXN_TYPE = 'DECLARE' | 'DEPLOY' | 'INVOKE' | 'L1_HANDLER';
+type BLOCK_STATUS = 'PENDING' | 'ACCEPTED_ON_L2' | 'ACCEPTED_ON_L1' | 'REJECTED';
+enum BLOCK_TAG {
+  'latest',
+  'pending',
+}
+type BLOCK_ID = { block_hash: BLOCK_HASH } | { block_number: BLOCK_NUMBER } | BLOCK_TAG;
 type MSG_TO_L1 = {
   to_address: FELT;
   payload: Array<FELT>;
@@ -32,45 +50,34 @@ type COMMON_RECEIPT_PROPERTIES = {
   transaction_hash: TXN_HASH;
   actual_fee: FELT;
   status: TXN_STATUS;
+  status_data?: string;
   block_hash: BLOCK_HASH;
   block_number: BLOCK_NUMBER;
-  type?: TXN_TYPE;
+};
+type MSG_TO_L2 = {
+  from_address: ETH_ADDRESS;
+  payload: FELT;
 };
 type INVOKE_TXN_RECEIPT_PROPERTIES = {
   messages_sent: MSG_TO_L1;
+  l1_origin_message?: MSG_TO_L2;
   events: EVENT;
 };
 type PENDING_COMMON_RECEIPT_PROPERTIES = {
   transaction_hash: TXN_HASH;
   actual_fee: FELT;
-  type?: TXN_TYPE;
 };
 type INVOKE_TXN_RECEIPT = COMMON_RECEIPT_PROPERTIES & INVOKE_TXN_RECEIPT_PROPERTIES;
-type L1_HANDLER_TXN_RECEIPT = COMMON_RECEIPT_PROPERTIES;
+// type L1_HANDLER_TXN_RECEIPT = COMMON_RECEIPT_PROPERTIES;
 type DECLARE_TXN_RECEIPT = COMMON_RECEIPT_PROPERTIES;
 type DEPLOY_TXN_RECEIPT = COMMON_RECEIPT_PROPERTIES;
 type PENDING_INVOKE_TXN_RECEIPT = PENDING_COMMON_RECEIPT_PROPERTIES & INVOKE_TXN_RECEIPT_PROPERTIES;
 type PENDING_TXN_RECEIPT = PENDING_INVOKE_TXN_RECEIPT | PENDING_COMMON_RECEIPT_PROPERTIES;
 type TXN_RECEIPT =
   | INVOKE_TXN_RECEIPT
-  | L1_HANDLER_TXN_RECEIPT
   | DECLARE_TXN_RECEIPT
   | DEPLOY_TXN_RECEIPT
   | PENDING_TXN_RECEIPT;
-
-export namespace RPC_1 {
-  export type GetTransactionReceiptResponse = TXN_RECEIPT;
-
-  export type Methods = {
-    starknet_getTransactionReceipt: {
-      QUERY: never;
-      REQUEST: any[];
-      RESPONSE: GetTransactionReceiptResponse;
-    };
-  };
-}
-
-// starknet_getBlockWithTxHashes
 type BLOCK_HEADER = {
   block_hash: BLOCK_HASH;
   parent_hash: BLOCK_HASH;
@@ -91,15 +98,6 @@ type PENDING_BLOCK_WITH_TX_HASHES = BLOCK_BODY_WITH_TX_HASHES & {
   sequencer_address: FELT;
   parent_hash: BLOCK_HASH;
 };
-
-// starknet_getBlockWithTx
-type BLOCK_STATUS = 'PENDING' | 'ACCEPTED_ON_L2' | 'ACCEPTED_ON_L1' | 'REJECTED';
-/**
- * "title": "An integer number in hex format (0x...)",
- * "pattern": "^0x[a-fA-F0-9]+$"
- */
-type NUM_AS_HEX = string;
-type SIGNATURE = Array<FELT>;
 type COMMON_TXN_PROPERTIES = {
   transaction_hash: TXN_HASH;
   max_fee: FELT;
@@ -108,7 +106,6 @@ type COMMON_TXN_PROPERTIES = {
   nonce: FELT;
   type: TXN_TYPE;
 };
-type ADDRESS = FELT;
 type FUNCTION_CALL = {
   contract_address: ADDRESS;
   entry_point_selector: FELT;
@@ -136,13 +133,11 @@ type BLOCK_WITH_TXS = {
   status: BLOCK_STATUS;
 } & BLOCK_HEADER &
   BLOCK_BODY_WITH_TXS;
-
 type PENDING_BLOCK_WITH_TXS = BLOCK_BODY_WITH_TXS & {
   timestamp: number;
   sequencer_address: FELT;
   parent_hash: BLOCK_HASH;
 };
-
 type CONTRACT_CLASS = {
   program: string; // A base64 representation of the compressed program code
   entry_points_by_type: {
@@ -150,19 +145,354 @@ type CONTRACT_CLASS = {
     EXTERNAL: CONTRACT_ENTRY_POINT_LIST;
     L1_HANDLER: CONTRACT_ENTRY_POINT_LIST;
   };
+  abi?: any; // Pathfinder exception from rpc 0.1.0
 };
-
 type CONTRACT_ENTRY_POINT_LIST = Array<CONTRACT_ENTRY_POINT>;
 type CONTRACT_ENTRY_POINT = {
   offset: NUM_AS_HEX;
   selector: FELT;
 };
+type STORAGE_DIFF_ITEM = {
+  address: FELT;
+  key: FELT;
+  value: FELT;
+};
+type DECLARED_CONTRACT_ITEM = {
+  class_hash: FELT;
+};
+type DEPLOYED_CONTRACT_ITEM = {
+  address: FELT;
+  class_hash: FELT;
+};
+type STATE_UPDATE = {
+  block_hash: BLOCK_HASH;
+  new_root: FELT;
+  old_root: FELT;
+  state_diff: {
+    storage_diffs: Array<STORAGE_DIFF_ITEM>;
+    declared_contracts: Array<DECLARED_CONTRACT_ITEM>;
+    deployed_contracts: Array<DEPLOYED_CONTRACT_ITEM>;
+    nonces: Array<{
+      contract_address: ADDRESS;
+      nonce: FELT;
+    }>;
+  };
+};
+type STORAGE_KEY = string;
+type EVENT_FILTER = {
+  from_block?: BLOCK_ID;
+  to_block?: BLOCK_ID;
+  address?: ADDRESS;
+  keys?: Array<FELT>;
+};
+type RESULT_PAGE_REQUEST = {
+  page_size: number;
+  page_number: number;
+};
+type EMITTED_EVENT = EVENT & {
+  block_hash: BLOCK_HASH;
+  block_number: BLOCK_NUMBER;
+  transaction_hash: TXN_HASH;
+};
+type SYNC_STATUS = {
+  starting_block_hash: BLOCK_HASH;
+  starting_block_num: NUM_AS_HEX;
+  current_block_hash: BLOCK_HASH;
+  current_block_num: NUM_AS_HEX;
+  highest_block_hash: BLOCK_HASH;
+  highest_block_num: NUM_AS_HEX;
+};
+type FEE_ESTIMATE = {
+  gas_consumed: NUM_AS_HEX;
+  gas_price: NUM_AS_HEX;
+  overall_fee: NUM_AS_HEX;
+};
+
+enum CALL_TYPE {
+  'DELEGATE',
+  'CALL',
+}
+enum ENTRY_POINT_TYPE {
+  'EXTERNAL',
+  'L1_HANDLER',
+  'CONSTRUCTOR',
+}
+type FUNCTION_INVOCATION = FUNCTION_CALL & {
+  caller_address: FELT;
+  code_address: FELT;
+  entry_point_type: ENTRY_POINT_TYPE;
+  call_type: CALL_TYPE;
+  result: FELT;
+  calls: FUNCTION_INVOCATION;
+  events: EVENT;
+  messages: MSG_TO_L1;
+};
+type TRACE_ROOT = {
+  nonce: FELT;
+  signature: FELT;
+  function_invocation: FUNCTION_INVOCATION;
+};
 
 export namespace OPENRPC {
-  export type GetBlockWithTxHashesResponse = BLOCK_WITH_TX_HASHES | PENDING_BLOCK_WITH_TX_HASHES;
-  export type GetBlockWithTxs = BLOCK_WITH_TXS | PENDING_BLOCK_WITH_TXS;
-  export type GetStorageAtResponse = FELT;
-  export type GetTransactionByHashResponse = TXN;
-  export type GetTransactionByBlockIdAndIndex = TXN;
-  export type GetClassResponse = CONTRACT_CLASS;
+  export type BlockWithTxHashes = BLOCK_WITH_TX_HASHES | PENDING_BLOCK_WITH_TX_HASHES;
+  export type BlockWithTxs = BLOCK_WITH_TXS | PENDING_BLOCK_WITH_TXS;
+  export type StateUpdate = STATE_UPDATE;
+  export type Storage = FELT;
+  export type Transaction = TXN;
+  export type TransactionReceipt = TXN_RECEIPT;
+  export type ContractClass = CONTRACT_CLASS;
+  export type CallResponse = Array<FELT>;
+  export type EstimatedFee = FEE_ESTIMATE;
+  export type BlockNumber = BLOCK_NUMBER;
+  export type BlockHashAndNumber = {
+    block_hash: BLOCK_HASH;
+    block_number: BLOCK_NUMBER;
+  };
+  export type ChainId = CHAIN_ID;
+  export type PendingTransactions = Array<TXN>;
+  export type ProtocolVersion = PROTOCOL_VERSION;
+  export type SyncingStatus = false | SYNC_STATUS;
+  export type Events = {
+    events: Array<EMITTED_EVENT>;
+    page_number: number;
+    is_last_page: boolean;
+  };
+  export type Nonce = FELT;
+  export type Trace = TRACE_ROOT;
+  export type Traces = Array<{
+    transaction_hash: FELT;
+    trace_root: TRACE_ROOT;
+  }>;
+  export type TransactionHash = TXN_HASH;
+  export type BlockHash = BLOCK_HASH;
+  export type EventFilter = EVENT_FILTER;
+  export type InvokedTransaction = { transaction_hash: TXN_HASH };
+  export type DeclaredTransaction = { transaction_hash: TXN_HASH; class_hash: FELT };
+  export type DeployedTransaction = { transaction_hash: TXN_HASH; contract_address: FELT };
+
+  // Final Methods
+  export type Methods = {
+    // Read API
+    starknet_getBlockWithTxHashes: {
+      params: { block_id: BLOCK_ID };
+      result: BlockWithTxHashes;
+      errors: Errors.INVALID_BLOCK_ID;
+    };
+    starknet_getBlockWithTxs: {
+      params: { block_id: BLOCK_ID };
+      result: BlockWithTxs;
+      errors: Errors.INVALID_BLOCK_ID;
+    };
+    starknet_getStateUpdate: {
+      params: { block_id: BLOCK_ID };
+      result: StateUpdate;
+      errors: Errors.INVALID_BLOCK_ID;
+    };
+    starknet_getStorageAt: {
+      params: { contract_address: ADDRESS; key: STORAGE_KEY; block_id: BLOCK_ID };
+      result: Storage;
+      errors: Errors.CONTRACT_NOT_FOUND | Errors.INVALID_BLOCK_ID;
+    };
+    starknet_getTransactionByHash: {
+      params: { transaction_hash: TXN_HASH };
+      result: Transaction;
+      errors: Errors.INVALID_TXN_HASH;
+    };
+    starknet_getTransactionByBlockIdAndIndex: {
+      params: { block_id: BLOCK_ID; index: number };
+      result: Transaction;
+      errors: Errors.INVALID_BLOCK_ID | Errors.INVALID_TXN_INDEX;
+    };
+    starknet_getTransactionReceipt: {
+      params: { transaction_hash: TXN_HASH };
+      result: TransactionReceipt;
+      errors: Errors.INVALID_TXN_HASH;
+    };
+    starknet_getClass: {
+      params: { class_hash: FELT };
+      result: ContractClass;
+      errors: Errors.INVALID_CONTRACT_CLASS_HASH;
+    };
+    starknet_getClassHashAt: {
+      params: { block_id: BLOCK_ID; contract_address: ADDRESS };
+      result: FELT;
+      errors: Errors.INVALID_BLOCK_ID | Errors.CONTRACT_NOT_FOUND;
+    };
+    starknet_getClassAt: {
+      params: { block_id: BLOCK_ID; contract_address: ADDRESS };
+      result: ContractClass;
+      errors: Errors.INVALID_BLOCK_ID | Errors.CONTRACT_NOT_FOUND;
+    };
+    starknet_getBlockTransactionCount: {
+      params: { block_id: BLOCK_ID };
+      result: number;
+      errors: Errors.INVALID_BLOCK_ID;
+    };
+    starknet_call: {
+      params: { request: FUNCTION_CALL; block_id: BLOCK_ID };
+      result: Array<FELT>;
+      errors:
+        | Errors.CONTRACT_NOT_FOUND
+        | Errors.INVALID_MESSAGE_SELECTOR
+        | Errors.INVALID_CALL_DATA
+        | Errors.CONTRACT_ERROR
+        | Errors.INVALID_BLOCK_ID;
+    };
+    starknet_estimateFee: {
+      params: { request: INVOKE_TXN; block_id: BLOCK_ID };
+      result: FEE_ESTIMATE;
+      errors:
+        | Errors.CONTRACT_NOT_FOUND
+        | Errors.INVALID_MESSAGE_SELECTOR
+        | Errors.INVALID_CALL_DATA
+        | Errors.CONTRACT_ERROR
+        | Errors.INVALID_BLOCK_ID;
+    };
+    starknet_blockNumber: {
+      result: BLOCK_NUMBER;
+      errors: Errors.NO_BLOCKS;
+    };
+    starknet_blockHashAndNumber: {
+      result: BLOCK_HASH & BLOCK_NUMBER;
+      errors: Errors.NO_BLOCKS;
+    };
+    starknet_chainId: {
+      result: CHAIN_ID;
+    };
+    starknet_pendingTransactions: {
+      result: PendingTransactions;
+    };
+    starknet_syncing: {
+      result: SyncingStatus;
+    };
+    starknet_getEvents: {
+      params: { filter: EVENT_FILTER & RESULT_PAGE_REQUEST };
+      result: { events: EMITTED_EVENT; page_number: number; is_last_page: boolean };
+      errors: Errors.PAGE_SIZE_TOO_BIG;
+    };
+    starknet_getNonce: {
+      params: { contract_address: ADDRESS };
+      result: FELT;
+      errors: Errors.CONTRACT_NOT_FOUND;
+    };
+
+    // Write API
+    starknet_addInvokeTransaction: {
+      params: {
+        function_invocation: FUNCTION_CALL;
+        signature: SIGNATURE;
+        max_fee: NUM_AS_HEX;
+        version: NUM_AS_HEX;
+      };
+      result: InvokedTransaction;
+    };
+    starknet_addDeclareTransaction: {
+      params: {
+        contract_class: CONTRACT_CLASS;
+        version: NUM_AS_HEX;
+      };
+      result: DeclaredTransaction;
+      errors: Errors.INVALID_CONTRACT_CLASS;
+    };
+    starknet_addDeployTransaction: {
+      params: {
+        contract_address_salt: FELT;
+        constructor_calldata: FELT;
+        contract_definition: CONTRACT_CLASS;
+      };
+      result: DeployedTransaction;
+      errors: Errors.INVALID_CONTRACT_CLASS;
+    };
+
+    // Trace API
+    starknet_traceTransaction: {
+      params: { transaction_hash: TXN_HASH };
+      result: Trace;
+      errors:
+        | Errors.INVALID_TXN_HASH
+        | Errors.NO_TRACE_AVAILABLE
+        | Errors.INVALID_BLOCK_HASH
+        | Errors.INVALID_TXN_HASH;
+    };
+    starknet_traceBlockTransactions: {
+      params: { block_hash: BLOCK_HASH };
+      result: Traces;
+      errors: Errors.INVALID_BLOCK_HASH;
+    };
+  };
+}
+
+export namespace Errors {
+  export interface FAILED_TO_RECEIVE_TXN {
+    code: 1;
+    message: 'Failed to write transaction';
+  }
+
+  export interface CONTRACT_NOT_FOUND {
+    code: 20;
+    message: 'Contract not found';
+  }
+
+  export interface INVALID_MESSAGE_SELECTOR {
+    code: 21;
+    message: 'Invalid message selector';
+  }
+
+  export interface INVALID_CALL_DATA {
+    code: 22;
+    message: 'Invalid call data';
+  }
+
+  export interface INVALID_BLOCK_ID {
+    code: 24;
+    message: 'Invalid block id';
+  }
+
+  export interface INVALID_TXN_INDEX {
+    code: 27;
+    message: 'Invalid transaction index in a block';
+  }
+
+  export interface INVALID_CONTRACT_CLASS_HASH {
+    code: 28;
+    message: 'The supplied contract class hash is invalid or unknown';
+  }
+
+  export interface PAGE_SIZE_TOO_BIG {
+    code: 31;
+    message: 'Requested page size is too big';
+  }
+
+  export interface NO_BLOCKS {
+    code: 32;
+    message: 'There are no blocks';
+  }
+
+  export interface CONTRACT_ERROR {
+    code: 40;
+    message: 'Contract error';
+  }
+
+  export interface INVALID_CONTRACT_CLASS {
+    code: 50;
+    message: 'Invalid contract class';
+  }
+
+  export interface NO_TRACE_AVAILABLE {
+    code: 10;
+    message: 'No trace available for transaction';
+    data: {
+      status: 'RECEIVED' | 'REJECTED';
+    };
+  }
+
+  export interface INVALID_BLOCK_HASH {
+    code: 24;
+    message: 'Invalid block hash';
+  }
+
+  export interface INVALID_TXN_HASH {
+    code: 25;
+    message: 'Invalid transaction hash';
+  }
 }
diff --git a/src/types/api/rpc.ts b/src/types/api/rpc.ts
index 9caa3418..4dacb26b 100644
--- a/src/types/api/rpc.ts
+++ b/src/types/api/rpc.ts
@@ -1,135 +1,71 @@
-import { StarknetChainId } from '../../constants';
-import { BlockIdentifier } from '../../provider/utils';
-import { Status } from '../lib';
-import { OPENRPC } from './openrpc';
+import { ADDRESS, FELT, OPENRPC } from './openrpc';
 
 export namespace RPC {
   export type Response = {
     id: number;
-    result: any;
     jsonrpc: string;
+    result?: any;
     error?: {
       code: string;
       message: string;
     };
   };
 
-  export type AddTransactionResponse = {
-    transaction_hash: string;
-  };
-
-  export type GetClassResponse = {
-    program: string;
-    entry_point_by_type: any;
-  };
-
-  export type DeclareResponse = {
-    transaction_hash: string;
-    class_hash: string;
-  };
-
-  export type EstimateFeeResponse = {
-    overall_fee: number;
-    gas_consumed: number;
-    gas_price: number;
-  };
-
-  export type GetBlockWithTxHashesResponse = OPENRPC.GetBlockWithTxHashesResponse;
-  export type GetBlockWithTxs = OPENRPC.GetBlockWithTxs;
-  export type GetStorageAtResponse = OPENRPC.GetStorageAtResponse;
-
-  export type GetTransactionReceiptResponse = {
-    txn_hash: string;
-    actual_fee: string;
-    status: Status;
-    status_data: string;
-    messages_sent: Array<MessageToL1>;
-    l1_origin_message: MessageToL2;
-    events: Array<StarknetEvent>;
-  };
-
-  interface CommonTransactionProperties {
-    txn_hash: string;
-    max_fee: string;
-    version: string;
-    nonce: string;
-    signature: Array<string>;
-  }
-
-  export interface InvokeTransactionResponse extends CommonTransactionProperties {
-    contract_address?: string;
-    entry_point_selector?: string;
-    calldata?: Array<string>;
-  }
-
-  export interface DeclareTransactionResponse extends CommonTransactionProperties {
-    contract_class?: GetClassResponse;
-    sender_address?: string;
-  }
-
-  export type GetTransactionByHashResponse = OPENRPC.GetTransactionByHashResponse;
-  export type GetTransactionByBlockIdAndIndex = OPENRPC.GetTransactionByBlockIdAndIndex;
-
+  export type ChainId = OPENRPC.ChainId;
+  export type ContractAddress = ADDRESS;
+  export type Felt = FELT;
+  export type ContractClass = OPENRPC.ContractClass;
+  export type StateUpdate = OPENRPC.StateUpdate;
+  export type Transaction = OPENRPC.Transaction;
+  export type PendingTransactions = OPENRPC.PendingTransactions;
+  export type TransactionHash = OPENRPC.TransactionHash;
+  export type Trace = OPENRPC.Trace;
+  export type Traces = OPENRPC.Traces;
+  export type BlockHash = OPENRPC.BlockHash;
+  export type BlockHashAndNumber = OPENRPC.BlockHashAndNumber;
+  export type GetClassResponse = OPENRPC.ContractClass;
+  export type EstimateFeeResponse = OPENRPC.EstimatedFee;
+  export type GetBlockWithTxHashesResponse = OPENRPC.BlockWithTxHashes;
+  export type GetBlockWithTxs = OPENRPC.BlockWithTxs;
+  export type GetStorageAtResponse = OPENRPC.Storage;
+  export type TransactionReceipt = OPENRPC.TransactionReceipt;
+  export type GetTransactionByHashResponse = OPENRPC.Transaction;
+  export type GetTransactionByBlockIdAndIndex = OPENRPC.Transaction;
   export type GetTransactionCountResponse = number;
-
-  export type GetBlockNumberResponse = number;
-
-  export type GetSyncingStatsResponse =
-    | {
-        starting_block_hash: string;
-        starting_block_num: string;
-        current_block_hash: string;
-        current_block_num: string;
-        highest_block_hash: string;
-        highest_block_num: string;
-      }
-    | boolean;
-
-  export type EventFilter = {
-    fromBlock: BlockIdentifier;
-    toBlock: BlockIdentifier;
-    address: string;
-    keys: string[];
-    page_size: number;
-    page_number: number;
-  };
-
-  export type GetEventsResponse = {
-    events: StarknetEmittedEvent[];
-    page_number: number;
-    is_last_page: number;
-  };
-
-  export type DeployContractResponse = {
-    transaction_hash: string;
-    contract_address: string;
-  };
-  // Other
-
-  export type StarknetEvent = {
-    from_address: string;
-    keys: string[];
-    data: string[];
-  };
-
-  export type StarknetEmittedEvent = {
-    event: StarknetEvent;
-    block_hash: string;
-    block_number: number;
-    transaction_hash: string;
-  };
-
-  export type MessageToL1 = {
-    to_address: string;
-    payload: string[];
-  };
-
-  export type MessageToL2 = {
-    from_address: string;
-    payload: string[];
-  };
+  export type GetBlockNumberResponse = OPENRPC.BlockNumber;
+  export type GetSyncingStatsResponse = OPENRPC.SyncingStatus;
+  export type EventFilter = OPENRPC.EventFilter;
+  export type GetEventsResponse = OPENRPC.Events;
+  export type InvokedTransaction = OPENRPC.InvokedTransaction;
+  export type DeclaredTransaction = OPENRPC.DeclaredTransaction;
+  export type DeployedTransaction = OPENRPC.DeployedTransaction;
 
   export type Methods = {
+    starknet_pendingTransactions: {
+      QUERY: never;
+      REQUEST: any[];
+      RESPONSE: PendingTransactions;
+    };
+    starknet_blockHashAndNumber: {
+      QUERY: never;
+      REQUEST: any[];
+      RESPONSE: BlockHashAndNumber;
+    };
+    starknet_getClassHashAt: {
+      QUERY: never;
+      REQUEST: any[];
+      RESPONSE: Felt;
+    };
+    starknet_getStateUpdate: {
+      QUERY: never;
+      REQUEST: any[];
+      RESPONSE: OPENRPC.StateUpdate;
+    };
+    starknet_getClass: {
+      QUERY: never;
+      REQUEST: any[];
+      RESPONSE: OPENRPC.ContractClass;
+    };
     starknet_getBlockWithTxHashes: {
       QUERY: never;
       REQUEST: any[];
@@ -143,7 +79,7 @@ export namespace RPC {
     starknet_getNonce: {
       QUERY: never;
       REQUEST: any[];
-      RESPONSE: string;
+      RESPONSE: OPENRPC.Nonce;
     };
     starknet_getStorageAt: {
       QUERY: never;
@@ -163,7 +99,7 @@ export namespace RPC {
     starknet_getTransactionReceipt: {
       QUERY: never;
       REQUEST: any[];
-      RESPONSE: GetTransactionReceiptResponse;
+      RESPONSE: TransactionReceipt;
     };
     starknet_getBlockTransactionCount: {
       QUERY: never;
@@ -178,7 +114,7 @@ export namespace RPC {
     starknet_estimateFee: {
       QUERY: never;
       REQUEST: any[];
-      RESPONSE: EstimateFeeResponse;
+      RESPONSE: OPENRPC.EstimatedFee;
     };
     starknet_blockNumber: {
       QUERY: never;
@@ -188,7 +124,7 @@ export namespace RPC {
     starknet_chainId: {
       QUERY: never;
       REQUEST: any[];
-      RESPONSE: StarknetChainId;
+      RESPONSE: OPENRPC.ChainId;
     };
     starknet_syncing: {
       QUERY: never;
@@ -203,22 +139,32 @@ export namespace RPC {
     starknet_addInvokeTransaction: {
       QUERY: never;
       REQUEST: any[];
-      RESPONSE: AddTransactionResponse;
+      RESPONSE: OPENRPC.InvokedTransaction;
     };
     starknet_addDeployTransaction: {
       QUERY: never;
       REQUEST: any[];
-      RESPONSE: DeployContractResponse;
+      RESPONSE: OPENRPC.DeployedTransaction;
     };
     starknet_addDeclareTransaction: {
       QUERY: never;
       REQUEST: any[];
-      RESPONSE: DeclareResponse;
+      RESPONSE: OPENRPC.DeclaredTransaction;
     };
     starknet_getClassAt: {
       QUERY: never;
       REQUEST: any[];
       RESPONSE: any;
     };
+    starknet_traceTransaction: {
+      QUERY: never;
+      REQUEST: any[];
+      RESPONSE: any;
+    };
+    starknet_traceBlockTransactions: {
+      QUERY: never;
+      REQUEST: any[];
+      RESPONSE: any;
+    };
   };
 }
diff --git a/src/utils/responseParser/rpc.ts b/src/utils/responseParser/rpc.ts
index 604deeaa..13d65500 100644
--- a/src/utils/responseParser/rpc.ts
+++ b/src/utils/responseParser/rpc.ts
@@ -24,6 +24,10 @@ type GetTransactionByHashResponse = RPC.GetTransactionByHashResponse & {
   [key: string]: any;
 };
 
+type TransactionReceipt = RPC.TransactionReceipt & {
+  [key: string]: any;
+};
+
 export class RPCResponseParser extends ResponseParser {
   public parseGetBlockResponse(res: RpcGetBlockResponse): GetBlockResponse {
     return {
@@ -51,10 +55,10 @@ export class RPCResponseParser extends ResponseParser {
   }
 
   public parseGetTransactionReceiptResponse(
-    res: RPC.GetTransactionReceiptResponse
+    res: TransactionReceipt
   ): GetTransactionReceiptResponse {
     return {
-      transaction_hash: res.txn_hash,
+      transaction_hash: res.transaction_hash,
       actual_fee: res.actual_fee,
       status: res.status,
       status_data: res.status_data,
@@ -78,20 +82,20 @@ export class RPCResponseParser extends ResponseParser {
     };
   }
 
-  public parseInvokeFunctionResponse(res: RPC.AddTransactionResponse): InvokeFunctionResponse {
+  public parseInvokeFunctionResponse(res: RPC.InvokedTransaction): InvokeFunctionResponse {
     return {
       transaction_hash: res.transaction_hash,
     };
   }
 
-  public parseDeployContractResponse(res: RPC.DeployContractResponse): DeployContractResponse {
+  public parseDeployContractResponse(res: RPC.DeployedTransaction): DeployContractResponse {
     return {
       transaction_hash: res.transaction_hash,
       contract_address: res.contract_address,
     };
   }
 
-  public parseDeclareContractResponse(res: RPC.DeclareResponse): DeclareContractResponse {
+  public parseDeclareContractResponse(res: RPC.DeclaredTransaction): DeclareContractResponse {
     return {
       transaction_hash: res.transaction_hash,
       class_hash: res.class_hash,


Test patch:
diff --git a/__tests__/defaultProvider.test.ts b/__tests__/defaultProvider.test.ts
index 8e4d6802..637ab7ba 100644
--- a/__tests__/defaultProvider.test.ts
+++ b/__tests__/defaultProvider.test.ts
@@ -139,10 +139,11 @@ describe('defaultProvider', () => {
 
   describeIfNotDevnet('Provider', () => {
     const provider = getTestProvider();
+    let latestBlock;
     describe(`Provider methods if not devnet`, () => {
       describe('getBlock', () => {
-        test('pending', async () => {
-          const latestBlock = await provider.getBlock();
+        test('getBlock by tag pending', async () => {
+          latestBlock = await provider.getBlock();
           expect(latestBlock).toHaveProperty('block_hash');
           expect(latestBlock).toHaveProperty('parent_hash');
           expect(latestBlock).toHaveProperty('block_number');
@@ -153,11 +154,8 @@ describe('defaultProvider', () => {
           expect(Array.isArray(latestBlock.transactions)).toBe(true);
         });
 
-        test('Block Hash 0x8a30a1212d142cb0053fe9921e1dbf64f651d328565bd2e7ac24059c270f43', async () => {
-          const block = await provider.getBlock(
-            '0x8a30a1212d142cb0053fe9921e1dbf64f651d328565bd2e7ac24059c270f43'
-          );
-
+        test('getBlock by Hash', async () => {
+          const block = await provider.getBlock(latestBlock.block_hash);
           expect(block).toHaveProperty('block_hash');
           expect(block).toHaveProperty('parent_hash');
           expect(block).toHaveProperty('block_number');
@@ -168,8 +166,8 @@ describe('defaultProvider', () => {
           expect(Array.isArray(block.transactions)).toBe(true);
         });
 
-        test('Block Number 102634', async () => {
-          const block = await provider.getBlock(102634);
+        test('getBlock by Number', async () => {
+          const block = await provider.getBlock(latestBlock.block_number);
           expect(block).toHaveProperty('block_hash');
           expect(block).toHaveProperty('parent_hash');
           expect(block).toHaveProperty('block_number');
diff --git a/__tests__/rpcProvider.test.ts b/__tests__/rpcProvider.test.ts
index 3bb9f82b..9fd05c09 100644
--- a/__tests__/rpcProvider.test.ts
+++ b/__tests__/rpcProvider.test.ts
@@ -1,5 +1,6 @@
-import { Account, RpcProvider, ec } from '../src';
+import { Account, GetBlockResponse, RpcProvider, ec } from '../src';
 import {
+  compiledErc20,
   compiledOpenZeppelinAccount,
   describeIfRpc,
   getTestAccount,
@@ -20,21 +21,115 @@ describeIfRpc('RPCProvider', () => {
     accountPublicKey = ec.getStarkKey(accountKeyPair);
   });
 
+  test('getChainId', async () => {
+    const chainId = await rpcProvider.getChainId();
+    expect(chainId).toBe('0x534e5f474f45524c49');
+  });
+
+  test('getPendingTransactions', async () => {
+    const transactions = await rpcProvider.getPendingTransactions();
+    expect(Array.isArray(transactions)).toBe(true);
+  });
+
+  test('getTransactionCount', async () => {
+    const count = await rpcProvider.getTransactionCount('latest');
+    expect(typeof count).toBe('number');
+  });
+
+  test('getBlockHashAndNumber', async () => {
+    const blockHashAndNumber = await rpcProvider.getBlockHashAndNumber();
+    expect(blockHashAndNumber).toHaveProperty('block_hash');
+    expect(blockHashAndNumber).toHaveProperty('block_number');
+  });
+
+  test('getStateUpdate', async () => {
+    const stateUpdate = await rpcProvider.getStateUpdate('latest');
+    expect(stateUpdate).toHaveProperty('block_hash');
+    expect(stateUpdate).toHaveProperty('new_root');
+    expect(stateUpdate).toHaveProperty('old_root');
+    expect(stateUpdate).toHaveProperty('state_diff');
+  });
+
+  xtest('getProtocolVersion', async () => {
+    await rpcProvider.getProtocolVersion();
+  });
+
   describe('RPC methods', () => {
-    test('getChainId', async () => {
-      const chainId = await rpcProvider.getChainId();
-      expect(chainId).toBe('0x534e5f474f45524c49');
+    let latestBlock: GetBlockResponse;
+
+    beforeAll(async () => {
+      latestBlock = await rpcProvider.getBlock('latest');
+    });
+
+    test('getBlockWithTxHashes', async () => {
+      const blockResponse = await rpcProvider.getBlockWithTxHashes(latestBlock.block_number);
+      expect(blockResponse).toHaveProperty('transactions');
+    });
+
+    test('getBlockWithTxs', async () => {
+      const blockResponse = await rpcProvider.getBlockWithTxs(latestBlock.block_number);
+      expect(blockResponse).toHaveProperty('transactions');
+    });
+
+    test('getTransactionByBlockIdAndIndex', async () => {
+      const transaction = await rpcProvider.getTransactionByBlockIdAndIndex(
+        latestBlock.block_number,
+        0
+      );
+      expect(transaction).toHaveProperty('transaction_hash');
+    });
+
+    xtest('traceBlockTransactions', async () => {
+      await rpcProvider.traceBlockTransactions(latestBlock.block_hash);
+    });
+
+    describe('deploy contract related tests', () => {
+      let contract_address;
+      let transaction_hash;
+
+      beforeAll(async () => {
+        ({ contract_address, transaction_hash } = await rpcProvider.deployContract({
+          contract: compiledOpenZeppelinAccount,
+          constructorCalldata: [accountPublicKey],
+          addressSalt: accountPublicKey,
+        }));
+        await rpcProvider.waitForTransaction(transaction_hash);
+      });
+
+      test('deployContract result', () => {
+        expect(contract_address).toBeTruthy();
+        expect(transaction_hash).toBeTruthy();
+      });
+
+      test('getTransactionByHash', async () => {
+        const transaction = await rpcProvider.getTransactionByHash(transaction_hash);
+        expect(transaction).toHaveProperty('transaction_hash');
+      });
+
+      test('getClassHashAt', async () => {
+        const classHash = await rpcProvider.getClassHashAt('latest', contract_address);
+        expect(typeof classHash).toBe('string');
+      });
+
+      xtest('traceTransaction', async () => {
+        await rpcProvider.traceTransaction(transaction_hash);
+      });
     });
 
-    test('deployContract', async () => {
-      const { contract_address, transaction_hash } = await rpcProvider.deployContract({
-        contract: compiledOpenZeppelinAccount,
-        constructorCalldata: [accountPublicKey],
-        addressSalt: accountPublicKey,
+    describe('declare contract related tests', () => {
+      let class_hash;
+
+      beforeAll(async () => {
+        ({ class_hash } = await rpcProvider.declareContract({
+          contract: compiledErc20,
+        }));
+      });
+
+      test('getClass', async () => {
+        const contractClass = await rpcProvider.getClass(class_hash);
+        expect(contractClass).toHaveProperty('program');
+        expect(contractClass).toHaveProperty('entry_points_by_type');
       });
-      await rpcProvider.waitForTransaction(transaction_hash);
-      expect(contract_address).toBeTruthy();
-      expect(transaction_hash).toBeTruthy();
     });
 
     test.todo('getEstimateFee');
diff --git a/__tests__/utils/utils.test.ts b/__tests__/utils/utils.test.ts
index 9875bc6c..55d4ec34 100644
--- a/__tests__/utils/utils.test.ts
+++ b/__tests__/utils/utils.test.ts
@@ -1,6 +1,7 @@
 import fs from 'fs';
 
 import { constants, hash, json, number, stark } from '../../src';
+import { Block } from '../../src/provider/utils';
 import { pedersen } from '../../src/utils/hash';
 
 const { IS_BROWSER } = constants;
@@ -112,3 +113,19 @@ describe('calculateContractAddressFromHash()', () => {
     );
   });
 });
+
+describe('new Block()', () => {
+  test('Block identifier and queryIdentifier', () => {
+    const blockA = new Block(0);
+    expect(blockA.identifier).toMatchObject({ block_number: 0 });
+    expect(blockA.queryIdentifier).toBe('blockNumber=0');
+
+    const blockB = new Block('latest');
+    expect(blockB.identifier).toBe('latest');
+    expect(blockB.queryIdentifier).toBe('blockNumber=latest');
+
+    const blockC = new Block('0x01');
+    expect(blockC.identifier).toMatchObject({ block_hash: '0x01' });
+    expect(blockC.queryIdentifier).toBe('blockHash=0x01');
+  });
+});