Repository: ecadlabs/taquito (ts)

Issue:
Rpc - support new properties for Kathmandu
Add support for the new operations `vdf_revelation` and `event` to `OperationContents`, `OperationContentsAndResult` and `OpKind`.
Support new properties `current_ballot`, `current_proposals` and `remaining_proposals` on the `DelegatesResponse`


Pull request description:
support new properties related to Kathmandu in Rpc package 
Closes #1862 
Thank you for your contribution to Taquito.

Before submitting this PR, please make sure:

- [ ] Your code builds cleanly without any errors or warnings
- [ ] You have added unit tests
- [ ] You have added integration tests (if relevant/appropriate)
- [ ] All public methods or types have TypeDoc coverage with a complete description, and ideally an @example
- [ ] You have added or updated corresponding documentation
- [ ] If relevant, you have written a first draft summary describing the change for inclusion in Release Notes. 

## Release Note Draft Snippet

__If relevant, please write a summary of your change that will be suitable for
inclusion in the Release Notes for the next Taquito release.__


Patch:
diff --git a/docs/batch-api.md b/docs/batch-api.md
index fa8dc0221..f465065b2 100644
--- a/docs/batch-api.md
+++ b/docs/batch-api.md
@@ -20,7 +20,12 @@ await op1.confirmation();
 await op2.confirmation();
 
 /*
- * Error Message returned by the node:
+ * Error Message returned by the node (since Kathmandu):
+ * Error while applying operation opHash: 
+ * Only one manager operation per manager per block allowed (found opHash2 with Xtez fee. 
+ * You may want to use --replace to provide adequate fee and replace it).
+ * 
+ * Error Message that was returned by the node (before Kathmandu):
  * "Error while applying operation opWH2nEcmmzUwK4T6agHg3bn9GDR7fW1ynqWL58AVRAb7aZFciD:
  * branch refused (Error:
  * Counter 1122148 already used for contract tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb (expected 1122149))"
diff --git a/packages/taquito-rpc/src/opkind.ts b/packages/taquito-rpc/src/opkind.ts
index 0c3883d35..9fb1316e2 100644
--- a/packages/taquito-rpc/src/opkind.ts
+++ b/packages/taquito-rpc/src/opkind.ts
@@ -26,4 +26,6 @@ export enum OpKind {
   TX_ROLLUP_DISPATCH_TICKETS = 'tx_rollup_dispatch_tickets',
   TRANSFER_TICKET = 'transfer_ticket',
   INCREASE_PAID_STORAGE = 'increase_paid_storage',
+  VDF_REVELATION = 'vdf_revelation',
+  EVENT = 'event',
 }
diff --git a/packages/taquito-rpc/src/types.ts b/packages/taquito-rpc/src/types.ts
index eec9cbb9c..176e2c090 100644
--- a/packages/taquito-rpc/src/types.ts
+++ b/packages/taquito-rpc/src/types.ts
@@ -106,6 +106,9 @@ export interface DelegatesResponse {
   deactivated: boolean;
   grace_period: number;
   voting_power?: BigNumber;
+  current_ballot?: OperationContentsBallotEnum;
+  current_proposals?: string[];
+  remaining_proposals?: number;
 }
 
 interface Frozenbalancebycycle {
@@ -223,6 +226,11 @@ export interface OperationContentsRevelation {
   nonce: string;
 }
 
+export interface OperationContentsVdfRevelation {
+  kind: OpKind.VDF_REVELATION;
+  solution: string[];
+}
+
 export interface OperationContentsDoubleEndorsement {
   kind: OpKind.DOUBLE_ENDORSEMENT_EVIDENCE;
   op1: InlinedEndorsement;
@@ -439,6 +447,7 @@ export type OperationContents =
   | OperationContentsPreEndorsement
   | OperationContentsDoublePreEndorsement
   | OperationContentsRevelation
+  | OperationContentsVdfRevelation
   | OperationContentsDoubleEndorsement
   | OperationContentsDoubleBaking
   | OperationContentsActivateAccount
@@ -834,6 +843,12 @@ export interface OperationContentsAndResultIncreasePaidStorage {
   metadata: OperationContentsAndResultMetadataIncreasePaidStorage;
 }
 
+export interface OperationContentsAndResultVdfRevelation {
+  kind: OpKind.VDF_REVELATION;
+  solution: string[];
+  metadata: OperationContentsAndResultMetadata;
+}
+
 export type OperationContentsAndResult =
   | OperationContentsAndResultEndorsement
   | OperationContentsAndResultPreEndorsement
@@ -860,7 +875,8 @@ export type OperationContentsAndResult =
   | OperationContentsAndResultTxRollupRemoveCommitment
   | OperationContentsAndResultTxRollupRejection
   | OperationContentsAndResultTransferTicket
-  | OperationContentsAndResultIncreasePaidStorage;
+  | OperationContentsAndResultIncreasePaidStorage
+  | OperationContentsAndResultVdfRevelation;
 
 export enum OPERATION_METADATA {
   TOO_LARGE = 'too large',
@@ -1058,9 +1074,15 @@ export interface ScriptedContracts {
   storage: MichelsonV1Expression;
 }
 
-export interface BondId {
-  tx_rollup: string;
-}
+export type BondId =
+  | {
+      sc_rollup?: never;
+      tx_rollup: string;
+    }
+  | {
+      sc_rollup: string;
+      tx_rollup?: never;
+    };
 
 export interface OperationBalanceUpdatesItem {
   kind: BalanceUpdateKindEnum;
@@ -1089,7 +1111,8 @@ export type InternalOperationResultKindEnum =
   | OpKind.REVEAL
   | OpKind.TRANSACTION
   | OpKind.ORIGINATION
-  | OpKind.DELEGATION;
+  | OpKind.DELEGATION
+  | OpKind.EVENT;
 
 export type SuccessfulManagerOperationResultKindEnum =
   | OpKind.REVEAL
@@ -1101,7 +1124,8 @@ export type InternalOperationResultEnum =
   | OperationResultReveal
   | OperationResultTransaction
   | OperationResultDelegation
-  | OperationResultOrigination;
+  | OperationResultOrigination
+  | OperationResultEvent;
 
 export interface OperationResultTxRollupOrigination {
   status: OperationResultStatusEnum;
@@ -1273,6 +1297,9 @@ export interface InternalOperationResult {
   value?: MichelsonV1Expression;
   limit?: string;
   result: InternalOperationResultEnum;
+  type?: MichelsonV1Expression;
+  tag?: string;
+  payload?: MichelsonV1Expression;
 }
 
 export interface SuccessfulManagerOperationResult {
@@ -1412,6 +1439,12 @@ export interface OperationResultOrigination {
   lazy_storage_diff?: LazyStorageDiff[];
 }
 
+export interface OperationResultEvent {
+  status: OperationResultStatusEnum;
+  consumed_milligas?: string;
+  errors?: TezosGenericOperationError[];
+}
+
 export interface OperationContentsAndResultMetadataOrigination {
   balance_updates: OperationMetadataBalanceUpdates[];
   operation_result: OperationResultOrigination;


Test patch:
diff --git a/integration-tests/injecting-multiple-manager-operations-in-a-block.spec.ts b/integration-tests/injecting-multiple-manager-operations-in-a-block.spec.ts
new file mode 100644
index 000000000..81dfd17f9
--- /dev/null
+++ b/integration-tests/injecting-multiple-manager-operations-in-a-block.spec.ts
@@ -0,0 +1,25 @@
+import { CONFIGS } from "./config";
+
+CONFIGS().forEach(({ lib, rpc, setup }) => {
+    const Tezos = lib;
+    describe(`Test injecting more than one manager operation in a block: ${rpc}`, () => {
+
+        beforeEach(async (done) => {
+            await setup()
+            done()
+        })
+        test('Verify that doing transfers without awaiting the confirmation after each will fail', async (done) => {
+            try {
+                const op1 = await Tezos.contract.transfer({ to: 'tz1ZfrERcALBwmAqwonRXYVQBDT9BjNjBHJu', amount: 1 });
+                const op2 = await Tezos.contract.transfer({ to: 'tz1ZfrERcALBwmAqwonRXYVQBDT9BjNjBHJu', amount: 2 });
+
+                await op1.confirmation();
+                await op2.confirmation();
+
+            } catch (error) {
+                expect(error.message).toContain('Only one manager operation per manager per block allowed');
+            }
+            done();
+        })
+    });
+})
diff --git a/packages/taquito-rpc/test/data/rpc-responses.ts b/packages/taquito-rpc/test/data/rpc-responses.ts
index 3f43ad4f9..674fd1e6b 100644
--- a/packages/taquito-rpc/test/data/rpc-responses.ts
+++ b/packages/taquito-rpc/test/data/rpc-responses.ts
@@ -2497,6 +2497,19 @@ export const delegatesIthacanetSample = {
   voting_power: 199,
 };
 
+export const delegatesKathmandunetSample = {
+  full_balance: '965532868030',
+  current_frozen_deposits: '96350095609',
+  frozen_deposits: '96350095609',
+  staking_balance: '970221941952',
+  delegated_contracts: ['tz1cjyja1TU6fiyiFav3mFAdnDsCReJ12hPD'],
+  delegated_balance: '4689073922',
+  deactivated: false,
+  grace_period: 42,
+  voting_power: '968128693450',
+  remaining_proposals: 20,
+};
+
 export const blockIthacanetSample = {
   protocol: 'Psithaca2MLRFYargivpo7YvUr7wUDqyxrdhC5CQq78mRvimz6A',
   chain_id: 'NetXnHfVqm9iesp',
@@ -4654,6 +4667,112 @@ export const blockKathmandunetSample = {
         signature:
           'sigdUXgzV3FcbhV7qUAYGCbV86xZEpcBq1S3Acng974GvG8rULLnoNkXn1dvKvfbfvz3zChYCpjcDmR8f1shjAg1uSksceRp',
       },
+      {
+        protocol: 'PtKathmankSpLLDALzWw7CGD2j2MtyveTwboEYokqUCP4a1LxMg',
+        chain_id: 'NetXi2ZagzEsXbZ',
+        hash: 'oorMQ4cCHReHtUdyEqpWBjyAgu59AWYMzSP5bSwi2gSGGHBSLF5',
+        branch: 'BKuq9qvyUfiZH64z7J7nxKAt7HGA1m2rgiR24XrCsAEgBh2JJd1',
+        contents: [
+          {
+            kind: 'transaction',
+            source: 'tz1ejWMc4oNPuYJcs2UBFALuzQy3jKcZxEwL',
+            fee: '673',
+            counter: '84777',
+            gas_limit: '4224',
+            storage_limit: '0',
+            amount: '0',
+            destination: 'KT1D7mKRckD2ZoWGcGtUvBpDxb48WxpnLu1Q',
+            metadata: {
+              balance_updates: [
+                {
+                  kind: 'contract',
+                  contract: 'tz1ejWMc4oNPuYJcs2UBFALuzQy3jKcZxEwL',
+                  change: '-673',
+                  origin: 'block',
+                },
+                {
+                  kind: 'accumulator',
+                  category: 'block fees',
+                  change: '673',
+                  origin: 'block',
+                },
+              ],
+              operation_result: {
+                status: 'applied',
+                storage: {
+                  prim: 'Unit',
+                },
+                consumed_milligas: '2123011',
+                storage_size: '133',
+              },
+              internal_operation_results: [
+                {
+                  kind: 'event',
+                  source: 'KT1D7mKRckD2ZoWGcGtUvBpDxb48WxpnLu1Q',
+                  nonce: 0,
+                  type: {
+                    prim: 'or',
+                    args: [
+                      {
+                        prim: 'nat',
+                      },
+                      {
+                        prim: 'string',
+                      },
+                    ],
+                  },
+                  tag: 'event',
+                  payload: {
+                    prim: 'Left',
+                    args: [
+                      {
+                        int: '10',
+                      },
+                    ],
+                  },
+                  result: {
+                    status: 'applied',
+                    consumed_milligas: '1000000',
+                  },
+                },
+                {
+                  kind: 'event',
+                  source: 'KT1D7mKRckD2ZoWGcGtUvBpDxb48WxpnLu1Q',
+                  nonce: 1,
+                  type: {
+                    prim: 'or',
+                    args: [
+                      {
+                        prim: 'nat',
+                        annots: ['%number'],
+                      },
+                      {
+                        prim: 'string',
+                        annots: ['%words'],
+                      },
+                    ],
+                  },
+                  tag: 'event',
+                  payload: {
+                    prim: 'Right',
+                    args: [
+                      {
+                        string: 'lorem ipsum',
+                      },
+                    ],
+                  },
+                  result: {
+                    status: 'applied',
+                    consumed_milligas: '1000000',
+                  },
+                },
+              ],
+            },
+          },
+        ],
+        signature:
+          'sigfSTrupvjTWBW4NNXJHLyNEd6gUuD3Jzm9YZzSrH82X3somYZPpgCayRTkzmk1NwxGQCKJHLGsv7xxhVNKsgtxTqF8FEqe',
+      },
     ],
   ],
 };
diff --git a/packages/taquito-rpc/test/taquito-rpc.spec.ts b/packages/taquito-rpc/test/taquito-rpc.spec.ts
index cd7283bae..03d6d9747 100644
--- a/packages/taquito-rpc/test/taquito-rpc.spec.ts
+++ b/packages/taquito-rpc/test/taquito-rpc.spec.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
 /* eslint-disable @typescript-eslint/no-non-null-assertion */
 import { OpKind, RpcClient } from '../src/taquito-rpc';
 import BigNumber from 'bignumber.js';
@@ -25,12 +26,14 @@ import {
   Inode,
   OtherElts,
   OperationContentsAndResultIncreasePaidStorage,
+  OperationResultEvent,
 } from '../src/types';
 import {
   blockIthacanetSample,
   blockJakartanetSample,
   blockKathmandunetSample,
   delegatesIthacanetSample,
+  delegatesKathmandunetSample,
 } from './data/rpc-responses';
 
 /**
@@ -92,7 +95,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBalance', () => {
-    it('query the right url and return a string', async (done) => {
+    it('should query the right url and return a string', async (done) => {
       httpBackend.createRequest.mockReturnValue(Promise.resolve('10000'));
       const balance = await client.getBalance(contractAddress);
 
@@ -108,7 +111,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getStorage', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getStorage(contractAddress);
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -121,7 +124,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getScript', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getScript(contractAddress);
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -134,7 +137,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getNormalizedScript', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getNormalizedScript(contractAddress);
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -148,7 +151,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getContract', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       httpBackend.createRequest.mockResolvedValue({ balance: '10000' });
       const response = await client.getContract(contractAddress);
 
@@ -165,7 +168,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getManagerKey', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getManagerKey(contractAddress);
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -178,7 +181,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getDelegate', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getDelegate(contractAddress);
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -191,7 +194,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBlockHash', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getBlockHash();
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -221,7 +224,7 @@ describe('RpcClient test', () => {
       grace_period: 146,
     };
 
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       httpBackend.createRequest.mockResolvedValue(sampleResponse);
       await client.getDelegates(contractAddress);
 
@@ -233,7 +236,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('parse the response properly', async (done) => {
+    it('should parse the response properly', async (done) => {
       httpBackend.createRequest.mockResolvedValue(sampleResponse);
       const response = await client.getDelegates(contractAddress);
 
@@ -267,7 +270,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('parse the response properly, proto10', async (done) => {
+    it('should parse the response properly, proto10', async (done) => {
       // deposit replaced by deposits
       httpBackend.createRequest.mockResolvedValue({
         balance: '5976016544884',
@@ -313,7 +316,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('parse the response properly, proto12', async (done) => {
+    it('should parse the response properly, proto12', async (done) => {
       httpBackend.createRequest.mockResolvedValue(delegatesIthacanetSample);
       const response = await client.getDelegates(contractAddress);
 
@@ -331,10 +334,30 @@ describe('RpcClient test', () => {
 
       done();
     });
+
+    it('should parse the response properly, proto14', async (done) => {
+      httpBackend.createRequest.mockResolvedValue(delegatesKathmandunetSample);
+      const response = await client.getDelegates(contractAddress);
+
+      expect(response).toEqual({
+        full_balance: new BigNumber('965532868030'),
+        current_frozen_deposits: new BigNumber('96350095609'),
+        frozen_deposits: new BigNumber('96350095609'),
+        staking_balance: new BigNumber('970221941952'),
+        delegated_contracts: ['tz1cjyja1TU6fiyiFav3mFAdnDsCReJ12hPD'],
+        delegated_balance: new BigNumber('4689073922'),
+        deactivated: false,
+        grace_period: 42,
+        voting_power: new BigNumber(968128693450),
+        remaining_proposals: 20,
+      });
+
+      done();
+    });
   });
 
   describe('getBigMapKey', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getBigMapKey(contractAddress, { key: 'test', type: 'string' } as any);
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
         method: 'POST',
@@ -348,7 +371,7 @@ describe('RpcClient test', () => {
   });
 
   describe('forgeOperation', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.forgeOperations({} as any);
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
         method: 'POST',
@@ -362,7 +385,7 @@ describe('RpcClient test', () => {
   });
 
   describe('injectOperations', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.injectOperation({} as any);
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
         method: 'POST',
@@ -376,7 +399,7 @@ describe('RpcClient test', () => {
   });
 
   describe('preapplyOperations', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       httpBackend.createRequest.mockResolvedValue({});
       await client.preapplyOperations({} as any);
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -391,7 +414,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBlockHeader', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       const sampleResponse = {
         protocol: 'Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd',
         chain_id: 'NetXdQprcVkpaWU',
@@ -440,7 +463,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBlockMetadata', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       const sampleResponse = {
         protocol: 'Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd',
         next_protocol: 'Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd',
@@ -565,7 +588,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getConstants Proto014', () => {
-    it('query the right url and casts relevant properties to BigNumber', async (done) => {
+    it('should query the right url and casts relevant properties to BigNumber', async (done) => {
       httpBackend.createRequest.mockResolvedValue({
         proof_of_work_nonce_size: 8,
         nonce_length: 32,
@@ -752,7 +775,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getConstants Proto012', () => {
-    it('query the right url and casts property to BigNumber', async (done) => {
+    it('should query the right url and casts property to BigNumber', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           proof_of_work_nonce_size: 8,
@@ -860,7 +883,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getConstants Proto007', () => {
-    it('query the right url and casts property to BigNumber', async (done) => {
+    it('should query the right url and casts property to BigNumber', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           proof_of_work_nonce_size: 8,
@@ -935,7 +958,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getConstants Proto006', () => {
-    it('properties return by the RPC are accessible and the ones that do not belong to proto6 are undefined', async (done) => {
+    it('should properties return by the RPC are accessible and the ones that do not belong to proto6 are undefined', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           proof_of_work_nonce_size: 8,
@@ -991,7 +1014,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getConstants Proto005', () => {
-    it('properties return by the RPC are accessible and the ones that do not belong to proto5 are undefined', async (done) => {
+    it('should properties return by the RPC are accessible and the ones that do not belong to proto5 are undefined', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           proof_of_work_nonce_size: 8,
@@ -1057,7 +1080,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBlock', () => {
-    it('query the right url and property for endorsement', async (done) => {
+    it('should query the right url and property for endorsement', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd',
@@ -1198,7 +1221,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBlock', () => {
-    it('query the right url and property for operation', async (done) => {
+    it('should query the right url and property for operation', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA',
@@ -1441,7 +1464,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('query the right url and property for operation, proto 9, endorsement_with_slot', async (done) => {
+    it('should query the right url and property for operation, proto 9, endorsement_with_slot', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i',
@@ -1529,7 +1552,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('query the right url and properties (big_map_diff and lazy_storage_diff) in transaction operation result, proto 9', async (done) => {
+    it('should query the right url and properties (big_map_diff and lazy_storage_diff) in transaction operation result, proto 9', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i',
@@ -2131,7 +2154,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('query the right url and properties (lazy_storage_diff of kind sapling_state) in transaction operation result, proto 8', async (done) => {
+    it('should query the right url and properties (lazy_storage_diff of kind sapling_state) in transaction operation result, proto 8', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA',
@@ -2243,7 +2266,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('Access new properties "liquidity_baking_escape_ema", "implicit_operations_results" and "subsidy" in block metadata, proto 10', async (done) => {
+    it('should access new properties "liquidity_baking_escape_ema", "implicit_operations_results" and "subsidy" in block metadata, proto 10', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PtGRANADsDU8R9daYKAgWnQYAJ64omN1o3KMGVCykShA97vQbvV',
@@ -2368,7 +2391,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('fetches a block having a RegisterGlobalConstant operation and it validates its properties, proto 11', async (done) => {
+    it('should fetch a block having a RegisterGlobalConstant operation and it validates its properties, proto 11', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PtHangzHogokSuiMHemCuowEavgYTP8J5qQ9fQS793MHYFpCY3r',
@@ -3026,6 +3049,54 @@ describe('RpcClient test', () => {
       expect(content.metadata.operation_result.consumed_milligas).toEqual('1000000');
       done();
     });
+
+    it('should be able to access the properties of internal operation type event, proto14', async (done) => {
+      httpBackend.createRequest.mockReturnValue(Promise.resolve(blockKathmandunetSample));
+
+      const response = await client.getBlock();
+      const content = response.operations[3][1]
+        .contents[0] as OperationContentsAndResultTransaction;
+
+      expect(content.metadata.internal_operation_results).toBeDefined();
+      expect(content.metadata.internal_operation_results![0].kind).toEqual(OpKind.EVENT);
+      expect(content.metadata.internal_operation_results![0].source).toEqual(
+        'KT1D7mKRckD2ZoWGcGtUvBpDxb48WxpnLu1Q'
+      );
+      expect(content.metadata.internal_operation_results![0].nonce).toEqual(0);
+
+      expect(content.metadata.internal_operation_results![0].amount).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].destination).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].parameters).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].public_key).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].balance).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].delegate).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].value).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].limit).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].script).toBeUndefined();
+
+      expect(content.metadata.internal_operation_results![0].type).toBeDefined();
+      expect(content.metadata.internal_operation_results![0].type).toEqual({
+        prim: 'or',
+        args: [{ prim: 'nat' }, { prim: 'string' }],
+      });
+      expect(content.metadata.internal_operation_results![0].tag).toBeDefined();
+      expect(content.metadata.internal_operation_results![0].tag).toEqual('event');
+      expect(content.metadata.internal_operation_results![0].payload).toBeDefined();
+      expect(content.metadata.internal_operation_results![0].payload).toEqual({
+        prim: 'Left',
+        args: [{ int: '10' }],
+      });
+      expect(content.metadata.internal_operation_results![0].result).toBeDefined();
+
+      const internalResult = content.metadata.internal_operation_results![0]
+        .result as OperationResultEvent;
+      expect(internalResult.status).toEqual('applied');
+      expect(internalResult.consumed_milligas).toBeDefined();
+      expect(internalResult.consumed_milligas).toEqual('1000000');
+      expect(internalResult.errors).toBeUndefined();
+
+      done();
+    });
   });
 
   describe('getBakingRights', () => {
@@ -3109,7 +3180,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBallotList', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve([
           {
@@ -3151,7 +3222,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBallots', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(Promise.resolve({ yay: 5943, nay: 0, pass: 0 }));
       const response = await client.getBallots();
 
@@ -3166,7 +3237,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getCurrentProposal', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve('PsBABY5HQTSkA4297zNHfsZNKtxULfL18y95qb3m53QJiXGmrbU')
       );
@@ -3183,7 +3254,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getCurrentQuorum', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(Promise.resolve(7291));
       const response = await client.getCurrentQuorum();
 
@@ -3198,7 +3269,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getVotesListings', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve([
           {
@@ -3259,7 +3330,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getProposals', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve([
           ['PsBABY5HQTSkA4297zNHfsZNKtxULfL18y95qb3m53QJiXGmrbU', 2832],
@@ -3279,7 +3350,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getEntrypoints', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue({ entrypoints: {} });
       const response = await client.getEntrypoints(contractAddress);
 
@@ -3293,7 +3364,7 @@ describe('RpcClient test', () => {
   });
 
   describe('runOperation', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       const testData = {};
 
       httpBackend.createRequest.mockResolvedValue({ content: {} });
@@ -3353,7 +3424,7 @@ describe('RpcClient test', () => {
   });
 
   describe('runView', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       const testData: RPCRunViewParam = {
         contract: 'test',
         entrypoint: 'test',
@@ -3381,7 +3452,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('query the right url and data with unparsing_mode overriden', async (done) => {
+    it('should query the right url and data with unparsing_mode overriden', async (done) => {
       const testData: RPCRunViewParam = {
         contract: 'test',
         entrypoint: 'test',
@@ -3404,7 +3475,7 @@ describe('RpcClient test', () => {
   });
 
   describe('packData', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockResolvedValue({ packed: 'cafe', gas: 'unaccounted' });
       const response = await client.packData({
         data: { string: 'test' },
@@ -3420,7 +3491,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('return a big number for gas when it is a big number', async (done) => {
+    it('should return a big number for gas when it is a big number', async (done) => {
       httpBackend.createRequest.mockResolvedValue({ packed: 'cafe', gas: '2' });
       const response = await client.packData({
         data: { string: 'test' },
@@ -3432,7 +3503,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('return undefined for gas when it is missing', async (done) => {
+    it('should return undefined for gas when it is missing', async (done) => {
       httpBackend.createRequest.mockResolvedValue({ packed: 'cafe' });
       const response = await client.packData({
         data: { string: 'test' },
@@ -3445,7 +3516,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBigMapExpr', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       await client.getBigMapExpr('1', '2');
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -3457,7 +3528,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getRpcUrl', () => {
-    it('return the RPC Url', () => {
+    it('should return the RPC Url', () => {
       const url = 'https://mainnet.api.tez.ie/';
       const rpcUrlMainnet = new RpcClient(url).getRpcUrl();
       expect(rpcUrlMainnet).toEqual('https://mainnet.api.tez.ie/');
@@ -3467,7 +3538,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getCurrentPeriod', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       const mockedResponse = {
         voting_period: {
           index: 87,
@@ -3491,7 +3562,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getSuccessorPeriod', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       const mockedResponse = {
         voting_period: {
           index: 87,
@@ -3515,7 +3586,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getSaplingDiffById', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       httpBackend.createRequest.mockResolvedValue({
         root: 'fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e',
         commitments_and_ciphertexts: [],
@@ -3539,7 +3610,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getSaplingDiffByContract', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       httpBackend.createRequest.mockResolvedValue({
         root: 'fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e',
         commitments_and_ciphertexts: [],
@@ -3565,7 +3636,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getProtocols', () => {
-    it('query the right url and return a ProtocolsResponse', async (done) => {
+    it('should query the right url and return a ProtocolsResponse', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PtHangz2aRngywmSRGGvrcTyMbbdpWdpFKuS4uMWxg2RaH9i1qx',