ethers.js-3-Providers

Providers

A Provider abstracts a connection to the Ethereum blockchain, for issuing queries and sending signed state changing transactions.

provider抽象到Ethereum区块链的连接,用于发出查询和发送签名状态更改交易。

The EtherscanProvider and InfuraProvider offer the ability to connect to public third-party providers without the need to run any Ethereum node yourself.

EtherscanProvider和InfuraProvider提供了连接到公共第三方提供商的能力,而不需要自己运行任何Ethereum节点。

The JsonRpcProvider and IpcProvider allow you to connect to Ethereum nodes you control or have access to, including mainnet, testnets, proof-of-authority (PoA) nodes or Ganache.

JsonRpcProvider和IpcProvider允许您连接到您控制或访问的Ethereum节点,包括mainnet、testnets、proof-of-authority (PoA)节点或Ganache。

If you already have a Web3 application, or Web3-compatible Provider (e.g. MetaMask’s web3.currentProvider), it can be wrapped by a Web3Provider to make it compatible with the ethers Provider API.

如果您已经有了一个Web3应用程序或兼容Web3的提供者(例如MetaMask的Web3 . currentprovider),那么它可以被Web3Provider包装,使之与ethers提供者API兼容。

For most situations, it is recommended that you use a default provider, which will connect to both Etherscan and INFURA simultaneously:

对于大多数情况,建议您使用默认提供程序,它将同时连接Etherscan和INFURA:

1.connect to a default provider

const ethers = require('ethers');
// You can use any standard network name
//  - "homestead"
//  - "rinkeby"
//  - "ropsten"
//  - "kovan"

let provider = ethers.getDefaultProvider('ropsten');
console.log(provider);
// FallbackProvider {
//   _network:
//    { name: 'ropsten',
//      chainId: 3,
//      ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
//      _defaultProvider: [Function] },
//   ready:
//    Promise {
//      { name: 'ropsten',
//        chainId: 3,
//        ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
//        _defaultProvider: [Function] } },
//   _lastBlockNumber: -2,
//   _balances: {},
//   _events: [],
//   _pollingInterval: 4000,
//   _emitted: { block: -2 },
//   _fastQueryDate: 0,
//   _providers:
//    [ InfuraProvider {
//        _network:
//         { name: 'ropsten',
//           chainId: 3,
//           ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
//           _defaultProvider: [Function] },
//        ready:
//         Promise {
//           { name: 'ropsten',
//             chainId: 3,
//             ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
//             _defaultProvider: [Function] } },
//        _lastBlockNumber: -2,
//        _balances: {},
//        _events: [],
//        _pollingInterval: 4000,
//        _emitted: { block: -2 },
//        _fastQueryDate: 0,
//        connection: { url: 'https://ropsten.infura.io/' },
//        apiAccessToken: null },
//      EtherscanProvider {
//        _network:
//         { name: 'ropsten',
//           chainId: 3,
//           ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
//           _defaultProvider: [Function] },
//        ready:
//         Promise {
//           { name: 'ropsten',
//             chainId: 3,
//             ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
//             _defaultProvider: [Function] } },
//        _lastBlockNumber: -2,
//        _balances: {},
//        _events: [],
//        _pollingInterval: 4000,
//        _emitted: { block: -2 },
//        _fastQueryDate: 0,
//        baseUrl: 'https://api-ropsten.etherscan.io',
//        apiKey: undefined } ] }

 

2.connect to MetaMask

<!doctype html>

<html>
  <head>
    <title>Tests</title>
  </head>

  <body>
      <br>

  </body>
<!-- This exposes the library as a global variable: ethers -->
<script src="https://cdn.ethers.io/scripts/ethers-v4.min.js"
        charset="utf-8"
        type="text/javascript">
</script>
<script>
    let provider = new ethers.providers.Web3Provider(window.web3.currentProvider);
    console.log(provider);
</script>
</html>

返回:

 

Connecting to Ethereum

There are several methods to connect to the Ethereum network provided. If you are not running your own local Ethereum node, it is recommended that you use the getDefaultProvider()method.几种连接network的方法。如果你没有使用本地的以太坊节点,那么推荐使用getDefaultProvider()方法

1.连接第三方provider

1)ethers . getDefaultProvider( [ network = “homestead” ] )   =>   Provider 推荐方法

This creates a FallbackProvider backed by multiple backends (INFURA and Etherscan).

This is the recommended method of connecting to the Ethereum network if you are not running your own Ethereum node.

举例看上面的(1.connect to a default provider)例子

2)new ethers . providers . EtherscanProvider( [ network = “homestead” ] [ , apiToken ] )

Connect to the Etherscan blockchain web service API.

Also See: Etherscan provider-specific Properties and Operations

const ethers = require('ethers');
// You can use any standard network name
//  - "homestead"
//  - "rinkeby"
//  - "ropsten"
//  - "kovan"

let etherscanProvider = new ethers.providers.EtherscanProvider('ropsten');
console.log(etherscanProvider);
// EtherscanProvider {
//   _network:
//    { name: 'ropsten',
//      chainId: 3,
//      ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
//      _defaultProvider: [Function] },
//   ready:
//    Promise {
//      { name: 'ropsten',
//        chainId: 3,
//        ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
//        _defaultProvider: [Function] } },
//   _lastBlockNumber: -2,
//   _balances: {},
//   _events: [],
//   _pollingInterval: 4000,
//   _emitted: { block: -2 },
//   _fastQueryDate: 0,
//   baseUrl: 'https://api-ropsten.etherscan.io',
//   apiKey: undefined }

 

3)new ethers . providers . InfuraProvider( [ network = “homestead” ] [ , apiAccessToken ] )

Connect to the INFURA hosted network of Ethereum nodes.

Also See: INFURA provider-specific Properties

const ethers = require('ethers');
// You can use any standard network name
//  - "homestead"
//  - "rinkeby"
//  - "ropsten"
//  - "kovan"

let infuraProvider = new ethers.providers.InfuraProvider('ropsten');
console.log(infuraProvider);
// InfuraProvider {
//   _network:
//    { name: 'ropsten',
//      chainId: 3,
//      ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
//      _defaultProvider: [Function] },
//   ready:
//    Promise {
//      { name: 'ropsten',
//        chainId: 3,
//        ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
//        _defaultProvider: [Function] } },
//   _lastBlockNumber: -2,
//   _balances: {},
//   _events: [],
//   _pollingInterval: 4000,
//   _emitted: { block: -2 },
//   _fastQueryDate: 0,
//   connection: { url: 'https://ropsten.infura.io/' },
//   apiAccessToken: null }

 

2.连接Geth or Parity节点
1)new ethers . providers . JsonRpcProvider( [ urlOrInfo = “http://localhost:8545” ] [ , network ] )

Connect to the JSON-RPC API URL urlorInfo of an Ethereum node, such as Parity or Geth.

The urlOrInfo may also be specified as an object with the properties:

  • url — the JSON-RPC URL (required)
  • user — a username to use for Basic Authentication (optional)用于身份认证,配置节点时设置
  • password — a password to use for Basic Authentication (optional)用于身份认证
  • allowInsecure — allow Basic Authentication over an insecure HTTP network (default: false)

Also See: JSON-RPC provider-specific Properties and Operations

const ethers = require('ethers');
let customHttpProvider = new ethers.providers.JsonRpcProvider("http://localhost:8545");
console.log(customHttpProvider);
// JsonRpcProvider {
//   ready: Promise { <pending> },
//   _lastBlockNumber: -2,
//   _balances: {},
//   _events: [],
//   _pollingInterval: 4000,
//   _emitted: { block: -2 },
//   _fastQueryDate: 0,
//   connection: { url: 'http://localhost:8545' } }

 

2)new ethers . providers . IpcProvider( path [ , network ] )

Connect to the JSON-RPC API path over IPC (named pipes) to an Ethereum node, such as Parity or Geth.

The network is also automatically detected if not specified; see the above description of network for JsonRpcProvider for details.

Also See: IPC provider-specific Properties and Operations

// Connect over named pipes using IPC:
let path = "/var/run/parity.ipc";
let ipcProvider = new ethers.providers.IpcProvider(path);

 

3.使用存在的Web3 Provider(如metamask)
new ethers . providers . Web3Provider( web3Provider [ , network ] )

Connect to an existing Web3 provider (e.g. web3Instance.currentProvider).

The network is also automatically detected if not specified; see the above description of network for JsonRpcProvider for details.

Also See: Web3 provider-specific Properties and Operations

可看上面的(2.connect to MetaMask)例子

new ethers . providers . FallbackProvider( providers )

Improves reliability by attempting each provider in turn, falling back to the next in the list if an error was encountered. The network is determined from the providers and the mustmatch each other.

Also See: Fallback provider-specific Properties

 

Properties属性

All properties are immutable unless otherwise specified, and will reflect their default values if left unspecified.除非另外指定,否则所有属性都是不可变的,如果不指定,它们将反映默认值。

Provider

prototype . blockNumber
The most recent block number (block height) this provider has seen and has triggered events for. If no block has been seen, this is null.
prototype . polling

mutable

If the provider is currently polling because it is actively watching for events. This may be set to enable/disable polling temporarily or disabled permanently to allow a node process to exit.

prototype . pollingInterval

mutable

The frequency (in ms) that the provider is polling. The default interval is 4 seconds.

This may make sense to lower for PoA networks or when polling a local node. When polling Etherscan or INFURA, setting this too low may result in the service blocking your IP address or otherwise throttling your API calls.

EtherscanProvider ( inherits from Provider )

prototype . apiToken
The Etherscan API Token (or null if not specified)

InfuraProvider ( inherits from JsonRpcProvider )

prototype . apiAccessToken
The INFURA API Access Token (or null if not specified)
const ethers = require('ethers');
let infuraProvider = new ethers.providers.InfuraProvider('ropsten');
console.log(infuraProvider.apiAccessToken);//null

JsonRpcProvider ( inherits from Provider )

prototype . connection

An object describing the connection of the JSON-RPC endpoint with the properties:

  • url — the JSON-RPC URL
  • user — a username to use for Basic Authentication (optional)
  • password — a password to use for Basic Authentication (optional)
  • allowInsecure — allows Basic Authentication over an insecure HTTP network

Web3Provider ( inherits from JsonRpcProvider )

prototype . provider

The underlying Web3-compatible provider from the Web3 library, for example an HTTPProvider or IPCProvider. The only required method on a Web3 provider is:

  • sendAsync ( method , params , callback )

FallbackProvider ( inherits from Provider )

prototype . providers
A copy of the array of providers (modifying this variable will not affect the attached providers)

IpcProvider ( inherits from JsonRpcProvider )

prototype . path
The JSON-RPC IPC (named pipe) path the provider is connected to.

 

Network

prototype . getNetwork ( )   =>   Promise<Network>
A Promise that resolves to a Network object describing the connected network and chain.
const ethers = require('ethers');
let infuraProvider = new ethers.providers.InfuraProvider('ropsten');
infuraProvider.getNetwork().then((network)=>{
    console.log(network);
    // { name: 'ropsten',
    //   chainId: 3,
    //   ensAddress: '0x112234455c3a32fd11230c42e7bccd4a84e02010',
    //   _defaultProvider: [Function] }
}).catch((e) =>{
    console.log(e);
});

 

Account

prototype . getBalance ( addressOrName [ , blockTag = “latest” ] )   =>   Promise<BigNumber>得到账户余额
Returns a Promise with the balance (as a BigNumber) of addressOrName at blockTag. (See: Block Tags)
prototype . getTransactionCount ( addressOrName [ , blockTag = “latest” ] )   =>   Promise<number> 得到交易数量
Returns a Promise with the number of sent transactions (as a Number) from addressOrNameat blockTag. This is also the nonce required to send a new transaction. (See: Block Tags)
const ethers = require('ethers');
let customHttpProvider = new ethers.providers.JsonRpcProvider("http://localhost:8545");
let address = '0x3455f15cc11f2e77c055f931a6c918ccc7c18fd8';
customHttpProvider.getBalance(address).then((balance)=>{
    console.log(ethers.utils.formatEther(balance));//98.99916
    console.log(balance);//BigNumber { _hex: '0x55de3ab7ffe0f8000' }
}).catch((e) =>{
    console.log(e);
});
customHttpProvider.getTransactionCount(address).then((count)=>{
    console.log("Total Transactions Ever Sent: " + count);//Total Transactions Ever Sent: 2
}).catch((e) =>{
    console.log(e);
});

 

Blockchain Status

prototype . getBlockNumber ( )   =>   Promise<number>
Returns a Promise with the latest block number (as a Number).
prototype . getGasPrice ( )   =>   Promise<BigNumber>
Returns a Promise with the current gas price (as a BigNumber).
prototype . getBlock ( blockHashOrBlockNumber )   =>   Promise<Block>
Returns a Promise with the block at blockHashOrBlockNumber. (See: Block Responses)
prototype . getTransaction ( transactionHash )   =>   Promise<TransactionResponse>
Returns a Promise with the transaction with transactionHash. (See: Transaction Responses)
prototype . getTransactionReceipt ( transactionHash )   =>   Promise<TransactionReceipt>
Returns a Promise with the transaction receipt with transactionHash. (See: Transaction Receipts)
const ethers = require('ethers');
let customHttpProvider = new ethers.providers.JsonRpcProvider("http://localhost:8545");
let address = '0x3455f15cc11f2e77c055f931a6c918ccc7c18fd8';
customHttpProvider.getBlockNumber().then((number)=>{
    console.log(number);//2
}).catch((e) =>{
    console.log(e);
});
customHttpProvider.getGasPrice().then((price)=>{
    console.log(ethers.utils.formatEther(price));//0.00000002
    console.log(price);//BigNumber { _hex: '0x4a817c800' }
}).catch((e) =>{
    console.log(e);
});
customHttpProvider.getBlock(1).then((block)=>{
    console.log(block);
    // { hash:
    //    '0xd29c8d0531a130af5474869baeb08c8a97e842e06501d98a60032406113e0a48',
    //   parentHash:
    //    '0xf215d4fa820518d2200b3ce42044aa8664e73486d21d8cea36d5a43a1648f32e',
    //   number: 1,
    //   timestamp: 1543212839,
    //   nonce: '0x0000000000000000',
    //   difficulty: 0,
    //   gasLimit: BigNumber { _hex: '0x6691b7' },
    //   gasUsed: BigNumber { _hex: '0x5208' },
    //   miner: '0x0000000000000000000000000000000000000000',
    //   extraData: '0x',
    //   transactions:
    //    [ '0xb48c1995addcf3268bdbe1a33878b7048de1fbfd5bc2ccb571ce63d2a4ab8953' ] }
}).catch((e) =>{
    console.log(e);
});
customHttpProvider.getTransaction('0x0d3ae20685f546518cd1cd061f765c755adcda00c07bf1e3fe6084a603762c75').then((transaction )=>{
    console.log(transaction);
    // { hash:
    //    '0x0d3ae20685f546518cd1cd061f765c755adcda00c07bf1e3fe6084a603762c75',
    //   blockHash:
    //    '0x8aac276fa0b7ad64ce63ce893039de3a9337fba3d6f7fc17f79222e21f308c10',
    //   blockNumber: 2,
    //   transactionIndex: 0,
    //   confirmations: 1,
    //   from: '0x3455f15cc11F2E77c055f931A6C918ccc7c18fd8',
    //   gasPrice: BigNumber { _hex: '0x04a817c800' },
    //   gasLimit: BigNumber { _hex: '0x033450' },
    //   to: '0x7DdaD6a67544efB0c51808c77009a7B98Cc81630',
    //   value: BigNumber { _hex: '0x0de0b6b3a7640000' },
    //   nonce: 1,
    //   data: '0x00',
    //   r:
    //    '0x76bcd7c3d8a29ac8c61923b8bb09ffa612d370f1a6a487e49cf1a4954e4d66ba',
    //   s:
    //    '0x7628db1233925ab6576bc2f1114381ccc57fe24c71a14339739de351150941b9',
    //   v: 3086425650564,
    //   creates: null,
    //   raw:
    //    '0xf873018504a817c80083033450947ddad6a67544efb0c51808c77009a7b98cc81630880de0b6b3a7640000008602ce9d4df584a076bcd7c3d8a29ac8c61923b8bb09ffa612d370f1a6a487e49cf1a4954e4d66baa07628db1233925ab6576bc2f1114381ccc57fe24c71a14339739de351150941b9',
    //   networkId: 1543212825264,
    //   wait: [Function] }
}).catch((e) =>{
    console.log(e);
});
customHttpProvider.getTransactionReceipt('0x0d3ae20685f546518cd1cd061f765c755adcda00c07bf1e3fe6084a603762c75').then((receipt)=>{
    console.log(receipt);
    // { contractAddress: null,
    //   transactionIndex: 0,
    //   gasUsed: BigNumber { _hex: '0x5208' },
    //   logsBloom:
    //    '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    //   blockHash:
    //    '0x8aac276fa0b7ad64ce63ce893039de3a9337fba3d6f7fc17f79222e21f308c10',
    //   transactionHash:
    //    '0x0d3ae20685f546518cd1cd061f765c755adcda00c07bf1e3fe6084a603762c75',
    //   logs: [],
    //   blockNumber: 2,
    //   confirmations: 1,
    //   cumulativeGasUsed: BigNumber { _hex: '0x5208' },
    //   status: 1,
    //   byzantium: true }

}).catch((e) =>{
    console.log(e);
});

 

Ethereum Naming Service 以太坊域名服务

The Ethereum Naming Service (ENS) allows easy to remember and use names to be assigned to Ethereum addresses. Any provider operation which takes an address may also take an ENS name.

ENS also provides the ability for a reverse lookup, which determines the name for an address if it has been configured.

prototype . resolveName ( ensName )   =>   Promise<Address> 将ens转成对应的账户address
Returns a Promise which resolves to the address of that the ensName resolves to (or null is not configured).
prototype . lookupAddress ( address )   =>   Promise<string> 将address转成对应的ens
Returns a Promise which resolves to the ENS name that address resolves to (or null if not configured).
const ethers = require('ethers');
let provider = ethers.getDefaultProvider();

provider.resolveName("registrar.firefly.eth").then(function(address) {
    console.log("Address: " + address);//Address: 0x6fC21092DA55B392b045eD78F4732bff3C580e2c
});

let address = "0x6fC21092DA55B392b045eD78F4732bff3C580e2c";
provider.lookupAddress(address).then(function(address) {
    console.log("Name: " + address);//Name: registrar.firefly.eth
});

 

Contract Execution

These are relatively low-level calls. The Contracts API should usually be used instead.

prototype . call ( transaction )   =>   Promise<hex>

Send the read-only (constant) transaction to a single Ethereum node and return a Promisewith the result (as a hex string) of executing it. (See Transaction Requests)将只读(常量)交易发送到单个Ethereum节点,并返回执行该交易的Promise(作为十六进制字符串)。

This is free, since it does not change any state on the blockchain.这个不花费gas,只是读取数据

prototype . estimateGas ( transaction )   =>   Promise<BigNumber>计算交易大概使用的gas

Send a transaction to a single Ethereum node and return a Promise with the estimated amount of gas required (as a BigNumber) to send it. (See Transaction Requests)

This is free, but only an estimate. Providing too little gas will result in a transaction being rejected (while still consuming all provided gas).

prototype . sendTransaction ( signedTransaction )   =>   Promise<TransactionResponse>发送交易

Send the signedTransaction to the entire Ethereum network and returns a Promise that resolves to the Transaction Response.

If an error occurs after the netowrk may have received the transaction, the promise will reject with the error, with the additional property transactionHash so that further processing may be done.

This will consume gas from the account that signed the transaction.这个要花费gas

const ethers = require('ethers');

let provider = ethers.getDefaultProvider('ropsten');
let address = "0x6fC21092DA55B392b045eD78F4732bff3C580e2c";//contract address

// First 4 bytes of the hash of "fee()" for the sighash selector
let data = ethers.utils.hexDataSlice(ethers.utils.id('fee()'), 0, 4);//读取_fee的值,_fee = 0.1 ether

let transaction = {
    to: address,//或使用contract的ENS name,'registrar.firefly.eth'
    data: data
}

let callPromise = provider.call(transaction);

callPromise.then((result) => {
    console.log(result);
    // "0x000000000000000000000000000000000000000000000000016345785d8a0000"

    console.log(ethers.utils.formatEther(result));
    // "0.1"
});

 

Contract State

prototype . getCode ( addressOrName )   =>   Promise<hex>
Returns a Promise with the bytecode (as a hex string) at  addressOrName.
prototype . getStorageAt ( addressOrName , position [ , blockTag = “latest” ] )   =>   Promise<hex>
Returns a Promise with the value (as a hex string) at addressOrName in position at blockTag. (See Block Tags)
prototype . getLogs ( filter )   =>   Promise< Log [ ] >
Returns a Promise with an array (possibly empty) of the logs that match the filter. (See Filters)
 
const ethers = require('ethers');
let provider = ethers.getDefaultProvider('ropsten');
let address = "0x6fC21092DA55B392b045eD78F4732bff3C580e2c";//contract address

//get contract code
let codePromise = provider.getCode(address);

codePromise.then((result) => {
   console.log(result);
});


//get contract storage value
let contractEnsName = 'registrar.firefly.eth';

// Position 0 in the FireflyRegistrar contract holds the ENS address
let storagePromise = provider.getStorageAt(contractEnsName, 0);

storagePromise.then((result) => {
   console.log(result);
   // "0x000000000000000000000000112234455c3a32fd11230c42e7bccd4a84e02010"
});


//get contract event logs
let topic = ethers.utils.id("nameRegistered(bytes32,address,uint256)");

let filter = {
    address: contractEnsName,
    fromBlock: 3313425,
    toBlock: 3313430,
    topics: [ topic ]
}

provider.getLogs(filter).then((result) => {
    console.log(result);
    // [ {
    //    blockNumber: 3313426,
    //    blockHash: "0xe01c1e437ed3af9061006492cb07454eca8561479454a709809b7897f225387d",
    //    transactionIndex: 5,
    //    removed: false,
    //    address: "0x6fC21092DA55B392b045eD78F4732bff3C580e2c",
    //    data: "0x00000000000000000000000053095760c154a1531a69fc718119d14c4aa1506f" +
    //            "000000000000000000000000000000000000000000000000016345785d8a0000",
    //    topics: [
    //      "0x179ef3319e6587f6efd3157b34c8b357141528074bcb03f9903589876168fa14",
    //      "0xe625ed7b108857745d1d9889a7ae05861d8aee38e0e92fd3a31191de01c2515b"
    //    ],
    //    transactionHash: "0x61d641aaf3dcf4cf6bafc3e79d332d8773ea0688f87eb00f8b60c3f0050e55f0",
    //    logIndex: 5
    // } ]

});

 

 

Events

These methods allow management of callbacks on certain events on the blockchain and contracts. They are largely based on the EventEmitter API.这些方法允许管理对区块链和合约上某些事件的回调。

监听:

prototype . on ( eventType , callback )   =>   Provider 监听eventType事件,触发则执行callback
Register a callback for any future eventType; see below for callback parameters
prototype . once ( eventType , callback)   =>   Provider 仅监听一次eventType事件,触发则执行callback
Register a callback for the next (and only next) eventType; see below for callback parameters
prototype . removeListener ( eventType , callback )   =>   boolean 移除并只移除第一个eventType事件监听器
Unregister the callback for eventType; if the same callback is registered more than once, only the first registered instance is removed
prototype . removeAllListeners ( eventType )   =>   Provider移除所有eventType监听器
Unregister all callbacks for eventType
prototype . listenerCount ( [ eventType ] )   =>   number 返回eventType事件监听器的个数
Return the number of callbacks registered for eventType, or if ommitted, the total number of callbacks registered
prototype . resetEventsBlock ( blockNumber )   =>   void 从blockNumber区块开始扫描事件
Begin scanning for events from blockNumber. By default, events begin at the block number that the provider began polling at.

Event Types事件类型

“block”

Whenever a new block is mined正在挖矿形成新区块时触发

callback( blockNumber )

“pending” 当有等待记录到区块上的交易添加到交易池时触发

Whenever a new transaction is added to the transaction pool. This is NOT available on Etherscan or INFURA providers and may not be reliable on any provider.

callback( transactionHash )

“error” 在事件中出现错误

Whenever an error occurs during an event.

callback( error )

any address 相关账户address的余额改变时触发

When the balance of the corresponding address changes.

callback( balance )

any transaction hash 当交易被记录到区块上时触发

When the corresponding transaction has been included in a block; also see Waiting for Transactions.

callback( transactionReceipt )

a filtered event object 得到相关主题和发送者地址的事件时触发,用于过滤事件的属性有:

When the an event is logged by a transaction to the address with the associated topics. The filtered event properties are:

  • address — the contract address to filter by (optional)
  • topics — the log topics to filter by (optional)

callback( log )

an array of topics 得到有着任意主题并发送给任意地址的交易

When any of the topics are logs by a transaction to any address. This is equivalent to using a filter object with no address.

 

Waiting for Transactions

prototype . waitForTransaction ( transactionHash )   =>   Promise<TransactionReceipt>
Return a Promise which resolves to the Transaction Receipt once transactionHash is mined.

1.new blocks

provider.on('block', (blockNumber) => {
    console.log('New Block: ' + blockNumber);
});

 

2.account balance changes

provider.on('0x46Fa84b9355dB0708b6A57cd6ac222950478Be1d', (balance) => {
    console.log('New Balance: ' + balance);
});

 

3.transaction mined

provider.once(transactionHash, (receipt) => {
    console.log('Transaction Minded: ' + receipt.hash);
    console.log(receipt);
);

// ... OR ...

provider.waitForTransaction(transactionHash).then((receipt) => {
    console.log('Transaction Mined: ' + receipt.hash);
    console.log(receipt);
});

 

4.a filtered event has been logged(上面的例子)

 

Objects and Types

There are several common objects and types that are commonly used as input parameters or return types for various provider calls.

对于各种提供程序调用,有几个常用对象和类型通常用作输入参数或返回类型。

Block Tag

A block tag is used to uniquely identify a block’s position in the blockchain:

a Number or hex string:数字或十六进制字符串说明区块数
Each block has a block number (eg. 42 or "0x2a.
“latest”:最新区块
The most recently mined block.
“pending”:等待挖矿记录的区块
The block that is currently being mined.

Block Responses区块返回的信息

{
    parentHash: "0x3d8182d27303d92a2c9efd294a36dac878e1a9f7cb0964fa0f789fa96b5d0667",
    hash: "0x7f20ef60e9f91896b7ebb0962a18b8defb5e9074e62e1b6cde992648fe78794b",
    number: 3346463,

    difficulty: 183765779077962,
    timestamp: 1489440489,
    nonce: "0x17060cb000d2c714",
    extraData: "0x65746865726d696e65202d20555331",

    gasLimit: utils.bigNumberify("3993225"),
    gasUsed: utils.bigNuberify("3254236"),

    miner: "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8",
    transactions: [
        "0x125d2b846de85c4c74eafb6f1b49fdb2326e22400ae223d96a8a0b26ccb2a513",
        "0x948d6e8f6f8a4d30c0bd527becbe24d15b1aba796f9a9a09a758b622145fd963",
        ... [ 49 more transaction hashes ] ...
        "0xbd141969b164ed70388f95d780864210e045e7db83e71f171ab851b2fba6b730"
    ]
}

 

Network返回连接的network的信息

A network repsents various properties of a network, such as mainnet (i.e. “homestead”) or one of the testnets (e.g. “ropsten”, “rinkeby” or “kovan”) or alternative networks (e.g. “classic”). A Network has the following properties:

  • name — the name of the network (e.g. “homestead”, “rinkeby”)
  • chainId — the chain ID (network ID) of the connected network
  • ensAddress — the address of ENS if it is deployed to the network, otherwise null

If a network does not have the ENS contract deployed to it, names cannot be resolved to addresses.如果网络没有部署ENS合约,名称就不能解析为地址,及ensAddress没有值,为null

let network = ethers.providers.getNetwork('homestead');//这个network有部署ENS合约,所以下面的ensAddress有值,否则为null
// {
//    chainId: 1,
//    ensAddress: "0x314159265dd8dbb310642f98f50c066173c1259b",
//    name: "homestead"
// }

没有部署的:

let network = {
    chainId: 1337,
    name: "dev"
}

 

Transaction Requests交易请求(即输入)

Any property which accepts a number may also be specified as a BigNumber or hex string. Any property may also be given as a Promise which resolves to the expected type.

{
    // Required unless deploying a contract (in which case omit)
    to: addressOrName,  // the target address or ENS name,目标地址或其ENS域名

    // These are optional/meaningless for call and estimateGas
    nonce: 0,           // the transaction nonce
    gasLimit: 0,        // the maximum gas this transaction may spend
    gasPrice: 0,        // the price (in wei) per unit of gas

    // These are always optional (but for call, data is usually specified)
    data: "0x",         // extra data for the transaction, or input for call
    value: 0,           // the amount (in wei) this transaction is sending
    chainId: 3          // the network ID; usually added by a signer
}

 

Transaction Response(交易返回,当blockNumber为null时则没记入区块,状态为pending)

{
    // Only available for mined transactions
    blockHash: "0x7f20ef60e9f91896b7ebb0962a18b8defb5e9074e62e1b6cde992648fe78794b",
    blockNumber: 3346463,
    timestamp: 1489440489,

    // Exactly one of these will be present (send vs. deploy contract)
    // They will always be a properly formatted checksum address
    creates: null,
    to: "0xc149Be1bcDFa69a94384b46A1F91350E5f81c1AB",

    // The transaction hash
    hash: "0xf517872f3c466c2e1520e35ad943d833fdca5a6739cfea9e686c4c1b3ab1022e",

    // See above "Transaction Requests" for details
    data: "0x",
    from: "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8",
    gasLimit: utils.bigNumberify("90000"),
    gasPrice: utils.bigNumberify("21488430592"),
    nonce: 0,
    value: utils.parseEther(1.0017071732629267),

    // The chain ID; 0 indicates replay-attack vulnerable
    // (eg. 1 = Homestead mainnet, 3 = Ropsten testnet)
    chainId: 1,

    // The signature of the transaction (TestRPC may fail to include these),签名
    r: "0x5b13ef45ce3faf69d1f40f9d15b0070cc9e2c92f3df79ad46d5b3226d7f3d1e8",
    s: "0x535236e497c59e3fba93b78e124305c7c9b20db0f8531b015066725e4bb31de6",
    v: 37,

    // The raw transaction (TestRPC may be missing this)
    raw: "0xf87083154262850500cf6e0083015f9094c149be1bcdfa69a94384b46a1f913" +
           "50e5f81c1ab880de6c75de74c236c8025a05b13ef45ce3faf69d1f40f9d15b0" +
           "070cc9e2c92f3df79ad46d5b3226d7f3d1e8a0535236e497c59e3fba93b78e1" +
           "24305c7c9b20db0f8531b015066725e4bb31de6"
}

 

Transaction Receipts(交易返回,得到这个值都说明记入了区块)

{
    transactionHash: "0x7dec07531aae8178e9d0b0abbd317ac3bb6e8e0fd37c2733b4e0d382ba34c5d2",

    // The block this transaction was mined into
    blockHash: "0xca1d4d9c4ac0b903a64cf3ae3be55cc31f25f81bf29933dd23c13e51c3711840",
    blockNumber: 3346629,

    // The index into this block of the transaction
    transactionIndex: 1,

    // The address of the contract (if one was created)
    contractAddress: null,

    // Gas
    cumulativeGasUsed: utils.bigNumberify("42000"),
    gasUsed: utils.bigNumberify("21000"),

    // Logs (an Array of Logs)
    log: [ ],
    logsBloom: "0x00" ... [ 256 bytes of 0 ] ... "00",

    // Post-Byzantium hard-fork
    byzantium: false

    ////////////
    // Pre-byzantium blocks will have a state root:
    root: "0x8a27e1f7d3e92ae1a01db5cce3e4718e04954a34e9b17c1942011a5f3a942bf4",

    ////////////
    // Post-byzantium blocks will have a status (0 indicated failure during execution)
    // status: 1
}

 

Log日志信息

{
    // The block this log was emitted by
    blockNumber:
    blockHash:

    // The transaction this log was emiited by
    transactionHash:
    transactionIndex:
    logIndex:

    // Whether the log has been removed (due to a chain re-org)
    removed: false,

    // The contract emitting the log
    address:

    // The indexed data (topics) and non-indexed data (data) for this log
    topics: []
    data:
}

 

Filters

Filtering on topics supports a somewhat complicated specification, however, for the vast majority of filters, a single topic is usually sufficient (see the example below).

对topics进行过滤支持某种复杂的规范,但是对于绝大多数过滤器来说,一个topics通常就足够了(参见下面的示例)。

The EtherscanProvider currently only supports a single topic.     EtherscanProvider目前只支持一个topics

{
    // Optional; The range of blocks to limit querying (See: Block Tags above)
    fromBlock: "latest",
    toBlock: "latest",

    // Optional; An address (or ENS name) to filter by
    address: addressOrName,

    // Optional; A (possibly nested) list of topics
    topics: [ topic1 ]
}

 

 

Provider Specific Extra API Calls额外的API调用

Etherscan

prototype . getEtherPrice ( ) 得到1 ether以太币在美国的价格
Returns a Promise with the price of ether in USD.
prototype . getHistory ( addressOrName [ , startBlock = 0 [ , endBlock = “latest” ] ] )得到所有from或to地址addressOrName的交易的序列
Returns a Promise with an array of Transaction Responses for each transaction to or from addressOrName between startBlock and endBlock (inclusive).
const ethers = require('ethers');

let etherscanProvider = new ethers.providers.EtherscanProvider();

// Getting the current Ethereum price
etherscanProvider.getEtherPrice().then(function(price) {
    console.log("Ether price in USD: " + price);//Ether price in USD: 113.74
});


// Getting the transaction history of an address
let address = '0xb2682160c482eB985EC9F3e364eEc0a904C44C23';
let startBlock = 3135808;
let endBlock = 5091477;
etherscanProvider.getHistory(address, startBlock, endBlock).then(function(history) {
    console.log(history);
    // [ { hash:
    //      '0x327632ccb6d7bb47b455383e936b2f14e6dc50dbefdc214870b446603b468675',
    //     blockHash:
    //      '0x0415f0d2741de45fb748166c7dc2aad9b3ff66bcf7d0a127f42a71d3e286c36d',
    //     blockNumber: 3135808,
    //     transactionIndex: 1,
    //     confirmations: 3639733,
    //     from: '0xb2682160c482eB985EC9F3e364eEc0a904C44C23',
    //     gasPrice: BigNumber { _hex: '0x04a817c800' },
    //     gasLimit: BigNumber { _hex: '0x0493e0' },
    //     to: '0xAe572713CfE65cd7033774170F029B7219Ee7f70',
    //     value: BigNumber { _hex: '0x0d2f13f7789f0000' },
    //     nonce: 25,
    //     data: '0x',
    //     creates: null,
    //     networkId: 0,
    //     timestamp: 1486416939 },
    //   { hash:
    //      '0x7c10f2e7125a1fa5e37b54f5fac5465e8d594f89ff97916806ca56a5744812d9',
    //     blockHash:
    //      '0xa597cd45a88f3adedc0134167183e4f2719f8c1a4af2eae26438fa998e98cd02',
    //     blockNumber: 5091477,
    //     transactionIndex: 188,
    //     confirmations: 1684064,
    //     from: '0x32DEF047DeFd076DB21A2D759aff2A591c972248',
    //     gasPrice: BigNumber { _hex: '0x11e1a300' },
    //     gasLimit: BigNumber { _hex: '0x5208' },
    //     to: '0xb2682160c482eB985EC9F3e364eEc0a904C44C23',
    //     value: BigNumber { _hex: '0x038d7ea4c68000' },
    //     nonce: 24,
    //     data: '0x',
    //     creates: null,
    //     networkId: 0,
    //     timestamp: 1518651764 } ]
});

 

JsonRpcProvider

prototype . send ( method , params )   =>   Promise<any> 调用JSON-RPC格式的方法,params为传入的参数。这对于调用非标准或不太常见的JSON-RPC方法非常有用
Send the JSON-RPC method with params. This is useful for calling non-standard or less common JSON-RPC methods. A Promise is returned which will resolve to the parsed JSON result.
prototype . listAccounts ( )   =>   Promise<Address [ ] >得到该节点中的所有账户的address信息
Returns a Promise with a list of all account addresses the node connected to this Web3 controls.
prototype . getSigner( [ indexOrAddress ] )   =>   JsonRpcSigner 得到下标为indexOrAddress的账户的signer.indexOrAddress不设置则默认为第一个账户
Returns a JsonRpcSigner attached to an account on the Ethereum node the Web3 object is connected to. If indexOrAddress is not specified, the first account on the node is used.
const ethers = require('ethers');
let customHttpProvider = new ethers.providers.JsonRpcProvider("http://localhost:8545");
let hash = "0x0d3ae20685f546518cd1cd061f765c755adcda00c07bf1e3fe6084a603762c75";
customHttpProvider.send('debug_traceTransaction', [hash,null]).then((result) => {
    console.log(result);//{ gas: 0, returnValue: '', structLogs: [] }
}).catch((e)=>{
    console.log(e);
});

// Get a signer for the account at index 1
customHttpProvider.listAccounts().then((accounts) => {
    console.log(accounts);
    // [ '0x3455f15cc11F2E77c055f931A6C918ccc7c18fd8',
    //   '0x7DdaD6a67544efB0c51808c77009a7B98Cc81630',
    //   '0xe9478EBcF4C755ad945a351261C8fa046672963b',
    //   '0x920f422B761976972a9eaDbeC1f5341a9747ea6a',
    //   '0xa17a7fA74a7dd57dfF005b45234292e7DaAF150c',
    //   '0x2a84Df83F765a7F0ed3a5c7728B48A86A098CD22',
    //   '0x8059664C0C773f1678e262968e4eeF9549E94862',
    //   '0xe4D3E77d20F910a44cfF97A47a736Ad387eA3061',
    //   '0x77a21706F9Cdd6c3476Dd2c6fa52D99c59DACB4A',
    //   '0x0F49e6b6c67CFd2Dc00DdE4bf24e4a99760F0f28' ]
    let signer = customHttpProvider.getSigner(accounts[1]);
    console.log(signer);
    // JsonRpcSigner {
    //   provider:
    //    JsonRpcProvider {
    //      ready: Promise { <pending> },
    //      _lastBlockNumber: -2,
    //      _balances: {},
    //      _events: [],
    //      _pollingInterval: 4000,
    //      _emitted: { block: -2 },
    //      _fastQueryDate: 0,
    //      connection: { url: 'http://localhost:8545' } },
    //   _address: '0x7DdaD6a67544efB0c51808c77009a7B98Cc81630' }
}).catch((e)=>{
    console.log(e);
});

 

JsonRpcSigner 看之前的Signer API

An account from a JSON-RPC API connection the conforms to the Signer API. The getSignermethod of a JsonRpcProvider should be used to instantiate these.

prototype . provider
The provider that this Signer is connected to.
prototype . getAddress ( )   =>   Promise<Address>
Returns a Promise that resolves to the account address.
prototype . getBalance ( [ blockTag = “latest” ] )   =>   Promise<BigNumber>
Returns a Promise for the account balance.
prototype . getTransactionCount ( [ blockTag = “latest” ] )   =>   Promise<number>
Returns a Promise for the account transaction count. This can be used to determine the next nonce to use for a transaction.
prototype . sendTransaction ( [ transactionRequest ] )   =>   Promise<TransactionResponse>

Returns a Promise that resolves to the Transaction Response for the sent transaction.

If an error occurs after the netowrk may have received the transaction, the promise will reject with the error, with the additional property transactionHash so that further processing may be done.

prototype . signMessage ( message )   =>   Promise<hex>
Returns a Promise that resolves the signature of a signed message, in the Flat Format.
prototype . unlock ( password )   =>   Promise<boolean>解锁账户
Returns a Promise the resolves to true or false, depending on whether the account unlock was successful.

 

 

 

posted @ 2018-11-26 20:35  慢行厚积  阅读(3484)  评论(0编辑  收藏  举报