Giter Site home page Giter Site logo

xf00f / web3x Goto Github PK

View Code? Open in Web Editor NEW
209.0 11.0 27.0 1.25 MB

Ethereum TypeScript Client Library - for perfect types and tiny builds.

TypeScript 97.72% JavaScript 2.26% HTML 0.01% Shell 0.01%
ethereum typescript api javascript swarm whisper web3 web3js

web3x's People

Contributors

alcuadrado avatar ondratra avatar xf00f 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  avatar  avatar

web3x's Issues

Contracts with no constructor cannot be deployed

Constructors are optional for solidity contracts.

  1. Build a contract without a constructor
  2. Create an instance without an address and attempt to deploy
  3. tx-deploy.ts encodeABI -> this.contractEntry is undefined.

lack of dependencies for @types/ws and net

This is awsome PJ!

I tried web3x-es, then got compile errors.
It resolved after installing @types/ws and net.

ERROR in node_modules/web3x-es/providers/ws.d.ts(6,23): error TS2688: Cannot find type definition file for 'ws'.
node_modules/web3x-es/providers/ws.d.ts(7,10): error TS2305: Module '"/client/node_modules/isomorphic-ws/index"' has no exported member 'ClientOptions'.
node_modules/web3x-es/providers/ws.d.ts(7,31): error TS2497: Module '"/client/node_modules/isomorphic-ws/index"' resolves to a non-module entity and cannot be imported using this construct.

Unhandled exception warning in Account.proptotype.sendTransaction

If no gas is provided to Account.proptotype.sendTransaction an exception is thrown, but not handled. In fact, any exception thrown here will lead to the same situation.

I guess the expected behavior would be for the Account to estimate the gas by calling the provider. This is an opinionated alternative though. The simplest alternative is for the error to be forwarded to the returned PromiEvent.

Here's a minimal production script:

import { HttpProvider } from 'web3x/providers';
import { Eth } from 'web3x/eth';
import { Account } from 'web3x/accounts';

async function main() {
  const provider = new HttpProvider('http://localhost:8545');
  const eth = Eth.fromProvider(provider);

  const localAccount = Account.create(eth);
  
  //This should throw something like "sender doesn't have enough funds to send tx"
  await localAccount.sendTransaction({to: localAccount.address, value: 1});
}

main().catch(console.error);

new metamask update breaks getReceipt

I am not sure if this is the right place to report this, but I have unsuccessfully tried to replicate this bug on other dapps which don't use web3x.

Last night there was a new update for metamask (7.7.0) that breaks "newBlockHeaders" subscription,

.on('data', async (blockHeader: BlockHeaderResponse, sub) => {
doesn't fire.

I can confirm it works on previous versions, and that on my end I haven't changed my source code.

EIP-1193 compatible providers

Hi @xf00f,

The EIP-1193 defines a standard javascript/typescript Ethereum provider API. It has already been implemented by MetaMask and Mist Browser, and is being implemented by web3.js.

The simpler way to implement it in web3x is having a special provider that wraps an EIP-1193 compatible one, exposing this interface. Users of web3x would have to use it in this way:

import { EthereumProviderAdapter } from 'web3x-es/providers';
import { Eth } from 'web3x-es/eth';

const provider = new EthereumProviderAdapter(window.ethereum);
const eth = Eth.fromProvider(provider);

From the user perspective it would be better to have native support, using it like this:

import { Eth } from 'web3x-es/eth';

const eth = Eth.fromProvider(window.ethereum);

This alternative feels more natural, specially when integrating with MetaMask or other dapp browsers. It may require a major refactor though.

Do you have any thought about? Any plan to implement it?

Import declaration conflicts with local declaration of 'Arrayish'.

When building the web3x package v4.0.5 with Typescript >= 3.7 following error occurs:

node_modules/web3x/ethers/bytes.d.ts(5,10): Error TS2440: Import declaration conflicts with local declaration of 'Arrayish'.

I am not exactly sure what is connection between the code in web3x/src/ethers/bytes.ts and ether.js project, but they were solving exactly the same error in ethers-io/ethers.js#622.

Consider splitting into multiple packages

Hi

First off, I want to thank and congratulate you on this library. We were looking at web3 and found both the implementation lacking and started building our own typescript library on top of the json rpc interface. However, recently I found your library which is far more complete and of quite high quality. Nice job especially for a mostly solo effort.

I started Integrating this package into some of our code, which worked well, but I was wondering about the dependencies. We don't mirror the web3 api and actually work on a generic multi blockchain api, with some key differences, especially in key management. So, we only need a part of this code. But that brings a number of dependencies for parts we don't use.

In particular, eth-lib and contract/abi* are quite useful standalone.

I wondered if you considered a lerna monorepo approach to split into multiple package, with the same high level entry point.

If you are interested, I can make a series of pr doing a gradual transition. But I do not want to undertake such a task if you do not like the idea.

In any case, thank you for publishing this library.

Some possible changes to EIP1193 and a call about them

Hey @xf00f,

I'm opening this issue because between a few interested parties we had an open call today to discuss possible changes on EIP1193 and its release schedule. The call wasn't very representative, so nothing was decided, and we are scheduling another one.

I think you may be interested in joining the next call, or the discord channel where this is being discussed. There are also some interesting discussions going on on ethereum magicians provider ring, and you may want to check them.

Best,
Patricio

Problems with personal_unlockAccount

Hi all,

first of all, cool project you have here!

Recently I faced a potential bug. When trying to use the personal_unlockAccount method, I get an error saying the method does not exist.
A bit of investigation showed that somewhere along the way the method and parameters seem to disappear.
Unfortunately I have not yet had the time to dig in deep enough to exactly pinpoint the issue.
The problem occurs both with websocket and HTTP providers (those are the ones I tried).

Can you reproduce the error? Is there a workaround for this?

Error: The method _ does not exist/is not available
at provider.send (/home/benjamin/Desktop/ONECLICK/one-click-server/node_modules/web3x/providers/legacy-provider-adapter.js:37:35)
at module.exports.request.onreadystatechange (/home/benjamin/Desktop/ONECLICK/one-click-server/node_modules/web3x/providers/http.js:73:17)
at emitOne (events.js:116:13)
at module.exports.emit (events.js:211:7)
at module.exports.EventTarget.dispatchEvent (/home/benjamin/Desktop/ONECLICK/one-click-server/node_modules/node-http-xhr/lib/node-event-target.js:114:8)
at module.exports.NodeHttpXHR._setReadyState (/home/benjamin/Desktop/ONECLICK/one-click-server/node_modules/node-http-xhr/lib/index.js:339:8)
at module.exports.onEnd (/home/benjamin/Desktop/ONECLICK/one-click-server/node_modules/node-http-xhr/lib/index.js:482:12)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)

Why checking for outputs to define if a function is constant ?

Why checking for outputs to define if a function is constant ?

web3x-codegen defines here a function constant if there are outputs. Why not rather checking for:

if (definition.constant)

A function can be state-modifying even if it has output, right ? I just wanted to understand why. I can do a PR if that makes sense to use the constant keyword of the ABI.

I know it doesn't change anything since the solidity compiler outputs the stateMutability parameters, but the vyper compiler doesn't. So that would help to be vyper-compatible.

Make typescript a runtime dependency

web3x-codegen requires typescript at runtime, but it is in devDependencies. So after installing web3x, web3x-codegen does not work out of the box.

Split up getBlock into getBlockWithTransactions and getBlockWithoutTransactions?

Not quite sure of great naming, but the original web3 API for getting the block could be improved.
getBlock(number, true || false // if we want full transactions)
...could be split s.t. basically:
getBlockWithTransactions(number): BlockResponse<TransactionResponse>
getBlockWithoutTransactions(number): BlockResponse<Buffer>

One might be able to use some typescript wizardry too here and not split up the method, some typescript pseudocode:

function getBlock<TGetFullTransactions extends boolean>(blockNumber: number | string | ..., includeFullTransactions: TGetFullTransactions): TGetFullTransactions extends true ? BlockResponse<TransactionResponse> : BlockResponse<Buffer>;

... happy to submit a PR if we agree this would be a good optimization.

Number returns are seen as string instead of BN.

Given a standard ERC20 token, and its definition for web3x-codegen to parse:

    "Token": {
      "source": "files",
      "abiFile": "./node_modules/contracts/build/abi/Token.abi",
      "initDataFile": "./node_modules/contracts/build/abi/Token.bin"
    }

The generated TS file is incorrect:

totalSupply(): TxCall<string>;

Given that the ABI definition says the function returns a uin256, shouldn't this return a BN allowing for greater abstraction?

[Feature Request] Easy parsing of transaction.input against a Contract method.

Unless I"m missing something, one cannot currently parse out the data inside transaction.input using a lot of the nice codegen features inside web3x. It would be really nice to have that ability.

Concrete use case: I have several scripts running that watch on new transactions and parse out input for particular actions. It's really fast right now as we can get all of the transactions for a particular block in one go: if we wanted to switch to parse out events we'd have to do N requests for each transaction in the request to get its receipt.

This library is amazing by the way: practically overnight I've significantly cleaned up our codebase, builds are much faster too. Thank you for all of the hard work you've put into it. ๐Ÿ‘

`Legacy providers only support notification event.` when using `WebsocketProvider`

I'm using the WebsocketProvider and I want to listen to provider events like connect, error, etc...

Right now I'm using this:

import { WebsocketProvider } from "web3x/providers";

const provider = new WebsocketProvider(ws_provider_path);
provider.on("connect", () => console.log("Provider connected."));

But I keep getting this error:

Error: Legacy providers only support notification event.

So why is the WebsocketProvider a legacy provider ? And how can I setup a non-legacy provider to listen to this kind of events ?

Document supported JS engines

Heho again! Thanks for building web3x!

When installing web3x on a Node.js 8 LTS system, I get the error

yarn install v1.13.0
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
error [email protected]: The engine "node" is incompatible with this module. Expected version ">= 10.0.0". Got "8.15.1"
error Found incompatible module
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
Retry 1/3 exited 1, retrying in 1 seconds...
yarn install v1.13.0
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
error [email protected]: The engine "node" is incompatible with this module. Expected version ">= 10.0.0". Got "8.15.1"
error Found incompatible module
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
Retry 2/3 exited 1, retrying in 2 seconds...
yarn install v1.13.0
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
error [email protected]: The engine "node" is incompatible with this module. Expected version ">= 10.0.0". Got "8.15.1"
error Found incompatible module
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

because the dependency bigint-buffer requires Node.js 10+.

Looking at the web3x code it seams that native bigint is also required. This limits the JS environments in which this library can be used to a few cutting edge engines. Would it be possible to use bn.js instead to make this work with Node.js 8 as well? In any case, I think the supported JS environments should be documented.

Problems decoding events

Contracts to reproduce:

TransferBug.sol

pragma solidity ^0.5.0;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC721/IERC721Full.sol";
import "openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol";

contract TransferBug is ERC721Full {

    using SafeERC20 for ERC20;

    constructor() public ERC721Full("transfer bug", "BUG") {
    }

    function testBug(uint256 amount, address tokenAddress) public {
        ERC20 token = ERC20(tokenAddress);
        token.safeTransferFrom(msg.sender, address(this), amount);
    }

}

Token.sol

pragma solidity ^0.5.0;
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";


contract Token is ERC20 {
    string public name;
    string public symbol;
    uint8 public decimals;
    address public supplier;

    constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 totalSupply) public {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;
        supplier = msg.sender;

        _mint(supplier, totalSupply);
    }
}

Simple test:

import { Token } from "../../src/contracts/cos/Token";
import { TransferBug } from "../../src/contracts/cos/TransferBug";
import { startLocalBlockchain } from "../../src/localBlockchain";

test("transferBug", async () => {
  const { eth, accounts } = await startLocalBlockchain({ hostname: "127.0.0.1", port: 8500, findNextPort: true });

  const from = accounts[0].address;

  const token = new Token(eth);
  await token
    .deploy("test", "TEST", 18, 10000000)
    .send({ from, gas: 40000000 })
    .getReceipt();
  const originalBalance = await token.methods.balanceOf(from).call();
  console.log("Original balance", originalBalance);

  const buggedContract = new TransferBug(eth);
  await buggedContract
    .deploy()
    .send({ from, gas: 40000000 })
    .getReceipt();

  console.log("Test contract addr", buggedContract.address);

  await token.methods
    .approve(buggedContract.address!, 10)
    .send({ from, gas: 40000000 })
    .getReceipt();

  const result = await buggedContract.methods
    .testBug(10, token.address!)
    .send({ from, gas: 40000000 })
    .getReceipt();
  console.log("Got test reuslt", result);
});

Error:

    Returned values aren't valid, did it run Out of Gas?

      at ABICoder.decodeParameters (node_modules/src/contract/abi-coder/index.ts:128:13)
      at ABICoder.decodeParameter (node_modules/src/contract/abi-coder/index.ts:115:17)
      at inputs.forEach (node_modules/src/contract/abi-coder/index.ts:177:20)
          at Array.forEach (<anonymous>)
      at ABICoder.decodeLog (node_modules/src/contract/abi-coder/index.ts:172:7)
      at Object.decodeEvent (node_modules/src/contract/decode-event-abi.ts:36:34)
      at ContractEventEntry.decodeEvent (node_modules/src/contract/abi/contract-event-entry.ts:62:12)
      at ContractAbi.decodeAnyEvent (node_modules/src/contract/abi/contract-abi.ts:47:4)
      at receipt.logs.map.log (node_modules/src/contract/sent-contract-tx.ts:38:25)
          at Array.map (<anonymous>)
      at SentContractTx.handleReceipt (node_modules/src/contract/sent-contract-tx.ts:38:25)

I logged the topics for the Transfer event:

[ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      '0x000000000000000000000000627306090abab3a6e1400e9345bc60c78a8bef57',
      '0x000000000000000000000000f12b5dd4ead5f743c6baa640b0216200e89b60da' ]

Looks like it is missing one topic. It is not anonymous, so it should have four: one for the hash of the signature and three for the parameters:

event Transfer(address indexed from, address indexed to, uint256 value);

This causes this line to fail because the 4th topic is not there: https://github.com/xf00f/web3x/blob/master/src/contract/abi-coder/index.ts#L176

BN typescript error

I'm testing this module and here's the error I see when I try to compile the code.

error TS2497: Module '"../node_modules/@types/bn.js/index"' resolves to a non-module entity and cannot be imported using this construct.

1 import * as BN from 'bn.js';

Why not improve the `@types/web3` typings on DefinitelyTyped instead?

This is awesome work! However, I can't really use this as I rely on the support of the existing Web3 team; this repo will likely not port every commit and release, and isn't part of the main ethereum organization.

Part of your 'why' in the readme is that the typings are not perfect. Why did you vote for porting all of Web3 to TypeScript instead of improving the existing DefinitelyTyped web3 typings (which in my mind is a pretty standard to get typings for several repos)? I totally get it if you just wanted to do this project for funsies, but I want to make sure the community at large benefits from your awesomeness as much as possible.

Will you be contributing to the DefinitelyTyped bindings as well to get those up to speed with your "lessons learned" from creating this port?

Thanks!! Also, thanks again for making this awesome port; I wish it was something I could use.

Not having `call` for transaction method is a mistake.

The fact that a contract.methods.aTransactionMethod(args...).send() is available but not a contract.methods.aTransactionMethod(args...).call() is a big problem for us, as it is very common practice to run a call "blank" before performing a real send transaction.

The reason behind this sort of choice is that revert messages cannot be read when they occur on a send - they can only be read when using call using direct bytecode ABI encoding.

An example of what this led us to do:

const REVERT_FUNCTION_ID = "0x08c379a0";

...

  safeSendTx = async (state: State, opts: any) => {
    if (!isInitialized(state)) {
      throw new Error("The provider isn't ready to relay transactions.");
    }
    // First, simulate the transaction for free.
    await this.simulateTxSend(state, opts);
    // If we're here, it's unlikelly that a revert will occur, as the simulation
    // didn't throw.
    const tx = await state.eth.sendTransaction(opts);
    const hash = await tx.getTxHash();
    try {
      return await tx.getReceipt();
    } catch (ex) {
      // Get some info about the failed transaction hash.
      const fullTx = await state.eth.getTransaction(hash);
      // As the transaction failed, we will try and simulate it again in the block
      // it failed to try and retrieve a "revert" message.
      await this.simulateTxSend(opts, fullTx.blockNumber || undefined);
      throw new Error("The transaction failed without a revert message.");
    }
  };

  simulateTxSend = async (state: State, opts: any, block?: BlockType) => {
    if (!isInitialized(state)) {
      throw new Error("The provider isn't ready to relay transactions.");
    }
    const txString = await state.eth.call(opts, block);
    if (!txString.startsWith(REVERT_FUNCTION_ID)) {
      return txString;
    }
    const enc = txString.substring(REVERT_FUNCTION_ID.length);
    const dec = abiCoder.decodeParameter("string", enc);
    throw new Error(dec);
  };

We have to call it like this:

          api
            .safeSendTx(state, {
              ...utils.chainGasOpts,
              data: transact.methods.approve(account, i).encodeABI(),
              from: state.account,
              to: utils.chainManifest.transact,
            })

This is really cumbersome - it would be great to have access to call even on transaction methods exactly like web3 and truffle do - allowing for shooting "blanks".

Please expose the option to call methods of contracts that are transactions.

Cannot `call()`.

I think there is an issue with the way Web3x decodes return values.

From a solidity (ERC20 compliant) token, we have a totalSupply method that returns an uint256.
From our code, we go:

token.methods.totalSupply().call()

where token is a new Token(eth, TOKEN_ADDRESS) generated using web3x-codegen.

The result looks like this:

index.js:155 Uncaught (in promise) Error: Returned values aren't valid, did it run Out of Gas?
    at ABICoder.decodeParameters (index.js:155)
    at ContractFunctionEntry.decodeReturnValue (contract-function-entry.js:67)
    at Tx._callee2$ (tx.js:106)
    at tryCatch (runtime.js:63)
    at Generator.invoke [as _invoke] (runtime.js:282)
    at Generator.prototype.<computed> [as next] (runtime.js:116)
    at asyncGeneratorStep (asyncToGenerator.js:3)
    at _next (asyncToGenerator.js:25)

It is worth mentioning that the generated typescript code for Token.ts looks like this:

interface TokenMethods {
    totalSupply(): TxCall<string>;
    ...
}

Shouldn't this be a BigNumber or something like that?

Unable to create contracts without address specified

On version v3.0.1.

When creating an instance of a contract without specifying an address, I get the following output: "No contract address."

This seems to be because of buildMethods in Contract. It visits every function in the abi and creates an executor for each one. When doing this, it checks if the address has been defined.

Thank you for the great library, it has saved me a lot of time.

eth_signTypedData example

Please provide an example for eth_signTypedData method. I'm trying to use your library instead of web3 and so far it works great!
However I'm trying to implement signTypedData and don't know exactly how. I'm getting Method not found error. Having a working example would help a lot.

Why does `ContractEntryDefinition` does not fit what webx-codegen outputs ?

When I generate my contract types with web3x-codegen I end up with MyContract.ts and MyContractAbi.ts as intended.

However, in some of my MyContractAbi.ts, the ContractAbi constructor should take an array of ContractEntryDefinition. However some of my entries are set with a gas parameter, which does not fit the ContractEntryDefinition interface. See below:

export default new ContractAbi([
  ...
  {
    "name": "myFunction",
    "outputs": [],
    "inputs": [ ],
    ...
    "gas": 175875
  },
  ...
]);

Hence I got some compiler errors.

What does it depend on to set this gas parameter ? Should we add it to the ContractEntryDefinition interface as an optional parameter ?

Incorrect import of dependency 'uuid'

The 'uuid' package used by utils/encryption.ts has no default export.
This produces the following error

Attempted import error: 'uuid' does not contain a default export (imported as 'uuid').

"typescript": "^4.0.5"

Missing finally

It seems like finally is missing from the PromiEvent class. I'm getting this error when trying to pull in this library to a react app that was created with CRA

Property 'then' in type 'PromiEvent<T>' is not assignable to the same property in base type 'Promise<T>'.
  Type '<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => PromiEvent<...>' is not assignable to type '<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<...>'.
    Property 'finally' is missing in type 'PromiEvent<TResult1 | TResult2>' but required in type 'Promise<TResult1 | TResult2>'.

15     then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined): PromiEvent<TResult1 | TResult2>;
       ~~~~

  node_modules/typescript/lib/lib.es2018.promise.d.ts:31:5
    31     finally(onfinally?: (() => void) | undefined | null): Promise<T>
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    'finally' is declared here.

I think it makes since to add here, I can do this in a PR if you want

Detecting Network ID / Account changes.

Using Web3x, is it a recommended way to useEffect and handlers for network ID and account changes? It's not clear whether the developer should rely on web3.js directly.

Some Account methods incorrectly receive Tx object

Account.prototype.sendTransaction and Account.prototype.sendTransaction receive Tx objects as their first parameter. They should receive something like:

interface LocalAccountTx {
    nonce?: string | number;
    chainId?: string | number;
    to?: string;
    data?: string;
    value?: string | number;
    gas: string | number;
    gasPrice?: string | number;
}

as the from param doesn't make sense here, and the gas param is required.

Expose Contract options

Contracts in web3x have their abi, eth (provider), and default options declared as private, so there is no way to get to these parameters used to construct the Contract. Web3js exposes these parameters as options property. Could we get the same in web3x?
https://web3js.readthedocs.io/en/v1.2.0/web3-eth-contract.html#new-contract

Real-world use case

I have a contract with ERC721 ABI "loaded in it". Since some older contracts follow the initial draft of ERC721 they miss getApproved and isApprovedForAll methods. One such example is CryptoKitties contract, which fortunately implement getApproved functionality via it's own kittyIndexToApproved.

At some point in code I want to do this:

const regularERC721Contract = new Contract<void>(eth, erc721ABI, contractAddress)

... more code here ...

// then clone contract and to append ABI for CK function `kittyIndexToApproved`
const extraAbi: ContractEntryDefinition[] = [{
    constant: true,
    inputs: [
        {
            'name': '',
            'type': 'uint256'
        }
    ],
    name: 'kittyIndexToApproved',
    outputs: [
        {
            'name': '',
            'type': 'address'
        }
    ],
    payable: false,
    stateMutability: 'view' as 'view',
    type: 'function' as 'function'
}]

const oldAbi = []
    .concat((contract as any).contractAbi.functions)
    .concat((contract as any).contractAbi.events)
    .concat((contract as any).contractAbi.ctor)
    .map(item => item.entry)
const newAbi: ContractAbi = new ContractAbi([
    ...oldAbi,
    ...abiToAppend,
])

const ckContract = new Contract<void>((contract as any).eth, newAbi, contract.address, (contract as any).defaultOptions)

Because of missing options property, I have to hack my way to Contract's private properties (via casting contract to any) that may be changed in the future.

With options feature code will be reduced to:

const regularERC721Contract = new Contract<void>(eth, erc721ABI, contractAddress)
const extraAbi: ContractEntryDefinition[] = [{
    ...
}]
const newAbi: ContractAbi = new ContractAbi([
    ...regularERC721Contract.options.jsonInterface,
    ...extraAbi
])

eth.personal.sign() + Metamask error

Hello,
I have possibly discovered error in web3x. I am using Metamask 6.6.1 and web3x 3.0.11. When I tried to sign a message via

const userAddress = Address.fromString('0x123...')
const eth = Eth.fromCurrentProvider()
const personal = new Personal(eth.provider)

const signature = await personal.sign('a2000ab', userAddress, '')

I got error MetaMask - RPC Error: TypeError: e.toLowerCase is not a function, that happened inside of metamask. After some debugging I found that it works when i convert address to lowercased string like this:

const signature = await personal.sign('a2000ab', <any> userAddress.toString().toLowerCase(), '')

I assume function sign() is missing this conversion to lowercase string. I could create pull request for this but I am not sure that wouldn't break other combination of Metamask + web3x versions. @xf00f can you have look at this, please?

Re-license to MIT

As started in #34 (comment), there is the idea of relicensing this project as MIT. I think this is a very valuable step and makes this library much more attractive than others in the Ethereum space.

I'm opening this issue

  • to get visibility over the state of the relicensing
  • to express that all contributions from my side (not much yet but who knows what) are free to be licensed as MIT

internalType (Solidity 0.5.11+) with web3x-codegen - TS errors with ABI TS files

In Solidity version 0.5.11 (https://github.com/ethereum/solidity/releases/tag/v0.5.11), an internalType key was added to the generated JSON ABI objects produced by the Solidity compiler.

When I compile contracts with version 0.5.10 of the Solidity compiler, I get entries like the following in the JSON ABI objects produced:

{
      "constant": true,
      "inputs": [
        {
          "name": "data",
          "type": "uint256[]"
        }
      ],
      "name": "myFunction",
      "outputs": [
        {
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "pure",
      "type": "function"
    }

When I compile contracts with version 0.5.11 of the Solidity compiler, I get entries like the following in the JSON ABI objects produced:

{
      "constant": true,
      "inputs": [
        {
          "internalType": "uint256[]",
          "name": "data",
          "type": "uint256[]"
        }
      ],
      "name": "myFunction",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "pure",
      "type": "function"
    }

web3x-codegen appears to prepare the TypeScript ABI files (the MyContractAbi.ts files generated from the Solidity contract MyContract) by copying the entries from the Solidity compiler's generated ABI JSON files, regardless of which subsets of each entry exist in the corresponding TypeScript type definitions in web3x. Thus, the new internalType field gets copied into the MyContractAbi.ts files even though the web3x AbiInput and AbiOutput types (what I think are the web3x types for the objects in the inputs and outputs arrays above) don't have internalType fields.

When I compile a project that uses the MyContract.ts and MyContractAbi.ts files produced when MyContract was compiled with Solidity 0.5.11, the presence of the new internalType key not mentioned in the web3x AbiInput and AbiOutput types causes the TypeScript compiler to output errors like the following:

Type '{ "internalType": string; "name": string; "type": string; }' is not assignable to type 'AbiInput'. 
 Type '{ "internalType": string; "name": string; "type": string; }' is not assignable to type 'AbiOutput'.

Since the entries of the inputs and outputs arrays for the smart contract functions are "not assignable" to the AbiInput and AbiOutput types, the TypeScript compiler throws additional "not assignable" errors with the enclosing ContractEntryDefinition objects.

Unclear how to unlock when required.

When using recent versions of Metamask, it's not clear how Web3x can be used to retrieve the address of the default account.

Using window.ethereum.enable() shows the Metamask authorization popup - how is this taken care of by Web3x?

Question about licensing

Hi @xf00f,

I analyzed all the dependencies from package.json, and none of them is GPL. They are MIT, BSD, ISC and Apache2, all of them are permissive licenses.

I noticed that there's also some parts of ethers.js inlined here, but that's also MIT. I'm not sure if there are parts of this project copied from web3.js. If it's only the API, using another license should be fine.

I'm wondering what's the reason to license this project as GLPv3. IMO that would inhibit adoption, as it can't be used in proprietary software, nor in project that don't agree with GLP's copyleft or don't want to be in this same position (eg: me).

Package.json invalid main + types

In package.json there is part

  "main": "./index.js",
  "types": "./index.d.ts",

but these two files don't actually exist. Because package is now spliited into subpackages e.g. web3x/eth I guess those lines should be removed.

Is "create" a reserved word?

Not sure what exactly causes this. I managed to reproduce the bug with a simple contract. It seems that the arguments to the contract are important, as a function with no arguments does not reproduce the bug.

Very simple contract to reproduce:

pragma solidity ^0.5.0;

contract ReproduceBug {

    address test;

    constructor(address _test) public {
    }

    function create(uint256 tokenId, address itemOwner, bytes32[] memory keys, bytes32[] memory values) public returns (bool) {
        return true;
    }

}

Gets built to:

import BN from "bn.js";
import { Address } from "web3x/address";
import { EventLog, TransactionReceipt } from "web3x/formatters";
import { Contract, ContractOptions, TxCall, TxSend, TxDeploy, EventSubscriptionFactory } from "web3x/contract";
import { Eth } from "web3x/eth";
import abi from "./ReproduceBugAbi";
interface ReproduceBugEvents {
}
interface ReproduceBugEventLogs {
}
interface ReproduceBugTxEventLogs {
}
export interface ReproduceBugTransactionReceipt extends TransactionReceipt<ReproduceBugTxEventLogs> {
}
interface ReproduceBugMethods {
    create(tokenId: number | string | BN, itemOwner: Address, keys: string[], values: string[]): TxSend<ReproduceBugTransactionReceipt>;
}
export interface ReproduceBugDefinition {
    methods: ReproduceBugMethods;
    events: ReproduceBugEvents;
    eventLogs: ReproduceBugEventLogs;
}
export class ReproduceBug extends Contract<ReproduceBugDefinition> {
    constructor(eth: Eth, address?: Address, options?: ContractOptions) {
        super(eth, abi, address, options);
    }
    deploy(_test: Address): TxSend<ReproduceBugTransactionReceipt> {
        return super.deployBytecode("0x608060405234801561001057600080fd5b506040516020806102668339810180604052602081101561003057600080fd5b810190808051906020019092919050505050610215806100516000396000f3fe608060405234801561001057600080fd5b5060043610610048576000357c01000000000000000000000000000000000000000000000000000000009004806304d36f081461004d575b600080fd5b6101c16004803603608081101561006357600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001906401000000008111156100aa57600080fd5b8201836020820111156100bc57600080fd5b803590602001918460208302840111640100000000831117156100de57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561013e57600080fd5b82018360208201111561015057600080fd5b8035906020019184602083028401116401000000008311171561017257600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506101db565b604051808215151515815260200191505060405180910390f35b60006001905094935050505056fea165627a7a72305820ebaafbde68517ea43a3c7558394ababa863d10665bf22c9d05691dbb010a15cc0029", _test) as any;
    }
}
export var ReproduceBugAbi = abi;

And a simple test I am using to reproduce it. The full setup works and when I change the name of the "create" function to "createTest" or anything else, it works!

import { startLocalBlockchain } from "@cos/blockchain";
import { Address } from "web3x/address";
import { formatBytes32String } from "web3x/ethers/utf8";
import { ReproduceBug } from "../../src/contracts/cos/ReproduceBug";

test("reverts when function name is create", async () => {
  const { eth, blockchain } = await startLocalBlockchain({ hostname: "127.0.0.1", port: 8500, findNextPort: true });

  const from = Address.fromString(Object.keys(blockchain.unlocked_accounts)[0]);

  const buggedContract = new ReproduceBug(eth);
  await buggedContract
    .deploy(from)
    .send({ from, gas: 40000000 })
    .getReceipt();
  console.log("Test contract addr", buggedContract.address);
  const result = await buggedContract.methods
    .create("1", Address.ZERO, [formatBytes32String("hallo")], [formatBytes32String("yoyo")])
    .send({ from, gas: 40000000 })
    .getReceipt();
  console.log("Got test reuslt", result);
});

Using truffle v0.5.4 to build the contract and web3x v3.0.1. Did not have this issue on version 2.

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.