Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Initial pass at converting from TruffleContract to Web3 #10

Merged
merged 18 commits into from
Mar 24, 2020

Conversation

liamzebedee
Copy link
Contributor

@liamzebedee liamzebedee commented Mar 12, 2020

This PR refactors our code to use Web3 as our library for interacting with contracts, replacing using of TruffleContract.

Conversion notes

  • Web3 returns strings instead of BN's for numbers.
    eg.
const creationCost = await this.systemContract.methods.createNewDepositFeeEstimate().call()
// creationCost = '2188250000000000'
  • Some contract calls involving external systems require us to insert gas estimates (see 2cfd25f for more)

@liamzebedee liamzebedee marked this pull request as ready for review March 19, 2020 08:51
@liamzebedee liamzebedee force-pushed the from-exotic-fruits-to-web3 branch 3 times, most recently from 24d74cb to b82ddcb Compare March 20, 2020 04:56
TruffleContract automatically calls estimateGas for many transactions. For Web3, it uses the gas estimates contained in the contract ABI's.

Unfortunately, these gas estimates in the ABI's do not include estimation of calls to abstract contracts (interfaces of externals, eg. IBondedECDSAKeepVendor).
- using .returnValues instead of .args
- setting defaultAccount for Deposit/Keep contract
This is more concise than the long lookup. web3-utils is installed as a peer dependency of the web3 package.
@liamzebedee liamzebedee force-pushed the from-exotic-fruits-to-web3 branch 2 times, most recently from a3c4e8d to 0addbb3 Compare March 20, 2020 07:42
Manual merge based off a `git diff`. It was easier than messing around with rebase.
@liamzebedee liamzebedee force-pushed the from-exotic-fruits-to-web3 branch from 0addbb3 to cacc5c5 Compare March 20, 2020 07:45
@liamzebedee liamzebedee changed the title [WIP] Initial pass at converting from TruffleContract to Web3 Initial pass at converting from TruffleContract to Web3 Mar 20, 2020
@liamzebedee liamzebedee requested a review from Shadowfiend March 20, 2020 08:02
For JS code that doesn't explictly declare its exports using ES6 Module Syntax (import/export), instead using CommonJS syntax (module.exports = xyz;), we can only import the default export.

See this article for a good reference - https://medium.com/the-node-js-collection/an-update-on-es6-modules-in-node-js-42c958b890c
Copy link
Contributor

@Shadowfiend Shadowfiend left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a long pass here. This mostly looks awesome, few remarks on things we can abstract better, couple of other improvements and tweaks that we can make separately.

return await this.systemContract.getAllowedLotSizes()
return (await this.systemContract.methods.getAllowedLotSizes().call()).map(
toBN
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does web3 return instead of BN here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the answer might be strings… If that's the case, I'm interested in using BigNumber rather than BN. tbtc-dapp already uses BigNumber, and switching back and forth between that and BN is a real pain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😬 Switching back-and-forth is a pain.

We do have inconsistent usage of big numbers:

Why BigNumber over BN? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BigNumber supports decimal math, BN only supports integers. BN is more performant. Right tool for the right job, but I think for frontend stuff being able to do decimal math is a strong win---in the case of the dApp, it's necessary, since we do signing fee math and display values in TBTC, not tSats or whatever we want to call them 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, thought there was a reason 😉

Do you think it's a small amount of work? Wondering if I can get the hardware wallet stuff done first before we do this. dApp works currently without it.

Also tSats is palindromic, mmmmm I like it...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah let's handle this after.

src/Deposit.js Outdated Show resolved Hide resolved
src/Deposit.js Show resolved Hide resolved
src/Deposit.js Outdated Show resolved Hide resolved
const contract = new web3.eth.Contract(artifact.abi)
contract.options.address = lookupAddress(artifact)
contract.options.from = web3.eth.defaultAccount
this[propertyName] = contract
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Crazy question here: do we want to store contract.methods? I feel like that's the only thing we actually interact with anywhere, and it would make the remaining interactions much cleaner. If we did that we'd probably want to name the properties e.g. tokenMethods, systemMethods, depositTokenMethods, etc, of course.

We probably still need access to the contract stuff for e.g. events, but I wonder if we don't invert the importance and give the *Methods objects a .contract property that references the contract.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, hadn't thought of that.

tokenMethods.balanceOf(address).call() vs. .tokenContract.methods.balanceOf(address).call() - how much cleaner does it seem? Moving in the direction of TruffleContract's API, I would want to remove .call too, so it's as simple as tokenMethods.balanceOf(address).

My opinion - could focus on improving other aspects first.

src/EthereumHelpers.js Outdated Show resolved Hide resolved
src/EthereumHelpers.js Outdated Show resolved Hide resolved
src/EthereumHelpers.js Show resolved Hide resolved
@@ -94,25 +97,28 @@ export default class Redemption {
"SignatureSubmitted",
{ digest: redemptionDigest }
)
const { r, s, recoveryID } = signatureEvent.args
const { r, s, recoveryID } = signatureEvent.returnValues
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are r and s here not strings now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, they are? Confused as to what you're getting at.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I asked this here for some reason, but it's because below you toString both of them.

Copy link
Contributor Author

@liamzebedee liamzebedee Mar 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I think single byte256 words are converted into BN/buffer instances by the ABI decoder? Not sure, to be perfectly honest.

@@ -1,4 +1,5 @@
import { TX } from "bcoin/lib/primitives/index.js"
import BcoinPrimitives from "bcoin/lib/primitives/index.js"
const { TX } = BcoinPrimitives
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mentioned it in the commit description. GitHub doesn't surface this though :/

For JS code that doesn't explictly declare its exports using ES6 Module Syntax (import/export), instead using CommonJS syntax (module.exports = xyz;), we can only import the default export.
See this article for a good reference - https://medium.com/the-node-js-collection/an-update-on-es6-modules-in-node-js-42c958b890c

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is… Strange. Our current code works fine, right? In the browser and on the command line with Node 12 latest?

Copy link
Contributor Author

@liamzebedee liamzebedee Mar 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To get this running, I have to run:

$ nvm use v12
# node v12.0.0
$ node --experimental-modules --experimental-json-modules --async-stack-traces example-local.js

Without this modified import syntax, the error that is thrown is:

(node:42107) ExperimentalWarning: The ESM module loader is experimental.
(node:42107) ExperimentalWarning: Importing JSON modules is an experimental feature. This feature could change at any time
file:///Users/liamz/go/src/github.com/keep-network/tbtc.js/src/lib/BitcoinTxParser.js:3
import { TX } from "bcoin/lib/primitives/index.js"
         ^^
SyntaxError: The requested module 'bcoin/lib/primitives/index.js' does not provide an export named 'TX'
    at ModuleJob._instantiate (internal/modules/esm/module_job.js:92:21)
    at async ModuleJob.run (internal/modules/esm/module_job.js:107:20)
    at async Loader.import (internal/modules/esm/loader.js:164:24)
```

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be interested in seeing how you ran it @Shadowfiend - I should've asked before. 😸 For reference, node v10 with --harmony wasn't working for me, but v12 was.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, v12 only, but never ran into this. Anyway, no need to block for now I guess.

@Shadowfiend
Copy link
Contributor

This feels real close… Interested in figuring out why that change for BcoinPrimitives wasn't necessary before…

I'm also interested in seeing a helper for the 0x replacement and leading .slice(2) that takes us from SPV proof land to Bitcoin land in the output scripts. Happy to merge now if you want to do that in a follow-up, just let me know.

@liamzebedee
Copy link
Contributor Author

@Shadowfiend I'll do a follow-up for the 0x replacement tomorrow. 👍

Copy link
Contributor

@Shadowfiend Shadowfiend left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oookay, let's land this!

@Shadowfiend Shadowfiend merged commit e93a8ba into master Mar 24, 2020
@Shadowfiend Shadowfiend deleted the from-exotic-fruits-to-web3 branch March 24, 2020 16:39
liamzebedee added a commit to keep-network/tbtc-dapp that referenced this pull request Apr 1, 2020
This was broken after we swapped from TruffleContract to web3.js in keep-network/tbtc.js#10
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants