Schema, mock data and resolvers.

This commit is contained in:
Ashwin Phatak 2021-05-11 16:32:04 +05:30
parent 2b4e1ba315
commit 7133b3ab86
5 changed files with 176 additions and 58 deletions

View File

@ -19,6 +19,7 @@
"homepage": "https://github.com/vulcanize/erc20-watcher#readme",
"dependencies": {
"@types/lodash": "^4.14.168",
"apollo-type-bigint": "^0.1.3",
"express": "^4.17.1",
"express-graphql": "^0.12.0",
"graphql": "^15.5.0",

View File

@ -1,29 +1,100 @@
type Author {
id: Int!
firstName: String
lastName: String
"""
the list of Posts by this author
"""
posts: [Post]
#
# ERC20 GQL schema
#
# Types
# Support uint256 values.
scalar BigInt
# Proof for returned data. Serialized blob for now.
# Will be converted into a well defined structure later.
type Proof {
data: String!
}
type Post {
id: Int!
title: String
author: Author
votes: Int
# Result type, with proof, for uint256 method return values.
type ResultUInt256 {
value: BigInt!
# Proof from state/storage trie.
proof: Proof
}
# the schema allows the following query:
# ERC20 Token https://eips.ethereum.org/EIPS/eip-20
# ABI: https://ethereumdev.io/abi-for-erc20-contract-on-ethereum/
type Token {
name: String!
symbol: String!
decimals: Int!
totalSupply: BigInt!
}
# Transfer Event
# Emitted by: `function transfer(address _to, uint256 _value) public returns (bool success)`
# Emitted by: `function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)`
type TransferEvent {
from: String!
to: String!
value: BigInt!
}
# Approval Event
# Emittted by: `function approve(address _spender, uint256 _value) public returns (bool success)`
type ApprovalEvent {
owner: String!
spender: String!
value: BigInt!
}
# All possible event types fired by an ERC20 contract.
union TokenEvent = TransferEvent | ApprovalEvent
# Result type, with proof, for event return values.
type ResultEvent {
event: TokenEvent!
# Proof from receipts trie.
proof: Proof
}
#
# Queries
#
type Query {
posts: [Post]
author(id: Int!): Author
# `function balanceOf(address _owner) public view returns (uint256 balance)`
balanceOf(
blockHash: String!
token: String!
owner: String!
): ResultUInt256!
# `function allowance(address _owner, address _spender) public view returns (uint256 remaining)`
allowance(
blockHash: String!
token: String!
owner: String!
spender: String!
): ResultUInt256!
# Get token events at a certain block, optionally filter by event name.
events(
blockHash: String!
token: String!
name: String
): [ResultEvent!]
}
# this schema allows the following mutation:
type Mutation {
upvotePost (
postId: Int!
): Post
#
# Subscriptions
#
type Subscription {
# Watch for token events (at head of chain).
onTokenEvent(token: String!): ResultEvent!
}

View File

@ -1,36 +1,51 @@
import 'lodash';
import 'graphql-import-node';
import { find, filter } from 'lodash';
import { makeExecutableSchema } from '@graphql-tools/schema';
import BigInt from 'apollo-type-bigint';
import * as typeDefs from './erc20.graphql';
import data from './mock-data';
const { posts, authors } = data;
import { blocks } from './mock-data';
const resolvers = {
Query: {
posts: () => posts,
author: (_, { id }) => find(authors, { id }),
},
BigInt: new BigInt('bigInt'),
Mutation: {
upvotePost: (_, { postId }) => {
const post = find(posts, { id: postId });
if (!post) {
throw new Error(`Couldn't find post with id ${postId}`);
TokenEvent: {
__resolveType: (obj) => {
if (obj.owner) {
return 'ApprovalEvent';
}
return 'TransferEvent';
}
},
Query: {
balanceOf: (_, { blockHash, token, owner }) => {
console.log('balanceOf', blockHash, token, owner);
return {
value: blocks[blockHash][token].balanceOf[owner],
proof: { data: '' }
}
post.votes += 1;
return post;
},
},
Author: {
posts: author => filter(posts, { authorId: author.id }),
},
allowance: (_, { blockHash, token, owner, spender }) => {
console.log('allowance', blockHash, token, owner, spender);
Post: {
author: post => find(authors, { id: post.authorId }),
},
return {
value: blocks[blockHash][token].allowance[owner][spender],
proof: { data: '' }
}
},
events: (_, { blockHash, token, name }) => {
console.log('events', blockHash, token, name);
return blocks[blockHash][token].events
.filter(e => !name || name === e.name)
.map(e => ({ 'event': e }));
}
}
};
export const schema = makeExecutableSchema({

View File

@ -1,17 +1,43 @@
const authors = [
{ id: 1, firstName: 'Tom', lastName: 'Coleman' },
{ id: 2, firstName: 'Sashko', lastName: 'Stubailo' },
{ id: 3, firstName: 'Mikhail', lastName: 'Novikov' },
];
// TODO: Pull mock data for 5 tokens from rinkeby.
const posts = [
{ id: 1, authorId: 1, title: 'Introduction to GraphQL', votes: 2 },
{ id: 2, authorId: 2, title: 'Welcome to Meteor', votes: 3 },
{ id: 3, authorId: 2, title: 'Advanced GraphQL', votes: 1 },
{ id: 4, authorId: 3, title: 'Launchpad is Cool', votes: 7 },
];
export default {
posts,
authors
export const tokens = {
'0xd87fea54f506972e3267239ec8e159548892074a': {
name: 'ChainLink Token',
symbol: 'LINK',
decimals: 18,
totalSupply: '1000000'
}
};
export const blocks = {
// Block hash.
'0x77b5479a5856dd8ec63df6aabf9ce0913071a6dda3a3d54f3c9c940574bcb8ab': {
// ERC20 token address.
'0xd87fea54f506972e3267239ec8e159548892074a': {
balanceOf: {
'0xDC7d7A8920C8Eecc098da5B7522a5F31509b5Bfc': 10000,
'0xCA6D29232D1435D8198E3E5302495417dD073d61': 500
},
allowance: {
'0xDC7d7A8920C8Eecc098da5B7522a5F31509b5Bfc': {
'0xCA6D29232D1435D8198E3E5302495417dD073d61': 100
}
},
events: [
{
name: 'Transfer',
from: '0xDC7d7A8920C8Eecc098da5B7522a5F31509b5Bfc',
to: '0xCA6D29232D1435D8198E3E5302495417dD073d61',
value: 500
},
{
name: 'Approval',
owner: '0xDC7d7A8920C8Eecc098da5B7522a5F31509b5Bfc',
spender: '0xCA6D29232D1435D8198E3E5302495417dD073d61',
value: 100
}
]
}
}
};

View File

@ -943,6 +943,11 @@ anymatch@~3.1.1:
normalize-path "^3.0.0"
picomatch "^2.0.4"
apollo-type-bigint@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/apollo-type-bigint/-/apollo-type-bigint-0.1.3.tgz#9242115ca909b9467ba5c4bc6493a56a06984c0b"
integrity sha512-nyfwEWRZ+kon3Nnot20DufGm2EHZrkJoryYzw3soD+USdxhkcW434w1c/n+mjMLQDl86Z6EvlkvMX5Lordf2Wg==
apollo-upload-client@14.1.3:
version "14.1.3"
resolved "https://registry.yarnpkg.com/apollo-upload-client/-/apollo-upload-client-14.1.3.tgz#91f39011897bd08e99c0de0164e77ad2f3402247"