Open timmornYE opened 4 years ago
At the moment, there's no integration for MetaMask. You could probably implement your own Credentials
subclass with it if you need it. That would allow you to re-use most web3dart apis.
Do you have a suggestion... what system would you use so that users can make a transaction (store data in a smart contract) from an angulardart app?
I haven't used web3dart in a production web project yet, so I don't have any suggestions. Using MetaMask would probably be a good option - I can help write an integration for it if you like.
Has there been any work done on this? I am interested in seeing examples and/or helping out with a standard implementation.
I haven't done any work on this yet, but I'll start working on it now. I'll let you know when I have a basic integration that can be used to sign raw transactions. From that point on it should be easier to add more functionality, for which I'd appreciate all kinds of help or PRs of course :)
Great! I'm happy to test something hacky if you push a branch or open a draft.
I've published my initial version to the metamask
branch. There's an example in example/metamask
.
Currently, web3dart assumes that it's able to sign arbitrary data. I thought that we could do that with MetaMask as well, but I looks like I was wrong. This means that some endpoints, in particular sendTransaction
and signTransaction
would have to be changed to no longer use the eth_*rawTransaction
rpc calls (or only use them when we have the private key). I'll think of a good api to support both approaches here.
Cool, I'll take a look. AFAIK you should still be able to construct a raw signed tx via sign
, though it may be more manual. Letting metamask forward automatically might be more appropriate in some cases though.
Hi @simolus3, would be great to get this stuff into a release, thanks for looking at it.
I had one comment, on it: I don't think it should have any metamask specific names or anything, most wallets (DApp browsers) support the same interface and as a developer, you don't need to know what wallet a user is using.
Yes, Metamask capability would be absolutely amazing to have. Thanks so much for this project!
BTW, I made a library over here to work with metamask and other DApp browsers: https://pub.dev/packages/flutter_web3_provider
may i know the status of this issue? I think this library will have more usage if metamask wallet connect is supported.
I've just added support for MetaMask on the master
branch in this repo.
Here's an example on how MetaMask support would look like: https://github.com/simolus3/web3dart/blob/96f94fd6e850383adde799e3adab154aeb1c300a/example/metamask/web/main.dart#L8-L24
There are still some pending todos:
sendTransaction
works.Hi @simolus3 , I confirm that sendTransaction
works with MetaMask.
However this line fails with the MetaMask RPC client:
_web3client.call(contract: _deployedContract, function: _ctTaskCount, params: []);
Everything else works the same until that line.
Isn't it supported at the moment? If it isn't, when would it be, approximately? Is there a workaround or a better solution?
That might be another bug, can you share the abi of the method you're calling and which response value you're getting that couldn't be parsed?
That might be another bug, can you share the abi of the method you're calling and which response value you're getting that couldn't be parsed?
Thanks for the response, here: @simolus3
pragma solidity ^0.5.16;
contract TodoList {
uint public taskCount;
struct Task {
string taskName;
bool isCompleted;
}
mapping(uint => Task) public todos;
event TaskCreated(string taskName, uint taskNumber);
constructor() public {
taskCount = 0;
}
function createTask(string memory _taskName) public {
todos[taskCount] = Task(_taskName, false);
emit TaskCreated(_taskName, taskCount);
++taskCount;
}
}
Here is the line I call it:
_deployedContract = DeployedContract(contractAbi, _contractAddress);
_ctTaskCount = _deployedContract.function("taskCount");
print('Requesting task count...');
List response = await _web3client.call(contract: _deployedContract, function: _ctTaskCount, params: []);
print('Extracting task count from the response...');
That last print() does not print so it fails at that .call
I assume.
I actually got invalid data back after calling that method. My local node only returns 0x
which is obviously not the uint256 we're expecting here.
Can you reproduce the same thing with the JS client?
const Contracts = require('web3-eth-contract');
Contracts.setProvider('http://localhost:8545');
let contract = new Contracts(
[
{
"constant": true,
"inputs": [],
"name": "taskCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
],
yourContractAddress,
);
contract.methods.taskCount().call(function (err, result) {
console.log(err);
console.log(result);
});
@simolus3 It prints correctly:
$ node index.js
null
1
Do you have the contract on ropsten or something? I tried to deploy it to a local ganache-cli node which didn't work as expected.
Do you have the contract on ropsten or something? I tried to deploy it to a local ganache-cli node which didn't work as expected.
Here is the truffle-config.js
. Maybe the issue is here?
module.exports = {
networks: {
development: {
host: "127.0.0.1",
port: 7545,
network_id: "*", // Match any network id
},
advanced: {
websockets: true, // Enable EventEmitter interface for web3 (default: false)
},
},
contracts_build_directory: "./src/abis/",
compilers: {
solc: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
};
I added that config to Ganache in Truffle Projects
section on Workspace.
I also call truffle migrate
.
I've just added support for MetaMask on the
master
branch in this repo.Here's an example on how MetaMask support would look like: https://github.com/simolus3/web3dart/blob/96f94fd6e850383adde799e3adab154aeb1c300a/example/metamask/web/main.dart#L8-L24
There are still some pending todos:
- ~transactions can't be signed yet~ Done,
sendTransaction
works.- real time updates for events are not yet supported
Many thanks for the support. I am planning to test this today/tomorrow , Is there any ETA for real time event support?
So far, couldn't figure out how to use events with MetaMask unfortunately. My understanding was that we could create subscriptions with eth_subscribe
and then get events through window.ethereum.on('message', ...)
, but that doesn't appear to work for me.
Hi there, nice work so far! @simolus3
I'll likely start work on some blockchain dapps soon, and am in the process of evaluating flutter vs some arbritary javascript libraries. Can you give me a rough estimation on the amount of time it took you so far, and might still take to have metamask and some of the otther most popular wallets reasonably usable in web3dart and therefore Flutter? I would really prefer to use flutter and dont mind contributing, but I do need to know roughly what i'm getting into.
Also, I believe web3dart and the currently wip metamask integration work in both Flutter web and mobile, correct?
So basically there are two ways to use web3dart:
window.ethereum
is available (mostly MetaMask). You don't manage the private keys yourself but instead rely on what the provider gives you. Signing transactions and messages is also delegated to the provider. This only works in Ethereum-enabled web browsers.There are some small remaining issues with the web implementation like real-time events not working, but in general both implementations should work. If you can contribute smaller fixes and improvements then I think it should work.
@simolus3 I noticed an issue with getting Erc20
balance in web3 (currently using MetaMask). It seems like RequestArguments
is not getting passed to Ethereum.request. See screenshot.
The code works fine when running on non-web platforms. I'm guessing because the non-web codepath use the JsonRpc implementation but web is using MetaMask rpc impl. Any idea what's going on?
this seems to fix the issue. I converted map to a JS object and list to JsArray in dart_wrappers.dart
import 'package:js/js_util.dart' as js;
Object _mapToJsObject(Map<String, dynamic> map) {
final object = js.newObject();
map.forEach((k, v) => js.setProperty(object as Object, k, v));
return object as Object;
}
Object _listToJsArray(List<dynamic> list) {
final array = JsArray.from(list);
return array;
}
then in DartEthereum
extension updated the following:
Future<dynamic> rawRequest(String method, {Object? params}) {
if (params != null && params is List) {
for (var i = 0; i < params.length; i++) {
if (params[i] is Map) {
params[i] = _mapToJsObject(params[i] as Map<String, dynamic>);
} else if (params[i] is List) {
params[i] = _listToJsArray(params[i] as List<dynamic>);
}
}
}
// No, this can't be simplified. Metamask wants `params` to be undefined.
final args = params == null
? RequestArguments(method: method)
: RequestArguments(method: method, params: params);
return promiseToFuture(request(args));
}
Thanks! I can also take care of it, but a PR for this would be really appreciated.
cool
I use web3dart with angulardart and found no information on how to connect to MetaMask. Is this possible?