From c93f36f54873903b4b16afffcf60d66068927eec Mon Sep 17 00:00:00 2001 From: hui-an-yang <106410553+hui-an-yang@users.noreply.github.com> Date: Mon, 28 Nov 2022 09:10:59 -0800 Subject: [PATCH] feat: removed Jakarta conditions in on chain view related files (#2138) re #2098 --- .../contract-execute-on-chain-view.spec.ts | 9 +- integration-tests/rpc-nodes.spec.ts | 6 +- .../contract-on-chain-view.ts | 161 ++----- .../contract/contract-on-chain-view.spec.ts | 433 ------------------ 4 files changed, 36 insertions(+), 573 deletions(-) diff --git a/integration-tests/contract-execute-on-chain-view.spec.ts b/integration-tests/contract-execute-on-chain-view.spec.ts index 3f270b3d3d..a898686eed 100644 --- a/integration-tests/contract-execute-on-chain-view.spec.ts +++ b/integration-tests/contract-execute-on-chain-view.spec.ts @@ -1,8 +1,7 @@ import { codeViewsTopLevel } from "./data/contract_views_top_level"; import { CONFIGS } from "./config"; import BigNumber from 'bignumber.js'; -import { Protocols, ViewSimulationError } from "@taquito/taquito"; -import { HttpResponseError } from "@taquito/http-utils"; +import { ViewSimulationError } from "@taquito/taquito"; CONFIGS().forEach(({ lib, rpc, setup }) => { const Tezos = lib; @@ -75,11 +74,7 @@ CONFIGS().forEach(({ lib, rpc, setup }) => { await contract.contractViews.test_failwith(3).executeView({ viewCaller: contract.address }); } catch (error: any) { const protocol = (await Tezos.rpc.getProtocols()).protocol - if(protocol === Protocols.PtJakart2) { - expect(error).toBeInstanceOf(HttpResponseError) - } else { - expect(error).toBeInstanceOf(ViewSimulationError) - } + expect(error).toBeInstanceOf(ViewSimulationError) } const viewSuccResult = await contract.contractViews.succ({ 0: 16, 1: contract.address }).executeView({ source, viewCaller: contract.address }); diff --git a/integration-tests/rpc-nodes.spec.ts b/integration-tests/rpc-nodes.spec.ts index d4fb6e256c..3d8823afe6 100644 --- a/integration-tests/rpc-nodes.spec.ts +++ b/integration-tests/rpc-nodes.spec.ts @@ -1,5 +1,5 @@ import { CONFIGS } from './config'; -import { Protocols, ChainIds } from "@taquito/taquito"; +import { Protocols } from "@taquito/taquito"; import { RpcClientCache, RpcClient, RPCRunViewParam, RPCRunScriptViewParam } from '@taquito/rpc'; import { encodeExpr } from '@taquito/utils'; import { Schema } from '@taquito/michelson-encoder'; @@ -126,7 +126,7 @@ CONFIGS().forEach( done(); }); - kathmandunetAndAlpha(`Fetches voting information about a delegate from RPC`, async (done) => { + it(`Fetches voting information about a delegate from RPC`, async (done) => { const votinInfo = await rpcClient.getVotingInfo(knownBaker); expect(votinInfo).toBeDefined(); done(); @@ -365,7 +365,7 @@ CONFIGS().forEach( done(); }); - kathmandunetAndAlpha('Verify that rpcClient.runScriptView executes michelson view', async (done) => { + it('Verify that rpcClient.runScriptView executes michelson view', async (done) => { const chainId = await Tezos.rpc.getChainId(); const params: RPCRunScriptViewParam = { contract: knownViewContract!, diff --git a/packages/taquito/src/contract/contract-methods/contract-on-chain-view.ts b/packages/taquito/src/contract/contract-methods/contract-on-chain-view.ts index c221812dba..88324f038f 100644 --- a/packages/taquito/src/contract/contract-methods/contract-on-chain-view.ts +++ b/packages/taquito/src/contract/contract-methods/contract-on-chain-view.ts @@ -14,45 +14,6 @@ import { ViewSimulationError, validateAndExtractFailwith, } from '../errors'; -import { Protocols } from '../../constants'; - -const runCodeHelper = ( - viewArgsType: MichelsonV1ExpressionExtended, - viewReturnType: MichelsonV1ExpressionExtended, - contractStorageType: MichelsonV1Expression, - viewInstructions: MichelsonV1ExpressionExtended[], - viewArgs: MichelsonV1Expression, - contractStorageValue: MichelsonV1Expression, - balance: string, - chain_id: string, - source?: string, - amount = '0' -): RPCRunCodeParam => { - return { - script: [ - { prim: 'parameter', args: [{ prim: 'pair', args: [viewArgsType, contractStorageType] }] }, - { prim: 'storage', args: [{ prim: 'option', args: [viewReturnType] }] }, - { - prim: 'code', - args: [ - [ - { prim: 'CAR' }, - viewInstructions, - { prim: 'SOME' }, - { prim: 'NIL', args: [{ prim: 'operation' }] }, - { prim: 'PAIR' }, - ], - ], - }, - ], - storage: { prim: 'None' }, - input: { prim: 'Pair', args: [viewArgs, contractStorageValue] }, - amount, - balance, - chain_id, - source, - }; -}; export interface ExecutionContextParams { source?: string; @@ -85,49 +46,20 @@ export class OnChainView { * @param executionContext.viewCaller the contract address which is the caller of view. */ async executeView(executionContext: ExecutionContextParams) { - const protocol = (await this._rpc.getProtocols()).protocol; - // TODO: remove if/else when support for Jakartanet is removed - if (protocol === Protocols.PtJakart2) { - this.verifyContextExecution(executionContext); - const balance = ( - await this._readProvider.getBalance(this._contractAddress, 'head') - ).toString(); - const chainId = await this._readProvider.getChainId(); - const storage = await this._readProvider.getStorage(this._contractAddress, 'head'); - return this.executeViewAndDecodeResult( - runCodeHelper( - this._smartContractViewSchema.viewArgsType, - this._smartContractViewSchema.viewReturnType, - this._contractStorageType, - this.adaptViewCodeToContext( - this._smartContractViewSchema.instructions, - executionContext.viewCaller, - balance - ), - this.transformArgsToMichelson(), - storage, - balance, - chainId, - executionContext.source - ), - protocol - ); - } else { - this.verifyContextExecution(executionContext); - const chainId = await this._readProvider.getChainId(); - const viewArgs = this.transformArgsToMichelson(); - const scriptView: RPCRunScriptViewParam = { - contract: this._contractAddress, - view: this._smartContractViewSchema.viewName, - input: viewArgs, - chain_id: chainId, - source: executionContext.viewCaller, - }; - if (executionContext.source) { - scriptView.payer = executionContext.source; - } - return this.executeViewAndDecodeResult(scriptView, protocol); + this.verifyContextExecution(executionContext); + const chainId = await this._readProvider.getChainId(); + const viewArgs = this.transformArgsToMichelson(); + const scriptView: RPCRunScriptViewParam = { + contract: this._contractAddress, + view: this._smartContractViewSchema.viewName, + input: viewArgs, + chain_id: chainId, + source: executionContext.viewCaller, + }; + if (executionContext.source) { + scriptView.payer = executionContext.source; } + return this.executeViewAndDecodeResult(scriptView); } private verifyContextExecution(executionContext: ExecutionContextParams) { @@ -198,55 +130,24 @@ export class OnChainView { return instructions; } - private async executeViewAndDecodeResult( - viewScript: RPCRunScriptViewParam | RPCRunCodeParam, - protocol: string - ) { - // TODO: remove if/else when support for Jakartanet is removed - if (protocol === Protocols.PtJakart2) { - let storage: MichelsonV1ExpressionExtended; - try { - storage = (await this._rpc.runCode(viewScript as RPCRunCodeParam)) - .storage as MichelsonV1ExpressionExtended; - } catch (error: any) { - const failWith = validateAndExtractFailwith(error); - throw failWith - ? new ViewSimulationError( - `The simulation of the on-chain view named ${ - this._smartContractViewSchema.viewName - } failed with: ${JSON.stringify(failWith)}`, - this._smartContractViewSchema.viewName, - failWith, - error - ) - : error; - } - if (!storage.args) { - throw new ViewSimulationError( - `View simulation failed with an invalid result: ${storage}`, - this._smartContractViewSchema.viewName - ); - } - return this._smartContractViewSchema.decodeViewResult(storage.args[0]); - } else { - let storage: MichelsonV1ExpressionExtended; - try { - storage = (await this._rpc.runScriptView(viewScript as RPCRunScriptViewParam)) - .data as MichelsonV1ExpressionExtended; - } catch (error: any) { - const failWith = validateAndExtractFailwith(error); - throw failWith - ? new ViewSimulationError( - `The simulation of the on-chain view named ${ - this._smartContractViewSchema.viewName - } failed with: ${JSON.stringify(failWith)}`, - this._smartContractViewSchema.viewName, - failWith, - error - ) - : error; - } - return this._smartContractViewSchema.decodeViewResult(storage); + private async executeViewAndDecodeResult(viewScript: RPCRunScriptViewParam | RPCRunCodeParam) { + let storage: MichelsonV1ExpressionExtended; + try { + storage = (await this._rpc.runScriptView(viewScript as RPCRunScriptViewParam)) + .data as MichelsonV1ExpressionExtended; + } catch (error: any) { + const failWith = validateAndExtractFailwith(error); + throw failWith + ? new ViewSimulationError( + `The simulation of the on-chain view named ${ + this._smartContractViewSchema.viewName + } failed with: ${JSON.stringify(failWith)}`, + this._smartContractViewSchema.viewName, + failWith, + error + ) + : error; } + return this._smartContractViewSchema.decodeViewResult(storage); } } diff --git a/packages/taquito/test/contract/contract-on-chain-view.spec.ts b/packages/taquito/test/contract/contract-on-chain-view.spec.ts index 1451168379..beeaf640d0 100644 --- a/packages/taquito/test/contract/contract-on-chain-view.spec.ts +++ b/packages/taquito/test/contract/contract-on-chain-view.spec.ts @@ -177,436 +177,3 @@ describe('OnChainView test on K protocol', () => { done(); }); }); - -describe('OnChainView test on J protocol', () => { - let view: OnChainView; - let mockRpcClient: { - getProtocols: jest.Mock; - getChainId: jest.Mock; - getBalance: jest.Mock; - runCode: jest.Mock; - getStorage: jest.Mock; - }; - let mockReadProvider: any; - beforeEach(() => { - mockRpcClient = { - getProtocols: jest.fn(), - getChainId: jest.fn(), - getBalance: jest.fn(), - runCode: jest.fn(), - getStorage: jest.fn(), - }; - mockRpcClient.getProtocols.mockResolvedValue({ protocol: Protocols.PtJakart2 }); - mockRpcClient.getChainId.mockResolvedValue('test_chain_id'); - mockRpcClient.getBalance.mockResolvedValue(new BigNumber(5000000)); - mockRpcClient.runCode.mockResolvedValue({ - storage: { prim: 'Some', args: [{ int: '23' }] }, - operations: [], - }); - mockRpcClient.getStorage.mockResolvedValue({ int: '3' }); - - mockReadProvider = new RpcReadAdapter(mockRpcClient as any); - - view = new OnChainView( - mockRpcClient as any, - mockReadProvider, - 'contractAddress', - new ViewSchema([ - { string: 'add' }, - { prim: 'nat' }, - { prim: 'nat' }, - [{ prim: 'UNPAIR' }, { prim: 'ADD' }], - ]), - { prim: 'nat' }, - 20 - ); - }); - - it('OnChainView is instantiable', () => { - expect(view).toBeInstanceOf(OnChainView); - }); - - it('should extract the signature of the view', () => { - expect(view.getSignature()).toEqual({ - parameter: 'nat', - result: 'nat', - }); - }); - - it('should execute of the view', async (done) => { - expect( - await view.executeView({ - viewCaller: 'KT1TRHzT3HdLe3whe35q6rNxavGx8WVFHSpH', - }) - ).toEqual(new BigNumber(23)); - - expect(mockRpcClient.getBalance).toHaveBeenCalledWith('contractAddress', { block: 'head' }); - expect(mockRpcClient.runCode).toHaveBeenCalledWith({ - script: [ - { prim: 'parameter', args: [{ prim: 'pair', args: [{ prim: 'nat' }, { prim: 'nat' }] }] }, - { prim: 'storage', args: [{ prim: 'option', args: [{ prim: 'nat' }] }] }, - { - prim: 'code', - args: [ - [ - { prim: 'CAR' }, - [{ prim: 'UNPAIR' }, { prim: 'ADD' }], - { prim: 'SOME' }, - { prim: 'NIL', args: [{ prim: 'operation' }] }, - { prim: 'PAIR' }, - ], - ], - }, - ], - storage: { prim: 'None' }, - input: { prim: 'Pair', args: [{ int: '20' }, { int: '3' }] }, - amount: '0', - balance: '5000000', - chain_id: 'test_chain_id', - }); - - done(); - }); - - it('should adapt the instructions SENDER, SELF_ADDRESS, BALANCE and AMOUNT to the context before executing the view', async (done) => { - const view = new OnChainView( - mockRpcClient as any, - mockReadProvider, - 'contractAddress', - new ViewSchema([ - { string: 'viewName' }, - { prim: 'nat' }, - { prim: 'nat' }, - [{ prim: 'SENDER' }, { prim: 'SELF_ADDRESS' }, { prim: 'BALANCE' }, { prim: 'AMOUNT' }], - ]), - { prim: 'nat' }, - 20 - ); - await view.executeView({ - viewCaller: 'KT1TRHzT3HdLe3whe35q6rNxavGx8WVFHSpH', - }); - - expect(mockRpcClient.getBalance).toHaveBeenCalledWith('contractAddress', { block: 'head' }); - expect(mockRpcClient.runCode).toHaveBeenCalledWith({ - script: [ - { prim: 'parameter', args: [{ prim: 'pair', args: [{ prim: 'nat' }, { prim: 'nat' }] }] }, - { prim: 'storage', args: [{ prim: 'option', args: [{ prim: 'nat' }] }] }, - { - prim: 'code', - args: [ - [ - { prim: 'CAR' }, - [ - [ - { - prim: 'PUSH', - args: [{ prim: 'address' }, { string: 'KT1TRHzT3HdLe3whe35q6rNxavGx8WVFHSpH' }], - }, - ], - [{ prim: 'PUSH', args: [{ prim: 'address' }, { string: 'contractAddress' }] }], - [{ prim: 'PUSH', args: [{ prim: 'mutez' }, { int: '5000000' }] }], - [{ prim: 'PUSH', args: [{ prim: 'mutez' }, { int: '0' }] }], - ], - { prim: 'SOME' }, - { prim: 'NIL', args: [{ prim: 'operation' }] }, - { prim: 'PAIR' }, - ], - ], - }, - ], - storage: { prim: 'None' }, - input: { prim: 'Pair', args: [{ int: '20' }, { int: '3' }] }, - amount: '0', - balance: '5000000', - chain_id: 'test_chain_id', - }); - - done(); - }); - - it('should adapt the view instructions to the context before executing it when there are nested instructions to replace', async (done) => { - // All occurences of `{ prim: 'SELF_ADDRESS' }` in the view instructions need to be replace with `[{ prim: 'PUSH', args: [{ prim: 'address' }, { string: 'contractAddress' }] }]` - const view = new OnChainView( - mockRpcClient as any, - mockReadProvider, - 'contractAddress', - new ViewSchema([ - { string: 'viewName' }, - { prim: 'nat' }, - { prim: 'nat' }, - [ - { prim: 'CAR' }, - { prim: 'DUP' }, - { prim: 'PUSH', args: [{ prim: 'nat' }, { int: '0' }] }, - { prim: 'COMPARE' }, - { prim: 'EQ' }, - { - prim: 'IF', - args: [ - [], - [ - { prim: 'DUP' }, - { prim: 'PUSH', args: [{ prim: 'nat' }, { int: '1' }] }, - { prim: 'COMPARE' }, - { prim: 'EQ' }, - { - prim: 'IF', - args: [ - [], - [ - { prim: 'DUP' }, - { prim: 'PUSH', args: [{ prim: 'nat' }, { int: '1' }] }, - { prim: 'SWAP' }, - { prim: 'SUB' }, - { prim: 'ABS' }, - { prim: 'SELF_ADDRESS' }, - { prim: 'SWAP' }, - { prim: 'VIEW', args: [{ string: 'fib' }, { prim: 'nat' }] }, - [ - { - prim: 'IF_NONE', - args: [ - [[{ prim: 'UNIT' }, { prim: 'FAILWITH' }]], - [ - { prim: 'SWAP' }, - { prim: 'PUSH', args: [{ prim: 'nat' }, { int: '2' }] }, - { prim: 'SWAP' }, - { prim: 'SUB' }, - { prim: 'ABS' }, - { prim: 'SELF_ADDRESS' }, - { prim: 'SWAP' }, - { prim: 'VIEW', args: [{ string: 'fib' }, { prim: 'nat' }] }, - [ - { - prim: 'IF_NONE', - args: [ - [[{ prim: 'UNIT' }, { prim: 'FAILWITH' }]], - [{ prim: 'ADD' }], - ], - }, - ], - ], - ], - }, - ], - ], - ], - }, - ], - ], - }, - ], - ]), - { prim: 'nat' }, - 20 - ); - await view.executeView({ - viewCaller: 'KT1TRHzT3HdLe3whe35q6rNxavGx8WVFHSpH', - }); - - expect(mockRpcClient.getBalance).toHaveBeenCalledWith('contractAddress', { block: 'head' }); - expect(mockRpcClient.runCode).toHaveBeenCalledWith({ - script: [ - { prim: 'parameter', args: [{ prim: 'pair', args: [{ prim: 'nat' }, { prim: 'nat' }] }] }, - { prim: 'storage', args: [{ prim: 'option', args: [{ prim: 'nat' }] }] }, - { - prim: 'code', - args: [ - [ - { prim: 'CAR' }, - [ - { prim: 'CAR' }, - { prim: 'DUP' }, - { prim: 'PUSH', args: [{ prim: 'nat' }, { int: '0' }] }, - { prim: 'COMPARE' }, - { prim: 'EQ' }, - { - prim: 'IF', - args: [ - [], - [ - { prim: 'DUP' }, - { prim: 'PUSH', args: [{ prim: 'nat' }, { int: '1' }] }, - { prim: 'COMPARE' }, - { prim: 'EQ' }, - { - prim: 'IF', - args: [ - [], - [ - { prim: 'DUP' }, - { prim: 'PUSH', args: [{ prim: 'nat' }, { int: '1' }] }, - { prim: 'SWAP' }, - { prim: 'SUB' }, - { prim: 'ABS' }, - [ - { - prim: 'PUSH', - args: [{ prim: 'address' }, { string: 'contractAddress' }], - }, - ], - { prim: 'SWAP' }, - { prim: 'VIEW', args: [{ string: 'fib' }, { prim: 'nat' }] }, - [ - { - prim: 'IF_NONE', - args: [ - [[{ prim: 'UNIT' }, { prim: 'FAILWITH' }]], - [ - { prim: 'SWAP' }, - { prim: 'PUSH', args: [{ prim: 'nat' }, { int: '2' }] }, - { prim: 'SWAP' }, - { prim: 'SUB' }, - { prim: 'ABS' }, - [ - { - prim: 'PUSH', - args: [{ prim: 'address' }, { string: 'contractAddress' }], - }, - ], - { prim: 'SWAP' }, - { prim: 'VIEW', args: [{ string: 'fib' }, { prim: 'nat' }] }, - [ - { - prim: 'IF_NONE', - args: [ - [[{ prim: 'UNIT' }, { prim: 'FAILWITH' }]], - [{ prim: 'ADD' }], - ], - }, - ], - ], - ], - }, - ], - ], - ], - }, - ], - ], - }, - ], - { prim: 'SOME' }, - { prim: 'NIL', args: [{ prim: 'operation' }] }, - { prim: 'PAIR' }, - ], - ], - }, - ], - storage: { prim: 'None' }, - input: { prim: 'Pair', args: [{ int: '20' }, { int: '3' }] }, - amount: '0', - balance: '5000000', - chain_id: 'test_chain_id', - }); - - done(); - }); - - it('should throw an error if the caller of the view is an invalid contract address', async (done) => { - try { - await view.executeView({ - viewCaller: 'notAnAddress', - }); - } catch (error) { - expect(error).toBeInstanceOf(InvalidViewSimulationContext); - } - done(); - }); - - it('should throw an error if an invalid address is set as the source of the view', async (done) => { - try { - await view.executeView({ - source: 'notAnAddress', - viewCaller: 'KT1TRHzT3HdLe3whe35q6rNxavGx8WVFHSpH', - }); - } catch (error) { - expect(error).toBeInstanceOf(InvalidViewSimulationContext); - } - done(); - }); - - it('should throw an error if the view response is invalid', async (done) => { - mockRpcClient.runCode.mockResolvedValue({ storage: {}, operations: [] }); - try { - await view.executeView({ - viewCaller: 'KT1TRHzT3HdLe3whe35q6rNxavGx8WVFHSpH', - }); - } catch (error) { - expect(error).toBeInstanceOf(ViewSimulationError); - } - done(); - }); - - it('should throw the original error when it does not contain a "with" property', async (done) => { - const httpError = new HttpResponseError( - 'fail', - STATUS_CODE.FORBIDDEN, - 'err', - 'test', - 'https://test.com' - ); - mockRpcClient.runCode.mockRejectedValue(httpError); - - try { - await view.executeView({ - viewCaller: 'KT1TRHzT3HdLe3whe35q6rNxavGx8WVFHSpH', - }); - } catch (error: any) { - expect(error).toBeInstanceOf(HttpResponseError); - } - - done(); - }); - - it('should throw a ViewSimulationError error with a detailed message if the view simulation reaches a failwith instruction', async (done) => { - const httpError = new HttpResponseError( - 'fail', - STATUS_CODE.FORBIDDEN, - 'err', - '[{},{"kind":"temporary","with":{"prim":"Unit"}}]', - 'https://test.com' - ); - mockRpcClient.runCode.mockRejectedValue(httpError); - - try { - await view.executeView({ - viewCaller: 'KT1TRHzT3HdLe3whe35q6rNxavGx8WVFHSpH', - }); - } catch (error: any) { - expect(error).toBeInstanceOf(ViewSimulationError); - expect(error.message).toEqual( - 'The simulation of the on-chain view named add failed with: {"prim":"Unit"}' - ); - expect(error.viewName).toEqual('add'); - expect(error.failWith).toEqual({ prim: 'Unit' }); - expect(error.originalError).toEqual(httpError); - } - - done(); - }); - - it('should throw a InvalidViewParameterError error if the parameter of the view is invalid', async (done) => { - view = new OnChainView( - mockRpcClient as any, - mockReadProvider, - 'contractAddress', - new ViewSchema([ - { string: 'add' }, - { prim: 'nat' }, - { prim: 'nat' }, - [{ prim: 'UNPAIR' }, { prim: 'ADD' }], - ]), - { prim: 'nat' }, - 'test' - ); - try { - await view.executeView({ - viewCaller: 'KT1TRHzT3HdLe3whe35q6rNxavGx8WVFHSpH', - }); - } catch (error) { - expect(error).toBeInstanceOf(InvalidViewParameterError); - } - done(); - }); -});