Port of ethers.js to Nim
Go to file
Eric Mastro a3e888128c feat: Allow contract transactions to be waited on
Allow waiting for a specified number of confirmations for contract transactions.

This change only requires an optional TransactionResponse return type to be added to the contract function. This allows the transaction hash to be passed to `.wait`.

For example, previously the `mint` method looked like this without a return value:
```
method mint(token: TestToken, holder: Address, amount: UInt256) {.base, contract.}
```
it still works without a return value, but if we want to wait for a 3 confirmations, we can now define it like this:
```
method mint(token: TestToken, holder: Address, amount: UInt256): ?TransactionResponse {.base, contract.}
```
and use like this:
```
let receipt = await token.connect(signer0)
                    .mint(accounts[1], 100.u256)
                    .wait(3) # wait for 3 confirmations
```
2022-05-23 11:27:26 +10:00
.github/workflows Fix CI 2022-01-27 10:07:52 +01:00
ethers feat: Allow contract transactions to be waited on 2022-05-23 11:27:26 +10:00
testmodule feat: Allow contract transactions to be waited on 2022-05-23 11:27:26 +10:00
testnode Ethereum test node deploys ERC20 token 2022-01-20 12:44:35 +01:00
.editorconfig Project setup 2022-01-17 17:04:14 +01:00
.gitignore Project setup 2022-01-17 17:04:14 +01:00
License.md Project setup 2022-01-17 17:04:14 +01:00
Readme.md version 0.1.6 2022-05-17 19:28:52 +02:00
ethers.nim Adds Signer.getGasPrice() 2022-01-24 12:12:52 +01:00
ethers.nimble version 0.1.6 2022-05-17 19:28:52 +02:00
nim.cfg Provider.getBlockNumber() 2022-01-18 14:26:41 +01:00

Readme.md

Nim Ethers

A port of the ethers.js library to Nim. Allows you to connect to an Ethereum node.

This is very much a work in progress; expect to see many things that are incomplete or wrong. Use at your own risk.

Installation

Use the Nimble package manager to add ethers to an existing project. Add the following to its .nimble file:

requires "https://github.com/status-im/nim-ethers >= 0.1.6 & < 0.2.0"

Usage

To connect to an Ethereum node, you require a Provider. Currently, only a JSON-RPC provider is supported:

import ethers
import chronos

let provider = JsonRpcProvider.new("ws://localhost:8545")
let accounts = await provider.listAccounts()

To interact with a smart contract, you need to define the contract functions in Nim. For example, to interact with an ERC20 token, you could define the following:

type Erc20 = ref object of Contract

proc totalSupply(token: Erc20): UInt256 {.contract, view.}
proc balanceOf(token: Erc20, account: Address): UInt256 {.contract, view.}
proc transfer(token: Erc20, recipient: Address, amount: UInt256) {.contract.}
proc allowance(token: Erc20, owner, spender: Address): UInt256 {.contract, view.}
proc approve(token: Erc20, spender: Address, amount: UInt256) {.contract.}
proc transferFrom(token: Erc20, sender, recipient: Address, amount: UInt256) {.contract.}

Notice how some functions are annotated with a {.view.} pragma. This indicates that the function does not modify the blockchain. See also the Solidity documentation on state mutability

Now that you've defined the contract interface, you can create an instance of it using its deployed address:

let address = Address.init("0x.....")
let token = Erc20.new(address, provider)

The functions that you defined earlier can now be called asynchronously:

let supply = await token.totalSupply()
let balance = await token.balanceOf(accounts[0])

These invocations do not yet change the state of the blockchain, even when we invoke those functions that lack a {.view.} pragma. To allow these changes to happen, we require an instance of a Signer first.

For example, to use the 4th account on the Ethereum node to sign transactions, you'd instantiate the signer as follows:

let signer = provider.getSigner(accounts[3])

And then connect the contract and signer:

let writableToken = token.connect(signer)

This allows you to make changes to the state of the blockchain:

await writableToken.transfer(accounts[7], 42.u256)

Which transfers 42 tokens from account 3 to account 7

Events

You can subscribe to events that are emitted by a smart contract. For instance, to get notified about token transfers you define the Transfer event:

type Transfer = object of Event
  sender {.indexed.}: Address
  receiver {.indexed.}: Address
  value: UInt256

Notice that Transfer inherits from Event, and that some event parameters are marked with {.indexed.} to match the definition in Solidity.

You can now subscribe to Transfer events by calling subscribe on the contract instance.

proc handleTransfer(transfer: Transfer) =
  echo "received transfer: ", transfer

let subscription = await token.subscribe(Transfer, handleTransfer)

When a Transfer event is emitted, the handleTransfer proc that you just defined will be called.

When you're no longer interested in these events, you can unsubscribe:

await subscription.unsubscribe()

Subscriptions are currently only supported when using a JSON RPC provider that is created with a websockets URL such as ws://localhost:8545.

Thanks

This library is inspired by the great work done by the ethers.js (no affiliation) and nim-web3 developers.