Skip to content

Commit 2ed3755

Browse files
committed
Initial commit
0 parents  commit 2ed3755

13 files changed

+5747
-0
lines changed

.gitignore

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# mono
2+
*.log
3+
etc/openvpn
4+
pkg
5+
src/dash/protobufs/*.proto
6+
src/reports/**/report.html
7+
src/reports/**/report.pdf
8+
src/vendor
9+
usr/local
10+
tmp
11+
.vimlocal
12+
13+
# macOS
14+
.DS_Store
15+
16+
# Python
17+
.ipynb_checkpoints
18+
*.ipynb
19+
__pycache__/
20+
*.py[cod]
21+
*$py.class
22+
.python-version
23+
.venv/
24+
25+
# Java
26+
*.jar
27+
28+
# Go
29+
bin/golint
30+
bin/protoc-gen-go
31+
bazel-*
32+
33+
# JavaScript
34+
node_modules

LICENSE

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright 2018 Distributed Systems, Inc.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.

README.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# eth-explorer
2+
3+
Explore the Ethereum blockchain using a rich GraphQL API.
4+
5+
## Usage
6+
7+
[Demo](https://multi-api-jisphshaoi.now.sh/)
8+
9+
```sh
10+
git clone [email protected]:dsys/eth-explorer.git
11+
cd eth-explorer
12+
yarn install
13+
yarn start # listening on localhost:4000
14+
```
15+
16+
## Development
17+
18+
```sh
19+
yarn dev
20+
```
21+
22+
## License
23+
24+
Apache 2.0

package.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "eth-explorer",
3+
"license": "Apache-2.0",
4+
"author": "Alex Kern <[email protected]>",
5+
"scripts": {
6+
"start": "nodemon -e js,graphql -x node -r dotenv/config src/index.js",
7+
"debug": "nodemon -e js,graphql -x node --inspect -r dotenv/config src/index.js",
8+
"playground": "graphql playground",
9+
"dev": "npm-run-all --parallel start playground"
10+
},
11+
"dependencies": {
12+
"graphql-yoga": "1.14.6",
13+
"web3": "^1.0.0-beta.34"
14+
},
15+
"devDependencies": {
16+
"dotenv": "5.0.1",
17+
"graphql-cli": "2.16.0",
18+
"nodemon": "1.17.5",
19+
"npm-run-all": "4.1.3"
20+
}
21+
}

src/index.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const { GraphQLServer } = require('graphql-yoga');
2+
const resolvers = require('./resolvers');
3+
4+
const server = new GraphQLServer({
5+
typeDefs: './src/schema.graphql',
6+
resolvers,
7+
context: req => ({ ...req })
8+
});
9+
10+
server.start(info =>
11+
// eslint-disable-next-line no-console
12+
console.log(
13+
`Server is running on http://localhost:${info.port}`
14+
)
15+
);

src/resolvers/EthereumAddress.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const { web3 } = require('../web3');
2+
3+
const EthereumAddress = {
4+
balance: ({ network = 'MAINNET', hash }, args, ctx, info) => {
5+
return web3[network].eth.getBalance(hash);
6+
},
7+
transactionCount: async ({ network = 'MAINNET', hash }, args, ctx, info) => {
8+
return web3[network].eth.getTransactionCount(hash);
9+
}
10+
};
11+
12+
module.exports = { EthereumAddress };

src/resolvers/EthereumBlock.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const { getBlock, getTransaction } = require('../web3');
2+
3+
const EthereumBlock = {
4+
parent: (parent, args, ctx, info) => {
5+
return getBlock({ hash: parent.parentHash, network: parent.network });
6+
},
7+
transactions: (parent, args, ctx, info) => {
8+
return parent.transactions.map(hash =>
9+
getTransaction({ network: args.network, hash })
10+
);
11+
}
12+
};
13+
14+
module.exports = { EthereumBlock };

src/resolvers/EthereumTransaction.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const { getBlock } = require('../web3');
2+
3+
const EthereumTransaction = {
4+
from: (parent, args, ctx, info) => {
5+
return { network: parent.network, hash: parent.from };
6+
},
7+
to: (parent, args, ctx, info) => {
8+
return { network: parent.network, hash: parent.to };
9+
},
10+
block: (parent, args, ctx, info) => {
11+
return getBlock({ network: parent.network, hash: parent.blockHash });
12+
}
13+
};
14+
15+
module.exports = { EthereumTransaction };

src/resolvers/Query.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const { web3, getBlock, getTransaction } = require('../web3');
2+
3+
const Query = {
4+
ethereumGasPrice(parent, { network = 'MAINNET' }) {
5+
return web3[network].eth.getGasPrice();
6+
},
7+
8+
ethereumAddress(parent, { hash, network = 'MAINNET' }, ctx, info) {
9+
return { hash, network };
10+
},
11+
12+
ethereumBlock(parent, args, ctx, info) {
13+
return getBlock(args);
14+
},
15+
16+
ethereumTransaction(parent, args, ctx, info) {
17+
return getTransaction(args);
18+
}
19+
};
20+
21+
module.exports = { Query };

src/resolvers/index.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const { EthereumAddress } = require('./EthereumAddress');
2+
const { EthereumBlock } = require('./EthereumBlock');
3+
const { EthereumTransaction } = require('./EthereumTransaction');
4+
const { Query } = require('./Query');
5+
6+
module.exports = {
7+
Query,
8+
EthereumAddress,
9+
EthereumTransaction,
10+
EthereumBlock
11+
};

src/schema.graphql

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
enum ETHEREUM_NETWORK {
2+
MAINNET
3+
ROPSTEN
4+
KOVAN
5+
RINKEBY
6+
}
7+
8+
type Query {
9+
ethereumGasPrice(network: ETHEREUM_NETWORK): String!
10+
11+
ethereumBlock(hash: String, number: Int, network: ETHEREUM_NETWORK): EthereumBlock
12+
ethereumTransaction(hash: String!, network: ETHEREUM_NETWORK): EthereumTransaction
13+
ethereumAddress(hash: String!, network: ETHEREUM_NETWORK): EthereumAddress
14+
}
15+
16+
type EthereumAddress {
17+
network: ETHEREUM_NETWORK!
18+
hash: String!
19+
balance: String!
20+
transactionCount: Int!
21+
}
22+
23+
type EthereumTransaction {
24+
network: ETHEREUM_NETWORK!
25+
hash: String!
26+
nonce: Int!
27+
block: EthereumBlock
28+
transactionIndex: Int!
29+
from: EthereumAddress
30+
to: EthereumAddress
31+
value: String!
32+
gas: Int!
33+
gasPrice: String!
34+
input: String!
35+
}
36+
37+
type EthereumBlock {
38+
network: ETHEREUM_NETWORK!
39+
hash: String!
40+
number: Int!
41+
parent: EthereumBlock
42+
nonce: String!
43+
sha3Uncles: String!
44+
logsBloom: String!
45+
transactionsRoot: String!
46+
stateRoot: String!
47+
miner: EthereumAddress!
48+
difficulty: String!
49+
totalDifficulty: String!
50+
size: Int!
51+
extraData: String!
52+
gasLimit: Int!
53+
gasUsed: Int!
54+
timestamp: Int!
55+
transactions: [EthereumTransaction!]!
56+
uncles: [EthereumBlock!]!
57+
}

src/web3.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const Web3 = require('web3');
2+
3+
const ETHEREUM_NETWORKS = ['MAINNET', 'ROPSTEN', 'KOVAN', 'RINKEBY'];
4+
const web3Connections = [];
5+
for (const network of ETHEREUM_NETWORKS) {
6+
web3Connections[network] = new Web3(
7+
new Web3.providers.HttpProvider(
8+
`https://${network}.infura.io/${process.env.INFURA_API_KEY}`
9+
)
10+
);
11+
}
12+
13+
async function getBlock({ hash, number, network = 'MAINNET' }) {
14+
const block = await web3Connections[network].eth.getBlock(hash || number);
15+
if (!block) return null;
16+
block.network = network;
17+
return block;
18+
}
19+
20+
async function getTransaction({ hash, network = 'MAINNET' }) {
21+
const tx = await web3Connections[network].eth.getTransaction(hash);
22+
if (!tx) return null;
23+
tx.network = network;
24+
return tx;
25+
}
26+
27+
module.exports = { web3: web3Connections, getBlock, getTransaction };

0 commit comments

Comments
 (0)