Providers API¶
A Provider abstracts a connection to the Ethereum blockchain, for issuing queries and sending state changing transactions.
Unlike the Web3 provider, there is no concept of accounts or signing entities in an Ethers Provider. It is simply a connection to the network, and cannot unlock accounts or sign and is unaware of your Ethereum addresses.
To manage state changing operations, you must use a Wallet to sign transactions. If you pass a wallet in as a signer to a Contract, this is managed for you by the contract.
Connecting to Ethereum¶
There are several ways to connect to the Ethereum blockchain:
- new ethers . providers . EtherscanProvider( [ network ] [ , apiToken ] )
Connect to the Etherscan blockchain web service API.
default: network=’homestead’, apiToken=null
- new ethers . providers . JsonRpcProvider( [ url ] [ , network ] )
Connect to the JSON-RPC API url of an Ethereum node, such as Parity or Geth.
default: url=”http://localhost:8545/”, network=’homestead’
- new ethers . providers . InfuraProvider( [ network ] [ , apiAccessToken ] )
Connect to the INFURA hosted network of Ethereum nodes.
default: network=’homestead’, apiAccessToken=null
- new ethers . providers . Web3Provider( web3Provider [ , network ] )
Connect to an existing Web3 provider (e.g. web3Instance.currentProvider).
default: network=’homestead’
- 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.
- ethers . providers . getDefaultProvider( [ network ] )
This automatically creates a FallbackProvider backed by INFURA and Etherscan; recommended
default: network=’homestead’
Examples¶
var providers = require('ethers').providers;
// Connect to Ropsten (the test network)
// You may specify any of:
// - boolean; true = ropsten, false = homestead
// - object; { name: 'ropsten', chainId: 3 } (see ethers.networks);
// - string; e.g. 'homestead', 'ropsten', 'rinkeby', 'kovan'
var network = providers.networks.ropsten;
// Connect to INFUA
var infuraProvider = new providers.InfuraProvider(network);
// Connect to Etherscan
var etherscanProvider = new providers.EtherscanProvider(network);
// Creating a provider to automatically fallback onto Etherscan
// if INFURA is down
var fallbackProvider = new providers.FallbackProvider([
infuraProvider,
etherscanProvider
]);
// This is equivalent to using the getDefaultProvider
var provider = providers.getDefaultProvider(network)
// Connect to a local Parity instance
var provider = new providers.JsonRpcProvider('http://localhost:8545', network);
// Connect to an injected Web3's provider (e.g. MetaMask)
var web3Provider = new providers.Web3Provider(web3.currentProvider, network);
Prototype¶
All properties are immutable, and reflect their default value if not specified, or if indirectly populated by child Objects.
Provider¶
- prototype . name
- The name of the network the provider is connected to (e.g. ‘homestead’, ‘ropsten’, ‘rinkeby’, ‘kovan’)
- prototype . chainId
- The chain ID (or network ID) this provider is connected as; this is used by signers to prevent replay attacks across compatible networks
FallbackProvider ( inherits from Provider )¶
- prototype . providers
- A copy of the array of providers (modifying this variable will not affect the providers attached)
JsonRpcProvider ( inherits from Provider )¶
- prototype . url
- The JSON-RPC URL the provider is connected to
- prototype . send ( method , params )
- 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.
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)
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 )
Account Actions¶
- prototype . getBalance ( addressOrName [ , blockTag ] )
Returns a Promise with the balance (as a BigNumber) of addressOrName at blockTag. (See: Block Tags)
default: blockTag=”latest”
- prototype . getTransactionCount ( addressOrName [ , blockTag ] )
Returns a Promise with the number of sent transactions (as a Number) from addressOrName at blockTag. This is also the nonce required to send a new transaction. (See: Block Tags)
default: blockTag=”latest”
- prototype . lookupAddress ( address )
- Returns a Promise which resolves to the ENS name (or null) that address resolves to.
- prototype . resolveName ( ensName )
- Returns a Promise which resolves to the address (or null) of that the ensName resolves to.
Examples¶
var ethers = require('ethers');
var providers = ethers.providers;
var provider = providers.getDefaultProvider('ropsten');
var address = "0x02F024e0882B310c6734703AB9066EdD3a10C6e0";
provider.getBalance(address).then(function(balance) {
// balance is a BigNumber (in wei); format is as a sting (in ether)
var etherString = ethers.utils.formatEther(balance);
console.log("Balance: " + etherString);
});
provider.getTransactionCount(address).then(function(transactionCount) {
console.log("Total Transactions Ever Send: " + transactionCount);
});
provider.resolveName("test.ricmoose.eth").then(function(address) {
console.log("Address: " + address);
});
Blockchain Status¶
- prototype . getBlockNumber ( )
- Returns a Promise with the latest block number (as a Number).
- prototype . getGasPrice ( )
- Returns a Promise with the current gas price (as a BigNumber).
- prototype . getBlock ( blockHashOrBlockNumber )
- Returns a Promise with the block at blockHashorBlockNumber. (See: Block Responses)
- prototype . getTransaction ( transactionHash )
- Returns a Promise with the transaction with transactionHash. (See: Transaction Responses)
- prototype . getTransactionReceipt ( transactionHash )
- Returns a Promise with the transaction receipt with transactionHash. (See: Transaction Receipts)
Examples¶
Current State
var provider = providers.getDefaultProvider();
provider.getBlockNumber().then(function(blockNumber) {
console.log("Current block number: " + blockNumber);
});
provider.getGasPrice().then(function(gasPrice) {
// gasPrice is a BigNumber; convert it to a decimal string
gasPriceString = gasPrice.toString();
console.log("Current gas price: " + gasPriceString);
});
Blocks
var provider = providers.getDefaultProvider();
// Block Number
provider.getBlock(3346773).then(function(block) {
console.log(block);
});
// Block Hash
var blockHash = "0x7a1d0b010393c8d850200d0ec1e27c0c8a295366247b1bd6124d496cf59182ad";
provider.getBlock(blockHash).then(function(block) {
console.log(block);
});
Transactions
var provider = providers.getDefaultProvider();
var transactionHash = "0x7baea23e7d77bff455d94f0c81916f938c398252fb62fce2cdb43643134ce4ed";
provider.getTransaction(transactionHash).then(function(transaction) {
console.log(transaction);
});
provider.getTransactionReceipt(transactionHash).then(function(transactionReceipt) {
console.log(transactionReceipt);
});
Ethereum Name Resolution¶
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.
It is often useful to resolve a name entered by a user or perform a reverse lookup of an address to get a more human readbale name.
Resolving Names
var providers = require('ethers').providers;
var provider = providers.getDefaultProvider();
provider.resolveName('registrar.firefly.eth').then(function(address) {
console.log(address);
// '0x6fC21092DA55B392b045eD78F4732bff3C580e2c'
});
Looking up Addresses
provider.lookupAddress('0x6fC21092DA55B392b045eD78F4732bff3C580e2c').then(function(name) {
console.log(name);
// 'registrar.firefly.eth'
});
Contract Execution¶
These are relatively low-level calls. The Contracts API should usually be used instead.
- prototype . call ( transaction )
Send the read-only (constant) transaction to a single Ethereum node and return a Promise with the result (as a hex string) of executing it. (See Transaction Requests)
This is free, since it does not change any state on the blockchain.
- prototype . estimateGas ( transaction )
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 )
Send the signedTransaction to the entire Ethereum network and returns a Promise with the transaction hash.
This will consume gas from the account that signed the transaction.
Examples¶
Call (Constant) Functions
var ethers = require('ethers');
var provider = ethers.providers.getDefaultProvider();
// setup a transaction to call the CryptoKitties.symbol() function
// CryptoKitties contract address
var address = "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d";
// first 8 nibbles of the hash of symbol()
var data = ethers.utils.id('symbol()').substring(0,10);
var transaction = {
to: address,
data: data
}
provider.call(transaction).then(function(result) {
console.log(result);
// '0x000000000000000000000000000000000000000000000000000000000000002'+
// '00000000000000000000000000000000000000000000000000000000000000002'+
// '434b000000000000000000000000000000000000000000000000000000000000'
});
sendTransaction
var ethers = require('ethers');
var privateKey = '0x0123456789012345678901234567890123456789012345678901234567890123';
var wallet = new ethers.Wallet(privateKey);
wallet.provider = ethers.providers.getDefaultProvider('ropsten');
var transaction = {
to: "0x88a5C2d9919e46F883EB62F7b8Dd9d0CC45bc290",
value: ethers.utils.parseEther("0.1")
};
var estimateGasPromise = wallet.estimateGas(transaction);
estimateGasPromise.then(function(gasEstimate) {
console.log(gasEstimate.toString());
transaction.gasLimit = gasEstimate;
// Send the transaction
var sendTransactionPromise = wallet.sendTransaction(transaction);
sendTransactionPromise.then(function(transactionHash) {
console.log(transactionHash);
});
});
Contract State¶
- prototype . getCode ( addressOrName )
- Returns a Promise with the bytecode (as a hex string) at addressOrName.
- prototype . getStorageAt ( addressOrName , position [ , blockTag ] )
Returns a Promise with the value (as a hex string) at addressOrName in position at blockTag. (See Block Tags)
default: blockTag= “latest”
- prototype . getLogs ( filter )
- Returns a Promise with an array (possibly empty) of the logs that match the filter. (See Filters)
Examples¶
getCode
var ethers = require('ethers');
var provider = ethers.providers.getDefaultProvider();
var contractAddress = '0x6fC21092DA55B392b045eD78F4732bff3C580e2c';
var contractEnsName = 'registrar.firefly.eth';
var codePromise = provider.getCode(contractEnsName);
codePromise.then(function(result){
console.log('getCode by ENS name:');
console.log(result);
});
var codeByAddressPromise = provider.getCode(contractAddress);
codeByAddressPromise.then(function(result){
console.log('getCode by contract address:');
console.log(result);
});
getStorageAt
var ethers = require('ethers');
var provider = ethers.providers.getDefaultProvider();
var contractEnsName = 'registrar.firefly.eth';
var storagePromise = provider.getStorageAt(contractEnsName, 0);
storagePromise.then(function(result){
console.log(result);
});
getLogs
var ethers = require('ethers');
var provider = ethers.providers.getDefaultProvider();
var cryptoKittiesContractAddress = '0x06012c8cf97BEaD5deAe237070F9587f8E7A266d';
var topic = '0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80';
var filter = {
fromBlock: 5044502,
address: cryptoKittiesContractAddress,
topics: [ topic ]
}
var filterPromise = provider.getLogs(filter);
filterPromise.then(function(result){
console.log(result);
});
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 )
- Register a callback for any future eventType; see below for callback parameters
- prototype . once ( eventType , callback)
- Register a callback for the next (and only next) eventType; see below for callback parameters
- prototype . removeListener ( eventType , callback )
- Unregister the callback for eventType; if the same callback is registered more than once, only the first registered instance is removed
- prototype . removeAllListeners ( eventType )
- Unregister all callbacks for eventType
- prototype . listenerCount ( [ eventType ] )
- Return the number of callbacks registered for eventType, or if ommitted, the total number of callbacks registered
- prototype . resetEventsBlock ( 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 )
- any address
When the balance of the corresponding address changes
callback( balance )
- any transaction hash
When the corresponding transaction is mined; also see Waiting for Transactions
callback( transaction )
- an array of topics
When any of the topics are triggered in a block’s logs; when using the Contract API, this is automatically handled;
callback( log )
Waiting for Transactions¶
- prototype . waitForTransaction ( transactionHash [ , timeout ] )
- Return a Promise which returns the transaction once transactionHash is mined, with an optional timeout (in milliseconds)
Examples¶
// Get notified on every new block
provider.on('block', function(blockNumber) {
console.log('New Block: ' + blockNumber);
});
// Get notified on account balance change
provider.on('0x46Fa84b9355dB0708b6A57cd6ac222950478Be1d', function(balance) {
console.log('New Balance: ' + balance);
});
// Get notified when a transaction is mined
provider.once(transactionHash, function(transaction) {
console.log('Transaction Minded: ' + transaction.hash);
console.log(transaction);
);
// OR equivalently the waitForTransaction() returns a Promise
provider.waitForTransaction(transactionHash).then(function(transaction) {
console.log('Transaction Mined: ' + transaction.hash);
console.log(transaction);
});
// Get notified when a contract event is logged
var eventTopic = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
provider.on([ eventTopic ], function(log) {
console.log('Event Log');
console.log(log);
});
Objects¶
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"
]
}
Transaction Requests¶
Any property which accepts a number may also be specified as a BigNumber or hex string.
// Example:
{
// Required unless deploying a contract (in which case omit)
to: addressOrName, // the target address or ENS name
// 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¶
// Example:
{
// Only available for mined transactions
blockHash: "0x7f20ef60e9f91896b7ebb0962a18b8defb5e9074e62e1b6cde992648fe78794b",
blockNumber: 3346463,
transactionIndex: 51,
// Exactly one of these will be present (send vs. deploy contract)
creates: null,
to: "0xc149Be1bcDFa69a94384b46A1F91350E5f81c1AB",
// The transaction hash
hash: "0xf517872f3c466c2e1520e35ad943d833fdca5a6739cfea9e686c4c1b3ab1022e",
// See above (Transaction Requests) for these explained
data: "0x",
from: "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8",
gasLimit: utils.bigNumberify("90000"),
gasPrice: utils.bigNumberify("21488430592"),
nonce: 0,
value: utils.parseEther(1.0017071732629267),
// The network ID (or chain ID); 0 indicates replay-attack vulnerable
// (eg. 1 = Homestead mainnet, 3 = Ropsten testnet)
networkId: 1,
// The signature of the transaction
r: "0x5b13ef45ce3faf69d1f40f9d15b0070cc9e2c92f3df79ad46d5b3226d7f3d1e8",
s: "0x535236e497c59e3fba93b78e124305c7c9b20db0f8531b015066725e4bb31de6",
v: 37,
// The raw transaction
raw: "0xf87083154262850500cf6e0083015f9094c149be1bcdfa69a94384b46a1f913" +
"50e5f81c1ab880de6c75de74c236c8025a05b13ef45ce3faf69d1f40f9d15b0" +
"070cc9e2c92f3df79ad46d5b3226d7f3d1e8a0535236e497c59e3fba93b78e1" +
"24305c7c9b20db0f8531b015066725e4bb31de6"
}
Transaction Receipts¶
// Example
{
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
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
}
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).
The EtherscanProvider only supports a single topic.
// Example
{
// 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¶
Etherscan¶
- prototype . getEtherPrice ( )
- Returns a Promise with the price of ether in USD.
- prototype . getHistory ( addressOrName [ , startBlock [ , endBlock ] ] )
- Returns a Promise with an array of Transaction Responses for each transaction to or from addressOrName between startBlock and endBlock (inclusive).
Examples
var provider = new ethers.providers.EtherscanProvider();
// Getting the current Ethereum price
provider.getEtherPrice().then(function(price) {
console.log("Ether price in USD: " + price);
});
// Getting the transaction history of an address
var address = '0xb2682160c482eB985EC9F3e364eEc0a904C44C23';
var startBlock = 3135808;
var endBlock = 5091477;
provider.getHistory(address, startBlock, endBlock).then(function(history) {
console.log(history);
// [
// {
// hash: '0x327632ccb6d7bb47b455383e936b2f14e6dc50dbefdc214870b446603b468675',
// blockHash: '0x0415f0d2741de45fb748166c7dc2aad9b3ff66bcf7d0a127f42a71d3e286c36d',
// blockNumber: 3135808,
// transactionIndex: 1,
// from: '0xb2682160c482eB985EC9F3e364eEc0a904C44C23',
// gasPrice: ethers.utils.bigNumberify('0x4a817c800'),
// gasLimit: ethers.utils.bigNumberify('0x493e0'),
// to: '0xAe572713CfE65cd7033774170F029B7219Ee7f70',
// value: ethers.utils.bigNumberify('0xd2f13f7789f0000'),
// nonce: 25,
// data: '0x',
// creates: null,
// networkId: 0
// },
// {
// hash: '0x7c10f2e7125a1fa5e37b54f5fac5465e8d594f89ff97916806ca56a5744812d9',
// ...
// }
// ]
});
Web3Provider¶
- prototype . listAccounts ( )
- Returns a Promise with a list of all accounts the node connected to this Web3 controls.
- prototype . getSigner( [ address ] )
- Returns a Signer that uses an account on the node the Web3 object is connected to. If no address is specified, the first account on the node is used.
Examples
web3Provider.listAccounts().then(function(accounts) {
var signer = web3Provider.getSigner(accounts[1]);
console.log(signer);
});