diff --git a/docs/web3-eth.rst b/docs/web3-eth.rst index 2c192ff2d15..cba1dd6e111 100644 --- a/docs/web3-eth.rst +++ b/docs/web3-eth.rst @@ -760,7 +760,7 @@ Example web3.eth.getPendingTransactions().then(console.log); > [ - { + { blockHash: '0x0000000000000000000000000000000000000000000000000000000000000000', blockNumber: null, from: '0x28bdb9c230f4d5e45435e4d006326ee32e46cb31', @@ -774,8 +774,8 @@ Example value: '0x0', v: '0x3d', r: '0xaabc9ddafffb2ae0bac4107697547d22d9383667d9e97f5409dd6881ce08f13f', - s: '0x69e43116be8f842dcd4a0b2f760043737a59534430b762317db21d9ac8c5034' - },....,{ + s: '0x69e43116be8f842dcd4a0b2f760043737a59534430b762317db21d9ac8c5034' + },....,{ blockHash: '0x0000000000000000000000000000000000000000000000000000000000000000', blockNumber: null, from: '0x28bdb9c230f4d5e45435e4d006326ee32e487b31', @@ -789,7 +789,7 @@ Example value: '0x0', v: '0x3d', r: '0x1ec191ef20b0e9628c4397665977cbe7a53a263c04f6f185132b77fa0fd5ca44', - s: '0x8a58e00c63e05cfeae4f1cf19f05ce82079dc4d5857e2cc281b7797d58b5faf' + s: '0x8a58e00c63e05cfeae4f1cf19f05ce82079dc4d5857e2cc281b7797d58b5faf' } ] @@ -1489,7 +1489,7 @@ Example .. _eth-getNodeInfo: getNodeInfo -========== +=========== .. code-block:: javascript @@ -1512,3 +1512,78 @@ Example > "Mist/v0.9.3/darwin/go1.4.1" ------------------------------------------------------------------------------ + +.. _eth-getProof: + +getProof +======== + +.. code-block:: javascript + + web3.eth.getProof(address, storageKey, blockNumber, [callback]) + +Returns the account and storage-values of the specified account including the Merkle-proof as described in `EIP-1186 `_. + +---------- +Parameters +---------- + +1. ``String`` 20 Bytes: The Address of the account or contract. +2. ``Array`` 32 Bytes: Array of storage-keys which should be proofed and included. See :ref:`web3.eth.getStorageAt `. +3. ``Number | String | "latest" | "earliest"``: Integer block number, or the string "latest" or "earliest". +4. ``Function`` - (optional) Optional callback, returns an error object as first parameter and the result as second. + +------- +Returns +------- + +``Promise`` - A account object. + + ``balance`` - The balance of the account. See :ref:`web3.eth.getBalance `. + ``codeHash`` - hash of the code of the account. For a simple Account without code it will return "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + ``nonce`` - Nonce of the account. + ``storageHash`` - SHA3 of the StorageRoot. All storage will deliver a MerkleProof starting with this rootHash. + ``accountProof`` - Array of rlp-serialized MerkleTree-Nodes, starting with the stateRoot-Node, following the path of the SHA3 (address) as key. + ``storageProof`` - Array of storage-entries as requested. + ``key`` - The requested storage key. + ``value`` - The storage value. + +------- +Example +------- + + +.. code-block:: javascript + + web3.eth.getProof( + "0x1234567890123456789012345678901234567890", + ["0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001"], + "latest" + ).then(console.log); + > { + "address": "0x1234567890123456789012345678901234567890", + "accountProof": [ + "0xf90211a090dcaf88c40c7bbc95a912cbdde67c175767b31173df9ee4b0d733bfdd511c43a0babe369f6b12092f49181ae04ca173fb68d1a5456f18d20fa32cba73954052bda0473ecf8a7e36a829e75039a3b055e51b8332cbf03324ab4af2066bbd6fbf0021a0bbda34753d7aa6c38e603f360244e8f59611921d9e1f128372fec0d586d4f9e0a04e44caecff45c9891f74f6a2156735886eedf6f1a733628ebc802ec79d844648a0a5f3f2f7542148c973977c8a1e154c4300fec92f755f7846f1b734d3ab1d90e7a0e823850f50bf72baae9d1733a36a444ab65d0a6faaba404f0583ce0ca4dad92da0f7a00cbe7d4b30b11faea3ae61b7f1f2b315b61d9f6bd68bfe587ad0eeceb721a07117ef9fc932f1a88e908eaead8565c19b5645dc9e5b1b6e841c5edbdfd71681a069eb2de283f32c11f859d7bcf93da23990d3e662935ed4d6b39ce3673ec84472a0203d26456312bbc4da5cd293b75b840fc5045e493d6f904d180823ec22bfed8ea09287b5c21f2254af4e64fca76acc5cd87399c7f1ede818db4326c98ce2dc2208a06fc2d754e304c48ce6a517753c62b1a9c1d5925b89707486d7fc08919e0a94eca07b1c54f15e299bd58bdfef9741538c7828b5d7d11a489f9c20d052b3471df475a051f9dd3739a927c89e357580a4c97b40234aa01ed3d5e0390dc982a7975880a0a089d613f26159af43616fd9455bb461f4869bfede26f2130835ed067a8b967bfb80", + "0xf90211a0395d87a95873cd98c21cf1df9421af03f7247880a2554e20738eec2c7507a494a0bcf6546339a1e7e14eb8fb572a968d217d2a0d1f3bc4257b22ef5333e9e4433ca012ae12498af8b2752c99efce07f3feef8ec910493be749acd63822c3558e6671a0dbf51303afdc36fc0c2d68a9bb05dab4f4917e7531e4a37ab0a153472d1b86e2a0ae90b50f067d9a2244e3d975233c0a0558c39ee152969f6678790abf773a9621a01d65cd682cc1be7c5e38d8da5c942e0a73eeaef10f387340a40a106699d494c3a06163b53d956c55544390c13634ea9aa75309f4fd866f312586942daf0f60fb37a058a52c1e858b1382a8893eb9c1f111f266eb9e21e6137aff0dddea243a567000a037b4b100761e02de63ea5f1fcfcf43e81a372dafb4419d126342136d329b7a7ba032472415864b08f808ba4374092003c8d7c40a9f7f9fe9cc8291f62538e1cc14a074e238ff5ec96b810364515551344100138916594d6af966170ff326a092fab0a0d31ac4eef14a79845200a496662e92186ca8b55e29ed0f9f59dbc6b521b116fea090607784fe738458b63c1942bba7c0321ae77e18df4961b2bc66727ea996464ea078f757653c1b63f72aff3dcc3f2a2e4c8cb4a9d36d1117c742833c84e20de994a0f78407de07f4b4cb4f899dfb95eedeb4049aeb5fc1635d65cf2f2f4dfd25d1d7a0862037513ba9d45354dd3e36264aceb2b862ac79d2050f14c95657e43a51b85c80", + "0xf90171a04ad705ea7bf04339fa36b124fa221379bd5a38ffe9a6112cb2d94be3a437b879a08e45b5f72e8149c01efcb71429841d6a8879d4bbe27335604a5bff8dfdf85dcea00313d9b2f7c03733d6549ea3b810e5262ed844ea12f70993d87d3e0f04e3979ea0b59e3cdd6750fa8b15164612a5cb6567cdfb386d4e0137fccee5f35ab55d0efda0fe6db56e42f2057a071c980a778d9a0b61038f269dd74a0e90155b3f40f14364a08538587f2378a0849f9608942cf481da4120c360f8391bbcc225d811823c6432a026eac94e755534e16f9552e73025d6d9c30d1d7682a4cb5bd7741ddabfd48c50a041557da9a74ca68da793e743e81e2029b2835e1cc16e9e25bd0c1e89d4ccad6980a041dda0a40a21ade3a20fcd1a4abb2a42b74e9a32b02424ff8db4ea708a5e0fb9a09aaf8326a51f613607a8685f57458329b41e938bb761131a5747e066b81a0a16808080a022e6cef138e16d2272ef58434ddf49260dc1de1f8ad6dfca3da5d2a92aaaadc58080", + "0xf851808080a009833150c367df138f1538689984b8a84fc55692d3d41fe4d1e5720ff5483a6980808080808080808080a0a319c1c415b271afc0adcb664e67738d103ac168e0bc0b7bd2da7966165cb9518080" + ], + "balance": 0, + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0, + "storageHash": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "storageProof": [ + { + "key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "value": '0', + "proof": [] + }, + { + "key": "0x0000000000000000000000000000000000000000000000000000000000000001", + "value": '0', + "proof": [] + } + ] + } + +------------------------------------------------------------------------------ diff --git a/packages/web3-core-method/src/index.js b/packages/web3-core-method/src/index.js index d0a4c7d928f..b0bd200c27e 100644 --- a/packages/web3-core-method/src/index.js +++ b/packages/web3-core-method/src/index.js @@ -43,6 +43,7 @@ export IsSyncingMethod from './methods/node/IsSyncingMethod'; export GetGasPriceMethod from './methods/node/GetGasPriceMethod'; export SubmitWorkMethod from './methods/node/SubmitWorkMethod'; export GetWorkMethod from './methods/node/GetWorkMethod'; +export GetProofMethod from './methods/node/GetProofMethod'; // Account export GetAccountsMethod from './methods/account/GetAccountsMethod'; diff --git a/packages/web3-core-method/src/methods/node/GetProofMethod.js b/packages/web3-core-method/src/methods/node/GetProofMethod.js new file mode 100644 index 00000000000..40fc233112f --- /dev/null +++ b/packages/web3-core-method/src/methods/node/GetProofMethod.js @@ -0,0 +1,56 @@ +/* + This file is part of web3.js. + + web3.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + web3.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with web3.js. If not, see . +*/ +/** + * @file GetProofMethod.js + * @author Prince Sinha + * @date 2019 + */ + +import AbstractMethod from '../../../lib/methods/AbstractMethod'; + +export default class GetProofMethod extends AbstractMethod { + /** + * @param {Utils} utils + * @param {Object} formatters + * @param {AbstractWeb3Module} moduleInstance + * + * @constructor + */ + constructor(utils, formatters, moduleInstance) { + super('eth_getProof', 3, utils, formatters, moduleInstance); + } + + /** + * This method will be executed after the RPC request. + * + * @method afterExecution + * + * @param {Object} response + * + * @returns {Object} + */ + afterExecution(response) { + response.nonce = this.utils.toBN(response.nonce).toString(10); + response.balance = this.utils.toBN(response.balance).toString(10); + + for (let i = 0; i < response.storageProof.length; i++) { + response.storageProof[i].value = this.utils.toBN(response.storageProof[i].value).toString(10); + } + + return response; + } +} diff --git a/packages/web3-core-method/tests/src/methods/node/GetProofMethodTest.js b/packages/web3-core-method/tests/src/methods/node/GetProofMethodTest.js new file mode 100644 index 00000000000..54a456c9697 --- /dev/null +++ b/packages/web3-core-method/tests/src/methods/node/GetProofMethodTest.js @@ -0,0 +1,65 @@ +import * as Utils from 'web3-utils'; +import AbstractMethod from '../../../../lib/methods/AbstractMethod'; +import GetProofMethod from '../../../../src/methods/node/GetProofMethod'; + +/** + * GetProofMethod test + */ +describe('GetProofMethodTest', () => { + let method; + + beforeEach(() => { + method = new GetProofMethod(Utils, null, {}); + }); + + it('constructor check', () => { + expect(method).toBeInstanceOf(AbstractMethod); + + expect(method.rpcMethod).toEqual('eth_getProof'); + + expect(method.parametersAmount).toEqual(3); + + expect(method.utils).toEqual(Utils); + + expect(method.formatters).toEqual(null); + }); + + it('afterExecution should map the response', () => { + const response = { + address: '0x1234567890123456789012345678901234567890', + accountProof: [ + '0xf90211a090dcaf88c40c7bbc95a912cbdde67c175767b31173df9ee4b0d733bfdd511c43a0babe369f6b12092f49181ae04ca173fb68d1a5456f18d20fa32cba73954052bda0473ecf8a7e36a829e75039a3b055e51b8332cbf03324ab4af2066bbd6fbf0021a0bbda34753d7aa6c38e603f360244e8f59611921d9e1f128372fec0d586d4f9e0a04e44caecff45c9891f74f6a2156735886eedf6f1a733628ebc802ec79d844648a0a5f3f2f7542148c973977c8a1e154c4300fec92f755f7846f1b734d3ab1d90e7a0e823850f50bf72baae9d1733a36a444ab65d0a6faaba404f0583ce0ca4dad92da0f7a00cbe7d4b30b11faea3ae61b7f1f2b315b61d9f6bd68bfe587ad0eeceb721a07117ef9fc932f1a88e908eaead8565c19b5645dc9e5b1b6e841c5edbdfd71681a069eb2de283f32c11f859d7bcf93da23990d3e662935ed4d6b39ce3673ec84472a0203d26456312bbc4da5cd293b75b840fc5045e493d6f904d180823ec22bfed8ea09287b5c21f2254af4e64fca76acc5cd87399c7f1ede818db4326c98ce2dc2208a06fc2d754e304c48ce6a517753c62b1a9c1d5925b89707486d7fc08919e0a94eca07b1c54f15e299bd58bdfef9741538c7828b5d7d11a489f9c20d052b3471df475a051f9dd3739a927c89e357580a4c97b40234aa01ed3d5e0390dc982a7975880a0a089d613f26159af43616fd9455bb461f4869bfede26f2130835ed067a8b967bfb80', + '0xf90211a0395d87a95873cd98c21cf1df9421af03f7247880a2554e20738eec2c7507a494a0bcf6546339a1e7e14eb8fb572a968d217d2a0d1f3bc4257b22ef5333e9e4433ca012ae12498af8b2752c99efce07f3feef8ec910493be749acd63822c3558e6671a0dbf51303afdc36fc0c2d68a9bb05dab4f4917e7531e4a37ab0a153472d1b86e2a0ae90b50f067d9a2244e3d975233c0a0558c39ee152969f6678790abf773a9621a01d65cd682cc1be7c5e38d8da5c942e0a73eeaef10f387340a40a106699d494c3a06163b53d956c55544390c13634ea9aa75309f4fd866f312586942daf0f60fb37a058a52c1e858b1382a8893eb9c1f111f266eb9e21e6137aff0dddea243a567000a037b4b100761e02de63ea5f1fcfcf43e81a372dafb4419d126342136d329b7a7ba032472415864b08f808ba4374092003c8d7c40a9f7f9fe9cc8291f62538e1cc14a074e238ff5ec96b810364515551344100138916594d6af966170ff326a092fab0a0d31ac4eef14a79845200a496662e92186ca8b55e29ed0f9f59dbc6b521b116fea090607784fe738458b63c1942bba7c0321ae77e18df4961b2bc66727ea996464ea078f757653c1b63f72aff3dcc3f2a2e4c8cb4a9d36d1117c742833c84e20de994a0f78407de07f4b4cb4f899dfb95eedeb4049aeb5fc1635d65cf2f2f4dfd25d1d7a0862037513ba9d45354dd3e36264aceb2b862ac79d2050f14c95657e43a51b85c80', + '0xf90171a04ad705ea7bf04339fa36b124fa221379bd5a38ffe9a6112cb2d94be3a437b879a08e45b5f72e8149c01efcb71429841d6a8879d4bbe27335604a5bff8dfdf85dcea00313d9b2f7c03733d6549ea3b810e5262ed844ea12f70993d87d3e0f04e3979ea0b59e3cdd6750fa8b15164612a5cb6567cdfb386d4e0137fccee5f35ab55d0efda0fe6db56e42f2057a071c980a778d9a0b61038f269dd74a0e90155b3f40f14364a08538587f2378a0849f9608942cf481da4120c360f8391bbcc225d811823c6432a026eac94e755534e16f9552e73025d6d9c30d1d7682a4cb5bd7741ddabfd48c50a041557da9a74ca68da793e743e81e2029b2835e1cc16e9e25bd0c1e89d4ccad6980a041dda0a40a21ade3a20fcd1a4abb2a42b74e9a32b02424ff8db4ea708a5e0fb9a09aaf8326a51f613607a8685f57458329b41e938bb761131a5747e066b81a0a16808080a022e6cef138e16d2272ef58434ddf49260dc1de1f8ad6dfca3da5d2a92aaaadc58080', + '0xf851808080a009833150c367df138f1538689984b8a84fc55692d3d41fe4d1e5720ff5483a6980808080808080808080a0a319c1c415b271afc0adcb664e67738d103ac168e0bc0b7bd2da7966165cb9518080' + ], + balance: '0x13f306a2409fc0000', + codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', + nonce: '0x1', + storageHash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', + storageProof: [ + { + key: '0x0000000000000000000000000000000000000000000000000000000000000000', + value: '0x0', + proof: [] + }, + { + key: '0x0000000000000000000000000000000000000000000000000000000000000001', + value: '0x0', + proof: [] + } + ] + }; + + const actualResponse = method.afterExecution(response); + + expect(actualResponse.nonce).toEqual('1'); + expect(actualResponse.balance).toEqual('23000000000000000000'); + + for (let i = 0; i < response.storageProof.length; i++) { + var actual = actualResponse.storageProof[i].value; + + expect(actual).toBe('0'); + } + }); +}); diff --git a/packages/web3-eth/src/factories/MethodFactory.js b/packages/web3-eth/src/factories/MethodFactory.js index f3fed3b7d1d..f0ae7ac607d 100644 --- a/packages/web3-eth/src/factories/MethodFactory.js +++ b/packages/web3-eth/src/factories/MethodFactory.js @@ -46,7 +46,8 @@ import { SubmitWorkMethod, VersionMethod, SendRawTransactionMethod, - EthSendTransactionMethod + EthSendTransactionMethod, + GetProofMethod } from 'web3-core-method'; import GetBlockMethod from '../methods/GetBlockMethod'; @@ -101,7 +102,8 @@ export default class MethodFactory extends AbstractMethodFactory { getPastLogs: GetPastLogsMethod, requestAccounts: RequestAccountsMethod, getId: VersionMethod, - getChainId: ChainIdMethod + getChainId: ChainIdMethod, + getProof: GetProofMethod }; } } diff --git a/packages/web3-eth/tests/src/factories/MethodFactoryTest.js b/packages/web3-eth/tests/src/factories/MethodFactoryTest.js index 91873e33c5b..7268096ab4d 100644 --- a/packages/web3-eth/tests/src/factories/MethodFactoryTest.js +++ b/packages/web3-eth/tests/src/factories/MethodFactoryTest.js @@ -23,7 +23,8 @@ import { RequestAccountsMethod, SendRawTransactionMethod, SubmitWorkMethod, - VersionMethod + VersionMethod, + GetProofMethod } from 'web3-core-method'; import * as Utils from 'web3-utils'; import {formatters} from 'web3-core-helpers'; @@ -90,7 +91,8 @@ describe('MethodFactoryTest', () => { getPastLogs: GetPastLogsMethod, requestAccounts: RequestAccountsMethod, getChainId: ChainIdMethod, - getId: VersionMethod + getId: VersionMethod, + getProof: GetProofMethod }); }); }); diff --git a/packages/web3-eth/types/index.d.ts b/packages/web3-eth/types/index.d.ts index 32f637d065c..ac7fb275eae 100644 --- a/packages/web3-eth/types/index.d.ts +++ b/packages/web3-eth/types/index.d.ts @@ -145,6 +145,8 @@ export class Eth extends AbstractWeb3Module { submitWork(data: [string, string, string], callback?: (error: Error, result: boolean) => void): Promise; pendingTransactions(callback?: (error: Error, result: []) => void): Promise<[]>; + + getProof(address: string, storageKey: string[], blockNumber: number | string | "latest" | "earliest", callback?: (error: Error, result: GetProof) => void): Promise; } export interface Methods { @@ -220,3 +222,23 @@ export interface Subscription { on(type: 'error', handler: (data: Error) => void): void } + +export interface GetProof { + jsonrpc: string; + id: number; + result: { + address: string; + accountProof: string[]; + balance: string; + codeHash: string; + nonce: string; + storageHash: string; + storageProof: StorageProof[]; + }; +} + +export interface StorageProof { + key: string; + value: string; + proof: string[]; +} diff --git a/packages/web3-eth/types/tests/eth.tests.ts b/packages/web3-eth/types/tests/eth.tests.ts index 6aa503a35e6..f16a7cb0f88 100644 --- a/packages/web3-eth/types/tests/eth.tests.ts +++ b/packages/web3-eth/types/tests/eth.tests.ts @@ -14,11 +14,12 @@ /** * @file eth-tests.ts * @author Josh Stevens + * @author Prince Sinha * @date 2018 */ import {Log, Transaction, TransactionReceipt, RLPEncodedTransaction} from 'web3-core'; -import {Eth, BlockHeader, Syncing, Block} from 'web3-eth'; +import {Eth, BlockHeader, Syncing, Block, GetProof} from 'web3-eth'; const eth = new Eth('http://localhost:8545'); @@ -457,3 +458,33 @@ eth.pendingTransactions(); // $ExpectType Promise<[]> eth.pendingTransactions((error: Error, result: []) => {}); + +// $ExpectType Promise +eth.getProof( + "0x1234567890123456789012345678901234567890", + ["0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001"], + "latest" +); + +// $ExpectType Promise +eth.getProof( + "0x1234567890123456789012345678901234567890", + ["0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001"], + "latest", + (error: Error, result: GetProof) => {} +); + +// $ExpectType Promise +eth.getProof( + "0x1234567890123456789012345678901234567890", + ["0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001"], + 10 +); + +// $ExpectType Promise +eth.getProof( + "0x1234567890123456789012345678901234567890", + ["0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001"], + 10, + (error: Error, result: GetProof) => {} +);