Giter Site home page Giter Site logo

xclud / web3dart Goto Github PK

View Code? Open in Web Editor NEW

This project forked from simolus3/web3dart

176.0 9.0 97.0 528 KB

Ethereum library, written in Dart.

Home Page: https://pub.dev/packages/web3dart

License: MIT License

Dart 100.00%
blockchain dart ethereum flutter web3

web3dart's Introduction

pub package likes points popularity license stars forks sdk version

A dart library that connects to interact with the Ethereum blockchain. It connects to an Ethereum node to send transactions, interact with smart contracts and much more!

Features

  • Connect to an Ethereum node with the rpc-api, call common methods
  • Send signed Ethereum transactions
  • Generate private keys, setup new Ethereum addresses
  • Call functions on smart contracts and listen for contract events
  • Code generation based on smart contract ABI for easier interaction

TODO

  • Encode all supported solidity types, although only (u)fixed, which are not commonly used, are not supported at the moment.

Usage

Credentials and Wallets

In order to send transactions on the Ethereum network, some credentials are required. The library supports raw private keys and v3 wallet files.

import 'dart:math'; //used for the random number generator

import 'package:web3dart/web3dart.dart';
// You can create Credentials from private keys
Credentials fromHex = EthPrivateKey.fromHex("c87509a[...]dc0d3");

// Or generate a new key randomly
var rng = Random.secure();
Credentials random = EthPrivateKey.createRandom(rng);

// In either way, the library can derive the public key and the address
// from a private key:
var address = credentials.address;
print(address.hex);

Another way to obtain Credentials which the library uses to sign transactions is the usage of a wallet file. Wallets store a private key securely and require a password to unlock. The library has experimental support for version 3 wallets commonly generated by other Ethereum clients:

import 'dart:io';
import 'package:web3dart/web3dart.dart';

String content = File("wallet.json").readAsStringSync();
Wallet wallet = Wallet.fromJson(content, "testpassword");

Credentials unlocked = wallet.privateKey;
// You can now use these credentials to sign transactions or messages

You can also create Wallet files with this library. To do so, you first need the private key you want to encrypt and a desired password. Then, create your wallet with

Wallet wallet = Wallet.createNew(credentials, "password", random);
print(wallet.toJson());

You can also write wallet.toJson() into a file which you can later open with MyEtherWallet (select Keystore / JSON File) or other Ethereum clients like geth.

Custom credentials

If you want to integrate web3dart with other wallet providers, you can implement Credentials and override the appropriate methods.

Connecting to an RPC server

The library won't send signed transactions to miners itself. Instead, it relies on an RPC client to do that. You can use a public RPC API like infura, setup your own using geth or, if you just want to test things out, use a private testnet with truffle and ganache. All these options will give you an RPC endpoint to which the library can connect.

import 'package:http/http.dart'; //You can also import the browser version
import 'package:web3dart/web3dart.dart';

var apiUrl = "http://localhost:7545"; //Replace with your API

var httpClient = Client();
var ethClient = Web3Client(apiUrl, httpClient);

var credentials = EthPrivateKey.fromHex("0x...");
var address = credentials.address;

// You can now call rpc methods. This one will query the amount of Ether you own
EtherAmount balance = ethClient.getBalance(address);
print(balance.getValueInUnit(EtherUnit.ether));

Sending transactions

Of course, this library supports creating, signing and sending Ethereum transactions:

import 'package:web3dart/web3dart.dart';

/// [...], you need to specify the url and your client, see example above
var ethClient = Web3Client(apiUrl, httpClient);

var credentials = EthPrivateKey.fromHex("0x...");

await client.sendTransaction(
  credentials,
  Transaction(
    to: EthereumAddress.fromHex('0xC91...3706'),
    gasPrice: EtherAmount.inWei(BigInt.one),
    maxGas: 100000,
    value: EtherAmount.fromUnitAndValue(EtherUnit.ether, 1),
  ),
);

Missing data, like the gas price, the sender and a transaction nonce will be obtained from the connected node when not explicitly specified. If you only need the signed transaction but don't intend to send it, you can use client.signTransaction.

Smart contracts

The library can parse the abi of a smart contract and send data to it. It can also listen for events emitted by smart contracts. See this file for an example.

Dart Code Generator

By using Dart's build system, web3dart can generate Dart code to easily access smart contracts.

Install web3dart_builders package

pub add web3dart_builders --dev

To use this feature, put a contract abi json somewhere into lib/. The filename has to end with .abi.json. Then, add a dev_dependency on the build_runner package and run

pub run build_runner build

You'll now find a .g.dart file containing code to interact with the contract.

Optional: Ignore naming suggestions for generated files

If importing contract ABIs with function names that don't follow dart's naming conventions, the dart analyzer will (by default) be unhappy about it, and show warnings. This can be mitigated by excluding all the generated files from being analyzed.
Note that this has the side effect of suppressing serious errors as well, should there exist any. (There shouldn't as these files are automatically generated).

Create a file named analysis_options.yaml in the root directory of your project:

analyzer:
  exclude: 
    - '**/*.g.dart'

See Customizing static analysis for advanced options.

Feature requests and bugs

Please file feature requests and bugs at the issue tracker. If you want to contribute to this library, please submit a Pull Request.

Testing

dart test test

web3dart's People

Contributors

alexeyinkin avatar andromeda911 avatar bcc0421 avatar botary avatar brickpop avatar brothereum avatar canewsin avatar chart21 avatar ciga2011 avatar dosco avatar eucalyptuslabs avatar ivaneidel avatar jmank88 avatar kevtechi avatar kirill09 avatar konstantinullrich avatar kulitech avatar ludowkm avatar maxholman avatar mjkim avatar modulovalue avatar muhammadsaddamnur avatar purplenoodlesoop avatar quetool avatar riccardodm97 avatar simolus3 avatar tim-eucalyptus avatar treeder avatar vinicentus avatar xclud avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

web3dart's Issues

RangeError: Value not in range: 32

When I call the balanceOf function of a ERC-20 contract i get the Error 'RangeError: Value not in range: 32'. After some debug fun it seems that there is some kind of problem with decoding the return value of the call, but am not entierly sure why there is a problem. Here is the code im working with:

`ethereumTokenBalance(String contractAddress) async {
var httpClient = Client();
Web3Client client = Web3Client(global.publicRpcEthereumMainNet, httpClient);
var contract = await ContractParser.fromAssets('abi.json', contractAddress);
var function = contract.function('balanceOf');
var balance = await client.call(
contract: contract,
function: function,
params: [EthereumAddress.fromHex(global.ownAddress)]);

return balance;
} class ContractParser {
static Future fromAssets(
String path, String contractAddress) async {
final contractJson =
jsonDecode(await rootBundle.loadString('assets/abi.json'));

return DeployedContract(
    ContractAbi.fromJson(jsonEncode(contractJson), 'token'),
    EthereumAddress.fromHex(contractAddress));

}
}`

the abi.json is a norml ERC-20 contract.

Custom filter refresh interval

Currently filters like eth_newPendingTransactionFilter refresh interval is hardcoded to be 2 seconds with _pingDuration constant in filters.dart. Then a timer is used with this interval. While 2 seconds may be enough for frontrunners on Ethereum with their long block, it is not enough for blockchains with shorter blocks and for backrunning on any blockchains.

I suggest to:

  1. Make an option to override this interval.
  2. Instead of a timer, use a loop with await Future.delayed().

Particularly, a loop solution would allow to not wait between calls for extreme extreme solutions.

For the interface we have the following options:

  1. Deprecate Web3Client.pendingTransactions and add a separate method with interval argument.
  2. Breaking change: Add a required argument to Web3Client.pendingTransactions since it is a very convenient name.
  3. Breaking change: Add an optional argument to Web3Client.pendingTransactions with the default of no waiting.
  4. Add an option to Web3Client to set all filters' intervals.

From the interface design point of view, (3) is the best, but it would change the behavior without breaking builds. So I suggest the roadmap:

  1. Do the Option 1 if we do this before the next breaking release.
  2. In the next breaking release, remove pendingTransactions.
  3. In yet the next breaking release do the Option 3.

Meanwhile another solution to refresh the filter at custom interval is to do

NFT(ERC721) estimateGas?

Hi,

To calculate gasLimit in real time, we are going to use estimateGas.
However, the returned gasLimit value is too small.
(ex, early 20,000, not 21,000 ^^)
If you actually send it, you will get over 50,000.
Is the method I used correct?
How can I get estimateGas for ERC721?
thank you

...
final contractFunction = contract.function('safeTransferFrom');
        return await client.estimateGas(
          sender: EthereumAddress.fromHex(from),
          to: EthereumAddress.fromHex(to),
          data: contractFunction.encodeCall([EthereumAddress.fromHex(from), EthereumAddress.fromHex(to), tokenId, Uint8List.fromList([])]),
          gasPrice: EtherAmount.inWei(gasPrice),
          amountOfGas: gasPrice,
          value: EtherAmount.inWei(BigInt.from(1)),
        );
...        

Getting transactions with eth_getBlockByNumber

eth_getBlockByNumber returns either transaction hashes or full transactions depending on the second boolean argument. For this we have Web3Client.getBlockInformation that also has an optional boolean argument which is sent but the transactions from the response are never parsed.

I need to parse them and so to add this functionality. We need to decide on Dart data structure because it is a bad practice to use List<dynamic> for this.

I suggest to:

  1. Subclass BlockInformation with BlockInformationWithTransactions and BlockInformationWithTransactionHashes. The subclasses would have transactions field of corresponding list type. The base class would not have this field.

  2. Add 2 methods to Web3Client: getBlockByNumberWithTransactions, getBlockByNumberWithTransactionHashes. They would return the corresponding block types. Their names are chosen to more closely match the RPC names. They would accept BlockNum as the first argument instead of String that getBlockInformation currently accepts, this is for consistency across other methods and for ease of calling.

  3. Deprecate the existing getBlockInformation method.

Polygon main and test net address?

I read through the docs but I wasn't clear on whether I can just use various RPC URLs across the different EVM chains.

I don't see how to specify url and chain is. Is this just for Ethereum and named chains like rinkby?

validate address

how to check enter address valid before send coin OR token to address ?

Wallet.toJson is slow on web

Hi
Wallet wallet = Wallet.createNew(EthPrivateKey.fromHex("1122"), "123456", Random.secure());
debugPrint(DateTime.now().toString());
var json = wallet.toJson(); //20 seconds
debugPrint(DateTime.now().toString());

this part take 20 second. is it normal or a bug ?

Estimating gas fee exception

I'm trying to estimate the gas fee for the ERC20 token transaction - in this case transferring DAI from one address to another (on Mumbai).

The code for estimating the gas fee:

final contract = DeployedContract(ContractAbi.fromJson(abi, token.id),  // 'dai'
          EthereumAddress.fromHex(token.contractAddress)); // 0xcB1e72786A6eb3b44C2a2429e317c8a2462CFeb1

final transferFunction = contract.function('transferFrom');

final transaction = Transaction.callContract(
  contract: contract,
  function: transferFunction,
  parameters: [
    EthereumAddress.fromHex(address),  // 0x2970C7181450B6c13071131f0005ccA18436c12B
    EthereumAddress.fromHex(recipientAddress),  // 0xc7c6BAEA62Ff6BBAca799156CC4e9f50BC9e8060
    10000000000000,  // 0.001 Dai
  ],
);

final fee = await _client.estimateGas(
  to: transaction.to,
  value: transaction.value,
  data: transaction.data,
);

However, I'm getting RPCError: got code 3 with msg "execution reverted: Dai/insufficient-allowance". The sender address holds enough tokens (approx. 0.0038 Dai). I have tried first to call approve with the same amount but I'm getting a different exception RPCError: got code -32000 with msg "already known" and the gas estimation still fails.

Any ideas on how to estimate correctly with web3dart?

Write functions in custom contract failing using infura and WalletConnect

When using walletconnect_dart (with infura) to provide credentials for transactions on mobile devices all write functions are failing with the following JS error.

Uncaught TypeError: Cannot read properties of null (reading 'addressBytes')

It looks to me like an address is not being passed correctly through to the underlying provider which is then throwing this error.

My CustomTransactionSender looks like this:

import 'dart:typed_data';

import 'package:walletconnect_dart/walletconnect_dart.dart';
import 'package:web3dart/crypto.dart';
import 'package:web3dart/web3dart.dart';

class WalletConnectEthereumCredentials extends CustomTransactionSender {
  WalletConnectEthereumCredentials({required this.wcProvider});

  final EthereumWalletConnectProvider wcProvider;

  @override
  Future<EthereumAddress> extractAddress() async {
    return EthereumAddress.fromHex(wcProvider.connector.session.accounts[0]);
  }

  @override
  Future<String> sendTransaction(Transaction transaction) async {
    final String hash = await wcProvider.sendTransaction(
      from: transaction.from!.hex,
      to: transaction.to?.hex,
      data: transaction.data,
      gas: transaction.maxGas,
      gasPrice: transaction.gasPrice?.getInWei,
      value: transaction.value?.getInWei,
      nonce: transaction.nonce,
    );

    return hash;
  }

  @override
  Future<MsgSignature> signToSignature(
    Uint8List payload, {
    int? chainId,
    bool isEIP1559 = false,
  }) async {
    throw UnimplementedError();
  }
}

sendTransaction gets invalid sender

I am using web3dart on Mumbai polygon. I constructed a Web3Client client with a https://polygon-mumbai.infura.io/v3/ URL. The API key is not filled in, but it's there.

First I get the estimated gas, and it's working fine.

BigInt estimateGas = await client.estimateGas(
  to: to,
  sender: EthereumAddress.fromHex(address),
  value: EtherAmount.fromUnitAndValue(
      EtherUnit.ether, BigInt.from(amount)),
);

and then I try to send some MATIC to the some address. The RPCError returns the message: "invalid sender".

try {
  await client.sendTransaction(
      credentials,
      Transaction(
        to: to,
        from: credentials.address,
        value: EtherAmount.fromUnitAndValue(
            EtherUnit.ether, BigInt.from(amount)),
      ),
    );
} on RPCError catch (e) {
  final message = e.message;
}

get transaction status in real time

is this package supports transaction subscription?
same as web3.eth.subscribe in web3.js
if it already supports it, how can I implement it.
and if not, is there a workaround?

Metamask error after transaction.callContract

Hi, when i make a transaction with my contractabi everything works perfectly. I managed to obtain credentials etc. When i open metamask and accept the incoming transactions everything is okay, but 5 seconds later i get the message: oops! Something went wrong! :/. When i tap on the error it opens an empty popup with no information. Thanks in advance!

Can't get any balance out of eth

E/flutter ( 9383): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: RangeError: Value not in range: 32
E/flutter ( 9383): #0 _rangeCheck (dart:typed_data-patch/typed_data_patch.dart:5075:5)
E/flutter ( 9383): #1 _ByteBuffer.asUint8List (dart:typed_data-patch/typed_data_patch.dart:1917:5)
E/flutter ( 9383): #2 _IntTypeBase.decode (package:web3dart/src/contracts/abi/integers.dart:37:31)
E/flutter ( 9383): #3 TupleType.decode (package:web3dart/src/contracts/abi/tuple.dart:106:29)
E/flutter ( 9383): #4 ContractFunction.decodeReturnValues (package:web3dart/src/contracts/abi/abi.dart:273:30)
E/flutter ( 9383): #5 Web3Client.call (package:web3dart/src/core/client.dart:354:21)
E/flutter ( 9383):
E/flutter ( 9383): #6 Token.getBalance (package:untitled_flutter_test/presenter/model/token.dart:48:22)
E/flutter ( 9383):
E/flutter ( 9383): #7 TestPlay.test4 (package:untitled_flutter_test/presenter/model/testPlay.dart:93:21)
E/flutter ( 9383):

testEthWallet = BigInt.parse("110925170330547180589658713797469555526567670447166036968931513412325485042143");
testEthNet = "https://ropsten.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161";
web3client = Web3Client(testEthNet, Client());
credentials = EthPrivateKey.fromInt(testEthWallet);

usdtAddress = EthereumAddress.fromHex("0xdac17f958d2ee523a2206206994597c13d831ec7");
ownAddress = credentials.address;
chainID = await _web3client.getNetworkId();

//crash v1
    final erc20 = Erc20(
      address: usdtAddress,
      client: _web3client,
      chainId: chainID,
    );
    final balanceUsdt = await erc20.balanceOf(ownAddress);

//crash v2
    final token = Token(
       address: usdtAddress, 
       client: _web3client,
    );
    final balance = await token.getBalance(ownAddress);

Eth balance, aka,
final balance = await web3client.getBalance(ownAddress);
works great, but that's it. I'm really missing something here, because it looks like I'm the only one who have this issue today.

Aight, let's go deeper

const abiCode ='[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_upgradedAddress","type":"address"}],"name":"deprecate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"deprecated","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_evilUser","type":"address"}],"name":"addBlackList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"upgradedAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maximumFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_maker","type":"address"}],"name":"getBlackListStatus","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowed","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newBasisPoints","type":"uint256"},{"name":"newMaxFee","type":"uint256"}],"name":"setParams","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"issue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"redeem","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"basisPointsRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBlackListed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_clearedUser","type":"address"}],"name":"removeBlackList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MAX_UINT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_blackListedUser","type":"address"}],"name":"destroyBlackFunds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_initialSupply","type":"uint256"},{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_decimals","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Issue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newAddress","type":"address"}],"name":"Deprecate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"feeBasisPoints","type":"uint256"},{"indexed":false,"name":"maxFee","type":"uint256"}],"name":"Params","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_blackListedUser","type":"address"},{"indexed":false,"name":"_balance","type":"uint256"}],"name":"DestroyedBlackFunds","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_user","type":"address"}],"name":"AddedBlackList","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_user","type":"address"}],"name":"RemovedBlackList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"}]';
final contract = DeployedContract(
  ContractAbi.fromJson(
    abiCode,
    'USDT',
  ),
  usdtAddress,
);

final balance = await _web3client.call(
  contract: contract,
  function: contract.function('balanceOf'),
  params: [ownAddress],
);

Same error, same line.

Error handling in getTransactionByHash

Currently for not-found transaction hashes this method breaks on passing null to TransactionInformation.fromMap. If one wants to handle this, it is hard to rely on this since it can change with implementation. A well-defined interface should do one of the following:

  1. Make this method nullable.
  2. Throw a specific exception.

Either one is a breaking change since someone may be cathing the current exception. Making it nullable is a harder change since it additionally affects successful scenario code.

Still I suggest making it nullable since the protocol returns null and views this as a normal result and not an error.

Calling custom RPC methods

There are methods not covered by the current client interface, like txpool_content. Is there a way to call them? I could not find one easily.

I suggest making Web3Client._makeRPCCall public so it is easy to call them. No matter how hard we try to wrap all standard methods, there still may be blockchains with their custom methods which we cannot call.

hexToInt raises exception on null string or "0x".

When hex string is null string or 0x hexToInt raises exception.
So, hexToInt should be changed like the following.

///Takes the hexadecimal input and creates a [BigInt].
BigInt hexToInt(String hex) {
  if (hex == '' || hex == '0x') return BigInt.from(0);
  return BigInt.parse(strip0x(hex), radix: 16);
}

Functions with Different Paramaters throws error

I am looking to encode a function call to make something more dynamic than using the generated contracts.
In this case, the ERC-721 standard contains two safeTransferFrom calls; one with data as a 4th param and one without.
The library throws because:

    try {
      ContractFunction _function = functions.singleWhere((f) => f.name == name);
      return _function;
    } catch (err, trace) {
      print("Error: $err\n$trace");
      rethrow;
    }
  }```

However, if this code is replaced with 

```ContractFunction function(String name) {
    try {
      ContractFunction _function = functions.firstWhere((f) => f.name == name);
      return _function;
    } catch (err, trace) {
      print("Error: $err\n$trace");
      rethrow;
    }
  }```
  
  Then it will take the first function that matches. This is my temporary hack since I know it will work with the only contracts I am supporting, however, for long term support; a secondary parameter should be optional that is the length of the number of params. Generally, the use of same name functions is not recommended in general; however, you cannot argue with OpenZeppelin. 

Therefore, this solution will enable you to pass in the number of params expected for a function that will be default by ignored. 

I will make a PR request at some point however, I need to check the differences. Currently, my repo is quite different than the original due to the original owner (no disrespect, the core library is great); never merging any of my suggestions. 

Additionally, while I do not have a dedicated server for this, if anyone that comes across this needs support you can join my Discord server and ping me in the #developers channel for greater response time. 

Ultimately, I will try to fix and merge all of the PRs, however, @xclud I believe we should consider starting from scratch. 

Uncaught (in promise) Error: FormatException: Invalid hexadecimal code unit U+005b. (at offset 40)

errors.dart:251 Uncaught (in promise) Error: FormatException: Invalid hexadecimal code unit U+005b. (at offset 40)
at Object.throw_ [as throw] (errors.dart:251:49)
at Object.digitForCodeUnit (utils.dart:34:3)
at Object._decode (decoder.dart:173:22)
at HexDecoder.convert (decoder.dart:31:5)
at HexCodec.decode (codec.dart:26:34)
at Object.hexToBytes (formatting.dart:44:21)
at EthereumAddress.fromHex (address.dart:45:30)
at home_provider.HomeProvider.new.callFunction (home_provider.dart:62:25)
at callFunction.next ()
at async_patch.dart:45:50
at _RootZone.runUnary (zone.dart:1685:54)
at _FutureListener.thenAwait.handleValue (future_impl.dart:159:18)
at handleValueCallback (future_impl.dart:766:44)
at _Future._propagateToListeners (future_impl.dart:795:13)
at async._AsyncCallbackEntry.new.callback (future_impl.dart:465:9)
at Object._microtaskLoop (schedule_microtask.dart:40:11)
at _startMicrotaskLoop (schedule_microtask.dart:49:5)
at async_patch.dart:166:15

2.4.0 conflicts with dart build runner

[WARNING] .dart_tool/build/entrypoint/build.dart:15:8: Error: Error when reading '../../../../.pub-cache/hosted/pub.dartlang.org/web3dart-2.4.0/lib/src/builder/builders.dart': No such file or directory
import 'package:web3dart/src/builder/builders.dart' as _i8;
       ^
.dart_tool/build/entrypoint/build.dart:43:45: Error: Undefined name 'abiGenerator'.
  _i1.apply(r'web3dart:abi_generator', [_i8.abiGenerator],
                                            ^^^^^^^^^^^^
.dart_tool/build/entrypoint/build.dart:48:59: Error: Undefined name 'deleteSource'.
  _i1.applyPostProcess(r'web3dart:delete_abi_source', _i8.deleteSource,
                                                          ^^^^^^^^^^^^
[INFO] Precompiling build script... completed, took 3.2s

[SEVERE] Failed to precompile build script .dart_tool/build/entrypoint/build.dart.
This is likely caused by a misconfigured builder definition.

Wrong address

I'm using bip39 lib to manage seed phrase after using the hexseed in this lib I got an address that not match with metamask address. Any idea, I saw someone using another lib to get key but I'm searching another way with this lib

Value not in range: 32 on balanceOf

Using the contract.dart example and using my own abi for balanceOf, i get this Value not in range: 32 error.

ABI for balanceOf:

{
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }

Tuple

Someone knows how to use it?
im trying to call a function with parameter of an object:
mint(wallet.address,
{
"trustType": 1,
"data": [5]
})

but its not working as javascript. how can i handle it?

RPC connect with Infura Project Secret

Hi, I'm calling eth_getBalance method will not work and giving me error like

{"jsonrpc":"2.0","error":{"code":-32002,"message":"rejected due to project ID settings"}}

After checking infura project setting security there enable project secret for every request so my question is that
How to pass project secret in Web3Dart client?

Transaction.callContract using 1559 and .signTransaction fails

I'm creating a signed transaction on a mobile client which is then passed to a node server for submission.
This works when not including 1559 gas parameters:

final transaction = Web3Dart.Transaction.callContract(
        contract: usdcContract,
        function: usdcContract.function('transferWithAuthorization'),
        parameters: [
          Web3Dart.EthereumAddress.fromHex(user.pubKey!),
          toAddress,
          amount,
          BigInt.from(validAfter),
          BigInt.from(validBefore),
          nonce.bytes,
          BigInt.from(sigParams.v),
          bigIntToUint8List(sigParams.r),
          bigIntToUint8List(sigParams.s),
        ]
);
final signedTx = await ethClient.signTransaction(
    wallet.privateKey, 
    transaction,
    chainId: config.chain.chainId, 
    fetchChainIdFromNetworkId: false);
hexTx = "0x" + hex.encode(signedTx);

But when adding the 1559 parameters maxFeePerGas and maxPriorityFeePerGas, it fails when submitting on the node server with the following error: transaction could not be decoded: could not decode RLP components: could not decode list item 3 to Address: invalid address: 0x22ecb25c00

final transaction = Web3Dart.Transaction.callContract(
        contract: usdcContract,
        function: usdcContract.function('transferWithAuthorization'),
        parameters: [
          Web3Dart.EthereumAddress.fromHex(user.pubKey!),
          toAddress,
          amount,
          BigInt.from(validAfter),
          BigInt.from(validBefore),
          nonce.bytes,
          BigInt.from(sigParams.v),
          bigIntToUint8List(sigParams.r),
          bigIntToUint8List(sigParams.s),
        ],
        maxFeePerGas: Web3Dart.EtherAmount.fromUnitAndValue(Web3Dart.EtherUnit.gwei, 150),
        maxPriorityFeePerGas: Web3Dart.EtherAmount.fromUnitAndValue(Web3Dart.EtherUnit.gwei, 3),
);
final signedTx = await ethClient.signTransaction(
    wallet.privateKey, 
    transaction,
    chainId: config.chain.chainId, 
    fetchChainIdFromNetworkId: false);
hexTx = "0x" + hex.encode(signedTx);

I'm using web3.js 1.7.1 on the node server and the js snippet for submitting the transaction is:

Web3.eth.sendSignedTransaction(hexTx, function (err, hash) {
    if (!err) {
      response.end(JSON.stringify({"hash": hash }));
    } else {
      response.end("Error!");
    }
  });

If I use .sendTransaction (instead of .signTransaction) on the mobile client using the 1559 parameters it works.
Is there something I'm missing in the combo of .callContract and .signTransaction when using 1559, or is something broken?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.