The Graph是用于索引和查问区块链数据的去中心化协定。建设subgraphs用规范 GraphQL API 查问这些索引解决了去中心化数据遍历的苦楚。
海量的去中心化数据难以统计计算,现通过一个为区块链数据提供索引的主机服务解决了这个问题。 应用规范 GraphQL API 查问这些索引(“subgraphs”)。 将来,主机服务将演变为具备雷同性能的齐全去中心化的协定。 两者都由 Graph Node 的开源实现提供反对,它提供了一种用于查问以太坊和IPFS网络数据的公开通明的解决方案,任何人都能够基于其提供的凋谢API创立并公布索引数据,即subgraph。
本篇入门文档通过一个简略交易量统计例子,带你领略一番如传统数据库信息汇聚之旅(收集与抓取),当具备THe Graph常识储备后,咱们就开始吧。
次要钻研路线(一路私服到底)
- 智能合约被truffer cmd 公布到truffle/ganache 容器(私链)
- 合约adress&abis与thegraph节点(私node)
- markdemo1工程(the graph)监听,收集数据,解决数据,包装通用查问
- the graph输入查问接口到Dapp2(8000->3000)/query page(8001)
- Dapp2 调用合约交易触发the graph输入变动
辅助输入:
- the graph subgraphs官网浏览https://thegraph.com/explorer 集体subgraphs核心https://thegraph.com/explorer/dashboard
- truffle/ganache 对智能合约治理(部署、调试)
- Rimax 浏览器版对合约操作
- Dapp2对智能合约的操作
- Dapp1对智能合约的监听
- truffle/ganache 、ganache cl、the graph私节点 部署和应用
- 各种网络、本机环境、脚本替换踩过的坑(坑就是是为后来者节约工夫)
- 公布一个线上subgraph到https://thegraph.com/explorer
线上体验subgraph
在 https://thegraph.com/explorer 上有很多subgraph,让咱们来看看uniswap-v2
Github | https://github.com/Uniswap | 公布地址 |
---|---|---|
ID | QmWTrJJ9W8h3JE19FhCzzPYsJ2tgXZCdUqnbyuo64ToTBN | subgraph |
Queries (HTTP) | https://api.thegraph.com/subg... | 大量可体验数据查问 |
uniswap-v2
关上浏览器体验一下先
2输出查问性能、参数和条件【点击紫色按钮】—>到节点数据中心3里->4.查问出冀望后果;当让2这个通用API也能够通过编程形式来调用,传入不同参数,体验下GraphQL API 查问
{ pairs{id}} | { pairs(where:{id:"0x00004ee988665cdda9a1080d5792cecd16dc1220"}){id}} | { pairs(orderBy:id){id}} |
The graph 用subgraph跟踪智能合约
数据抓取/事件监控数据汇聚及查问
获取存储展现线上智能合约的subgraph简略例子markdemo1
1. 抓以后工夫到上次update工夫内的记录
2. 存交易大于2的记录
3. 取某客户所以交易记录的条数和汇总金额
4. 以上仅在设想中(实在the graph 就是踩好坑)
按 the graph 思路来
1) 零碎初始化把链上最近的区块拉下了,定时取最近区块
2)subgraph的监听事件(原理就是event监听统统拉下数据,所以1,2,3就无意义)是拉下所有数据
3)让咱们来看看我踩过的那些坑
- mac机器环境遗留问题brew upgrade 时文件找不到,长期解决找到一个同目录类似文件替换(始终睡不着觉,后找到计划见附录brew upgrade装置报错问题解决替换homebrew-bottles)代理端口8001和the graph 零碎端口抵触,改代理
- yarn,git的代理和镜像要不停切换来应答家喻户晓的网络现状
- docker 里the graph拜访里面truffle/ganache系统配置,脚本生成一个拜访不可达ip172.18.2.0,批改为本机IP 192.168.0.136(不能应用127.0.0.1补脑docker拜访localhost回到哪里?)
- sel 命令第二次替换合同号要用第一次的合同号:例子程序中有2合同,可能都会再批改一次
- truffle/ganache每次启动会生成不同的账号序列,所以不同工夫导入合同的owner不同的,不要记第一个账号,会坑死人(能够用合同的历史交易记录查看owner,见markdemo2)
4) 写subgraph 须要留神或曾经实现的脚手架 - id: ID! 要求每个实体都有一个非空的不反复主键ID
- dataSources数据源配置初始读取块跳过合同公布之前的那些块:startBlock: 6627917
公布subgraph例子markdemo1
先要部署容器公布一个智能合约(可参见Hardhat + VS code,本篇应用Ganache部署)
Step 1: Ganache and Required Parameters
$ ganache-cli -h 0.0.0.0
例如:ganache-cli -h 0.0.0.0 -v /db -b 6 -a 8 -e 1000 -d expect chair toe trade spider wedding say item scare fog shrimp garlic
关上存在库,设置主动挖矿工夫6,设置8个1000gas账号,导入现有私钥,(-d ,能够是里面,也可用-m产生)启动阐明(罕用-account –db –blockTime)
置信原文,了解更合乎你的口味,技术文档每个人了解的角度不一样关注的重点不一样,用心点也不一样
–db 关上(记得这个目录和文件要有读写权限,能力操作前面的账户导入什么的)
–account: 指定账户私钥和账户余额来创立初始测试账户。可屡次设置
请留神,私钥长度为64个字符,并且必须以0x前缀的十六进制字符串模式输出。余额能够输出为一个整数或0x前缀的十六进制值,指定该帐户中wei的数量。
应用--account时,不会为您创立HD钱包。
-u or --unlock: 指定 - unlock...屡次传递地址或帐户索引以解锁特定帐户。当与 -- secure一起应用时,--unlock将笼罩指定帐户的锁定状态。
$ ganache-cli --secure --unlock "0x1234..." --unlock "0xabcd..."
-b 或r –blockTime: 指定主动挖矿的blockTime,以秒为单位。默认值为0,示意不进行主动挖矿??一交易一块(ganache will instantly mine a new block for every transaction)。
- -a 或 –accounts: 指定启动时要创立的测试账户数量。
- -e 或 –defaultBalanceEther: 调配给每个测试账户的ether数量,默认值为100。
- -b 或r –blockTime: 指定主动挖矿的blockTime,以秒为单位。默认值为0,示意不进行主动挖矿。
- -d 或 –deterministic: 基于预约的助记词(mnemonic)生成固定的测试账户地址。
- -n 或 –secure: 默认锁定所有测试账户,有利于进行第三方交易签名。
- -m 或 –mnemonic: 用于生成测试账户地址的助记词。
- -p 或 –port: 设置监听端口,默认值为8545。
- -h 或 –hostname: 设置监听主机,默认值同NodeJS的server.listen()。
- -s 或 –seed: 设置生成助记词的种子。
- -g 或 –gasPrice: 设定Gas价格,默认值为20000000000。
- -l 或 –gasLimit: 设定Gas下限,默认值为90000。
- -f 或 –fork: 从一个运行中的以太坊节点客户端软件的指定区块分叉。输出值该当是该节点旳HTTP地址和端口,例如http://localhost:8545。 可选应用@标记来指定具体区块,例如:http://localhost:8545@1599200。
- -i 或 –networkId:指定网络id。默认值为以后工夫,或应用所分叉链的网络id。
- –db: 设置保留链数据的目录。如果该门路中曾经有链数据,ganache-cli将用它初始化链而不是从新创立。
- –debug:输入VM操作码,用于调试。
- –mem:输入ganache-cli内存应用统计信息,这将代替规范的输入信息。
- –noVMErrorsOnRPCResponse:不把失败的交易作为RCP谬误发送。开启这个标记使错误报告形式兼容其余的节点客户端,例如geth和Parity。
-a or --accounts: Specify the number of accounts to generate at startup.-e or --defaultBalanceEther: Amount of ether to assign each test account. Default is 100.-b or --blockTime: Specify blockTime in seconds for automatic mining. If you don't specify this flag, ganache will instantly mine a new block for every transaction. Using the --blockTime flag is discouraged unless you have tests which require a specific mining interval.-d or --deterministic: Generate deterministic addresses based on a pre-defined mnemonic.-n or --secure: Lock available accounts by default (good for third party transaction signing)-m or --mnemonic: Use a bip39 mnemonic phrase for generating a PRNG seed, which is in turn used for hierarchical deterministic (HD) account generation.-p or --port: Port number to listen on. Defaults to 8545.-h or --host or --hostname: Hostname to listen on. Defaults to 127.0.0.1 (defaults to 0.0.0.0 for Docker instances of ganache-cli).-s or --seed: Use arbitrary data to generate the HD wallet mnemonic to be used.-g or --gasPrice: The price of gas in wei (defaults to 20000000000)-l or --gasLimit: The block gas limit (defaults to 0x6691b7)--callGasLimit: Sets the transaction gas limit for eth_call and eth_estimateGas calls. Must be specified as a hex string. Defaults to "0x1fffffffffffff" (Number.MAX_SAFE_INTEGER)-k or --hardfork: Allows users to specify which hardfork should be used. Supported hardforks are byzantium, constantinople, petersburg, istanbul, and muirGlacier (default).-f or --fork: Fork from another currently running Ethereum client at a given block. Input should be the HTTP location and port of the other client, e.g. http://localhost:8545. You can optionally specify the block to fork from using an @ sign: http://localhost:8545@1599200.forkCacheSize: number - The maximum size, in bytes, of the in-memory cache for queries on a chain fork. Defaults to 1_073_741_824 bytes (1 gigabyte). You can set this to 0 to disable caching (not recommended), or to -1 for unlimited (will be limited by your node process).-i or --networkId: Specify the network id ganache-cli will use to identify itself (defaults to the current time or the network id of the forked blockchain if configured)--chainId: Specify the Chain ID ganache-cli will use for eth_chainId RPC and the CHAINID opcode. For legacy reasons, the default is currently 1337 for eth_chainId RPC and 1 for the CHAINID opcode. Setting this flag will align the chainId values. This will be fixed in the next major version of ganache-cli and ganache-core!--db: Specify a path to a directory to save the chain database. If a database already exists, ganache-cli will initialize that chain instead of creating a new one.--debug: Output VM opcodes for debugging--mem: Output ganache-cli memory usage statistics. This replaces normal output.-q or --quiet: Run ganache-cli without any logs.-v or --verbose: Log all requests and responses to stdout-? or --help: Display help information--version: Display the version of ganache-cli--account_keys_path or --acctKeys: Specifies a file to save accounts and private keys to, for testing.--noVMErrorsOnRPCResponse: Do not transmit transaction failures as RPC errors. Enable this flag for error reporting behaviour which is compatible with other clients such as geth and Parity.--allowUnlimitedContractSize: Allows unlimited contract sizes while debugging. By enabling this flag, the check within the EVM for contract size limit of 24KB (see EIP-170) is bypassed. Enabling this flag will cause ganache-cli to behave differently than production environments.--keepAliveTimeout: Sets the HTTP server's keepAliveTimeout in milliseconds. See the NodeJS HTTP docs for details. 5000 by default.-t or --time: Date (ISO 8601) that the first block should start. Use this feature, along with the evm_increaseTime method to test time-dependent code.
Step 2: Running a local Graph node
在~graph-node/docker目录下
$ docker-compose up;
或
#!/bin/bashdocker-compose down -v;if [ -d "data" ]then echo "Found old data for the graph node - deleting it"; # we need to sudo this to remove system locked files sudo rm -rf data/;fidocker-compose up;
graph-node_1 | Jun 24 01:34:13.558 WARN Trying again after net_version RPC call failed (attempt #18) with result Err(Transport error: Error(Connect, Os { code: 111, kind: ConnectionRefused, message: "Connection refused" })), provider: mainnet-rpc-0
graph-node_1 | Jun 24 01:34:14.517 ERRO Connection to provider failed. Not using this provider, error: deadline has elapsed, provider: mainnet-rpc-0
该报错会引起第三步(Step 3)报错:
Failed to deploy to Graph node http://127.0.0.1:8020/: Ethereum network not supported by registrar: mainnet.
解决:ConnectionRefused个别是对方服务器不能到达
找到docker/docker-compose.yml-e 的ethereum: ’mainnet:http://host.docker.internal:8545'
批改为本地:ethereum: 'mainnet:http://192.168.0.136:8545'
Step 3-0: 公布markdemo1合同
$ truffle compile$ truffle migrate
Migrations:0x83Ad4160F00259D6D329c09A1436386a706e3818
GravatarRegistr:0xE54bA45F29b4247D75e86fD7A83a1E44160610D2
$ sed -i -e 's/0x2E645469f354BB4F5c8a05B3b30A929361cf77eC/0x83Ad4160F00259D6D329c09A1436386a706e3818/g' subgraph.yaml
Step 3: Deploying to your local Graph Node
$ yarn create-local$ yarn build && yarn deploy-local
最初例子输入成果如下:(http://127.0.0.1:8000/subgraphs/name/moluoping/markg)
Step 4: Dapp 调用
$ git clone https://github.com/graphprotocol/ethdenver-dapp/$ echo 'REACT_APP_GRAPHQL_ENDPOINT=http://localhost:8000/subgraphs/name/moluoping/markdemo1' > .env$ yarn && yarn start
监听智能合约交易事件subgraph例子markdemo2
上一章节简略阐明了一个子graph公布过程,上面将在Dapp工程中增加上面代码,演示整个智能合约事件监听过程
var Web3 = require("web3")var web3;if (typeof web3 !== 'undefined') { web3 = new Web3(web3.currentProvider);} else { web3 = new Web3(new Web3.providers.WebsocketProvider("ws://127.0.0.1:8545"));}web3.eth.defaultAccount = '0x4386997160134D4a67FD6A14DE7f924315D6F0A4';console.log('defaultAccount:' + web3.eth.defaultAccount)var contractAbi = [{"constant":false,"inputs":[{"name":"_imageUrl","type":"string"}],"name":"updateGravatarImage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"setMythicalGravatar","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"getGravatar","outputs":[{"name":"","type":"string"},{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"gravatarToOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"ownerToGravatar","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_displayName","type":"string"}],"name":"updateGravatarName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_displayName","type":"string"},{"name":"_imageUrl","type":"string"}],"name":"createGravatar","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"gravatars","outputs":[{"name":"owner","type":"address"},{"name":"displayName","type":"string"},{"name":"imageUrl","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"displayName","type":"string"},{"indexed":false,"name":"imageUrl","type":"string"}],"name":"NewGravatar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"displayName","type":"string"},{"indexed":false,"name":"imageUrl","type":"string"}],"name":"UpdatedGravatar","type":"event"}]//Abi data from// truffle/ganache:markdemo1/abis/Gravity.json// Remix:web https://remix.ethereum.org/ tab 'SOLIDITY COMPILER'->bottom 'abi'var contractAbiTruffle=contractAbivar contractAbiRemix=contractAbivar contractaAddressRemix ='0x4ef9BEb56eB0Ab92CDeD01Eff9A60554aE594d45'// Remix:web https://remix.ethereum.org/ tab 'DEPLOY & RUN TRANSACTIONS'->bottom 'Deployed Contracts' listvar contractaAddressTruffle ='0x38FcB3d9c3C8958373D61B702049D695A6725AFE'//$ truffle migrate{ var MyContract = new web3.eth.Contract(contractAbiRemix, contractaAddressRemix); MyContract.methods.updateGravatarName('aaaa').send({from: "0x4386997160134D4a67FD6A14DE7f924315D6F0A4"}) .then(console.log); //from data: this app project http://localhost:3000/F12 history event data returnValues->"owner" MyContract.methods.getGravatar('0x38FcB3d9c3C8958373D61B702049D695A6725AFE').call() .then(console.log);}// {// var MyContract = new web3.eth.Contract(contractAbiTruffle, contractaAddressTruffle);// MyContract.methods.updateGravatarName('bbbb').send({from: '0xC187EB4620dCEF0FFe5C45566969BdF2be3Ea7B7'})// .then(console.log);// //from data: this app project http://localhost:3000/F12 history event data returnValues->"owner"// MyContract.methods.getGravatar('0x38FcB3d9c3C8958373D61B702049D695A6725AFE').call()// .then(console.log);// }var myEventNew = MyContract.events.NewGravatar({ filter:{}, fromBlock: 0}, function(error, event){}) .on('data', function(event){ console.log('NewGravatar'); console.log(event); // same results as the optional callback above }) .on('changed', function(event){ // remove event from local database }) .on('error', console.error);var myEventUpdate = MyContract.events.UpdatedGravatar({ filter:{}, fromBlock: 0}, function(error, event){}) .on('data', function(event){ console.log('UpdatedGravatar'); console.log(event); // same results as the optional callback above }) .on('changed', function(event){ // remove event from local database }) .on('error', console.error);
- 上个例子中truffle/ganache环境中在$truffle migrate 可见智能合约地址,Abi数据能够在markdemo1工程markdemo1/abis/Gravity.json获取,然而初学者先用Remix体验。
- 看下面代码
而后就进去了,数据终于跑起来了.......
markdemo3(一个销量统计subgraph)
subgraph 在the graph市场上线
1. github网站注册账号
上github网站登录(无账号注册新账号)
2. 获取thegraph网站令牌
在 https://thegraph.com/explorer/dashboard/ 关联登录后,获取tocken
3. 创立subgraphgraph
graph init --from-example moluo..../markdemo3
graph init --from-contract <CONTRACT_ADDRESS> \ [--network <ETHEREUM_NETWORK>] \ [--abi <FILE>] \ <GITHUB_USER>/<SUBGRAPH_NAME> [<DIRECTORY>]
moluo.... github账号名/markdemo3 subgraph名字 创立工程并编译和产生相干资源
✔Subgraph name·moluo..../markdemo3
✔Directory to create the subgraph in·markdemo3
———
✔ Cloning example subgraph
✔ Update subgraph name and commands in package.json
✔ Initialize subgraph repository
✔ Install dependencies with yarn
✔ Generate ABI and schema types with yarn codegen
能够从以上脚本运行看编译过程
4. 公布到线上
a. 用令牌登thegraph开发核心
$ graph auth https://api.thegraph.com/deploy/880d70986bfc4172902641d870d96f37
graph auth https://api.thegraph.com/deploy/ <access-token>
<access-token>为第2步的获取tocken 留神tocken与后面有个空格,这是两个参数
#如果报The original error was: Cannot find module 'keytar'$ npm i -g keytar
b. 创立subgraph名字
https://thegraph.com/explorer/dashboard/
subgraph首字母大写,其余随便。
c. 将你的subgraph公布到thegraph.com
$ cd markdemo3$ yarn deploy
如果没有做b步骤,将报错
You may need to create subgraph at https://thegraph.com/explorer...
error Command failed with exit code 1.
c.如果一起顺利,你能够看到:https://api.thegraph.com/subgraphs/name/moluoping/markdemo3
例子解析(聚焦subgraph的markdemo4)
该例子间接从容器中合同向导生成subgraph工程:
$ graph init --from-contract 0x1e1215caD01aD7192832e0DACfA930Caf0132b43 --network mainnet --abi markdemo4.json moluoping/markdemo4
智能合约是从Remix中部署的,在Remix页面的编译页面能够copy到contract adress,部署页面能够copy到abi并保留成文件,graph init会生成性能必要的脚手架文件,并把合同的第一个事件监听函数作为查问实体主动代码生成(其余智能合约函数被正文)
这个工程就简洁很多,因为没有智能合约及智能合约部署相干文件,上面简略介绍下:
1) subgraph.yaml 本例address,abi来源于命令行依据将来设置,startBlock定义监控链上开始区块
source:
address: '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95'
abi: Contract
startBlock: 88888
2) schema.graphql定义可查问的实体
当初如同都是可被GraphGl查问的实体,不可查问的实体如同还没凋谢
ID必须string字段
GraphGl是图数据库规范,所以多看看多对多关系。
3) mapping.ts 事件处理实现
配置在subgraph.yaml
eventHandlers:
- event: Transfer(indexed address,indexed address,uint256)
handler: handleTransfer - event: Burn(indexed address,uint256)
handler: handleBurn
file: ./src/mapping.ts
event 变量蕴含了合约相干(事件,合约函数)
ExampleEntity "../generated/schema" 蕴含对the subgraph本地长久化相干
4) generated里向导产生的class
本地读写类schema.ts
智能合约函数类Contract.ts
5) 其余
package.json蕴含了subgraph从编译到本地部署、the graph部署的命令行
其余文件都是copy生成的
THe Graph基础知识
- theGraph社区
1) 官网
https://www.thegraph.com/
https://thegraph.com/docs/define-a-subgraph
2) 社区入门:以太坊数据索引平台The Graph应用教程 https://developer.aliyun.com/article/776668 - 常识体系
1) 深刻理解The Graph(上
https://zhuanlan.zhihu.com/p/196773044
2) 深刻理解The Graph(下
https://thegraph.com/blog/the-graph-network-in-depth-part-2
3) 以太坊开发(一)——Truffle和Ganache
https://blog.csdn.net/TurkeyCock/article/details/79165602
4) 以太坊测试网络Rinkeby应用教程(没钱买币但又想玩以太坊怎么办?用以太坊测试网络吧~~~~)
https://blog.csdn.net/wuhuimin521/article/details/85135610 - 利用
1) 应用 TheGraph 欠缺Web3 事件数据检索
https://learnblockchain.cn/article/1589
原文链接:https://soliditydeveloper.com/thegraph
作者:MarkusWaas
2) 以太坊truffle+ganache合约部署调试及web3.js事件监听过程记录
https://www.e-learn.cn/topic/3716459
原文链接:https://my.oschina.net/u/4277087/blog/4325668
不羁岁月 提交于 2020-08-06 04:50:03
3) 全副教程web3.js 1.0中文手册
http://cw.hubwiz.com/card/c/web3.js-1.0/1/4/8/
https://github.com/bluketalk/sweb3
欢送区块链行业气味相投的小伙伴增加小极微信,退出blockgeek区块链技术交换群,独特推动区块链技术遍及和倒退~