ethers.js-6-Low-Level API
Low-Level API
These are advanced, low-level API features that should, for most people not be necessary to worry about.
They are lightly documented here, and in the future will have more documentation, but the emphasis at this point is documenting the more common methods.
对于大多数人来说,这些是高级的、低级的API特性,不需要担心。
这里对它们进行了简单的文档化,将来还会有更多的文档化,但是现在的重点是对更常见的方法进行文档化。
ABI Coder
Creating Instances
- new ethers . utils . AbiCoder ( [ coerceFunc ] )
- Create a new ABI Coder object, which calls coerceFunc for each parsed value during decoding. The coerceFunc should have the signature:
function(type, value)
. - 创建一个新的ABI编码器对象,该对象在解码期间为每个解析值调用coerceFunc。coerceFunc应该具有以下签名:函数(类型,值)。
Static Properties 其静态属性
- ethers . utils . defaultAbiCoder
- A default instance of the coder which can be used, which has a coerceFunc which will call
toNumber()
on BigNumbers whose type is less than 53 bits and is safe for JavaScript Number instances.一个可以使用的编码器的默认实例,它有一个cocefunc,它将对小于53位的BigNumbers调用toNumber(),并且对于JavaScript Number实例是安全的。
Prototype
- prototype . encode ( types , values ) => hex
- Returns a hex string of the values encoded as the types. Throws if a value is invalid for the type.
- 返回编码为类型的值的十六进制字符串。如果该类型的值无效,则throws。
- prototype . decode ( types , data ) => Result
- Returns an Object by parsing data assuming types, with each parameter accessible as a positional parameters. Throws if data is invalid for the types.
- 通过解析假设类型的数据返回一个对象,每个参数都可以作为位置参数访问。如果数据对类型无效,则throws。
HDNode
A Hierarchical Deterministic Wallet represents a large tree of private keys which can reliably be reproduced from an initial seed. Each node in the tree is represented by an HDNode which can be descended into.
HD钱包表示可以从seed可靠地复制的大型私有密钥树。树中的每个节点都由一个HDNode表示。
A mnemonic phrase represents a simple way to generate the initial seed.助记词表示生成初始seed的简单方法。
See the BIP 32 Specification to learn more about HD Wallets and hardened vs non-hardened nodes.
See the BIP 39 Specification to learn more about Mnemonic Phrases.
Creating Instances
- ethers . utils . HDNode . fromMnemonic ( mnemonic ) => HDNode
- Create an HDNode from a mnemonic phrase.使用mnemonic生成HDNode
- ethers . utils . HDNode . fromSeed ( seed ) => HDNode
- Create an HDNode from a seed. 使用seed生成HDNode
Prototype 得到相应的值
- prototype . privateKey
- The hex string private key for this node.
- prototype . publicKey
- The (compressed) public key for this node.
- prototype . chainCode
- The chain code for this node.
- prototype . index
- The index (from the parent) of this node (0 for the master node).
- prototype . depth
- The depth within the hierarchy of this node.
Deriving Child Nodes
- prototype . derivePath ( path ) => HDNode
- Derive the path from this node. Path is slash (/) delimited path components. The first component may be “m” for master (which enforces the starting node is in fact a master node) and each subsequent path component should be a positive integer (up to 31 bits), which can optionally include an apostrophe (‘) to indicate hardened derivation for that path components. See below for some examples.
- 从这个节点派生路径派生。路径是斜杠(/)分隔的路径组件。第一个组件可能是主节点的“m”(它强制起始节点实际上是主节点),而每个后续路径组件应该是一个正整数(最多31位),可以选择包含一个撇号('),以指示该路径组件的经过hardern的派生。请看下面的一些例子
Static Methods
- ethers . utils . HDNode . mnemonicToEntropy ( mnemonic ) => hex
- Convert a mnemonic to its binary entropy. (throws an error if the checksum is invalid)
- ethers . utils . HDNode . entropyToMnemonic ( entropy ) => string
- Convert the binary entropy to the mnemonic phrase.
- ethers . utils . HDNode . mnemonicToSeed ( mnemonic ) => hex
- Compute the BIP39 seed from mnemonic.
- ethers . utils . HDNode . isValidMnemonic ( string ) => boolean
- Returns true if and only if the string is a valid mnemonic (including the checksum)
let HDNode = require('ethers').utils.HDNode; let mnemonic = "radar blur cabbage chef fix engine embark joy scheme fiction master release"; let masterNode = HDNode.fromMnemonic(mnemonic); console.log(masterNode);//这里得到的masterNode是根结点,从其path值可看出 path: 'm' // HDNode { // keyPair: // KeyPair { // privateKey: // '0xbc9d46102ab7c7655fd22ab24046e57f02f68b47a66f74443e3c239d82593b93', // publicKey: // '0x04605d5bf64aabe87513169f5f98d6813921d7678012a5140aae5e8aa4cfd1570a29be0a527ef438f10801c793b914af9fc941fcbe19f654870379228da947f686', // compressedPublicKey: // '0x02605d5bf64aabe87513169f5f98d6813921d7678012a5140aae5e8aa4cfd1570a', // publicKeyBytes: // [ 2, // 96, // 93, // 91, // 246, // 74, // 171, // 232, // 117, // 19, // 22, // 159, // 95, // 152, // 214, // 129, // 57, // 33, // 215, // 103, // 128, // 18, // 165, // 20, // 10, // 174, // 94, // 138, // 164, // 207, // 209, // 87, // 10 ] }, // privateKey: // '0xbc9d46102ab7c7655fd22ab24046e57f02f68b47a66f74443e3c239d82593b93', // publicKey: // '0x02605d5bf64aabe87513169f5f98d6813921d7678012a5140aae5e8aa4cfd1570a', // address: '0x986208F71F84015389Ea40470846B9A730A0dd18', // chainCode: // '0x58d21a9c66b7d15789b793c90c08252a3ded88fc64ffd8b08381e447e615fca3', // index: 0, // depth: 0, // mnemonic: // 'radar blur cabbage chef fix engine embark joy scheme fiction master release', // path: 'm' } console.log(); let standardEthereum = masterNode.derivePath("m/44'/60'/0'/0/0"); console.log(standardEthereum);//这个这是在上面的根结点的基础上,派生路径为"m/44'/60'/0'/0/0"的子节点 // HDNode { // keyPair: // KeyPair { // privateKey: // '0xb96e9ccb774cc33213cbcb2c69d3cdae17b0fe4888a1ccd343cbd1a17fd98b18', // publicKey: // '0x0405b7d0996e99c4a49e6c3b83288f4740d53662839eab1d97d14660696944b8bbe24fabdd03888410ace3fa4c5a809e398f036f7b99d04f82a012dca95701d103', // compressedPublicKey: // '0x0305b7d0996e99c4a49e6c3b83288f4740d53662839eab1d97d14660696944b8bb', // publicKeyBytes: // [ 3, // 5, // 183, // 208, // 153, // 110, // 153, // 196, // 164, // 158, // 108, // 59, // 131, // 40, // 143, // 71, // 64, // 213, // 54, // 98, // 131, // 158, // 171, // 29, // 151, // 209, // 70, // 96, // 105, // 105, // 68, // 184, // 187 ] }, // privateKey: // '0xb96e9ccb774cc33213cbcb2c69d3cdae17b0fe4888a1ccd343cbd1a17fd98b18', // publicKey: // '0x0305b7d0996e99c4a49e6c3b83288f4740d53662839eab1d97d14660696944b8bb', // address: '0xaC39b311DCEb2A4b2f5d8461c1cdaF756F4F7Ae9', // chainCode: // '0x41ef8d5b6140f4c88b4568eb2e719016844f89b770279c247ab00a136f1ec9b3', // index: 0, // depth: 5, // mnemonic: // 'radar blur cabbage chef fix engine embark joy scheme fiction master release', // path: "m/2147483692'/2147483708'/2147483648'/0/0" }
Interface
The Interface Object is a meta-class that accepts a Solidity (or compatible) Application Binary Interface (ABI) and populates functions to deal with encoding and decoding the parameters to pass in and results returned.
接口对象是一个元类,它接受一个可靠(或兼容)应用程序二进制接口(ABI),并填充函数来处理要传入的参数的编码和解码以及返回的结果。
Creating an Instance
- new ethers . utils . Interface ( abi )
- Returns a new instance and populates the properties with the ABI constructor, methods and events. The abi may be either a JSON string or the parsed JSON Object.返回一个新实例,并用ABI构造函数、方法和事件填充属性。abi可以是JSON字符串,也可以是解析后的JSON对象。
Prototype通过该对象可更改ABI的相对应的内容
- prototype . abi
- A copy of the ABI is returned, modifying this object will not alter the ABI.返回ABI的副本,修改此对象不会更改ABI。
- prototype . deployFunction
- A DeployDesciption for the constructor defined in the ABI, or the default constructor if omitted.对ABI中定义的构造函数进行部署,如果省略了,则使用默认构造函数。
- prototype . events
- An object of all the events available in the ABI, by name and signature, which map to a EventDescription.ABI中所有可用事件的对象,按名称和签名,映射到事件描述。
- prototype . functions
- An object of all the functions available in the ABI, by name and signature, which map to a FunctionDescription.ABI中所有可用函数的对象,按名称和签名,映射到函数描述。
Parsing Objects
- prototype . parseTransaction ( transaction ) => TransactionDescription
- Parse transaction and return a description of the call it represents.解析交易并返回它所表示的调用的描述。描述下面有讲
- prototype . parseLog ( log ) => LogDescription
- Parse log and return a description of the event logs it represents.解析日志并返回它所表示的调用的描述。
Object Test Functions
- prototype . isInterface ( value ) => boolean
- Returns true if value is an Interface.
- prototype . isIndexed ( value ) => boolean
- Returns true if value is a dynamic Indexed value, which means the actual value of value is the hash of the actual value.如果值是动态索引值,则返回true,这意味着值的实际值是实际值的散列。
Descriptions描述
写出每类描述会显示的内容
Deploy Description构造函数的描述
name description inputs The description of the constructor input parameters payable Whether the constructor can accept Ether encode(params) A function which encodes params
Event Description事件描述
name description name The event name (e.g. “Transfer”) signature The event signature (e.g. “Transfer(address indexed,address indexed,uint256)”) inputs The event input parameters anonymous Whether the event is an anonymous event topic The topic for this event signature encodeTopics(params) A function which computes filter topics for given params decode(data, topics) A function to parse the log result data and topics
Function Description函数描述
name description name The method name (e.g. “transfer”) type The method type (i.e. “call” or “transaction”) signature The method signature (e.g. “transfer(address to, uint256 amount)”) sighash The signature hash of the signature (4 bytes) inputs The description of the method input parameters outputs The description of the method output parameters payable Whether the method can accept Ether gas The maximum gas this method will consume (null if unknown) encode(params) A function which encodes params decode(data) A function which decodes the result data
Log Description日志描述
name description name The event name (e.g. “Transfer”) signature The event signature (e.g. “Transfer(address indexed,address indexed,uint256)”) topics The event topics decode(data, topics) A function to parse the logs values The decoded values of the event
Transaction Description交易描述
name description name The method name (e.g. “transfer”) args The arguments passed to the method signature The method signature (e.g. “transfer(address to, uint256 amount)”) sighash The signature hash of the signature (4 bytes) decode(data) A function to parse the result data value The value (in wei) of the transaction
Provider (Sub-Classing)
See the Provider API for more common usage. This documentation is designed for developers that are sub-classing BaseProvider.
有关更常见的用法,请参见提供Provider API。此文档是为子类化BaseProvider的开发人员设计的。
Static Methods
- BaseProvider . inherits ( childProvider ) => void
- Set up childProvider as an provider, inheriting the parent prototype and set up a prototype.inherits on the childProvider.将childProvider设置为提供者,继承父原型并设置原型。继承childProvider
Prototype
- prototype . perform ( method , params ) => Promise<any>
- The only method needed to override in a subclass. All values are sanitized and defaults populated in params and the result is sanitized before returning. Returns a Promise, see the example below for overview of method and params.
- 在子类中唯一需要重写的方法。所有值都经过清理,默认值以参数形式填充,结果在返回之前经过清理。返回Promise,有关方法和参数的概述,请参见下面的示例。
const ethers = require('ethers'); // The new provider Object function DemoProvider(something) { let network = getNetworkSomehow() // The super must be called with either a Network or a Promise // that resolves to a Network ethers.providers.BaseProvider.call(this, network); ethers.utils.defineReadOnly(this, 'somethingElse', somethingElse); } // Inherit the Provider ethers.providers.BaseProvider.inherits(DemoProvider); // Override perform DemoProvider.prototype.perform = function(method, params) { switch (method) { case 'getBlockNumber': // Params: // { } case 'getGasPrice': // Params: // { } case 'getBalance': // Params: // { // address: address, // blockTag: blockTag // } case 'getTransactionCount': // Params: // { // address: address, // blockTag: blockTag // } case 'getCode': // Params: // { // address: address, // blockTag: blockTag // } case 'getStorageAt': // Params: // { // address: address, // position: hexString, // blockTag: blockTag // } case 'sendTransaction': // Params: // { // signedTransaction: hexString // } case 'getBlock': // Params: // Exactly one of the following will be specified, the other will be absent // { // blockHash: blockHash, // blockTag: blockTag // } case 'getTransaction': // Params: // { // transactionHash: hexString // } case 'getTransactionReceipt': // Params: // { // transactionHash: hexString // } case 'call': // Params: // { // transaction: See Transaction Requests (on Providers API) // } case 'estimateGas': // Params: // { // transaction: See Transaction Requests (on Providers API) // } case 'getLogs': // Params: // { // address: address, // fromBlock: blockTag, // toBlock: blockTag, // topics: array (possibly nested) of topics // } default: break; } return Promise.reject(new Error('not implemented - ' + method));//到调用的方法没有找到时,就说明没有实现 };
Recursive-Length Prefixed Encoding (RLP)
This encoding method is used internally for several aspects of Ethereum, such as encoding transactions and determining contract addresses. For most developers this should not be necessary to use.
这种编码方法在内部用于Ethereum的几个方面,例如编码事务和确定合同地址。对于大多数开发人员来说,没有必要使用它。
RLP can encode nested arrays, with data as hex strings and Uint8Array (or other non-Arrayarrayish objects). A decoded object will always have data represented as hex strings and Arrays.
RLP可以对嵌套数组进行编码,数据可以是十六进制字符串和Uint8Array(或其他非arrayarrayish对象)。解码后的对象总是用十六进制字符串和数组表示数据。
See: https://github.com/ethereum/wiki/wiki/RLP
Static Methods
- ethers . utils . RLP . encode( object ) => hex
- Encodes an object as an RLP hex string. (throws an Error if the object contains invalid items)将对象编码为RLP十六进制字符串。(如果对象包含无效项,则抛出错误)
- ethers . utils . RLP . decode( hexStringOrArrayish ) => any
- Decode hexStringOrArrayish into the encoded object. (throws an Error if invalid RLP-coded data)解码hexStringOrArrayish到编码的对象。(如果rlp编码的数据无效,则抛出错误)
-
let object = [ ["0x42"], "0x1234", [ [], [] ] ]; let encoded = ethers.utils.RLP.encode(object); console.log(encoded); // 0xc8c142821234c2c0c0 let decoded = ethers.utils.RLP.decode(encoded); console.log(decoded); // [ [ '0x42' ], '0x1234', [ [], [] ] ]
Signing Key
The SigningKey interface provides an abstraction around the secp256k1 elliptic curve cryptography library, which signs digests, computes public keys from private keys and performs ecrecover which computes a public key from a digest and a signature.
SigningKey接口提供了一个围绕secp256k1椭圆曲线密码库的抽象,它对摘要进行签名,从私钥计算公钥,并执行ecrecovery(从摘要和签名计算公钥)。
Creating Instances
- new ethers . utils . SigningKey ( privateKey )
- Create a new SigningKey and compute the corresponding public key and address. A private key may be a any hex string or an Arrayish representing 32 bytes.创建一个新的签名密钥并计算相应的公钥和地址。私钥可以是任何十六进制字符串,也可以是表示32字节的数组。
Prototype
- prototype . address
- The Ethereum checksum address for this key pair.得到密钥对的校验和地址
- prototype . privateKey
- The private key for the key pair.得到密钥对的私钥
- prototype . publicKey
- The uncompressed public key for the key pair.得到密钥对的公钥
Cryptographic Operations
- prototype . signDigest ( messageDigest ) => hex
- The flat-format Signature for the digests, signed by this key pair.摘要的flat格式签名,由此密钥对签名。
- prototype . computeSharedSecret ( publicOrPrivateKey ) => hex
- Compute the ECDH shared secret from this keys private key and the publicOrPrivateKey. In is generally considered good practice to further hash this value before using it as a key.从这个密钥、私钥和公钥计算ECDH共享密钥。通常将该值用作键被认为是在进一步散列之前的好操作。
TypeError: Cannot read property 'computePublicKey' of undefined
解决办法:使用
const secp256k1 = require("ethers/utils/secp256k1"); let compressed = true; let publicKey = sec256k1.computePublicKey(someKey, compressed);
const ethers = require('ethers'); const secp256k1 = require("ethers/utils/secp256k1"); let privateKey = '0x0123456789012345678901234567890123456789012345678901234567890123'; let signingKey = new ethers.utils.SigningKey(privateKey); console.log(signingKey); // SigningKey { // privateKey: // '0x0123456789012345678901234567890123456789012345678901234567890123', // keyPair: // KeyPair { // privateKey: // '0x0123456789012345678901234567890123456789012345678901234567890123', // publicKey: // '0x046655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515217e88dd05e938efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e', // compressedPublicKey: // '0x026655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515', // publicKeyBytes: // [ 2, // 102, // 85, // 254, // 237, // 77, // 33, // 76, // 38, // 30, // 10, // 107, // 85, // 67, // 149, // 89, // 111, // 31, // 20, // 118, // 167, // 125, // 153, // 149, // 96, // 229, // 168, // 223, // 155, // 138, // 26, // 53, // 21 ] }, // publicKey: // '0x046655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515217e88dd05e938efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e', // address: '0x14791697260E4c9A71f18484C9f997B308e59325' } console.log('Address: ' + signingKey.address); // "Address: 0x14791697260E4c9A71f18484C9f997B308e59325" let message = "Hello World"; let messageBytes = ethers.utils.toUtf8Bytes(message); console.log(messageBytes);//Uint8Array [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 ] let messageDigest = ethers.utils.keccak256(messageBytes); console.log("Digest: " + messageDigest); // "Digest: 0x592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba" let signature = signingKey.signDigest(messageDigest); console.log(signature); // { // v: 27, // r: "0x79f56f3422dc67f57b2aeeb0b20295a99ec90420b203177f83d419c98beda7fe", // s: "0x1a9d05433883bdc7e6d882740f4ea7921ef458a61b2cfe6197c2bb1bc47236fd" // } let privateShare = signingKey.computeSharedSecret(privateKey);//与下面使用publicKey得到的值时是相同的 console.log('privateShare : '+privateShare);//privateShare : 0xa442c51323b66fa73009ab663eb4ad3793a6becc400fb28582413750b84fcb28 let recovered = ethers.utils.recoverAddress(messageDigest, signature); console.log("Recovered: " + recovered); // "Recovered: 0x14791697260E4c9A71f18484C9f997B308e59325" let publicKey = signingKey.publicKey; console.log('Public Key: ' + publicKey); // "Public Key: 0x046655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515217e88dd05e938efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e" let publicShare = signingKey.computeSharedSecret(publicKey); console.log('publicShare : '+publicShare);//publicShare : 0xa442c51323b66fa73009ab663eb4ad3793a6becc400fb28582413750b84fcb28 let compressedPublicKey = secp256k1.computePublicKey(publicKey, true); let uncompressedPublicKey = secp256k1.computePublicKey(publicKey, false); console.log(compressedPublicKey); // "0x026655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515" console.log(uncompressedPublicKey); // "0x046655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a35" + // "15217e88dd05e938efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e" let address = ethers.utils.computeAddress(publicKey); console.log('Address: ' + address); // "Address: 0x14791697260E4c9A71f18484C9f997B308e59325"