npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

apollo-link-ethereum-resolver-ethersjs

v0.1.8

Published

Ethers.js bindings for [apollo-link-ethereum](../../../..).

Downloads

20

Readme

apollo-link-ethereum-resolver-ethersjs

Ethers.js bindings for apollo-link-ethereum.

Setup

Install required packages:

$ yarn add apollo-link-ethereum apollo-link-ethereum-resolver-ethersjs

Setup a new Apollo Client:

import { ApolloClient } from 'apollo-client'
import { ApolloLink } from 'apollo-link'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { withClientState } from 'apollo-link-state'
import { EthereumLink } from 'apollo-link-ethereum'
import { EthersResolver } from 'apollo-link-ethereum-resolver-ethersjs'
import { AbiMapping } from 'apollo-link-ethereum'
import { ethers } from 'ethers'

import mkrAbi from './mkrAbi'

export const abiMapping = new AbiMapping()
abiMapping.addAbi('MKR', mkrAbi)
abiMapping.addAddress('MKR', 1, '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2')

const provider = new ethers.getDefaultProvider('homestead')

const ethersResolver = new EthersResolver({
  abiMapping,
  provider
})

const ethereumLink = new EthereumLink(ethersResolver)

const cache = new InMemoryCache()

const stateLink = withClientState({
  cache
})

export const apolloClient = new ApolloClient({
  cache,
  link: ApolloLink.from([stateLink, ethereumLink])
})

Now you can use Ethereum contracts deployed to a network as a data source.

Usage

GraphQL queries are supported by custom directives.

Query Directives

  • @contract: declares that the query and sub-queries are for an Ethereum contract.
  • @call: interprets the query as an eth_call (default for sub-queries of @contract)
  • @pastEvents: retrieves past events of a contract

Subscription Directives

  • @block: subscribes to new blocks
  • @contract: declares that the query and sub-queries are for an Ethereum contract.
  • @events: listens for new events from the containing @contract

Example using React

import React, { Component } from 'react'
import { Query } from 'react-apollo'
import { get } from 'lodash'

const GET_TOKEN_INFO = gql`
  query GetTokenInfo($tokenAddress: String!) {
    ERC20Token @contract(address: $tokenAddress) {
      totalSupply
      myBalance: balanceOf(address: "0xff536c5497c7b244c25ca6b31a5af1545d0c6184")
      allEvents @pastEvents(fromBlock: "0", toBlock: "latest")
    }
  }
`

export class App extends Component {
  render() {

    return (
      <Query
        query={GET_TOKEN_INFO}
        variables={ { address: "0xa95e94ac1d1e5c57413a281f0197140fbb6d4ccf" } }>

        {({ data }) => {
          return (
            <div className="App">
              <header className="App-header">
                <p>
                  Network Status: {get(data, 'status.isConnected', 'Unknown')}
                </p>
                <p>
                  Edit <code>src/App.js</code> and save to reload.
                </p>
                <p>
                  <i>{(get(data, 'ERC20Token.myBalance') || '').toString()}</i>
                  <br />
                  <i>{(get(data, 'ERC20Token.totalSupply') || '').toString()}</i>
                  <br />
                  <i>{(get(data, 'ERC20Token.allEvents') || []).length}</i>
                </p>
              </header>
            </div>
          )
        }}

      </Query>
    )
  }
}

Reference

EthersResolver

Provides Ethers.js bindings for EthereumLink. You'll need to create an instance of EthersResolver and pass it to the EthereumLink constructor.

new EthersResolver(options)

Creates a new EthersResolver.

| Option | Description | | --- | --- | | abiMapping | instance of AbiMapping | | provider | Ethers.js provider | defaultFromBlock | the block number to use as the default "fromBlock" for event queries if none is provided. | | defaultToBlock | the block number to use as the default "toBlock" for event queries if none is provided. |

Query Directives

@contract

Sets up the context of a query containing web3 calls. This can be used in either a query or a subscription. The field name to which the @contract directive is applied will be used as the contract name for ABI and address lookups. You will likely need to use the type and id arguments to @contract in order for Apollo Client to correctly cache the results.

For example:

const GET_TOKEN_INFO = gql`
  query GetTokenInfo {
    myResult: ERC20Token @contract {
      totalSupply
    }
  }
}
`

Here we see the field ERC20Token has the @contract directive and is being aliased to myResult. ERC20Token will be used as the contract name.

@contract Arguments

  • type: The name to use as the __typename for the results. This is important to Apollo Client so that it can distinguish objects in the cache. By default it will use the name of the contract, but if you wish to separate sets of calls you can do so with the type argument.
  • id: The id to set in the result. Since Ethereum calls do not generate a GraphQL compliant shape, we can set an id field to help Apollo Client out.
  • address: The address of the contract. Normally this is determined by looking up the address using the AbiMapping. Otherwise you can override it here.

If you would like to override the address:

const GET_TOKEN_INFO = gql`
  query GetTokenInfo($tokenAddress: String!) {
    ERC20Token @contract(address: $tokenAddress) {
      totalSupply
    }
  }
}
`

The above example will lookup the ABI using the name 'ERC20Token', and set the contract address to be the parameter $tokenAddress.

@call

By default, fields within a @contract query that don't have any custom directives will be treated as a @call. A call is just a standard Ethereum contract call. You can pass parameters to the field, and pass options to the call using the @call directive.

For example:

const GET_TOKEN_INFO = gql`
  query GetTokenInfo {
    ERC20Token @contract {
      totalSupply
    }
  }
}
`

The field totalSupply will default to a @call directive. The directive will call the totalSupply function on the ERC20Token contract as defined in the AbiMapping.

@call Arguments

  • all arguments to the field will be reduced to a flat array and passed to Ethereum.
  • all arguments to the directive will be passed as options to Ethers, allowing you to override gas price, limit etc.

Argument example:

const GET_TOKEN_INFO = gql`
  query GetTokenInfo {
    ERC20Token @contract {
      balanceOf(address: '0x1c127465b8ba9cab06b014551ff5c809cadb59bd') @call(gasLimit: 500000)
    }
  }
}
`

Will call ERC20Token#balanceOf("0x1c127465b8ba9cab06b014551ff5c809cadb59bd") with a gas limit of 500000. See Ethers.js for more details on what can be overridden.

@pastEvents

This directive will retrieve all past events for the contract. It will use the name of the field as the filter so you can target specific events. If the name of the field is 'allEvents' then all of the events will be retrieved.

For example:

const GET_TOKEN_INFO = gql`
  query GetTokenInfo($address: String!) {
    ERC20Token @contract {
      allEvents @pastEvents(extraTopics: { types: ["uint256", "address", "address"], values: [null, null, $address] })
    }
  }
`

The above query will retrieve all past logs with the 3rd indexed Event parameter as the provided $address variable, for the ERC20Token contract defined in the AbiMapping. Because the field name is allEvents, topic0 will be a wildcard. The remaining topics will be interpreted as 'extra topics'.

You may also wish to look for specific events:

const GET_TOKEN_INFO = gql`
  query GetTokenInfo($address: String!) {
    ERC20Token @contract {
      Transfer(fromAddress: $address) @pastEvents(fromBlock: "430000", toBlock: "450000")
    }
  }
`

The above query will retrieve all Transfer events whose first argument matches $address between blocks 430000 and 450000. Note here that field arguments will be reduced to a flat array, so the fromAddress in this case is unused.

@pastEvents Arguments

If the field name is allEvents, then topic0 will be the wildcard topic. Otherwise, the ABI will be used to determine topic0.

  • field arguments are reduced to a flat array and encoded as additional topics (not applicable for field name allEvents)
  • directive arguments:
    • address: override the contract address
    • fromBlock: the starting block number for the search
    • toBlock: the last block number for the search
    • extraTopics: extra topics to be concatentated onto the base topics. It's an object with two fields types and values:
      • types: an array of the solidity data types of the fields
      • values: an array of the values to encode

Subscription Directives

@contract

Same as @contract above.

@events

Same interface as @pastEvents, but used to listen to new events.

For example:

const transferSubscription = gql`
  subscription transferSubscription {
    ERC20Token @contract {
      Transfer @events
    }
  }
`

Will listen for all Transfer events from the ERC20Token contract.