web3dart icon indicating copy to clipboard operation
web3dart copied to clipboard

Re-enable support for the web

Open simolus3 opened this issue 6 years ago • 20 comments

We import package:isolate to relay expensive operations onto a background isolate. Sadly, the current design means that package:web3dart/web3dart.dart has to import package:isolate, which we can't use on the web.

We could extract the isolate logic into another library, say package:web3dart/isolate.dart, to fix this. It would require a breaking change though.

simolus3 avatar Jan 18 '20 09:01 simolus3

@simolus3 Could https://api.flutter.dev/flutter/foundation/compute.html be an alternative for the isolate library?

gatanga avatar Jan 26 '20 16:01 gatanga

It's not that we can't use dart:isolate - we just can't have package:web3dart/web3dart.dart depend on it.

I'll add an interface and an implementation without dart:isolate to the main library. Another implementation using dart:isolate would live in another library, say package:web3dart/isolate.dart. As long as users don't import that in a web app, everything should be fine.

simolus3 avatar Jan 26 '20 20:01 simolus3

I've made some progress, but some tests are failing on the web (I blame floating-points). I'll look into that tomorrow.

simolus3 avatar Jan 26 '20 20:01 simolus3

Thank you so much @simolus3 . Much appreciated. I am looking so much forward to the web support working.

Again, thanks for the time.

I will clone the web3dart repo and try to play with https://github.com/simolus3/web3dart/commit/e6545e6611c5e93f1178a5cccc292a6a94aa8be7

gatanga avatar Jan 26 '20 23:01 gatanga

@gatanga I've just released version 2.0.0-dev as a preview to pub, so you can use it without a local fork:

dependencies:
  web3dart: ^2.0.0-dev

Please let me know if you run into any problems! If everything goes well, I'll make this the proper 2.0 release.

simolus3 avatar Jan 28 '20 15:01 simolus3

@simolus3 Thank you so much for this. I will play with it starting today for the rest of the week. I will let you know of my findings as early next week or by the weekend.

This is incredible

gatanga avatar Jan 28 '20 15:01 gatanga

@simolus3 I am busy testing dev 2.0.

I used var credentials = ethClient.credentialsFromPrivateKey("0x..."); to get credentials then I followed https://github.com/simolus3/web3dart/blob/development/example/contracts.dart as an example to call a setter method in my contract.

However, I am getting this error:

{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32000,
    "message": "invalid sender"
  }
}

I am connecting to Rinkeby test net using Infura API. In Android and iOS libraries, the chain ID is detected automatically. In Javascript, I set it manually. How does the chain ID selection work with web3dart?

gatanga avatar Jan 29 '20 16:01 gatanga

@simolus3 Don't worry. I set the chain ID to 4 and it's working like a charm. Thank you.

gatanga avatar Jan 29 '20 16:01 gatanga

@simolus3 I have bumped into another issue for the web.

So on Android/iOS, if there is a POST request, the client just makes that POST request. However, on the web, most of the time the browser will make an OPTIONS call first before making the actual request.

await sendTransaction is assuming that the response of that OPTIONS request is the actual response which is not right.

Any idea how we can fix this?

gatanga avatar Jan 29 '20 17:01 gatanga

@simolus3 Update. I am actually able to use to get a transaction hash when i do sendTransaction when I run the app using flutter run -d chrome. It is only failing if I build in release mode and serve over a server. Also If I try to it as part of a chrome plugin the sendTransaction returns only after the OPTIONS response

gatanga avatar Jan 29 '20 19:01 gatanga

@simolus3 Update: => It was my mistake. I have now managed to call a setter method of my smart contract in 3 cases:

  • Debug build web app built using flutter run -d chrome

  • Web app served over a normal server

  • And a Chrome extension

I plan to test it on Firefox extensions tomorrow. I will give you feedback

gatanga avatar Jan 29 '20 20:01 gatanga

Also, if you do welcome contributions, I would love to add the ability to create HD wallets in the future

gatanga avatar Jan 29 '20 20:01 gatanga

Update: => It was my mistake

If this is something others might run into as well, it should be reflected in the documentation. Do you know what went wrong?

if you do welcome contributions, I would love to add the ability to create HD wallets in the future

Contributions are always welcome! Just let me know if you need any pointers.

simolus3 avatar Jan 29 '20 20:01 simolus3

@simolus3 It was something stupid. So initially I had something like this: var response = await platform.invokeMethod("mySmartContractSetterMethod)". This was used to call the Android and iOS code. Then adding support for flutter web, I used the ternary operator and had this:

var response = kIsWeb? mySmartContractSetterMethodFromWeb3dartmanager : await platform.invokeMethod("mySmartContractSetterMethod)". So technically, I forgot the keyword await. It was supposed to be var response = kIsWeb? await mySmartContractSetterMethodFromWeb3dartmanager : await platform.invokeMethod("mySmartContractSetterMethod)".

So for that reason, it was not waiting for the response to come back. I could still see all the requests and responses via dev-tools.

gatanga avatar Jan 30 '20 12:01 gatanga

@simolus3 For the contributions, I will definitely let you know.

gatanga avatar Jan 30 '20 12:01 gatanga

@simolus3 I am hitting another issue. So when I call a setter function in my smart contract, the transaction goes through initially and it shows me the gas consumed is around 0.001035034 Ether. However after a few seconds to a minute, Etherscan tells me this : Warning! Error encountered during contract execution [execution reverted] and the transaction fee changes to 0.00008904 Ether

All works alright on Android using Web3java library and iOS using web3.swift.pod.

I can't quite figure out why this is happening

gatanga avatar Jan 30 '20 13:01 gatanga

If I try to set the gas price and the max gas like this:

Transaction.callContract(
          gasPrice: EtherAmount.inWei(BigInt.one),
          maxGas: 100000,
        )

, I then get the response

{
  "jsonrpc": "2.0",
  "id": 2,
  "error": {
    "code": -32000,
    "message": "replacement transaction underpriced"
  }
}

And if I do not set the gas price and the max price, then the transaction is rejected and when I check on EtherScan, it seems the issue is that the gas limit is too low: 63,165

gatanga avatar Jan 30 '20 13:01 gatanga

Thank you for trying it out, this is valuable feedback!

Regarding the [execution reverted] problem: It likely indicates that we're sending invalid data to the contract, like paying a non-payable function or something. To help me debug this, can you provide

  • the signature of the contract
  • which arguments you passed
  • either the data to sendRawTransaction from dev-tools, or the parsed data as it shows up on EtherScan.

If you have a comparison transaction made with another library and can provide the arguments and generated data for that as well, it would help a lot. Thanks!

The "replacement transaction underpriced" error indicates that you've sent multiple transactions with the same nonce. Specifically, I think this happens when the first transaction hasn't been mined yet. Web3Dart will check how many transaction the sending address has, then add one for the nonce. We should probably include pending transactions for that as well.

And if I do not set the gas price and the max price, then the transaction is rejected

I think we ask the node for an estimation of how much gas is required if the parameter isn't set. I'll check what's going wrong here.

simolus3 avatar Jan 30 '20 23:01 simolus3

@simolus3 Thanks for this. I will collect the data and share with you

gatanga avatar Feb 04 '20 16:02 gatanga

@simolus3 Sorry. It's been a hectic 2 weeks. I could not return to working on my project.

Instead of gasPrice: EtherAmount.inWei(BigInt.one) from the example, I used gasPrice: EtherAmount.fromUnitAndValue(EtherUnit.gwei, 1), all worked so smooth. So arguments supplied to the contract were not the issue. The consumed gas was 0.00005259 Ether

Even when I did not supply this value (to let the library determine this), it did not work. So, I will have a deeper look into how this

gatanga avatar Feb 15 '20 01:02 gatanga