Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: replace @metamask/ethjs-{contract,query} packages with @ethersproject for EIP1193 compatibility #155

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { PollingBlockTracker } = require('@metamask/eth-block-tracker')
const Eth = require('@metamask/ethjs-query')
const EthContract = require('@metamask/ethjs-contract')
const { Web3Provider } = require('@ethersproject/providers')
const { Contract } = require('@ethersproject/contracts')
const Token = require('./token')
const abi = require('human-standard-token-abi')
const SafeEventEmitter = require('@metamask/safe-event-emitter').default
Expand All @@ -19,9 +19,7 @@ class TokenTracker extends SafeEventEmitter {
pollingInterval,
})

const eth = new Eth(opts.provider)
const contract = new EthContract(eth)
this.TokenContract = contract(abi)
this.provider = opts.provider

const tokens = opts.tokens || []
this.balanceDecimals = opts.balanceDecimals
Expand Down Expand Up @@ -52,6 +50,14 @@ class TokenTracker extends SafeEventEmitter {
return this.tokens.map(token => token.serialize())
}

getContractAtAddress(tokenAddress) {
return new Contract(
tokenAddress,
abi,
new Web3Provider(this.provider),
)
}

async updateBalances() {
try {
await Promise.all(this.tokens.map((token) => {
Expand All @@ -68,7 +74,7 @@ class TokenTracker extends SafeEventEmitter {
createTokenFrom (opts, balanceDecimals) {
const owner = this.userAddress
const { address, symbol, balance, decimals } = opts
const contract = this.TokenContract.at(address)
const contract = this.getContractAtAddress(address)
return new Token({
address,
symbol,
Expand Down
6 changes: 5 additions & 1 deletion lib/token.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const BN = require('bn.js')
const { BigNumber } = require("@ethersproject/bignumber")
const util = require('./util')

/**
Expand Down Expand Up @@ -137,7 +138,10 @@ class Token {
}

if (result) {
const val = result[0]
let val = result
if (BigNumber.isBigNumber(result)) {
val = new BN(result.toString())
}
this[key] = val
return val
}
Expand Down
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@
"/lib"
],
"dependencies": {
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/contracts": "^5.7.0",
"@ethersproject/providers": "^5.7.2",
"@metamask/eth-block-tracker": "^11.0.3",
"@metamask/ethjs-contract": "^0.4.1",
"@metamask/ethjs-query": "^0.7.1",
"@metamask/safe-event-emitter": "^3.0.0",
"bn.js": "^5.2.1",
"deep-equal": "^2.2.0",
Expand All @@ -55,7 +56,7 @@
"@lavamoat/allow-scripts": "^2.3.1",
"@lavamoat/preinstall-always-fail": "^2.0.0",
"@metamask/auto-changelog": "^3.4.3",
"ganache": "7.3.1",
"ganache": "7.9.2",
"solc": "^0.4.26",
"tape": "^5.6.1"
},
Expand All @@ -71,7 +72,9 @@
"ganache>keccak": true,
"ganache>leveldown": true,
"ganache>secp256k1": true,
"ganache>utf-8-validate": true
"ganache>utf-8-validate": true,
"ganache>@trufflesuite/uws-js-unofficial>bufferutil": false,
"ganache>@trufflesuite/uws-js-unofficial>utf-8-validate": false
}
}
}
30 changes: 12 additions & 18 deletions test/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ const assert = require('assert').strict
const fs = require('fs')
const path = require('path')
const ganache = require('ganache')
const Eth = require('@metamask/ethjs-query')
const EthContract = require('@metamask/ethjs-contract')
const { Web3Provider } = require('@ethersproject/providers')
const { ContractFactory } = require('@ethersproject/contracts')
const solc = require('solc')

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

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

const owner = addresses[0]
const contract = new EthContract(eth)
const abi = JSON.parse(SimpleTokenDeployer.interface)
const StandardToken = contract(abi, SimpleTokenDeployer.bytecode, {
from: owner,
gas: '3000000',
gasPrice: '875000000',
})
const factory = new ContractFactory(abi, SimpleTokenDeployer.bytecode, ethersProvider.getSigner(owner))

const txHash = await StandardToken.new(qty)
const token = await factory.deploy(qty)
const txHash = token.deployTransaction.hash
assert.ok(txHash, 'should have published the token and returned a transaction hash')

await new Promise((resolve) => setTimeout(resolve, 300))
const receipt = await eth.getTransactionReceipt(txHash)
await token.deployed()
const receipt = await ethersProvider.getTransactionReceipt(txHash)

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

const token = StandardToken.at(tokenAddress)
const result = await token.balanceOf(owner)
const balance = result[0]
assert.equal(balance.toString(10), qty, 'owner should have all')
const balance = await token.balanceOf(owner)
assert.equal(balance.toString(), qty, 'owner should have all')

return { addresses, eth, provider, token, tokenAddress }
return { addresses, provider, token, tokenAddress }
}

module.exports = { setupSimpleTokenEnvironment }
53 changes: 20 additions & 33 deletions test/integration/human-standard-token.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ const fs = require('fs')
const path = require('path')
const test = require('tape')
const ganache = require('ganache')
const provider = ganache.provider()

const { Web3Provider } = require('@ethersproject/providers')
const { ContractFactory } = require('@ethersproject/contracts')
const solc = require('solc')
const TokenTracker = require('../../lib')
const BN = ('bn.js')

const Eth = require('@metamask/ethjs-query')
const EthContract = require('@metamask/ethjs-contract')
const eth = new Eth(provider)
const contract = new EthContract(eth)

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

const ethersProvider = new Web3Provider(provider)

test('testrpc has addresses', function (t) {
eth.accounts()
ethersProvider.listAccounts()
.then((accounts) => {
addresses = accounts
t.ok(accounts, 'loaded accounts')
Expand All @@ -34,34 +32,23 @@ test('testrpc has addresses', function (t) {

test('HumanStandardToken publishing token & checking balance', function (t) {
const abi = JSON.parse(HumanStandardDeployer.interface)
const HumanStandardToken = contract(abi, HumanStandardDeployer.bytecode, {
from: addresses[0],
gas: '3000000',
gasPrice: '875000000',
})
const humanStandardToken = HumanStandardToken.new('1000',
'DanBucks',
'2', // decimals
SET_SYMBOL)
.then((txHash) => {
t.ok(txHash, 'publishes a txHash')
const factory = new ContractFactory(abi, HumanStandardDeployer.bytecode, ethersProvider.getSigner(addresses[0]))

return new Promise((res, rej) => {
setTimeout(() => res(txHash), 200)
})
factory.deploy('1000', 'DanBucks', '2', SET_SYMBOL, {
gasLimit: '3000000',
gasPrice: '875000000',
})
.then((txHash) => {
return eth.getTransactionReceipt(txHash)
.then((contract) => {
t.ok(contract.deployTransaction.hash, 'publishes a txHash')
return contract.deployed()
})
.then((receipt) => {
const addr = receipt.contractAddress
tokenAddress = addr
token = HumanStandardToken.at(addr)
.then((deployedContract) => {
token = deployedContract
tokenAddress = token.address
return token.balanceOf(addresses[0])
})
.then((res) => {
const balance = res[0]
t.equal(balance.toString(10), '1000', 'owner should have all')
.then((balance) => {
t.equal(balance.toString(), '1000', 'owner should have all')
t.end()
})
.catch((reason) => {
Expand Down Expand Up @@ -90,8 +77,8 @@ test('HumanStandardToken balances are tracked', function (t) {
t.equal(tracked.balance.toString(10), '1000', 'initial balance loaded')
return token.transfer(addresses[1], '110')
})
.then((txHash) => {
return eth.getTransactionReceipt(txHash)
.then((tx) => {
return ethersProvider.getTransactionReceipt(tx.hash)
})
.then((receipt) => {
var a = new Promise((res, rej) => { setTimeout(res, 200) })
Expand Down
12 changes: 7 additions & 5 deletions test/integration/simple-token.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,16 @@ const less = '10000000000000000000' // 100 x 10 ^ 17

test('StandardToken balances are tracked', function (t) {
let addresses
let eth
let token
let tokenAddress
let tokenTracker
let provider
setupSimpleTokenEnvironment()
.then((environment) => {
addresses = environment.addresses
eth = environment.eth
token = environment.token
tokenAddress = environment.tokenAddress
const { provider } = environment
provider = environment.provider
tokenTracker = new TokenTracker({
userAddress: addresses[0],
provider,
Expand All @@ -43,8 +42,11 @@ test('StandardToken balances are tracked', function (t) {
t.equal(tracked.balance.toString(10), qty, 'initial balance loaded')
return token.transfer(addresses[1], less)
})
.then((txHash) => {
return eth.getTransactionReceipt(txHash)
.then((tx) => {
return provider.request({
method: 'eth_getTransactionReceipt',
params: [tx.hash],
})
})
.then((receipt) => {
var a = new Promise((res, rej) => { setTimeout(res, 200) })
Expand Down
48 changes: 19 additions & 29 deletions test/integration/token-precision.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ const fs = require('fs')
const path = require('path')
const test = require('tape')
const ganache = require('ganache')
const provider = ganache.provider()
const solc = require('solc')
const TokenTracker = require('../../lib')
const BN = require('bn.js')
const util = require('../../lib/util')
const { ContractFactory } = require('@ethersproject/contracts')
const { Web3Provider } = require('@ethersproject/providers')

const Eth = require('@metamask/ethjs-query')
const EthContract = require('@metamask/ethjs-contract')
const eth = new Eth(provider)
const contract = new EthContract(eth)
const provider = ganache.provider()
const ethersProvider = new Web3Provider(provider)
let count = 0

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

let addresses = []
let token, tokenAddress, tracked
let tokenAddress, tracked

test('testrpc has addresses', function (t) {
eth.accounts()
ethersProvider.listAccounts()
.then((accounts) => {
addresses = accounts
t.ok(accounts, 'loaded accounts')
Expand Down Expand Up @@ -99,32 +98,23 @@ function generateTestWithParams(opts = {}) {
test(`Generated token precision test ${++count}`, function (t) {
const abi = JSON.parse(SimpleTokenDeployer.interface)
const owner = addresses[0]
const StandardToken = contract(abi, SimpleTokenDeployer.bytecode, {
from: owner,
gas: '3000000',
gasPrice: '875000000',
})
StandardToken.new(qty, precision)
.then((txHash) => {
t.ok(txHash, 'publishes a txHash')
const factory = new ContractFactory(abi, SimpleTokenDeployer.bytecode, ethersProvider.getSigner(owner))

return new Promise((res, rej) => {
setTimeout(() => res(txHash), 300)
})
factory.deploy(qty, precision, {
gasLimit: 3000000,
gasPrice: 875000000
})
.then((txHash) => {
return eth.getTransactionReceipt(txHash)
.then((token) => {
t.ok(token.deployTransaction.hash, 'publishes a txHash')
return token.deployed()
})
.then((receipt) => {
const addr = receipt.contractAddress
t.ok(addr, 'should have an address')
tokenAddress = addr
token = StandardToken.at(addr)
return token.balanceOf(owner)
.then((deployedToken) => {
t.ok(deployedToken.address, 'should have an address')
tokenAddress = deployedToken.address
return deployedToken.balanceOf(owner)
})
.then((res) => {
const balance = res[0]
t.equal(balance.toString(10), qty, 'owner should have all')
.then((balance) => {
t.equal(balance.toString(), qty, 'owner should have all')

var tokenTracker = new TokenTracker({
userAddress: addresses[0],
Expand Down
Loading
Loading