Skip to content

Commit 0f783c6

Browse files
authored
feat: replace @metamask/ethjs-{contract,query} packages with @ethersproject for EIP1193 compatibility (#155)
1 parent c99293b commit 0f783c6

8 files changed

Lines changed: 573 additions & 307 deletions

File tree

lib/index.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const { PollingBlockTracker } = require('@metamask/eth-block-tracker')
2-
const Eth = require('@metamask/ethjs-query')
3-
const EthContract = require('@metamask/ethjs-contract')
2+
const { Web3Provider } = require('@ethersproject/providers')
3+
const { Contract } = require('@ethersproject/contracts')
44
const Token = require('./token')
55
const abi = require('human-standard-token-abi')
66
const SafeEventEmitter = require('@metamask/safe-event-emitter').default
@@ -19,9 +19,7 @@ class TokenTracker extends SafeEventEmitter {
1919
pollingInterval,
2020
})
2121

22-
const eth = new Eth(opts.provider)
23-
const contract = new EthContract(eth)
24-
this.TokenContract = contract(abi)
22+
this.provider = opts.provider
2523

2624
const tokens = opts.tokens || []
2725
this.balanceDecimals = opts.balanceDecimals
@@ -52,6 +50,14 @@ class TokenTracker extends SafeEventEmitter {
5250
return this.tokens.map(token => token.serialize())
5351
}
5452

53+
getContractAtAddress(tokenAddress) {
54+
return new Contract(
55+
tokenAddress,
56+
abi,
57+
new Web3Provider(this.provider),
58+
)
59+
}
60+
5561
async updateBalances() {
5662
try {
5763
await Promise.all(this.tokens.map((token) => {
@@ -68,7 +74,7 @@ class TokenTracker extends SafeEventEmitter {
6874
createTokenFrom (opts, balanceDecimals) {
6975
const owner = this.userAddress
7076
const { address, symbol, balance, decimals } = opts
71-
const contract = this.TokenContract.at(address)
77+
const contract = this.getContractAtAddress(address)
7278
return new Token({
7379
address,
7480
symbol,

lib/token.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const BN = require('bn.js')
2+
const { BigNumber } = require("@ethersproject/bignumber")
23
const util = require('./util')
34

45
/**
@@ -137,7 +138,10 @@ class Token {
137138
}
138139

139140
if (result) {
140-
const val = result[0]
141+
let val = result
142+
if (BigNumber.isBigNumber(result)) {
143+
val = new BN(result.toString())
144+
}
141145
this[key] = val
142146
return val
143147
}

package.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@
3838
"/lib"
3939
],
4040
"dependencies": {
41+
"@ethersproject/bignumber": "^5.7.0",
42+
"@ethersproject/contracts": "^5.7.0",
43+
"@ethersproject/providers": "^5.7.2",
4144
"@metamask/eth-block-tracker": "^11.0.3",
42-
"@metamask/ethjs-contract": "^0.4.1",
43-
"@metamask/ethjs-query": "^0.7.1",
4445
"@metamask/safe-event-emitter": "^3.0.0",
4546
"bn.js": "^5.2.1",
4647
"deep-equal": "^2.2.0",
@@ -55,7 +56,7 @@
5556
"@lavamoat/allow-scripts": "^2.3.1",
5657
"@lavamoat/preinstall-always-fail": "^2.0.0",
5758
"@metamask/auto-changelog": "^3.4.3",
58-
"ganache": "7.3.1",
59+
"ganache": "7.9.2",
5960
"solc": "^0.4.26",
6061
"tape": "^5.6.1"
6162
},
@@ -71,7 +72,9 @@
7172
"ganache>keccak": true,
7273
"ganache>leveldown": true,
7374
"ganache>secp256k1": true,
74-
"ganache>utf-8-validate": true
75+
"ganache>utf-8-validate": true,
76+
"ganache>@trufflesuite/uws-js-unofficial>bufferutil": false,
77+
"ganache>@trufflesuite/uws-js-unofficial>utf-8-validate": false
7578
}
7679
}
7780
}

test/helper.js

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ const assert = require('assert').strict
22
const fs = require('fs')
33
const path = require('path')
44
const ganache = require('ganache')
5-
const Eth = require('@metamask/ethjs-query')
6-
const EthContract = require('@metamask/ethjs-contract')
5+
const { Web3Provider } = require('@ethersproject/providers')
6+
const { ContractFactory } = require('@ethersproject/contracts')
77
const solc = require('solc')
88

99
const source = fs.readFileSync(path.resolve(__dirname, 'contracts/Token.sol')).toString();
@@ -13,35 +13,29 @@ const SimpleTokenDeployer = compiled.contracts[':SimpleToken']
1313
const defaultQuantity = '100000000000000000000' // 100 x 10 ^ 18
1414
async function setupSimpleTokenEnvironment ({ qty = defaultQuantity } = {}) {
1515
const provider = ganache.provider()
16-
const eth = new Eth(provider)
16+
const ethersProvider = new Web3Provider(provider)
1717

18-
const addresses = await eth.accounts()
18+
const addresses = await ethersProvider.listAccounts()
1919
assert(addresses.length > 0, 'test network should be initialized with accounts')
2020

2121
const owner = addresses[0]
22-
const contract = new EthContract(eth)
2322
const abi = JSON.parse(SimpleTokenDeployer.interface)
24-
const StandardToken = contract(abi, SimpleTokenDeployer.bytecode, {
25-
from: owner,
26-
gas: '3000000',
27-
gasPrice: '875000000',
28-
})
23+
const factory = new ContractFactory(abi, SimpleTokenDeployer.bytecode, ethersProvider.getSigner(owner))
2924

30-
const txHash = await StandardToken.new(qty)
25+
const token = await factory.deploy(qty)
26+
const txHash = token.deployTransaction.hash
3127
assert.ok(txHash, 'should have published the token and returned a transaction hash')
3228

33-
await new Promise((resolve) => setTimeout(resolve, 300))
34-
const receipt = await eth.getTransactionReceipt(txHash)
29+
await token.deployed()
30+
const receipt = await ethersProvider.getTransactionReceipt(txHash)
3531

3632
const tokenAddress = receipt.contractAddress
3733
assert.ok(tokenAddress, 'should have a token address')
3834

39-
const token = StandardToken.at(tokenAddress)
40-
const result = await token.balanceOf(owner)
41-
const balance = result[0]
42-
assert.equal(balance.toString(10), qty, 'owner should have all')
35+
const balance = await token.balanceOf(owner)
36+
assert.equal(balance.toString(), qty, 'owner should have all')
4337

44-
return { addresses, eth, provider, token, tokenAddress }
38+
return { addresses, provider, token, tokenAddress }
4539
}
4640

4741
module.exports = { setupSimpleTokenEnvironment }

test/integration/human-standard-token.js

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,13 @@ const fs = require('fs')
22
const path = require('path')
33
const test = require('tape')
44
const ganache = require('ganache')
5-
const provider = ganache.provider()
6-
5+
const { Web3Provider } = require('@ethersproject/providers')
6+
const { ContractFactory } = require('@ethersproject/contracts')
77
const solc = require('solc')
88
const TokenTracker = require('../../lib')
9-
const BN = ('bn.js')
109

11-
const Eth = require('@metamask/ethjs-query')
12-
const EthContract = require('@metamask/ethjs-contract')
13-
const eth = new Eth(provider)
14-
const contract = new EthContract(eth)
1510

11+
const provider = ganache.provider()
1612
const source = fs.readFileSync(path.resolve(__dirname, '..', 'contracts/Token.sol')).toString();
1713
const compiled = solc.compile(source, 1)
1814
const HumanStandardDeployer = compiled.contracts[':HumanStandardToken']
@@ -23,8 +19,10 @@ const EXPECTED_SYMBOL = 'EXP'
2319
let addresses = []
2420
let token, tokenAddress, tracked
2521

22+
const ethersProvider = new Web3Provider(provider)
23+
2624
test('testrpc has addresses', function (t) {
27-
eth.accounts()
25+
ethersProvider.listAccounts()
2826
.then((accounts) => {
2927
addresses = accounts
3028
t.ok(accounts, 'loaded accounts')
@@ -34,34 +32,23 @@ test('testrpc has addresses', function (t) {
3432

3533
test('HumanStandardToken publishing token & checking balance', function (t) {
3634
const abi = JSON.parse(HumanStandardDeployer.interface)
37-
const HumanStandardToken = contract(abi, HumanStandardDeployer.bytecode, {
38-
from: addresses[0],
39-
gas: '3000000',
40-
gasPrice: '875000000',
41-
})
42-
const humanStandardToken = HumanStandardToken.new('1000',
43-
'DanBucks',
44-
'2', // decimals
45-
SET_SYMBOL)
46-
.then((txHash) => {
47-
t.ok(txHash, 'publishes a txHash')
35+
const factory = new ContractFactory(abi, HumanStandardDeployer.bytecode, ethersProvider.getSigner(addresses[0]))
4836

49-
return new Promise((res, rej) => {
50-
setTimeout(() => res(txHash), 200)
51-
})
37+
factory.deploy('1000', 'DanBucks', '2', SET_SYMBOL, {
38+
gasLimit: '3000000',
39+
gasPrice: '875000000',
5240
})
53-
.then((txHash) => {
54-
return eth.getTransactionReceipt(txHash)
41+
.then((contract) => {
42+
t.ok(contract.deployTransaction.hash, 'publishes a txHash')
43+
return contract.deployed()
5544
})
56-
.then((receipt) => {
57-
const addr = receipt.contractAddress
58-
tokenAddress = addr
59-
token = HumanStandardToken.at(addr)
45+
.then((deployedContract) => {
46+
token = deployedContract
47+
tokenAddress = token.address
6048
return token.balanceOf(addresses[0])
6149
})
62-
.then((res) => {
63-
const balance = res[0]
64-
t.equal(balance.toString(10), '1000', 'owner should have all')
50+
.then((balance) => {
51+
t.equal(balance.toString(), '1000', 'owner should have all')
6552
t.end()
6653
})
6754
.catch((reason) => {
@@ -90,8 +77,8 @@ test('HumanStandardToken balances are tracked', function (t) {
9077
t.equal(tracked.balance.toString(10), '1000', 'initial balance loaded')
9178
return token.transfer(addresses[1], '110')
9279
})
93-
.then((txHash) => {
94-
return eth.getTransactionReceipt(txHash)
80+
.then((tx) => {
81+
return ethersProvider.getTransactionReceipt(tx.hash)
9582
})
9683
.then((receipt) => {
9784
var a = new Promise((res, rej) => { setTimeout(res, 200) })

test/integration/simple-token.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,16 @@ const less = '10000000000000000000' // 100 x 10 ^ 17
1111

1212
test('StandardToken balances are tracked', function (t) {
1313
let addresses
14-
let eth
1514
let token
1615
let tokenAddress
1716
let tokenTracker
17+
let provider
1818
setupSimpleTokenEnvironment()
1919
.then((environment) => {
2020
addresses = environment.addresses
21-
eth = environment.eth
2221
token = environment.token
2322
tokenAddress = environment.tokenAddress
24-
const { provider } = environment
23+
provider = environment.provider
2524
tokenTracker = new TokenTracker({
2625
userAddress: addresses[0],
2726
provider,
@@ -43,8 +42,11 @@ test('StandardToken balances are tracked', function (t) {
4342
t.equal(tracked.balance.toString(10), qty, 'initial balance loaded')
4443
return token.transfer(addresses[1], less)
4544
})
46-
.then((txHash) => {
47-
return eth.getTransactionReceipt(txHash)
45+
.then((tx) => {
46+
return provider.request({
47+
method: 'eth_getTransactionReceipt',
48+
params: [tx.hash],
49+
})
4850
})
4951
.then((receipt) => {
5052
var a = new Promise((res, rej) => { setTimeout(res, 200) })

test/integration/token-precision.js

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@ const fs = require('fs')
22
const path = require('path')
33
const test = require('tape')
44
const ganache = require('ganache')
5-
const provider = ganache.provider()
65
const solc = require('solc')
76
const TokenTracker = require('../../lib')
87
const BN = require('bn.js')
98
const util = require('../../lib/util')
9+
const { ContractFactory } = require('@ethersproject/contracts')
10+
const { Web3Provider } = require('@ethersproject/providers')
1011

11-
const Eth = require('@metamask/ethjs-query')
12-
const EthContract = require('@metamask/ethjs-contract')
13-
const eth = new Eth(provider)
14-
const contract = new EthContract(eth)
12+
const provider = ganache.provider()
13+
const ethersProvider = new Web3Provider(provider)
1514
let count = 0
1615

1716
const source = fs.readFileSync(path.resolve(__dirname, '..', 'contracts/ZeppelinToken.sol')).toString();
@@ -20,10 +19,10 @@ const compiled = solc.compile(source, 1)
2019
const SimpleTokenDeployer = compiled.contracts[':TutorialToken']
2120

2221
let addresses = []
23-
let token, tokenAddress, tracked
22+
let tokenAddress, tracked
2423

2524
test('testrpc has addresses', function (t) {
26-
eth.accounts()
25+
ethersProvider.listAccounts()
2726
.then((accounts) => {
2827
addresses = accounts
2928
t.ok(accounts, 'loaded accounts')
@@ -99,32 +98,23 @@ function generateTestWithParams(opts = {}) {
9998
test(`Generated token precision test ${++count}`, function (t) {
10099
const abi = JSON.parse(SimpleTokenDeployer.interface)
101100
const owner = addresses[0]
102-
const StandardToken = contract(abi, SimpleTokenDeployer.bytecode, {
103-
from: owner,
104-
gas: '3000000',
105-
gasPrice: '875000000',
106-
})
107-
StandardToken.new(qty, precision)
108-
.then((txHash) => {
109-
t.ok(txHash, 'publishes a txHash')
101+
const factory = new ContractFactory(abi, SimpleTokenDeployer.bytecode, ethersProvider.getSigner(owner))
110102

111-
return new Promise((res, rej) => {
112-
setTimeout(() => res(txHash), 300)
113-
})
103+
factory.deploy(qty, precision, {
104+
gasLimit: 3000000,
105+
gasPrice: 875000000
114106
})
115-
.then((txHash) => {
116-
return eth.getTransactionReceipt(txHash)
107+
.then((token) => {
108+
t.ok(token.deployTransaction.hash, 'publishes a txHash')
109+
return token.deployed()
117110
})
118-
.then((receipt) => {
119-
const addr = receipt.contractAddress
120-
t.ok(addr, 'should have an address')
121-
tokenAddress = addr
122-
token = StandardToken.at(addr)
123-
return token.balanceOf(owner)
111+
.then((deployedToken) => {
112+
t.ok(deployedToken.address, 'should have an address')
113+
tokenAddress = deployedToken.address
114+
return deployedToken.balanceOf(owner)
124115
})
125-
.then((res) => {
126-
const balance = res[0]
127-
t.equal(balance.toString(10), qty, 'owner should have all')
116+
.then((balance) => {
117+
t.equal(balance.toString(), qty, 'owner should have all')
128118

129119
var tokenTracker = new TokenTracker({
130120
userAddress: addresses[0],

0 commit comments

Comments
 (0)