ethers.js/docs.wrm/api/signer.wrm

431 lines
15 KiB
Plaintext
Raw Normal View History

2020-06-12 10:38:55 +03:00
2020-05-08 10:24:40 +03:00
_section: Signers @<signers>
2020-06-12 10:38:55 +03:00
A **Signer** in //ethers// is an abstraction of an Ethereum Account,
which can be used to sign messages and transactions and send
signed transactions to the Ethereum Network to execute state
changing operations.
2020-11-23 07:03:50 +03:00
The available operations depend largely on the sub-class used.
2020-06-12 10:38:55 +03:00
For example, a Signer from MetaMask can send transactions and sign
messages but cannot sign a transaction (without broadcasting it).
The most common Signers you will encounter are:
- [[Wallet]], which is a class which knows its private key and can
execute any operations with it
- [[JsonRpcSigner]], which is connected to a [[JsonRpcProvider]] (or
sub-class) and is acquired using [getSigner](JsonRpcProvider-getSigner)
2020-05-08 10:24:40 +03:00
_subsection: Signer @<Signer> @SRC<abstract-signer:class.Signer>
2020-11-23 07:03:50 +03:00
The **Signer** class is abstract and cannot be directly instantiated.
2020-06-12 10:38:55 +03:00
2020-11-23 07:03:50 +03:00
Instead use one of the concrete sub-classes, such as the [[Wallet]],
2020-06-12 10:38:55 +03:00
[[VoidSigner]] or [[JsonRpcSigner]].
2020-01-10 09:01:00 +03:00
2020-05-08 10:24:40 +03:00
_property: signer.connect(provider) => [[Signer]] @<Signer-connect>
2020-01-10 09:01:00 +03:00
Sub-classes **must** implement this, however they may simply throw an error
if changing providers is not supported.
2020-06-12 10:38:55 +03:00
_property: signer.getAddress() => Promise<string<[[address]]>> @<Signer-getaddress> @SRC<abstract-signer:Signer.connect>
2020-01-10 09:01:00 +03:00
Returns a Promise that resolves to the account address.
This is a Promise so that a **Signer** can be designed around an
asynchronous source, such as hardware wallets.
Sub-classes **must** implement this.
2020-05-08 10:24:40 +03:00
_property: Signer.isSigner(object) => boolean @<Signer-isSigner> @SRC<abstract-signer>
2021-07-02 06:25:01 +03:00
Returns true if and only if //object// is a **Signer**.
2020-01-10 09:01:00 +03:00
2020-05-08 10:24:40 +03:00
_heading: Blockchain Methods @<Signer--blockchain-methods>
2020-01-10 09:01:00 +03:00
2020-05-08 10:24:40 +03:00
_property: signer.getBalance([ blockTag = "latest" ]) => Promise<[[BigNumber]]> @<Signer-getBalance> @SRC<abstract-signer>
2020-02-01 11:39:21 +03:00
Returns the balance of this wallet at //blockTag//.
2020-05-08 10:24:40 +03:00
_property: signer.getChainId() => Promise<number> @<Signer-getChainId> @SRC<abstract-signer>
Returns the chain ID this wallet is connected to.
2020-05-08 10:24:40 +03:00
_property: signer.getGasPrice() => Promise<[[BigNumber]]> @<Signer-getGasPrice> @SRC<abstract-signer>
2020-02-01 11:39:21 +03:00
Returns the current gas price.
2020-05-08 10:24:40 +03:00
_property: signer.getTransactionCount([ blockTag = "latest" ]) => Promise<number> @<Signer-getTransactionCount> @SRC<abstract-signer>
2020-02-01 11:39:21 +03:00
Returns the number of transactions this account has ever sent. This
is the value required to be included in transactions as the ``nonce``.
2020-05-08 10:24:40 +03:00
_property: signer.call(transactionRequest) => Promise<string<[[DataHexString]]>> @<Signer-call> @SRC<abstract-signer>
2020-02-01 11:39:21 +03:00
Returns the result of calling using the //transactionRequest//, with this
account address being used as the ``from`` field.
2020-05-08 10:24:40 +03:00
_property: signer.estimateGas(transactionRequest) => Promise<[[BigNumber]]> @<Signer-estimateGas> @SRC<abstract-signer>
2020-02-01 11:39:21 +03:00
Returns the result of estimating the cost to send the //transactionRequest//,
with this account address being used as the ``from`` field.
2020-06-12 10:38:55 +03:00
_property: signer.resolveName(ensName) => Promise<string<[[address]]>> @<Signer-resolveName> @SRC<abstract-signer>
2020-02-01 11:39:21 +03:00
Returns the address associated with the //ensName//.
2020-01-10 09:01:00 +03:00
2020-06-12 10:38:55 +03:00
_heading: Signing @<Signer--signing-methods>
2020-01-10 09:01:00 +03:00
2020-05-08 10:24:40 +03:00
_property: signer.signMessage(message) => Promise<string<[RawSignature](signature-raw)>> @<Signer-signMessage>
This returns a Promise which resolves to the [[signature-raw]]
2020-01-10 09:01:00 +03:00
of //message//.
A signed message is prefixd with ``"\\x19Ethereum Signed Message:\\n"`` and
the length of the message, using the [hashMessage](utils-hashMessage)
method, so that it is [EIP-191](link-eip-191) compliant. If recovering
the address in Solidity, this prefix will be required to create a matching
hash.
2020-01-10 09:01:00 +03:00
Sub-classes **must** implement this, however they may throw if signing a
2020-06-12 10:38:55 +03:00
message is not supported, such as in a Contract-based Wallet or
Meta-Transaction-based Wallet.
2020-01-10 09:01:00 +03:00
_note: Note
If //message// is a string, it is **treated as a string** and
converted to its representation in UTF8 bytes.
2020-05-08 10:24:40 +03:00
**If and only if** a message is a [[Bytes]] will it be treated as
2020-01-10 09:01:00 +03:00
binary data.
For example, the string ``"0x1234"`` is 6 characters long (and in
this case 6 bytes long). This is **not** equivalent to the array
``[ 0x12, 0x34 ]``, which is 2 bytes long.
A common case is to sign a hash. In this case, if the hash is a
string, it **must** be converted to an array first, using the
[arrayify](utils-arrayify) utility function.
_null:
2020-05-08 10:24:40 +03:00
_property: signer.signTransaction(transactionRequest) => Promise<string<[[DataHexString]]>> @<Signer-signTransaction>
2020-01-10 09:01:00 +03:00
Returns a Promise which resolves to the signed transaction of the
//transactionRequest//. This method does not populate any missing fields.
Sub-classes **must** implement this, however they may throw if signing a
2020-06-12 10:38:55 +03:00
transaction is not supported, which is common for security reasons in many
clients.
2020-01-10 09:01:00 +03:00
2020-05-08 10:24:40 +03:00
_property: signer.sendTransaction(transactionRequest) => Promise<[[providers-TransactionResponse]]> @<Signer-sendTransaction>
2020-01-10 09:01:00 +03:00
This method populates the transactionRequest with missing fields, using
2020-05-08 10:24:40 +03:00
[populateTransaction](Signer-populateTransaction) and returns a Promise which resolves to the transaction.
2020-01-10 09:01:00 +03:00
2020-06-12 10:38:55 +03:00
Sub-classes **must** implement this, however they may throw if sending a
transaction is not supported, such as the [[VoidSigner]] or if the
Wallet is offline and not connected to a [[Provider]].
2020-01-10 09:01:00 +03:00
2020-11-23 07:03:50 +03:00
_property: signer._signTypedData(domain, types, value) => Promise<string<[RawSignature](signature-raw)>> @<Signer-signTypedData>
Signs the typed data //value// with //types// data structure for //domain// using
the [[link-eip-712]] specification.
_warning: Experimental feature (this method name will change)
This is still an experimental feature. If using it, please specify the **exact**
version of ethers you are using (e.g. spcify ``"5.0.18"``, **not** ``"^5.0.18"``) as
the method name will be renamed from ``_signTypedData`` to ``signTypedData`` once
it has been used in the field a bit.
_code: Typed Data Example @lang<javascript>
//_hide: signer = new Wallet("0x1234567890123456789012345678901234567890123456789012345678901234");
2020-11-23 07:03:50 +03:00
// All properties on a domain are optional
const domain = {
name: 'Ether Mail',
version: '1',
chainId: 1,
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC'
};
// The named list of all type definitions
const types = {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' }
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' }
]
};
// The data to sign
const value = {
from: {
name: 'Cow',
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826'
},
to: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'
},
contents: 'Hello, Bob!'
};
//_result:
signature = await signer._signTypedData(domain, types, value);
//_log:
2020-11-23 07:03:50 +03:00
2020-05-08 10:24:40 +03:00
_heading: Sub-Classes @<Signer--subclassing>
2020-01-10 09:01:00 +03:00
It is very important that all important properties of a **Signer** are
**immutable**. Since Ethereum is very asynchronous and deals with critical
data (such as ether and other potentially valuable crypto assets), keeping
2020-06-12 10:38:55 +03:00
properties such as the //provider// and //address// static throughout the
life-cycle of the Signer helps prevent serious issues and many other classes
and libraries make this assumption.
2020-01-10 09:01:00 +03:00
A sub-class **must** extend Signer and **must** call ``super()``.
2020-01-10 09:01:00 +03:00
2020-05-08 10:24:40 +03:00
_property: signer.checkTransaction(transactionRequest) => [[providers-TransactionRequest]] @<Signer-checkTransaction> @SRC<abstract-signer>
2020-11-23 07:03:50 +03:00
This is generally not required to be overridden, but may be needed to provide
2020-02-01 11:39:21 +03:00
custom behaviour in sub-classes.
This should return a **copy** of the //transactionRequest//, with any properties
needed by ``call``, ``estimateGas`` and ``populateTransaction`` (which is used
by sendTransaction). It should also throw an error if any unknown key is specified.
2020-11-23 07:03:50 +03:00
The default implementation checks only if valid [[providers-TransactionRequest]] properties
2020-06-12 10:38:55 +03:00
exist and adds ``from`` to the transaction if it does not exist.
If there is a ``from`` field it **must** be verified to be equal to the Signer's address.
2020-05-08 10:24:40 +03:00
_property: signer.populateTransaction(transactionRequest) => Promise<[[providers-TransactionRequest]]> @<Signer-populateTransaction> @SRC<abstract-signer>
2020-11-23 07:03:50 +03:00
This is generally not required to be overridden, but may be needed to provide
2020-02-01 11:39:21 +03:00
custom behaviour in sub-classes.
This should return a **copy** of //transactionRequest//, follow the same procedure
as ``checkTransaction`` and fill in any properties required for sending a transaction.
The result should have all promises resolved; if needed the [resolveProperties](utils-resolveproperties)
utility function can be used for this.
2020-02-01 11:39:21 +03:00
The default implementation calls ``checkTransaction`` and resolves to if it is an
ENS name, adds ``gasPrice``, ``nonce``, ``gasLimit`` and ``chainId`` based on the
related operations on Signer.
2020-01-10 09:01:00 +03:00
2020-06-12 10:38:55 +03:00
2020-05-08 10:24:40 +03:00
_subsection: Wallet @<Wallet> @INHERIT<[[ExternallyOwnedAccount]] and [[Signer]]> @SRC<wallet:class.Wallet>
2020-01-10 09:01:00 +03:00
2020-05-08 10:24:40 +03:00
The Wallet class inherits [[Signer]] and can sign transactions and messages
2020-01-10 09:01:00 +03:00
using a private key as a standard Externally Owned Account (EOA).
2020-05-08 10:24:40 +03:00
_property: new ethers.Wallet(privateKey [ , provider ]) @<Wallet-constructor> @SRC<wallet:constructor.Wallet>
2020-01-10 09:01:00 +03:00
Create a new Wallet instance for //privateKey// and optionally
connected to the //provider//.
2020-05-08 10:24:40 +03:00
_property: ethers.Wallet.createRandom( [ options = { } ]) => [[Wallet]] @<Wallet-createRandom> @SRC<wallet>
2020-01-10 09:01:00 +03:00
Returns a new Wallet with a random private key, generated from
cryptographically secure entropy sources. If the current environment
does not have a secure entropy source, an error is thrown.
2020-06-12 10:38:55 +03:00
Wallets created using this method will have a mnemonic.
2020-05-08 10:24:40 +03:00
_property: ethers.Wallet.fromEncryptedJson(json, password [ , progress ]) => Promise<[[Wallet]]> @<Wallet-fromEncryptedJson> @SRC<wallet>
2020-06-12 10:38:55 +03:00
Create an instance from an encrypted JSON wallet.
If //progress// is provided it will be called during decryption
with a value between 0 and 1 indicating the progress towards
completion.
2020-01-10 09:01:00 +03:00
2020-05-08 10:24:40 +03:00
_property: ethers.Wallet.fromEncryptedJsonSync(json, password) => [[Wallet]] @<Wallet-fromEncryptedJsonSync> @SRC<wallet>
2020-04-17 05:25:05 +03:00
Create an instance from an encrypted JSON wallet.
This operation will operate synchronously which will lock up the user
interface, possibly for a non-trivial duration. Most applications should
use the asynchronous ``fromEncryptedJson`` instead.
2020-06-12 10:38:55 +03:00
_property: ethers.Wallet.fromMnemonic(mnemonic [ , path, [ wordlist ] ]) => [[Wallet]] @<Wallet.fromMnemonic>
2020-01-10 09:01:00 +03:00
Create an instance from a mnemonic phrase.
2020-06-12 10:38:55 +03:00
If path is not specified, the Ethereum default path is used (i.e. ``m/44'/60'/0'/0/0``).
2020-01-10 09:01:00 +03:00
If wordlist is not specified, the English Wordlist is used.
2020-06-12 10:38:55 +03:00
_heading: Properties @<Wallet--properties>
2020-01-10 09:01:00 +03:00
2020-06-12 10:38:55 +03:00
_property: wallet.address => string<[[address]]>
2020-01-10 09:01:00 +03:00
The address for the account this Wallet represents.
2020-05-08 10:24:40 +03:00
_property: wallet.provider => [[Provider]]
2020-11-23 07:03:50 +03:00
The provider this wallet is connected to, which will be used for any [[Signer--blockchain-methods]]
2020-01-10 09:01:00 +03:00
methods. This can be null.
_note: Note
A **Wallet** instance is immutable, so if you wish to change the Provider, you
2020-05-08 10:24:40 +03:00
may use the [connect](Signer-connect) method to create a new instance connected
2020-01-10 09:01:00 +03:00
to the desired provider.
2020-05-08 10:24:40 +03:00
_property: wallet.publicKey => string<[[DataHexString]]<65>>
2020-01-10 09:01:00 +03:00
The uncompressed public key for this Wallet represents.
2020-06-12 10:38:55 +03:00
_heading: Methods @<Wallet--methods>
2020-01-10 09:01:00 +03:00
2020-06-12 10:38:55 +03:00
_property: wallet.encrypt(password, [ options = { }, [ progress ] ]) => Promise<string> @<Wallet-encrypt>
2020-01-10 09:01:00 +03:00
Encrypt the wallet using //password// returning a Promise which resolves
to a JSON wallet.
2020-06-12 10:38:55 +03:00
If //progress// is provided it will be called during decryption
with a value between 0 and 1 indicating the progress towards
completion.
_code: Wallet Examples @lang<javascript>
// Create a wallet instance from a mnemonic...
mnemonic = "announce room limb pattern dry unit scale effort smooth jazz weasel alcohol"
walletMnemonic = Wallet.fromMnemonic(mnemonic)
// ...or from a private key
walletPrivateKey = new Wallet(walletMnemonic.privateKey)
//_result:
2020-06-12 10:38:55 +03:00
walletMnemonic.address === walletPrivateKey.address
//_log:
2020-06-12 10:38:55 +03:00
// The address as a Promise per the Signer API
//_result:
2021-06-11 00:38:38 +03:00
await walletMnemonic.getAddress()
//_log:
2020-06-12 10:38:55 +03:00
// A Wallet address is also available synchronously
//_result:
2020-06-12 10:38:55 +03:00
walletMnemonic.address
//_log:
2020-06-12 10:38:55 +03:00
// The internal cryptographic components
//_result:
2020-06-12 10:38:55 +03:00
walletMnemonic.privateKey
//_log:
//_result:
2020-06-12 10:38:55 +03:00
walletMnemonic.publicKey
//_log:
2020-06-12 10:38:55 +03:00
// The wallet mnemonic
//_result:
2020-06-12 10:38:55 +03:00
walletMnemonic.mnemonic
//_log:
2020-06-12 10:38:55 +03:00
// Note: A wallet created with a private key does not
// have a mnemonic (the derivation prevents it)
//_result:
2020-06-12 10:38:55 +03:00
walletPrivateKey.mnemonic
//_log:
2020-06-12 10:38:55 +03:00
// Signing a message
//_result:
await walletMnemonic.signMessage("Hello World")
//_log:
2020-06-12 10:38:55 +03:00
tx = {
to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
value: utils.parseEther("1.0")
}
// Signing a transaction
//_result:
await walletMnemonic.signTransaction(tx)
//_log:
2020-06-12 10:38:55 +03:00
// The connect method returns a new instance of the
// Wallet connected to a provider
//_result:
2020-06-12 10:38:55 +03:00
wallet = walletMnemonic.connect(provider)
//_null:
2020-06-12 10:38:55 +03:00
// Querying the network
//_result:
await wallet.getBalance();
//_log:
//_result:
await wallet.getTransactionCount();
//_log:
2020-06-12 10:38:55 +03:00
// Sending ether
//_hide: wallet = localSigner; /* prevent insufficient funds error from blowing up the docs */
//_result:
await wallet.sendTransaction(tx)
//_log:
2020-06-12 10:38:55 +03:00
2020-01-10 09:01:00 +03:00
2020-05-08 10:24:40 +03:00
_subsection: VoidSigner @<VoidSigner> @INHERIT<[[Signer]]> @SRC<abstract-signer:class.VoidSigner>
2020-01-10 09:01:00 +03:00
A **VoidSigner** is a simple Signer which cannot sign.
It is useful as a read-only signer, when an API requires a
Signer as a parameter, but it is known only read-only operations
will be carried.
For example, the ``call`` operation will automatically have the
provided address passed along during the execution.
2020-06-12 10:38:55 +03:00
_property: new ethers.VoidSigner(address [ , provider ]) => [[VoidSigner]]
2020-01-10 09:01:00 +03:00
Create a new instance of a **VoidSigner** for //address//.
2020-06-12 10:38:55 +03:00
_property: voidSigner.address => string<[[address]]>
2020-01-10 09:01:00 +03:00
The address of this **VoidSigner**.
2020-06-12 10:38:55 +03:00
_code: VoidSigner Pre-flight Example @lang<javascript>
address = "0x8ba1f109551bD432803012645Ac136ddd64DBA72"
signer = new ethers.VoidSigner(address, provider)
// The DAI token contract
abi = [
"function balanceOf(address) view returns (uint)",
"function transfer(address, uint) returns (bool)"
]
contract = new ethers.Contract("dai.tokens.ethers.eth", abi, signer)
// Get the number of tokens for this account
//_result:
2020-06-12 10:38:55 +03:00
tokens = await contract.balanceOf(signer.getAddress())
//_log:
2020-06-12 10:38:55 +03:00
//
// Pre-flight (check for revert) on DAI from the signer
//
// Note: We do not have the private key at this point, this
// simply allows us to check what would happen if we
// did. This can be useful to check before prompting
// a request in the UI
//
// This will pass since the token balance is available
//_result:
await contract.callStatic.transfer("donations.ethers.eth", tokens)
//_log:
2020-06-12 10:38:55 +03:00
// This will fail since it is greater than the token balance
//_throws:
await contract.callStatic.transfer("donations.ethers.eth", tokens.add(1))
//_log:
2020-06-12 10:38:55 +03:00
2020-01-10 09:01:00 +03:00
2020-05-08 10:24:40 +03:00
_subsection: ExternallyOwnedAccount @<ExternallyOwnedAccount>
2020-01-10 09:01:00 +03:00
2020-02-25 22:57:11 +03:00
This is an interface which contains a minimal set of properties
required for Externally Owned Accounts which can have certain
operations performed, such as encoding as a JSON wallet.
2020-06-12 10:38:55 +03:00
_property: eoa.address => string<[[address]]>
2020-01-10 09:01:00 +03:00
The [[address]] of this EOA.
2020-05-08 10:24:40 +03:00
_property: eoa.privateKey => string<[[DataHexString]]<32>>
2020-01-10 09:01:00 +03:00
The privateKey of this EOA
2020-05-08 10:24:40 +03:00
_property: eoa.mnemonic => [[Mnemonic]]
2020-01-10 09:01:00 +03:00
2020-02-25 22:57:11 +03:00
//Optional//. The account HD mnemonic, if it has one and can be
2020-11-23 07:03:50 +03:00
determined. Some sources do not encode the mnemonic, such as
2020-02-25 22:57:11 +03:00
HD extended keys.