docs: added more docs for getting started
This commit is contained in:
parent
fb035d8416
commit
4de185b5c7
@ -1,29 +1,29 @@
|
|||||||
_section: Getting Started @<getting-started> @priority<100>
|
_section: Getting Started @<getting-started> @priority<100>
|
||||||
|
|
||||||
This
|
This is a very short introduction to Ethers, but covers many of the
|
||||||
The v6 getting started is coming soon...
|
most common operations that developers require and provides a
|
||||||
|
starting point for those newer to Ethereum.
|
||||||
|
|
||||||
_heading: Installing
|
|
||||||
|
|
||||||
_code: Install via NPM @lang<shell>
|
_heading: Getting Ethers
|
||||||
# Create a new folder for your project
|
|
||||||
/home/ricmoo> mkdir test-ethers
|
|
||||||
/home/ricmoo> cd test-ethers
|
|
||||||
|
|
||||||
|
If using NPM, you must first install Ethers.
|
||||||
|
|
||||||
|
_code: installing via NPM @lang<shell>
|
||||||
# Install ethers
|
# Install ethers
|
||||||
/home/ricmoo/test-ethers> npm install ethers@beta-exports
|
/home/ricmoo/test-ethers> npm install ethers@beta
|
||||||
|
|
||||||
_heading: Importing
|
_null:
|
||||||
|
|
||||||
Everything in Ethers is exported at the root as well as on the ``ethers``
|
Everything in Ethers is exported from its root as well as on the ``ethers``
|
||||||
object. There are also ``exports`` in the ``package.json`` to facilitate
|
object. There are also ``exports`` in the ``package.json`` to facilitate
|
||||||
sub-packages.
|
more fine-grained importing.
|
||||||
|
|
||||||
Generally this documentation will presume all exports from ethers
|
Generally this documentation will presume all exports from ethers
|
||||||
have been imported in the code examples, but you may import the
|
have been imported in the code examples, but you may import the
|
||||||
necessary objects any way you wish.
|
necessary objects any way you wish.
|
||||||
|
|
||||||
_code: Node.js @lang<script>
|
_code: importing in Node.js @lang<script>
|
||||||
// Import everything
|
// Import everything
|
||||||
import { ethers } from "ethers";
|
import { ethers } from "ethers";
|
||||||
|
|
||||||
@ -33,28 +33,80 @@ _code: Node.js @lang<script>
|
|||||||
// Import from a specific export
|
// Import from a specific export
|
||||||
import { HDNodeWallet } from "ethers/wallet";
|
import { HDNodeWallet } from "ethers/wallet";
|
||||||
|
|
||||||
_code: Web Browsers (ESM) @lang<script>
|
_code: importing ESM in a browser @lang<script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { ethers } from "https://cdnjs.cloudflare.com/ajax/libs/ethers/5.7.2/ethers.min.js";
|
import { ethers } from "https://cdnjs.cloudflare.com/ajax/libs/ethers/5.7.2/ethers.min.js";
|
||||||
// Your code here...
|
// Your code here...
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
_subsection: Some Common Terminology
|
_subsection: Some Common Terminology @<starting-glossary>
|
||||||
|
|
||||||
_heading: PROVIDER
|
To begin, it is useful to have a basic understanding of the types of
|
||||||
|
objects available and what they are responsible for, at a high level.
|
||||||
|
|
||||||
_heading: SIGNER
|
_heading: Provider
|
||||||
|
|
||||||
_heading: TRANSACTION
|
A [[Provider]] is a read-only connection to the blockchain, which allows
|
||||||
|
querying the blockchain state, such as accout, block or transaction details,
|
||||||
|
querying event logs or evaluating read-only code using call.
|
||||||
|
|
||||||
|
If you are coming from Web3.js, you are used to a **Provider** offering
|
||||||
|
both read and write access. In Ethers, all write operations are further
|
||||||
|
abstracted into another Object, the **Signer**.
|
||||||
|
|
||||||
|
_heading: Signer
|
||||||
|
|
||||||
|
A [[Signer]] wraps all operations that interact with an account. An
|
||||||
|
account generally has a private key located //somewhere//, which can be
|
||||||
|
used to sign a variety of types of payloads.
|
||||||
|
|
||||||
|
The private key may be located in memory (using a [[Wallet]]) or
|
||||||
|
protected via some IPC layer, such as MetaMask which proxies interaction
|
||||||
|
from a website to a browser plug-in, which keeps the private key out of
|
||||||
|
the reach of the website and only permits interaction after requesting
|
||||||
|
permission from the user and receiving authorization.
|
||||||
|
|
||||||
|
_heading: Transaction
|
||||||
|
|
||||||
|
To make any state changes to the blockchain, a transaction is required,
|
||||||
|
which requires a fee be paid, where the fee covers the associated costs
|
||||||
|
with executing the transaction (such as reading the disk and performing
|
||||||
|
maths) and storing the updated information.
|
||||||
|
|
||||||
|
If a transaction reverts, a fee must still be paid, since the validator
|
||||||
|
still had to expend resources to try running the transaction to determine
|
||||||
|
that it reverted and the details of its failure are still be recorded.
|
||||||
|
|
||||||
|
Transactions include sending ether from one user to another, deploying
|
||||||
|
a **Contract** or executing a state-changing operation against a
|
||||||
|
**Contract**.
|
||||||
|
|
||||||
|
_heading: Contract
|
||||||
|
|
||||||
|
A [[Contract]] is a program that has been deployed to the blockchain,
|
||||||
|
which includes some code and has allocated storage which it can read
|
||||||
|
from and write to.
|
||||||
|
|
||||||
|
It may be read from when it is connected to a [[Provider]] or
|
||||||
|
state-changing operations can be called when connected to a [[Signer]].
|
||||||
|
|
||||||
_heading: Receipt
|
_heading: Receipt
|
||||||
|
|
||||||
_heading: CONTRACT
|
Once a **Transaction** has been submitted to the blockchain, it is placed
|
||||||
|
in the memory pool (mempool) until a validator decides to include it.
|
||||||
|
|
||||||
|
A transaction's changes are only made once it has been included in the
|
||||||
|
blockchain, at which time a receipt is available, which includes details
|
||||||
|
about the transaction, such as which block it was included in, the actual
|
||||||
|
fee paid, gas used, all the events that it emitted and whether it was
|
||||||
|
successful or reverted.
|
||||||
|
|
||||||
|
|
||||||
|
_subsection: Connecting to Ethereum @<starting-connecting>
|
||||||
|
|
||||||
_subsection: Connecting to Ethereum
|
This very first thing needed to begin interacting with the blockchain is
|
||||||
|
connecting to it using a [[Provider]].
|
||||||
|
|
||||||
_heading: MetaMask (and other injected providers)
|
_heading: MetaMask (and other injected providers)
|
||||||
|
|
||||||
@ -107,7 +159,7 @@ When using your own Ethereum node or a developer-base blockchain,
|
|||||||
such as Hardhat or Ganache, you can get access the accounts with
|
such as Hardhat or Ganache, you can get access the accounts with
|
||||||
[[JsonRpcProvider-getSigner]].
|
[[JsonRpcProvider-getSigner]].
|
||||||
|
|
||||||
_code: @lang<script>
|
_code: connecting to a JSON-RPC URL @lang<script>
|
||||||
|
|
||||||
// If no %%url%% is provided, it connects to the default
|
// If no %%url%% is provided, it connects to the default
|
||||||
// http://localhost:8545, which most nodes use.
|
// http://localhost:8545, which most nodes use.
|
||||||
@ -117,9 +169,51 @@ _code: @lang<script>
|
|||||||
signer = await provider.getSigner()
|
signer = await provider.getSigner()
|
||||||
|
|
||||||
|
|
||||||
_subsection: Interacting with the Blockchain
|
_subsection: User Interaction @<starting-display>
|
||||||
|
|
||||||
_heading: Querying State (reading)
|
All units in Ethereum tend to be integer values, since dealing with
|
||||||
|
decimals and floating points can lead to inprecise and non-obvious
|
||||||
|
results when performing mathematic operations.
|
||||||
|
|
||||||
|
As a result, the internal units used (e.g. wei) which are suited for
|
||||||
|
machine-readable purposes and maths are often very large and not
|
||||||
|
terribly human-readable.
|
||||||
|
|
||||||
|
For example, imagine dealing with dollars and cents; you would show
|
||||||
|
values like ``"$2.56"``. In the blockchain world we would keep all
|
||||||
|
values as cents, so that would be ``256`` cents, internally.
|
||||||
|
|
||||||
|
So, when accepting data that a user types, it must be converted from
|
||||||
|
its decimal string representation (e.g. ``"2.56"``) to its lowest-unit
|
||||||
|
integer representation (e.g. ``256``). And when displaying a value to
|
||||||
|
a user the opposite operation is necessary.
|
||||||
|
|
||||||
|
In Ethereum, //one ether// is equal to ``10 *\* 18`` wei and //one gwei//
|
||||||
|
is equal to ``10 *\* 9`` wei, so the values get very large very quickly,
|
||||||
|
so some convenience functions are provided to help convert between
|
||||||
|
representations.
|
||||||
|
|
||||||
|
_code: @lang<javascript>
|
||||||
|
// Convert user-provided strings in ether to wei for a value
|
||||||
|
eth = parseEther("1.0")
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
// Convert user-provided strings in gwei to wei for max base fee
|
||||||
|
feePerGas = parseUnits("4.5", "gwei")
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
// Convert a value in wei to a string in ether to display in a UI
|
||||||
|
formatEther(eth)
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
// Convert a value in wei to a string in gwei to display in a UI
|
||||||
|
formatUnits(feePerGas, "gwei")
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
|
||||||
|
_subsection: Interacting with the Blockchain @<starting-blockchain>
|
||||||
|
|
||||||
|
_heading: Querying State
|
||||||
|
|
||||||
Once you have a [[Provider]], you have a read-only connection to
|
Once you have a [[Provider]], you have a read-only connection to
|
||||||
the data on the blockchain. This can be used to query the current
|
the data on the blockchain. This can be used to query the current
|
||||||
@ -145,7 +239,7 @@ _code: @lang<javascript>
|
|||||||
await provider.getTransactionCount("ethers.eth")
|
await provider.getTransactionCount("ethers.eth")
|
||||||
//_result:
|
//_result:
|
||||||
|
|
||||||
_heading: Sending Transactions (writing)
|
_heading: Sending Transactions
|
||||||
|
|
||||||
To write to the blockchain you require access to a private key
|
To write to the blockchain you require access to a private key
|
||||||
which controls some account. In most cases, those private keys
|
which controls some account. In most cases, those private keys
|
||||||
@ -169,39 +263,239 @@ _code: @lang<script>
|
|||||||
receipt = await tx.wait();
|
receipt = await tx.wait();
|
||||||
//_result:
|
//_result:
|
||||||
|
|
||||||
_heading: User Interaction
|
|
||||||
|
|
||||||
explain ether vs gwei... format vs parse. getAddress, resolveAddress
|
_subsection: Contracts @<starting-contracts>
|
||||||
|
|
||||||
_code: @lang<javascript>
|
A **Contract** is a meta-class, which means that its definition
|
||||||
// Convert user-provided strings in ether to wei for a value
|
its derived at run-time, based on the ABI it is passed, which then
|
||||||
eth = parseEther("1.0")
|
determined what mehods and properties are available on it.
|
||||||
//_result:
|
|
||||||
|
|
||||||
// Convert user-provided strings in gwei to wei for max base fee
|
_heading: Application Binary Interface (ABI)
|
||||||
feePerGas = parseUnits("4.5", "gwei")
|
|
||||||
//_result:
|
|
||||||
|
|
||||||
// Convert a value in wei to a string in ether to display in a UI
|
Since all operations that occur on the blockchain must be encoded
|
||||||
formatEther(eth)
|
as binary data, we need a concise way to define how to convert
|
||||||
//_result:
|
between common objects (like strings and numbers) and its binary
|
||||||
|
representation, as well as encode the ways to call and interpret
|
||||||
|
the Contract.
|
||||||
|
|
||||||
// Convert a value in wei to a string in gwei to display in a UI
|
For any method, event or error you wish to use, you must include a
|
||||||
formatUnits(feePerGas, "gwei")
|
[[Fragment]] to inform Ethers how it should encode the request and
|
||||||
//_result:
|
decode the result.
|
||||||
|
|
||||||
_subsection: Contracts
|
Any methods or events that are not needed can be safely excluded.
|
||||||
|
|
||||||
|
There are several common formats available to describe an ABI. The
|
||||||
|
Solidity compiler usually dumps a JSON representation but when typing
|
||||||
|
an ABI by hand it is often easier (and more readable) to use the
|
||||||
|
human-readable ABI, which is just the Solidity signautre.
|
||||||
|
|
||||||
|
_code: simplified ERC-20 ABI @lang<script>
|
||||||
|
abi = [
|
||||||
|
"function decimals() returns (string)",
|
||||||
|
"function symbol() returns (string)",
|
||||||
|
"function balanceOf(address addr) returns (uint)"
|
||||||
|
]
|
||||||
|
|
||||||
|
// Create a contract
|
||||||
|
contract = new Contract("dai.tokens.ethers.eth", abi, provider)
|
||||||
|
|
||||||
_heading: Read-only methods (i.e. ``view`` and ``pure``)
|
_heading: Read-only methods (i.e. ``view`` and ``pure``)
|
||||||
|
|
||||||
|
A read-only method is one which cannot change the state of the
|
||||||
|
blockchain, but often provide a simple interface to get important
|
||||||
|
data about a Contract.
|
||||||
|
|
||||||
|
_code: reading the DAI ERC-20 contract @lang<javascript>
|
||||||
|
// The contract ABI (fragments we care about)
|
||||||
|
abi = [
|
||||||
|
"function decimals() view returns (uint8)",
|
||||||
|
"function symbol() view returns (string)",
|
||||||
|
"function balanceOf(address a) view returns (uint)"
|
||||||
|
]
|
||||||
|
|
||||||
|
// Create a contract; connected to a Provider, so it may
|
||||||
|
// only access read-only methods (like view and pure)
|
||||||
|
contract = new Contract("dai.tokens.ethers.eth", abi, provider)
|
||||||
|
|
||||||
|
// The symbol name for the token
|
||||||
|
sym = await contract.symbol()
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
// The number of decimals the token uses
|
||||||
|
decimals = await contract.decimals()
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
// Read the token balance for an account
|
||||||
|
balance = await contract.balanceOf("ethers.eth")
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
// Format the balance for humans, such as in a UI
|
||||||
|
formatUnits(balance, decimals)
|
||||||
|
//_result:
|
||||||
|
|
||||||
_heading: State-changing Methods
|
_heading: State-changing Methods
|
||||||
|
|
||||||
_heading: Estimating Gas and fees
|
_code: change state on an ERC-20 contract @lang<script>
|
||||||
|
|
||||||
|
abi = [
|
||||||
|
"function transfer(address to, uint amount)"
|
||||||
|
]
|
||||||
|
|
||||||
|
// Connected to a Signer; can make state changing transactions,
|
||||||
|
// which will cost the account ether
|
||||||
|
contract = new Contract("dai.tokens.ethers.eth", abi, signer)
|
||||||
|
|
||||||
|
// Send 1 DAI
|
||||||
|
amount = parseUnits("1.0", 18);
|
||||||
|
|
||||||
|
// Send the transaction
|
||||||
|
tx = await contract.transfer("ethers.eth", amount)
|
||||||
|
//_result: @TODO
|
||||||
|
|
||||||
|
// Currently the transaction has been sent to the mempool,
|
||||||
|
// but has not yet been included. So, we...
|
||||||
|
|
||||||
|
// ...wait for the transaction to be included.
|
||||||
|
await tx.wait()
|
||||||
|
//_result: @TODO
|
||||||
|
|
||||||
|
_code: forcing a call (simulation) of a state-changing method @lang<javascript>
|
||||||
|
|
||||||
|
abi = [
|
||||||
|
"function transfer(address to, uint amount) returns (bool)"
|
||||||
|
]
|
||||||
|
|
||||||
|
// Connected to a Provider since we only require read access
|
||||||
|
contract = new Contract("dai.tokens.ethers.eth", abi, provider)
|
||||||
|
|
||||||
|
amount = parseUnits("1.0", 18)
|
||||||
|
|
||||||
|
// There are many limitations to using a static call, but can
|
||||||
|
// often be useful to preflight a transaction.
|
||||||
|
await contract.transfer.staticCall("ethers.eth", amount)
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
// We can also simulate the transaction as another account
|
||||||
|
other = new VoidSigner("0x643aA0A61eADCC9Cc202D1915D942d35D005400C")
|
||||||
|
contractAsOther = contract.connect(other.connect(provider))
|
||||||
|
await contractAsOther.transfer.staticCall("ethers.eth", amount)
|
||||||
|
//_result:
|
||||||
|
|
||||||
_heading: Listening to Events
|
_heading: Listening to Events
|
||||||
|
|
||||||
|
When adding event listeners for a named event, the event parameters
|
||||||
|
are destructed for the listener.
|
||||||
|
|
||||||
|
There is always one additional parameter passed to a listener, which
|
||||||
|
is an [[EventPayload]], which includes more information about the event
|
||||||
|
including the filter and a method to remove that listener.
|
||||||
|
|
||||||
|
_code: listen for ERC-20 events @lang<script>
|
||||||
|
abi = [
|
||||||
|
"event Transfer(address indexed from, address indexed to, uint amount)"
|
||||||
|
]
|
||||||
|
|
||||||
|
// Create a contract; connected to a Provider, so it may
|
||||||
|
// only access read-only methods (like view and pure)
|
||||||
|
contract = new Contract("dai.tokens.ethers.eth", abi, provider)
|
||||||
|
|
||||||
|
// Begin listening for any Transfer event
|
||||||
|
contract.on("Transfer", (from, to, _amount, event) => {
|
||||||
|
const amount = formatEther(_amount, 18)
|
||||||
|
console.log(`${ from } => ${ to }: ${ amount }`);
|
||||||
|
|
||||||
|
// The `event.log` has the entire EventLog
|
||||||
|
|
||||||
|
// Optionally, convenience method to stop listening
|
||||||
|
event.removeListener();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Same as above
|
||||||
|
contract.on(contract.filters.Transfer, (from, to, amount, event) => {
|
||||||
|
// See above
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen for any Transfer to "ethers.eth"
|
||||||
|
filter = contract.filters.Transfer("ethers.eth")
|
||||||
|
contract.on(filter, (from, to, amount, event) => {
|
||||||
|
// `to` will always be equal to the address of "ethers.eth"
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listen for any event, whether it is present in the ABI
|
||||||
|
// or not. Since unknown events can be picked up, the
|
||||||
|
// parameters are not destructed.
|
||||||
|
contract.on("*", (event) => {
|
||||||
|
// The `event.log` has the entire EventLog
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_heading: Query Historic Events
|
_heading: Query Historic Events
|
||||||
|
|
||||||
|
When querying within a large range of blocks, some backends may
|
||||||
|
be prohibitively slow, may return an error or may truncate the
|
||||||
|
results without any indication. This is at the discretion of each
|
||||||
|
backend.
|
||||||
|
|
||||||
_subsection: Signing Messages
|
_code: query historic ERC-20 events @lang<javascript>
|
||||||
|
abi = [
|
||||||
|
"event Transfer(address indexed from, address indexed to, uint amount)"
|
||||||
|
]
|
||||||
|
|
||||||
|
// Create a contract; connected to a Provider, so it may
|
||||||
|
// only access read-only methods (like view and pure)
|
||||||
|
contract = new Contract("dai.tokens.ethers.eth", abi, provider)
|
||||||
|
|
||||||
|
// Query the last 100 blocks for any transfer
|
||||||
|
filter = contract.filters.Transfer
|
||||||
|
events = await contract.queryFilter(filter, -100)
|
||||||
|
|
||||||
|
// The events are a normal Array
|
||||||
|
events.length
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
// The first matching event
|
||||||
|
events[0]
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
// Query all time for any transfer to ethers.eth
|
||||||
|
filter = contract.filters.Transfer("ethers.eth")
|
||||||
|
events = await contract.queryFilter(filter)
|
||||||
|
|
||||||
|
// The first matching event
|
||||||
|
events[0]
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
|
||||||
|
_subsection: Signing Messages @<starting-signing>
|
||||||
|
|
||||||
|
A private key can do a lot more than just sign a transaction to authorize
|
||||||
|
it. It can also be used to sign other forms of data, which are then able
|
||||||
|
to be validated for other purposes.
|
||||||
|
|
||||||
|
For example, signing **a message** can be used to prove ownership of an
|
||||||
|
account which a website could use to authenicate a user and log them in.
|
||||||
|
|
||||||
|
_code: @lang<javascript>
|
||||||
|
|
||||||
|
// Our signer; Signing messages does not require a Provider
|
||||||
|
signer = new Wallet(id("test"))
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
message = "sign into ethers.org?"
|
||||||
|
|
||||||
|
// Signing the message
|
||||||
|
sig = await signer.signMessage(message);
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
// Validating a message; notice the address matches the signer
|
||||||
|
verifyMessage(message, sig)
|
||||||
|
//_result:
|
||||||
|
|
||||||
|
_null:
|
||||||
|
|
||||||
|
Many other more advanced protocols built on top of signed messages are
|
||||||
|
used to allow a private key to authorize other users to transfer their
|
||||||
|
tokens, allowing the transaction fees of the transfer to be paid by
|
||||||
|
someone else.
|
||||||
|
|
||||||
|
145
docs.wrm/migrating.wrm
Normal file
145
docs.wrm/migrating.wrm
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
_section: Migrating from v5 @<migrating> @priority<-10>
|
||||||
|
|
||||||
|
This guide aims to capture some of the high-level differences
|
||||||
|
between v5 and v6 to help those migrating an existing app and
|
||||||
|
those already familiar with v5 that just need a quick primer.
|
||||||
|
|
||||||
|
The biggest differnce in v6 is the use of modern ES6 features,
|
||||||
|
so a lot of changes are largely internal.
|
||||||
|
|
||||||
|
- [Contracts](migrate-contracts)
|
||||||
|
- [Importing](migrate-importing)
|
||||||
|
|
||||||
|
|
||||||
|
_subsection: Contracts @<migrate-contracts>
|
||||||
|
|
||||||
|
The [[Contract]] is an ES6 Proxy, which means it can resolve
|
||||||
|
method names at run-time.
|
||||||
|
|
||||||
|
_heading: Ambiguous Methods
|
||||||
|
|
||||||
|
In v5, in the case of an ambiguous method, it was necessary to
|
||||||
|
look up a method by its canonical normalized signature. In v6
|
||||||
|
the signature does not need to be normalized and the Typed API
|
||||||
|
provides a cleaner way to access the desired method.
|
||||||
|
|
||||||
|
In v5, duplicate definitions also injected warnings into the
|
||||||
|
console, since there was no way to detect them at run-time.
|
||||||
|
|
||||||
|
_code: contracts in v5 @lang<script>
|
||||||
|
abi = [
|
||||||
|
"function foo(address bar)",
|
||||||
|
"function foo(uint160 bar)",
|
||||||
|
]
|
||||||
|
contract = new Contract(address, abi, provider)
|
||||||
|
|
||||||
|
// In v5 it was necessary to specify the fully-qualified normalized
|
||||||
|
// signature to access the desired method. For example:
|
||||||
|
contract["foo(address)"](addr)
|
||||||
|
|
||||||
|
// These would fail, since there signature is not normalized:
|
||||||
|
contract["foo(address )"](addr)
|
||||||
|
contract["foo(address addr)"](addr)
|
||||||
|
|
||||||
|
// This would fail, since the method is ambiguous:
|
||||||
|
contract.foo(addr)
|
||||||
|
|
||||||
|
_code: contracts in v6 @lang<script>
|
||||||
|
abi = [
|
||||||
|
"function foo(address bar)",
|
||||||
|
"function foo(uint160 bar)",
|
||||||
|
]
|
||||||
|
contract = new Contract(address, abi, provider)
|
||||||
|
|
||||||
|
// Any of these work fine:
|
||||||
|
contract["foo(address)"](addr)
|
||||||
|
contract["foo(address )"](addr)
|
||||||
|
contract["foo(address addr)"](addr)
|
||||||
|
|
||||||
|
// This still fails, since there is no way to know which
|
||||||
|
// method was intended
|
||||||
|
contract.foo(addr)
|
||||||
|
|
||||||
|
// However, the Typed API makes things a bit easier, since it
|
||||||
|
// allows providing typing information to the Contract:
|
||||||
|
contract.foo(Typed.address(addr))
|
||||||
|
|
||||||
|
_heading: Other Method Operations
|
||||||
|
|
||||||
|
In v5, contracts contained a series of method buckets, which
|
||||||
|
then in turn had all signatures and non-ambiguous names
|
||||||
|
attached to them to perform less-common operations.
|
||||||
|
|
||||||
|
In v6, the methods each have their own less-common operations
|
||||||
|
attached directly to them.
|
||||||
|
|
||||||
|
_code: other operations in v5 @lang<script>
|
||||||
|
|
||||||
|
// The default action chooses send or call base on method
|
||||||
|
// type (pure, view, constant, non-payable or payable)
|
||||||
|
contract.foo(addr)
|
||||||
|
|
||||||
|
// This would perform the default action, but return a Result
|
||||||
|
// object, instead of destructing the value
|
||||||
|
contract.functions.foo(addr)
|
||||||
|
|
||||||
|
// Forces using call
|
||||||
|
contract.staticCall.foo(addr)
|
||||||
|
|
||||||
|
// Estimate the gas
|
||||||
|
contract.estimateGas.foo(addr)
|
||||||
|
|
||||||
|
// Populate a transaction
|
||||||
|
contract.populateTransaction.foo(addr)
|
||||||
|
|
||||||
|
_code: other operations in v6 @lang<script>
|
||||||
|
|
||||||
|
// Still behaves the same
|
||||||
|
contract.foo(addr)
|
||||||
|
|
||||||
|
// Perform a call, returning a Result object directly
|
||||||
|
contract.foo.staticCallResult(addr)
|
||||||
|
|
||||||
|
// Forces using call (even for payable and non-payable)
|
||||||
|
contract.foo.staticCall(addr)
|
||||||
|
|
||||||
|
// Forces sending a transaction (even for pure and view)
|
||||||
|
contract.foo.send(addr)
|
||||||
|
|
||||||
|
// Estimate the gas
|
||||||
|
contract.foo.estimateGas(addr)
|
||||||
|
|
||||||
|
// Populate a transaction
|
||||||
|
contract.foo.populateTransaction(addr)
|
||||||
|
|
||||||
|
|
||||||
|
_subsection: Importing @<migrate-importing>
|
||||||
|
|
||||||
|
In v5, the project was maintained as a large set of sub-packages
|
||||||
|
managed as a monorepo.
|
||||||
|
|
||||||
|
In v6 all imports are available in the root package, and for those
|
||||||
|
who wish to have finer-grained control, the ``pkg.exports`` makes
|
||||||
|
certain folders avilable directly.
|
||||||
|
|
||||||
|
_code: importing in v5 @lang<script>
|
||||||
|
|
||||||
|
// Many things (but not all) we available on the root package
|
||||||
|
import { ethers } from "ethers"
|
||||||
|
|
||||||
|
// But some packages were grouped behind an additional property
|
||||||
|
import { providers } from "ethers"
|
||||||
|
const { InfuraProvider } = providers
|
||||||
|
|
||||||
|
// For granular control, importing from the sub-package
|
||||||
|
// was necessary
|
||||||
|
import { InfuraProvider } from "@ethersproject/providers"
|
||||||
|
|
||||||
|
_code: importing in v6 @lang<script>
|
||||||
|
|
||||||
|
// Everything is available on the root package
|
||||||
|
import { ethers } from "ethers"
|
||||||
|
import { InfuraProvider } from "ethers"
|
||||||
|
|
||||||
|
// The pkg.exports provides granular access
|
||||||
|
import { InfuraProvider } from "ethers/providers"
|
Loading…
Reference in New Issue
Block a user