├── README.md ├── cases └── README.md ├── cluster-demo ├── README.md ├── main.js ├── master.js ├── package.json ├── snapshot.png └── worker.js ├── config.ini中的signature-provider └── README.md ├── dfuse ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── Dfuse.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ └── serviceWorker.js └── yarn.lock ├── eosio.cdt ├── README.md └── contracttest │ ├── CMakeLists.txt │ ├── build │ └── deploy.sh │ ├── include │ └── contracttest │ │ └── contracttest.hpp │ └── src │ └── contracttest.cpp ├── eosio.token ├── README.md ├── eosio.token.cpp └── eosio.token.hpp ├── eosio.token的transfer的memo长度 └── README.md ├── eosio的history插件自定义过滤 └── README.md ├── eosio的mongo插件的使用 └── README.md ├── eosio的快照功能 └── README.md ├── eosio获取账号actions └── README.md ├── eosio计算ram价格 └── README.md ├── eosio通过插件存储账号余额到mongo └── README.md ├── eos合约action命名 └── README.md ├── lnmp └── lnmp迁移.md ├── mongodb简单使用 └── README.md ├── react-intl ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── Intl │ ├── Intl.js │ └── Intlapi.js │ ├── index.css │ ├── index.js │ ├── locale │ ├── en_US.js │ └── zh_CN.js │ ├── logo.svg │ └── serviceWorker.js ├── scatter交易missing-required-accounts └── README.md ├── transaction-declares-authority错误 └── README.md ├── 节点rpc无法访问 └── README.md └── 获取eosio表的所有scope的表数据 └── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Developer 2 | - [cases](./cases/) 3 | - [dfuse](./dfuse/) 4 | - [react-intl](./react-intl/) 5 | - [eosio.cdt](./eosio.cdt) 6 | - [lnmp迁移](./lnmp/lnmp迁移.md) 7 | - [eosio.token](./eosio.token) 8 | - [eosio的mongo插件的使用](./eosio的mongo插件的使用/) 9 | - [eosio的快照功能](./eosio的快照功能/) 10 | - [获取eosio表的所有scope的表数据](./获取eosio表的所有scope的表数据/) 11 | - [eosio的history插件自定义过滤](./eosio的history插件自定义过滤/) 12 | - [mongodb简单使用](./mongodb简单使用/) 13 | - [eosio通过插件存储账号余额到mongo](./eosio通过插件存储账号余额到mongo/) 14 | - [cluster-demo](./cluster-demo/) 15 | - [eosio获取账号actions](./eosio获取账号actions/) 16 | - [eosio计算ram价格](./eosio计算ram价格/) 17 | - [config.ini中的signature-provider](./config.ini中的signature-provider/) 18 | - [eos合约action命名](./eos合约action命名/) 19 | - [节点rpc无法访问](./节点rpc无法访问/) 20 | - [transaction declares authority错误](./transaction-declares-authority错误/) 21 | - [eosio.token的transfer的memo长度](./eosio.token的transfer的memo长度/) 22 | - [scatter交易missing required accounts](./scatter交易missing-required-accounts/) -------------------------------------------------------------------------------- /cases/README.md: -------------------------------------------------------------------------------- 1 | - [Mac下iTerm2让SSH记录远程服务器账号和密码](https://blog.csdn.net/shaobo8910/article/details/75514849) 2 | - [iTerm2保持连接](https://www.v2ex.com/t/155773) -------------------------------------------------------------------------------- /cluster-demo/README.md: -------------------------------------------------------------------------------- 1 | ## cluster 2 | node.js内置的实现并发的模块,该demo模拟并发处理。 3 | 4 | ### 运行 5 | `$: node main.js` 6 | 7 | ### 结果截图 8 | ![snapshot](./snapshot.png) 9 | 10 | ### 参考 11 | - [https://www.ibm.com/developerworks/cn/opensource/os-cn-nodejs-practice/index.html](https://www.ibm.com/developerworks/cn/opensource/os-cn-nodejs-practice/index.html) 12 | -------------------------------------------------------------------------------- /cluster-demo/main.js: -------------------------------------------------------------------------------- 1 | var exuteFibo = require('./master'); 2 | console.log('=====Start========'); 3 | var st = Date.now(); 4 | exuteFibo().then(result => { 5 | console.log(`Finish all work and using ${Date.now() - st} ms`); 6 | console.log('####Get result from multiple-processes: '+ result); 7 | }); 8 | 9 | // st = Date.now(); 10 | // exuteFibo().then(function(result){ 11 | // console.log(`Finish all work and using ${Date.now() - st} ms`); 12 | // console.log('####Get result1 from mutliple-processes: '+ result); 13 | // }); 14 | -------------------------------------------------------------------------------- /cluster-demo/master.js: -------------------------------------------------------------------------------- 1 | function exuteFibo() { 2 | return (new Promise( 3 | (reslove, reject) => { 4 | let result = []; 5 | let workerID = []; 6 | let cluster = require('cluster'); 7 | let numCPUs = require('os').cpus().length; 8 | 9 | cluster.setupMaster({ 10 | exec: 'worker.js', 11 | slient: true, 12 | }); 13 | 14 | cluster.on('fork', (worker) => { 15 | if (workerID.indexOf(worker.id) !== -1) { 16 | console.log(`[master ${process.pid}] : fork worker ${worker.id}`); 17 | } 18 | }); 19 | cluster.on('exit', (worker, code, signal) => { 20 | console.log(`[master] : worker ${worker.id} died`); 21 | }); 22 | 23 | let st = Date.now(); 24 | let numOfCompelete = 0; 25 | let collection = [44, 42, 42, 43]; 26 | 27 | for (let i = 0; i < Math.min(numCPUs, collection.length); i++) { 28 | wk = cluster.fork(); 29 | workerID.push(wk.id); 30 | wk.send(collection[i]); 31 | } 32 | 33 | workerID.forEach((id) => { 34 | cluster.workers[id].on('message', (msg) => { 35 | console.log(`[master] receive message from [worker${id}]: ${msg}`); 36 | result.push(msg); 37 | 38 | numOfCompelete++; 39 | if (numOfCompelete === collection.length) { 40 | console.log(`[master] finish all work and using ${Date.now() - st} ms`); 41 | workerID.forEach((id) => { 42 | if (!cluster.workers[id].suicide) { 43 | cluster.workers[id].disconnect(); 44 | } 45 | }); 46 | reslove(result); 47 | } 48 | }); 49 | }); 50 | } 51 | )); 52 | } 53 | 54 | module.exports = exuteFibo; 55 | -------------------------------------------------------------------------------- /cluster-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cluster-demo", 3 | "version": "1.0.0", 4 | "description": "cluster", 5 | "main": "main.js", 6 | "scripts": { 7 | "test": "node main.js" 8 | }, 9 | "keywords": [ 10 | "cluster" 11 | ], 12 | "author": "ly", 13 | "license": "ISC" 14 | } 15 | -------------------------------------------------------------------------------- /cluster-demo/snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayJay1024/Developer/b525d3364bc7fb0c0b351ba83c86e4cd1065f633/cluster-demo/snapshot.png -------------------------------------------------------------------------------- /cluster-demo/worker.js: -------------------------------------------------------------------------------- 1 | // 这里是master fork的worker 2 | cluster = require('cluster'); 3 | 4 | function fibo(n) { 5 | return n == 0 ? 0 : n > 1 ? fibo(n - 1) + fibo(n - 2) : 1; 6 | } 7 | 8 | console.log(`[worker ${cluster.worker.id}] start ...` ); 9 | 10 | process.on('message', (msg) => { 11 | let st = Date.now(); 12 | console.log(`[worker ${cluster.worker.id}] start to work`); 13 | let result = fibo(msg); 14 | console.log(`[worker ${cluster.worker.id}] worker finish work and using ${Date.now() - st} ms`); 15 | process.send(result); // master订阅了该worker得message,所以master将收到该result 16 | }); 17 | -------------------------------------------------------------------------------- /config.ini中的signature-provider/README.md: -------------------------------------------------------------------------------- 1 | ## 概述: 2 | 如果你要部署一个 EOSIO 的出块节点,你可能会关心这个问题。如果不是,或者你只是部署一个普通节点,那你不用care这里说的。 3 | 4 | ## `signature-provider`应该填哪对秘钥: 5 | 在节点的配置文件`config.ini`中,`signature-provider`应该填哪一对秘钥呢?可能你会和刚开始的我一样,觉得应该填的是出块账号对应的 owner 或 active 的 key ,但其实这是不建议的,因为涉及到安全问题。 6 | 其实你完全可以通过 `cleos create key --to-console` 出来一对`key` ,只要你注册出块节点的时候使用这个`key`,那么`signature-provider`你就可以使用这对`key`。 7 | 即,只要保证`signature-provider`用的是注册时的就行,至于注册你用哪个,你爱用哪个用哪个。 8 | -------------------------------------------------------------------------------- /dfuse/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /dfuse/README.md: -------------------------------------------------------------------------------- 1 | ### Dfuse是EOS Canada为EOS开发打造的流式API,可以让开发者更轻松流畅的获取链上信息。使用Websocket协议,可以主动推送数据至客户端。 2 | ### 官网: [https://dfuse.io/zh/](https://dfuse.io/zh/) 3 | ### 使用示例 4 | ``` 5 | // token字段后面的是key,目前属于beta版本,可以在官网免费申请 6 | this.ws_url = "wss://mainnet.eos.dfuse.io/v1/stream?token=eyJhbGciOiJLTVNFUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJiZXRhLXVzZXJzLmVvc3dzLmlvIiwiZXhwIjoxNTQyMDgyNjk5LCJqdGkiOiI5MGYxNGI2Yy0xMGZhLTQ3NzEtYTNlYS0xZDMxOWFkMzFiZWQiLCJpYXQiOjE1Mzk0OTA2OTksImlzcyI6ImVvc3dzLmlvIiwic3ViIjoiMTM3MDQyOTUyQHFxLmNvbSJ9.bbz_udBFm9eJ3PCbS1NNX4a3EPQhjo0vpqNPRmko7ZIu4BdnYc3OEWPKc8FqVt3bnNsswt13XtIrH0nCVjjkWg"; 7 | 8 | // 初始化WebSocket 9 | this.ws = new WebSocket(this.ws_url); 10 | 11 | // 设置客户端接收到服务端推送的回调 12 | this.ws.onopen = (evt) => { 13 | console.log("ws is opened"); 14 | } 15 | this.ws.onmessage = (evt) => { 16 | console.log("ws rev data: ", evt.data); 17 | } 18 | 19 | // 根据官网的发送格式,侦听eosbetdice11收到转账的action 20 | let _send_data = { 21 | "type": "get_actions", 22 | "listen": true, 23 | "req_id": "123", 24 | // "start_block": 22266908, 25 | // "fetch": true, 26 | "data": { 27 | "account": "eosio.token", 28 | "action_name": "transfer", 29 | "receiver": "eosbetdice11", 30 | } 31 | }; 32 | this.ws.send(JSON.stringify(_send_data)); 33 | ``` 34 | ### Demo 35 | ``` 36 | $ yarn install 37 | $ yarn start 38 | ``` 39 | -------------------------------------------------------------------------------- /dfuse/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dfuse-demo", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "react": "^16.5.2", 7 | "react-dom": "^16.5.2", 8 | "react-scripts": "2.0.5" 9 | }, 10 | "scripts": { 11 | "start": "react-scripts start", 12 | "build": "react-scripts build", 13 | "test": "react-scripts test", 14 | "eject": "react-scripts eject" 15 | }, 16 | "eslintConfig": { 17 | "extends": "react-app" 18 | }, 19 | "browserslist": [ 20 | ">0.2%", 21 | "not dead", 22 | "not ie <= 11", 23 | "not op_mini all" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /dfuse/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayJay1024/Developer/b525d3364bc7fb0c0b351ba83c86e4cd1065f633/dfuse/public/favicon.ico -------------------------------------------------------------------------------- /dfuse/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 22 | React App 23 | 24 | 25 | 28 |
29 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /dfuse/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /dfuse/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 40vmin; 8 | } 9 | 10 | .App-header { 11 | background-color: #282c34; 12 | min-height: 100vh; 13 | display: flex; 14 | flex-direction: column; 15 | align-items: center; 16 | justify-content: center; 17 | font-size: calc(10px + 2vmin); 18 | color: white; 19 | } 20 | 21 | .App-link { 22 | color: #61dafb; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { 27 | transform: rotate(0deg); 28 | } 29 | to { 30 | transform: rotate(360deg); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /dfuse/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | // import logo from './logo.svg'; 3 | // import './App.css'; 4 | 5 | import Dfuse from './Dfuse'; 6 | 7 | class App extends Component { 8 | render() { 9 | return ( 10 | //
11 | //
12 | // logo 13 | //

14 | // Edit src/App.js and save to reload. 15 | //

16 | // 22 | // Learn React 23 | // 24 | //
25 | //
26 |
27 | 28 |
29 | ); 30 | } 31 | } 32 | 33 | export default App; 34 | -------------------------------------------------------------------------------- /dfuse/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /dfuse/src/Dfuse.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class Dfuse extends Component { 4 | constructor(props) { 5 | super(props); 6 | 7 | this.state = { 8 | ws_state: null, 9 | } 10 | 11 | this.ws_url = "wss://mainnet.eos.dfuse.io/v1/stream?token=eyJhbGciOiJLTVNFUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJiZXRhLXVzZXJzLmVvc3dzLmlvIiwiZXhwIjoxNTQyMDgyNjk5LCJqdGkiOiI5MGYxNGI2Yy0xMGZhLTQ3NzEtYTNlYS0xZDMxOWFkMzFiZWQiLCJpYXQiOjE1Mzk0OTA2OTksImlzcyI6ImVvc3dzLmlvIiwic3ViIjoiMTM3MDQyOTUyQHFxLmNvbSJ9.bbz_udBFm9eJ3PCbS1NNX4a3EPQhjo0vpqNPRmko7ZIu4BdnYc3OEWPKc8FqVt3bnNsswt13XtIrH0nCVjjkWg"; 12 | 13 | this.restartWS = this.restartWS.bind(this); 14 | } 15 | 16 | componentDidMount = () => { 17 | this.restartWS(); 18 | 19 | setInterval(() => { 20 | switch (this.ws.readyState) { 21 | case WebSocket.CONNECTING: 22 | this.setState({ ws_state: "connecting" }); 23 | break; 24 | case WebSocket.OPEN: 25 | this.setState({ ws_state: "open" }); 26 | break; 27 | case WebSocket.CLOSING: 28 | this.setState({ ws_state: "closing" }); 29 | break; 30 | case WebSocket.CLOSED: 31 | this.setState({ ws_state: "cloed" }); 32 | break; 33 | default: 34 | // this never happens 35 | break; 36 | } 37 | }, 500); 38 | } 39 | 40 | closeWS = () => { 41 | console.log("close ws"); 42 | this.ws.close(); 43 | } 44 | 45 | sendWS = () => { 46 | console.log("send ws"); 47 | 48 | let _send_data = { 49 | "type": "get_actions", 50 | "listen": true, 51 | "req_id": "123", 52 | // "start_block": 22266908, 53 | // "fetch": true, 54 | "data": { 55 | "account": "eosio.token", 56 | "action_name": "transfer", 57 | "receiver": "eosbetdice11", 58 | } 59 | }; 60 | this.ws.send(JSON.stringify(_send_data)); 61 | } 62 | 63 | unlistenWS = () => { 64 | console.log("unlisten ws"); 65 | 66 | let _send_data = { 67 | "type": "unlisten", 68 | "data": { 69 | "req_id": "123" 70 | } 71 | }; 72 | this.ws.send(JSON.stringify(_send_data)); 73 | } 74 | 75 | restartWS = () => { 76 | console.log("restart ws"); 77 | this.ws = new WebSocket(this.ws_url); 78 | this.ws.onopen = (evt) => { 79 | console.log("ws is opened"); 80 | } 81 | this.ws.onmessage = (evt) => { 82 | console.log("ws rev data: ", evt.data); 83 | } 84 | } 85 | 86 | 87 | render() { 88 | return ( 89 |
90 |
This is dfuse demo
91 | 94 | 97 | 100 | 103 |
104 | ws.readyState: {this.state.ws_state} 105 |
106 |
107 | ); 108 | } 109 | } 110 | 111 | export default Dfuse; -------------------------------------------------------------------------------- /dfuse/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 5 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 6 | sans-serif; 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | } 10 | 11 | code { 12 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 13 | monospace; 14 | } 15 | -------------------------------------------------------------------------------- /dfuse/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: http://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /dfuse/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /dfuse/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read http://bit.ly/CRA-PWA. 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | installingWorker.onstatechange = () => { 64 | if (installingWorker.state === 'installed') { 65 | if (navigator.serviceWorker.controller) { 66 | // At this point, the updated precached content has been fetched, 67 | // but the previous service worker will still serve the older 68 | // content until all client tabs are closed. 69 | console.log( 70 | 'New content is available and will be used when all ' + 71 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.' 72 | ); 73 | 74 | // Execute callback 75 | if (config && config.onUpdate) { 76 | config.onUpdate(registration); 77 | } 78 | } else { 79 | // At this point, everything has been precached. 80 | // It's the perfect time to display a 81 | // "Content is cached for offline use." message. 82 | console.log('Content is cached for offline use.'); 83 | 84 | // Execute callback 85 | if (config && config.onSuccess) { 86 | config.onSuccess(registration); 87 | } 88 | } 89 | } 90 | }; 91 | }; 92 | }) 93 | .catch(error => { 94 | console.error('Error during service worker registration:', error); 95 | }); 96 | } 97 | 98 | function checkValidServiceWorker(swUrl, config) { 99 | // Check if the service worker can be found. If it can't reload the page. 100 | fetch(swUrl) 101 | .then(response => { 102 | // Ensure service worker exists, and that we really are getting a JS file. 103 | if ( 104 | response.status === 404 || 105 | response.headers.get('content-type').indexOf('javascript') === -1 106 | ) { 107 | // No service worker found. Probably a different app. Reload the page. 108 | navigator.serviceWorker.ready.then(registration => { 109 | registration.unregister().then(() => { 110 | window.location.reload(); 111 | }); 112 | }); 113 | } else { 114 | // Service worker found. Proceed as normal. 115 | registerValidSW(swUrl, config); 116 | } 117 | }) 118 | .catch(() => { 119 | console.log( 120 | 'No internet connection found. App is running in offline mode.' 121 | ); 122 | }); 123 | } 124 | 125 | export function unregister() { 126 | if ('serviceWorker' in navigator) { 127 | navigator.serviceWorker.ready.then(registration => { 128 | registration.unregister(); 129 | }); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /eosio.cdt/README.md: -------------------------------------------------------------------------------- 1 | ## eosio.cdt test 2 | ### 官方仓库: [https://github.com/EOSIO/eosio.cdt](https://github.com/EOSIO/eosio.cdt) 3 | - 在`Mac OS X`用`Brew`安装完之后,可以`brew link eosio.cdt`一下,这样就会在`/usr/local/bin/`下创建符号链接 4 | - 如果之前有`make install eosio`,`brew link`可能会提示需要删除一些`/usr/local/bin/`下已存在的文件,比如`/usr/local/bin/eosio-abigen`,按照提示使用`rm`删除即可 5 | ### 编译和部署 6 | ``` 7 | $ cd contracttest/build 8 | $ cmake .. 9 | $ make 10 | $ ./deploy.sh 11 | ``` -------------------------------------------------------------------------------- /eosio.cdt/contracttest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(contracttest VERSION 1.0.0) 3 | 4 | # 这句要加上,要不然下面 add_contract 将出错 5 | find_package(eosio.cdt) 6 | 7 | ### Only generate the wasm 8 | #add_executable( contracttest.wasm ${CMAKE_CURRENT_SOURCE_DIR}/src/contracttest.cpp ) 9 | 10 | ### Generate the wasm and abi 11 | add_contract(contracttest contracttest ${CMAKE_CURRENT_SOURCE_DIR}/src/contracttest.cpp) 12 | target_include_directories(contracttest.wasm 13 | PUBLIC 14 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 15 | 16 | set_target_properties(contracttest.wasm 17 | PROPERTIES 18 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -------------------------------------------------------------------------------- /eosio.cdt/contracttest/build/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cleos set contract contracttest ../build contracttest.wasm contracttest.abi -p contracttest 4 | -------------------------------------------------------------------------------- /eosio.cdt/contracttest/include/contracttest/contracttest.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | using namespace eosio; 6 | 7 | // class [[eosio::contract]] contracttest : public contract { // 这样也是可以的,[[eosio::contract]]只能放 class 和 contracttest 中间 8 | CONTRACT contracttest : public contract { 9 | public: 10 | // using contract::contract; // 或下一行 11 | contracttest( name s, name code, datastream ds ) : contract( s, code, ds ) {} // 或上一行 12 | 13 | ACTION sayhi( name user ); // 严格检查user合法性(不能超过12个字符,有下列字符组成: .12345abcdefghijklmnopqrstuvwxyz) 14 | // ACTION sayhi( capi_name user ); // 不会检查user是否合法 15 | 16 | // 这样也是可以的 17 | // [[eosio::action]] 18 | // void sayhi( name user ); 19 | }; 20 | -------------------------------------------------------------------------------- /eosio.cdt/contracttest/src/contracttest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace eosio; 4 | 5 | void contracttest::sayhi( name user ) { 6 | print( "Hello ", name{user} ); 7 | } 8 | 9 | // 原来的叫 EOSIO_API 10 | EOSIO_DISPATCH( contracttest, (sayhi) ) -------------------------------------------------------------------------------- /eosio.token/README.md: -------------------------------------------------------------------------------- 1 | ## eosio.token 2 | 由于系统的`eosio.token`合约相较于早期进行了更新,如新增了`retire`接口等,重新梳理一下(见代码注释) 3 | ## [仓库](https://github.com/EOSIO/eosio.contracts/tree/master/eosio.token) 4 | ## [v1.5.0](https://github.com/EOSIO/eosio.contracts/releases/tag/v1.5.0) -------------------------------------------------------------------------------- /eosio.token/eosio.token.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @copyright defined in eos/LICENSE.txt 4 | */ 5 | 6 | #include 7 | 8 | namespace eosio { 9 | 10 | // 给issue账号创建代币,代币符号和发型数量为maximum_supply 11 | void token::create( name issuer, 12 | asset maximum_supply ) 13 | { 14 | // 据此我们知道,如果创建合约的账号没有授予权限给别的账号,则只有它自己才可以创建新的代币 15 | require_auth( _self ); 16 | 17 | auto sym = maximum_supply.symbol; 18 | eosio_assert( sym.is_valid(), "invalid symbol name" ); 19 | eosio_assert( maximum_supply.is_valid(), "invalid supply"); 20 | eosio_assert( maximum_supply.amount > 0, "max-supply must be positive"); 21 | 22 | // 确认该合约下还没存在该代币 23 | stats statstable( _self, sym.code().raw() ); 24 | auto existing = statstable.find( sym.code().raw() ); 25 | eosio_assert( existing == statstable.end(), "token with symbol already exists" ); 26 | 27 | // 向合约的multi_index表添加代币信息 28 | statstable.emplace( _self, [&]( auto& s ) { 29 | s.supply.symbol = maximum_supply.symbol; // 代币符号,初始数量默认为0 30 | s.max_supply = maximum_supply; // 发行量和符号 31 | s.issuer = issuer; // 打币发行者 32 | }); 33 | } 34 | 35 | // 代币发行者给to账号发送代币,发送数量为quantity,附加备注信息为memo 36 | void token::issue( name to, asset quantity, string memo ) 37 | { 38 | auto sym = quantity.symbol; 39 | eosio_assert( sym.is_valid(), "invalid symbol name" ); 40 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); // 备注信息不能超过 256 bytes 41 | 42 | // 确认该合约下存在该代币 43 | stats statstable( _self, sym.code().raw() ); 44 | auto existing = statstable.find( sym.code().raw() ); 45 | eosio_assert( existing != statstable.end(), "token with symbol does not exist, create token before issue" ); 46 | const auto& st = *existing; 47 | 48 | require_auth( st.issuer ); // 该动作需要代币发行者的授权 49 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 50 | eosio_assert( quantity.amount > 0, "must issue positive quantity" ); 51 | 52 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 53 | eosio_assert( quantity.amount <= st.max_supply.amount - st.supply.amount, "quantity exceeds available supply"); // 不能超过剩余发行数量 54 | 55 | // 更新已发行的数量 56 | statstable.modify( st, same_payer, [&]( auto& s ) { 57 | s.supply += quantity; 58 | }); 59 | 60 | // 因为下面如果to != st.issuer的时候,执行的transfer里面会做sub_balance, 61 | // 所以这里需要增加发行者的accounts表的代币数量 62 | add_balance( st.issuer, quantity, st.issuer ); // 影响accounts表 63 | 64 | // 上面add_balance使发行者拥有了quantity数量的代币, 65 | // 如果to账号不是发行者,则发行者通过转账的方式,把刚才quantity数量的代币转给to 66 | if( to != st.issuer ) { 67 | SEND_INLINE_ACTION( *this, transfer, { {st.issuer, "active"_n} }, 68 | { st.issuer, to, quantity, memo } 69 | ); 70 | } 71 | } 72 | 73 | // 销毁代币,数量为quantity,附加备注信息为memo 74 | void token::retire( asset quantity, string memo ) 75 | { 76 | auto sym = quantity.symbol; 77 | eosio_assert( sym.is_valid(), "invalid symbol name" ); 78 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); 79 | 80 | // 确保该合约下存在该代币 81 | stats statstable( _self, sym.code().raw() ); 82 | auto existing = statstable.find( sym.code().raw() ); 83 | eosio_assert( existing != statstable.end(), "token with symbol does not exist" ); 84 | const auto& st = *existing; 85 | 86 | require_auth( st.issuer ); // 销毁操作需要得到发行者的授权 87 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 88 | eosio_assert( quantity.amount > 0, "must retire positive quantity" ); 89 | 90 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 91 | 92 | // 更新已发行(流通中)的数量 93 | statstable.modify( st, same_payer, [&]( auto& s ) { 94 | s.supply -= quantity; 95 | }); 96 | 97 | // 销毁数量为quantity,则从发行者手中减去这么多数量的代币 98 | sub_balance( st.issuer, quantity ); 99 | } 100 | 101 | // from给to转账,数量为quantity,转账备注为memo 102 | void token::transfer( name from, 103 | name to, 104 | asset quantity, 105 | string memo ) 106 | { 107 | eosio_assert( from != to, "cannot transfer to self" ); // 不能给自己转账 108 | require_auth( from ); // 需要得到from的授权 109 | eosio_assert( is_account( to ), "to account does not exist"); 110 | auto sym = quantity.symbol.code(); 111 | stats statstable( _self, sym.raw() ); 112 | const auto& st = statstable.get( sym.raw() ); // 如果合约的stat表中不存在该代币,执行get操作将回滚这次转账(transfer)操作 113 | 114 | // 把该转账操作通知给from和to 115 | require_recipient( from ); 116 | require_recipient( to ); 117 | 118 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 119 | eosio_assert( quantity.amount > 0, "must transfer positive quantity" ); 120 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 121 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); 122 | 123 | auto payer = has_auth( to ) ? to : from; 124 | 125 | sub_balance( from, quantity ); 126 | add_balance( to, quantity, payer ); // 如果to账号第一次获得该代币,add_balance中执行multi_index表插入的时候,payer将支付ram费用 127 | } 128 | 129 | // 从owner账号中,减去value数量的代币 130 | void token::sub_balance( name owner, asset value ) { 131 | accounts from_acnts( _self, owner.value ); 132 | 133 | const auto& from = from_acnts.get( value.symbol.code().raw(), "no balance object found" ); // 确保owner已经拥有该代币 134 | eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" ); // 确保余额充足 135 | 136 | // 更新owner的表数据 137 | from_acnts.modify( from, owner, [&]( auto& a ) { 138 | a.balance -= value; 139 | }); 140 | } 141 | 142 | // 给owner账号增加value数量的代币,如果owner第一次获得该代币,将由ram_payer支付ram费用 143 | void token::add_balance( name owner, asset value, name ram_payer ) 144 | { 145 | accounts to_acnts( _self, owner.value ); 146 | auto to = to_acnts.find( value.symbol.code().raw() ); 147 | if( to == to_acnts.end() ) { // 说明第一次获得该代币 148 | to_acnts.emplace( ram_payer, [&]( auto& a ){ // 向表中添加记录,并由ram_payer支付ram费用(记录需要保存到ram中) 149 | a.balance = value; 150 | }); 151 | } else { // 说明不是第一次获得该代币 152 | to_acnts.modify( to, same_payer, [&]( auto& a ) { // 这里的same_payer指的是上面emplace时的ram_payer,这里的数据占用ram大小没有改变,所以ram费用没有增加也没有减少 153 | a.balance += value; // 更新表中的数据 154 | }); 155 | } 156 | } 157 | 158 | // 如果owner已经拥有该代币的话,open将不会更改任何东西 159 | // 如果owner还未拥有该代币,ram_payer将帮助它支付ram费用,以在表中添加一条余额为0的代币记录 160 | void token::open( name owner, const symbol& symbol, name ram_payer ) 161 | { 162 | require_auth( ram_payer ); // 支付ram费用的账号需要授权 163 | 164 | auto sym_code_raw = symbol.code().raw(); 165 | 166 | stats statstable( _self, sym_code_raw ); 167 | const auto& st = statstable.get( sym_code_raw, "symbol does not exist" ); 168 | eosio_assert( st.supply.symbol == symbol, "symbol precision mismatch" ); 169 | 170 | accounts acnts( _self, owner.value ); 171 | auto it = acnts.find( sym_code_raw ); 172 | 173 | // 如果owner还未拥有该代币,则向表中添加一条记录,余额为0,由ram_payer来支付ram费用 174 | if( it == acnts.end() ) { 175 | acnts.emplace( ram_payer, [&]( auto& a ){ 176 | a.balance = asset{0, symbol}; 177 | }); 178 | } 179 | } 180 | 181 | // 如果owner的symbol代币余额为0,通过close可以释放该代币占用的ram 182 | void token::close( name owner, const symbol& symbol ) 183 | { 184 | require_auth( owner ); 185 | accounts acnts( _self, owner.value ); 186 | auto it = acnts.find( symbol.code().raw() ); 187 | eosio_assert( it != acnts.end(), "Balance row already deleted or never existed. Action won't have any effect." ); // 确保owner拥有该代币 188 | eosio_assert( it->balance.amount == 0, "Cannot close because the balance is not zero." ); // 确保owner的该币的余额为0 189 | acnts.erase( it ); // 删除表中的记录 190 | } 191 | 192 | } /// namespace eosio 193 | 194 | EOSIO_DISPATCH( eosio::token, (create)(issue)(transfer)(open)(close)(retire) ) 195 | -------------------------------------------------------------------------------- /eosio.token/eosio.token.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @copyright defined in eos/LICENSE.txt 4 | */ 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace eosiosystem { 13 | class system_contract; 14 | } 15 | 16 | namespace eosio { 17 | 18 | using std::string; 19 | 20 | // [[eosio::contract]]:新的生成ABI属性标注 21 | class [[eosio::contract("eosio.token")]] token : public contract { 22 | public: 23 | using contract::contract; 24 | 25 | // [[eosio::action]]:新的生成ABI属性标注 26 | [[eosio::action]] 27 | void create( name issuer, // 用的是name,原来的account_name已弃用 28 | asset maximum_supply); 29 | 30 | [[eosio::action]] 31 | void issue( name to, asset quantity, string memo ); 32 | 33 | [[eosio::action]] 34 | void retire( asset quantity, string memo ); // 新增的action 35 | 36 | [[eosio::action]] 37 | void transfer( name from, 38 | name to, 39 | asset quantity, 40 | string memo ); 41 | 42 | [[eosio::action]] 43 | void open( name owner, const symbol& symbol, name ram_payer ); // 新增的action 44 | 45 | [[eosio::action]] 46 | void close( name owner, const symbol& symbol ); // 新增的action 47 | 48 | static asset get_supply( name token_contract_account, symbol_code sym_code ) 49 | { 50 | stats statstable( token_contract_account, sym_code.raw() ); 51 | const auto& st = statstable.get( sym_code.raw() ); 52 | return st.supply; 53 | } 54 | 55 | static asset get_balance( name token_contract_account, name owner, symbol_code sym_code ) 56 | { 57 | accounts accountstable( token_contract_account, owner.value ); 58 | const auto& ac = accountstable.get( sym_code.raw() ); 59 | return ac.balance; 60 | } 61 | 62 | private: 63 | // [[eosio::table]]:新的生成ABI属性标注 64 | struct [[eosio::table]] account { 65 | asset balance; 66 | 67 | // 主索引,multi_index表必须,multi_index的get/find/upper_bound/lower_bound等操作会根据索引过滤 68 | // 除了主索引,还可以自定义二级索引,二级索引不是multi_index表必须的 69 | uint64_t primary_key()const { return balance.symbol.code().raw(); } 70 | }; 71 | 72 | struct [[eosio::table]] currency_stats { 73 | asset supply; 74 | asset max_supply; 75 | name issuer; 76 | 77 | uint64_t primary_key()const { return supply.symbol.code().raw(); } 78 | }; 79 | 80 | // 如果账号A拥有eosio.token的EOS币,将会存在一张code为eosio.token,scope为A,名为accounts的multi_index表 81 | typedef eosio::multi_index< "accounts"_n, account > accounts; 82 | 83 | // 如果eosio.token合约发行了一个叫EOS的币,将会存在一张code为eosio.token,scope为EOS,名为stat的multi_index表 84 | typedef eosio::multi_index< "stat"_n, currency_stats > stats; 85 | 86 | void sub_balance( name owner, asset value ); 87 | void add_balance( name owner, asset value, name ram_payer ); 88 | }; 89 | 90 | } /// namespace eosio 91 | -------------------------------------------------------------------------------- /eosio.token的transfer的memo长度/README.md: -------------------------------------------------------------------------------- 1 | ## 概述: 2 | 平时我们进行 EOS 币转账的时候,`memo`最多可以填多少个汉字、多少个英文字符呢? 3 | 4 | 官方`eosio.token`合约的`transfer`方法,`memo`被断言为长度小于等于`256`(`eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" )`),那么作为一名“专业”码农应该觉得可以输入纯英文字符最多`256`个,纯汉字减半,然鹅在链上跑的时候,并不是酱紫的。 5 | 6 | ## 敲黑板: 7 | 在链上跑的时候,纯汉字最多可以输入`85`个,纯英文字符可以输入`258`个。每个汉字占用`length`为`3`。 8 | -------------------------------------------------------------------------------- /eosio的history插件自定义过滤/README.md: -------------------------------------------------------------------------------- 1 | ## history插件自定义filter 2 | 3 | #### 以只过滤`eosio.token`的`transfer`为例 4 | 5 | 在history_plugin.cpp文件中 6 | 7 | ``` 8 | void on_action_trace( const action_trace& at ) { 9 | // if( filter( at ) ) { // 先注释掉原来的 10 | if( 1 ) { // if 1 测试,使每次都进入这里 11 | //idump((fc::json::to_pretty_string(at))); 12 | auto& chain = chain_plug->chain(); 13 | chainbase::database& db = const_cast( chain.db() ); // Override read-only access to state DB (highly unrecommended practice!) 14 | 15 | db.create( [&]( auto& aho ) { 16 | auto ps = fc::raw::pack_size( at ); 17 | aho.packed_action_trace.resize(ps); 18 | datastream ds( aho.packed_action_trace.data(), ps ); 19 | fc::raw::pack( ds, at ); 20 | aho.action_sequence_num = at.receipt.global_sequence; 21 | aho.block_num = chain.pending_block_state()->block_num; 22 | aho.block_time = chain.pending_block_time(); 23 | aho.trx_id = at.trx_id; 24 | }); 25 | 26 | // 先注释掉原来的 27 | // auto aset = account_set( at ); 28 | // for( auto a : aset ) { 29 | // record_account_action( a, at ); 30 | // } 31 | 32 | // 添加自定义的过滤 33 | auto rev = at.receipt.receiver; 34 | auto acc = at.act.account; 35 | auto nam = at.act.name; 36 | if ( acc == N(eosio.token) && nam == N(transfer) ) { 37 | record_account_action( rev, at ); 38 | } 39 | } 40 | if( at.receipt.receiver == chain::config::system_account_name ) 41 | on_system_action( at ); 42 | for( const auto& iline : at.inline_traces ) { 43 | on_action_trace( iline ); 44 | } 45 | } 46 | ``` 47 | 48 | 修改完后回到`eosio`源码根目录,执行`./eosio_build.sh`。使用该`build`出来的`nodeos`启动,启动后通过`cleos get actions eosio.token`查看。 49 | -------------------------------------------------------------------------------- /eosio的mongo插件的使用/README.md: -------------------------------------------------------------------------------- 1 | ## eosio提供了mongo插件,实现把数据导到mongo中,从而可以更加灵活的操作数据。 2 | ## 配置(config.ini) 3 | ``` 4 | plugin = eosio::mongo_db_plugin 5 | mongodb-uri = mongodb://localhost:27017 6 | ``` 7 | ## 本地启动mongo 8 | ``` 9 | $ sudo mongod 10 | ``` 11 | ## 重启nodeos 12 | ``` 13 | $ nodeos --replay-blockchain --hard-replay-blockchain --mongodb-wipe 14 | ``` 15 | ## mongo中查询 16 | ``` 17 | $ mongo 18 | > show dbs 19 | EOS 0.372GB 20 | ... 21 | 22 | > use EOS 23 | switched to db EOS 24 | 25 | > show tables 26 | account_controls 27 | accounts 28 | action_traces 29 | block_states 30 | blocks 31 | pub_keys 32 | transaction_traces 33 | transactions 34 | 35 | > db.accounts.find().pretty() 36 | { 37 | "_id" : ObjectId("5bf3cfbf4f6371c75cdc8890"), 38 | "name" : "superoneiobp", 39 | "createdAt" : ISODate("2018-11-20T09:11:27.309Z") 40 | } 41 | ... 42 | ``` -------------------------------------------------------------------------------- /eosio的快照功能/README.md: -------------------------------------------------------------------------------- 1 | EOS Snapshot可以帮助Nodeos快速的恢复数据 2 | ## 一、配置(在config.ini中) 3 | ``` 4 | // 配置保存snapshot的路径 5 | snapshots-dir = "snapshots" 6 | 7 | // 插件 8 | plugin = eosio::chain_api_plugin 9 | plugin = eosio::chain_plugin 10 | plugin = eosio::net_plugin 11 | plugin = eosio::producer_api_plugin 12 | ``` 13 | ## 二、重启nodeos 14 | ## 三、创建snapshot 15 | ``` 16 | // 下面将会在snapshots-dir下生成一个head_block_id的bin文件 17 | $ curl http://127.0.0.1:8888/v1/producer/create_snapshot 18 | ``` 19 | ## 从快照恢复数据 20 | ``` 21 | // 删除data下除blocks/blocks.log的其他文件 22 | // 启动nodeos的时候添加--snapshot参数,指定snapshot文件路径 23 | $ nodeos --snapshot + snapshot path 24 | ``` 25 | -------------------------------------------------------------------------------- /eosio获取账号actions/README.md: -------------------------------------------------------------------------------- 1 | ## 概述: 2 | 有时候我们使用别人的 rpc 地址,`get actions`的时候返回的是空: 3 | ``` 4 | $: cleos -u https://别人的rpc.io get actions myaccount111 5 | # seq when contract::action => receiver trx id... args 6 | ================================================================================================================ 7 | ``` 8 | 9 | 这是因为,你使用的这个别人的 rpc 地址,他的 nodeos 没有打开`filter-on`配置,或者他只开了他需要监听的账号和 action ,这个时候,你就要另找 rpc 地址了。 10 | 11 | ## 配置自己的节点: 12 | 如果你有自己的节点,你想用自己节点的 rpc 查找 actions ,应该怎么配置呢? 13 | 当然,你可以在 `config.ini` 配置文件中,设置 `filter-on = *` ,这样会记录全网的所有账号,以及所有的 actions ,但是你要认识到这需要很大的服务器物理内存。 14 | 如果你只需要记录账号`myaccount111`的`transfer`,你只用这样配置就好了:`filter-on = myaccount111::transfer`。 15 | -------------------------------------------------------------------------------- /eosio计算ram价格/README.md: -------------------------------------------------------------------------------- 1 | ## 首先获取多索引表`rammarket`的数据: 2 | ``` 3 | $: cleos -u https://nodes.get-scatter.com:443 get table eosio eosio rammarket 4 | { 5 | "rows": [{ 6 | "supply": "10000000000.0000 RAMCORE", 7 | "base": { 8 | "balance": "70910488246 RAM", 9 | "weight": "0.50000000000000000" 10 | }, 11 | "quote": { 12 | "balance": "1722420.0326 EOS", 13 | "weight": "0.50000000000000000" 14 | } 15 | } 16 | ], 17 | "more": false 18 | } 19 | ``` 20 | 21 | ## 那么`n KB`的内存价格为: 22 | ``` 23 | n KB内存需要的EOS = ( n * quote.balance ) / ( n + base.balance / 1024 ) 24 | -------------------------------------------------------------------------------- /eosio通过插件存储账号余额到mongo/README.md: -------------------------------------------------------------------------------- 1 | ## 通过mongo_db_plugin存储账号余额到mongodb 2 | 3 | 我们这里以存储`eosio.token`的`EOS`余额为例,思路是在发生`transfer`的时候,我们捕获该`action`,然后更新双方的余额。 4 | 5 | 首先,在`class mongo_db_plugin_impl`中声明我们需要的变量和函数 6 | ``` 7 | static const std::string accounts_col; 8 | static const std::string pub_keys_col; 9 | static const std::string account_controls_col; 10 | + 11 | + // for get currency balance 12 | + mongocxx::collection _currency_balance; // mongo集合的handle 13 | + static const std::string currency_balance_col; // 将存放mongo集合的名称 14 | + chain_plugin* chain_plug_handle; // chain_plugin 中 get_currency_balance 可以帮助我们获取余额信息 15 | + void update_currency_balance( const chain::action_trace& ); // 我们的操作放到这里进行 16 | ``` 17 | 18 | 给集合取名为`currency_balance` 19 | ``` 20 | const std::string mongo_db_plugin_impl::account_controls_col = "account_controls"; 21 | +const std::string mongo_db_plugin_impl::currency_balance_col = "currency_balance"; // mongo中集合将显示的是这个 22 | ``` 23 | 24 | 在`mongo_db_plugin_impl::consume_blocks`中初始化`handle` 25 | ``` 26 | _account_controls = mongo_conn[db_name][account_controls_col]; 27 | + _currency_balance = mongo_conn[db_name][currency_balance_col]; 28 | ``` 29 | 30 | 在`mongo_db_plugin_impl::init()`中给集合定义一个索引 31 | ``` 32 | account_controls.create_index( bsoncxx::from_json( R"xxx({ "controlling_account" : 1 })xxx" )); 33 | 34 | + // currency_balance index 35 | + auto currency_balance = mongo_conn[db_name][currency_balance_col]; 36 | + currency_balance.create_index( bsoncxx::from_json( R"xxx({ "name" : 1 })xxx" )); // name字段索引为升序 37 | + currency_balance.create_index( bsoncxx::from_json( R"xxx({ "balance" : -1 })xxx" )); // balance字段索引为降序 38 | + 39 | } catch (...) { 40 | handle_mongo_exception( "create indexes", __LINE__ ); 41 | ``` 42 | 43 | 在`mongo_db_plugin::plugin_initialize`中实例化`chain_plug_handle` 44 | ``` 45 | auto& chain = chain_plug->chain(); 46 | my->chain_id.emplace( chain.get_chain_id()); 47 | 48 | + // 给 chain_plug_handle 实例化 49 | + my->chain_plug_handle = chain_plug; 50 | + 51 | my->accepted_block_connection.emplace( chain.accepted_block.connect( [&]( const chain::block_state_ptr& bs ) { 52 | my->accepted_block( bs ); 53 | } )); 54 | ``` 55 | 56 | 定义我们的`update_currency_balance`函数 57 | ``` 58 | +void mongo_db_plugin_impl::update_currency_balance( const chain::action_trace& atrace ) { 59 | + using namespace bsoncxx::types; 60 | + using bsoncxx::builder::basic::kvp; 61 | + using bsoncxx::builder::basic::make_document; 62 | + 63 | + auto receiver = atrace.receipt.receiver; 64 | + if ( atrace.act.account == name("eosio.token") && atrace.act.name == name("transfer") ) { 65 | + chain_apis::read_only::get_currency_balance_params params = chain_apis::read_only::get_currency_balance_params { 66 | + .code = name("eosio.token"), 67 | + .account = receiver, 68 | + .symbol = "EOS", 69 | + }; 70 | + 71 | + chain_apis::read_only ro_api = chain_plug_handle->get_read_only_api(); 72 | + vector asserts = ro_api.get_currency_balance( params ); 73 | + if ( !asserts.empty() ) { 74 | + asset balance = asserts.at(0); 75 | + auto now = std::chrono::duration_cast( 76 | + std::chrono::microseconds{fc::time_point::now().time_since_epoch().count()} ); 77 | + 78 | + // ilog( "${a}'s balance: ${b}", ("a", atrace.receipt.receiver.to_string())("b", balance.to_string()) ); 79 | + 80 | + mongocxx::options::update update_opts{}; 81 | + update_opts.upsert( true ); 82 | + 83 | + const double balance_real = balance.to_real(); 84 | + const string receiver_str = receiver.to_string(); 85 | + 86 | + auto update = make_document( 87 | + kvp( "$set", make_document( kvp( "name", receiver_str), 88 | + kvp( "balance", balance_real), 89 | + kvp( "createdAt", b_date{now} )) 90 | + ) 91 | + ); 92 | + 93 | + try { 94 | + if( !_currency_balance.update_one( make_document( kvp( "name", receiver_str )), update.view(), update_opts )) { 95 | + EOS_ASSERT( false, chain::mongo_db_update_fail, "Failed to insert account ${n}", ("n", receiver)); 96 | + } 97 | + } catch (...) { 98 | + handle_mongo_exception( "update_currency", __LINE__ ); 99 | + } 100 | + } 101 | + } 102 | +} 103 | + 104 | mongo_db_plugin_impl::mongo_db_plugin_impl() 105 | { 106 | } 107 | ``` 108 | 109 | `mongodb-wipe`的时候,应该删除集合,在`mongo_db_plugin_impl::wipe_database`添加如下 110 | ``` 111 | auto pub_keys = mongo_conn[db_name][pub_keys_col]; 112 | auto account_controls = mongo_conn[db_name][account_controls_col]; 113 | + auto currency_balance = mongo_conn[db_name][currency_balance_col]; 114 | 115 | pub_keys.drop(); 116 | account_controls.drop(); 117 | + currency_balance.drop(); 118 | ilog("done wipe_database"); 119 | ``` 120 | 121 | 准备好了之后,重新`./eosio_build.sh`,然后使用该`nodeos`重启节点(当然重启节点前需要配置好`mongo`插件,并且`sudo mongod`启动了`mongo`服务)。 122 | 通过`shell`查看`mongo`结果: 123 | ``` 124 | $ mongo 125 | 126 | > show dbs 127 | EOS 0.093GB 128 | ... 129 | 130 | > use EOS 131 | switched to db EOS 132 | 133 | > show collections 134 | account_controls 135 | accounts 136 | action_traces 137 | block_states 138 | blocks 139 | currency_balance 140 | pub_keys 141 | transaction_traces 142 | transactions 143 | // 通过上面show collections可以看到我们自定义的currency_balance集合了 144 | 145 | // 按照balance降序显示 146 | > db.currency_balance.find().sort({balance:-1}).pretty() 147 | { 148 | "_id" : ObjectId("5bf684f44549fee6d16a0888"), 149 | "name" : "eosio.stake", 150 | "balance" : 240020654.8, 151 | "createdAt" : ISODate("2018-11-22T10:52:39.140Z") 152 | } 153 | { 154 | "_id" : ObjectId("5bf684f64549fee6d16a2964"), 155 | "name" : "eosio.faucet", 156 | "balance" : 199999730, 157 | "createdAt" : ISODate("2018-11-22T10:51:18.982Z") 158 | } 159 | ... 160 | ``` -------------------------------------------------------------------------------- /eos合约action命名/README.md: -------------------------------------------------------------------------------- 1 | ## 概述: 2 | EOS 中,合约的`action`对应合约 C++ 代码中的一个函数,如果你认为这个函数可以像传统 C++ 编码那样命名,那就错了。因为对应合约的`action`,所以有一些规则限制。 3 | 4 | ## 出错: 5 | 如果编译或执行合约的某个`action`,出现以下提示,说明`action`对应的函数命名不合规范: 6 | ``` 7 | Name should be less than 13 characters and only contains the following symbol .12345abcdefghijklmnopqrstuvwxyz 8 | ``` 9 | 10 | ## 规范: 11 | 从`出错`提示知道,`action`对应的函数名,长度不能超过`12`个字符,并且只能由`.12345abcdefghijklmnopqrstuvwxyz`这些字符组成。 12 | -------------------------------------------------------------------------------- /lnmp/lnmp迁移.md: -------------------------------------------------------------------------------- 1 | ## LNMP(Linux Nginx Mysql PHP) 2 | ### LNMP官网:[https://lnmp.org/](https://lnmp.org/) 3 | ### 这里记录一下LNMP部署的站点从云服务器A迁移到云服务器B的过程,服务器的系统为Ubuntu 16.04 64位,LNMP1.5 4 | - 首先,使用LNMP搭建的网站根站点一般在`/home/wwwroot`下,默认站点目录是`default`(通过`/usr/local/nginx/conf/nginx.conf`可知),`default`里面还有一个`phpmyadmin`目录,由此,大概你能猜到能做什么了(由于安全问题,`default`和`phpmyadmin`可能已被重命名,这样就能禁止通过网页访问`phpmyadmin`等)。 5 | - 因为`Nginx`可以为同一`IP`绑定多个域名,所以`/home/wwwroot`下除了`default`应该还有别的站点目录。在对应站点目录找到数据库账号和密码。 6 | - 通过浏览器使用`IP`访问,这时访问的应该是`/home/wwwroot/default`,页面上有`探针`、`phpinfo`、`phpMyadmin`等功能链接。 7 | - 通过`phpMyadmin`导出数据库。 8 | - 使用`探针`查看站点`Mysql`数据库、`PHP`模块、`LNMP`的版本。 9 | - 到`LNMP`[官网](https://lnmp.org/)下载对应的版本。 10 | - 按照官网[安装](https://lnmp.org/install.html)教程进行安装,安装过程中选择对应的`Mysql`、`PHP`版本。 11 | - 安装完成后通过`IP`访问看是否出现`LNMP`页面。然后通过`phpMyadmin`创建数据库账号,并且导入数据库,设置数据库拥有者权限。 12 | - 打包网站代码,并上传至新的服务器对应的站点目录下。 13 | - 如果`Nginx`有绑定多域名,则打包原服务器`/usr/local/nginx/conf`下的`vhost`,并上传到新的站点服务器相应目录下。 14 | - `sudo /etc/init.d/nginx restart`重启服务,然后通过域名访问网站。 15 | ### 踩坑 16 | 如果网站是基于`thinkphp`等一些框架的,这时候通过域名访问可能返回的是`500`错误。这个问题的原因很可能是由于`LNMP`的防跨域引起的。 17 | 根据[这里](https://lnmp.org/faq/lnmp-vhost-add-howto.html)的说法,在`thinkphp`、`codeigniter`、`laravel`等框架下,网站目录一般是在`public`下,但 18 | 是`public`下的程序要跨目录调用`public`上级目录下的文件,因为`LNMP`默认是不允许跨目录访问的,所以都是必须要将防跨目录访问的设置去掉:`LNMP 1.4`或以上将 `/usr/local/nginx/conf/fastcgi.conf`里面的`fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/"`这一行删除或在行首添加 19 | `#`号注释掉,然后`sudo /etc/init.d/nginx restart`重启`Nginx`服务。 -------------------------------------------------------------------------------- /mongodb简单使用/README.md: -------------------------------------------------------------------------------- 1 | ## MongoDB简介 2 | MongoDB是一个基于分布式文件存储,介于关系型和非关系型的数据库。 3 | 今天我们通过第三方平台(如Google等)可以很轻易地访问和抓取用户数据。用户的个人信息、社交网络、地理位置,用户生成的数据和用户操作日子已经成倍的增加。我们如果要对这些数据挖掘,那SQL数据库已经不适合这些应用了,NoSQL(即No Only SQL,MongoDB就是这种类型的数据库之一)数据库的发展却能很好的处理这些大数据。 4 | MongoDB将数据存储为一个文档,数据结构有键值对(key=>value)组成,类似于JSON对象,MongoDB中叫BSON(即序列化的二进制JSON)。 5 | ## MacOS平台安装MongoDB 6 | 官网提供了安装包:[https://www.mongodb.com/download-center#community](https://www.mongodb.com/download-center#community); 7 | 也可以通过brew进行安装: 8 | ``` 9 | $ sudo brew install mongodb 10 | 11 | // 安装支持 TLS/SSL 命令 12 | $ sudo brew install mongodb --with-openssl 13 | 14 | // 安装最新开发版本 15 | $sudo brew install mongodb --devel 16 | ``` 17 | ## MongoDB操作 18 | #### 运行 19 | ``` 20 | // 创建一个数据库存储目录 21 | $ sudo mkdir -p /data/db 22 | 23 | // 启动 mongodb,默认数据库目录即为 /data/db 24 | $ sudo mongod 25 | 26 | // 打开另一个终端连接刚启动的mongod服务 27 | $ mongo 28 | ``` 29 | #### 操作(启动mongo连接数据库服务后) 30 | ##### 显示数据库 31 | ``` 32 | // 显示所有数据库列表 33 | > show dbs 34 | 35 | // 显示当前的数据库或集合 36 | > db 37 | ``` 38 | ##### 使用mytest数据库,如果不存在则新建 39 | `> use mytest` 40 | ##### 删除mytest数据库 41 | ``` 42 | > use mytest 43 | > db.dropDatabase() 44 | ``` 45 | ##### 创建集合 46 | ``` 47 | // 在test数据库上创建一个叫kk的集合 48 | > use test 49 | > db.createCollection("kk") 50 | 51 | // 或者插入数据的时候,也会自动创建集合 52 | > db.kk.insert({"name" : "hhily"}) 53 | ``` 54 | ##### 查看集合 55 | `> show collections` 56 | ##### 删除集合 57 | ``` 58 | // 删除test数据库中叫kk的集合 59 | > use test 60 | > db.kk.drop() 61 | ``` 62 | ##### 插入文档 63 | ``` 64 | // 在runoob数据库col集合中插入一条文档 65 | > use runoob 66 | > db.col.insert({title: 'MongoDB 教程', 67 | description: 'MongoDB 是一个 Nosql 数据库', 68 | by: '菜鸟教程', 69 | url: 'http://www.runoob.com', 70 | tags: ['mongodb', 'database', 'NoSQL'], 71 | likes: 100 72 | }) 73 | // 上面的插入中,如果col集合不存在,将新建 74 | ``` 75 | ##### 查询文档 76 | ``` 77 | > db.col.find().pretty() 78 | // or 79 | > db.col.findOne().pretty() 80 | ``` 81 | ##### 更新文档 82 | `> db.col.updateOne({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})` 83 | ##### 删除文档 84 | `db.col.deleteMany({'title':'MongoDB 教程'})` 85 | -------------------------------------------------------------------------------- /react-intl/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | 23 | *.lock 24 | -------------------------------------------------------------------------------- /react-intl/README.md: -------------------------------------------------------------------------------- 1 | ### react-intl 是一个语言本地化的库 2 | *我们可以通过配置 `json` 文件或 `js` 文件实现多语言切换,可以还在用这么 `low` 的方法真的有钱途嘛~* 3 | *比如中文的货币符号是 '¥',英文是 '$',这些通过配置 `react-intl` 都能自动帮我们处理好。* 4 | ### 仓库地址:[https://github.com/yahoo/react-intl](https://github.com/yahoo/react-intl) 5 | `react-intl` 可以使用组件的方式,或 `api` 的方式进行语言本地化。推荐使用组件的方式,只有在组件方式不可用时(比如使用 `antd` 的`message`输出提示消息时),才选择使用 `api` 的方式。 6 | ### 使用示例 7 | ``` 8 | // 准备语言文件 locale/zh_CN.js 和 locale/en_US.js 9 | const zh_CN = { 10 | "intl.say_hello": "您好,{name} !", 11 | } 12 | export default zh_CN; 13 | const en_US = { 14 | "intl.say_hello": "Hello, {name} !", 15 | } 16 | export default en_US; 17 | 18 | // 初始化 19 | import {addLocaleData, IntlProvider} from 'react-intl'; 20 | import en from 'react-intl/locale-data/en'; 21 | import zh from 'react-intl/locale-data/zh'; 22 | import zh_CN from './locale/zh_CN'; 23 | import en_US from './locale/en_US'; 24 | 25 | // 初始化 26 | addLocaleData([...en, ...zh]); 27 | const arrLang = []; 28 | arrLang['zh'] = zh_CN; 29 | arrLang['en'] = en_US; 30 | 31 | // 父组件进行包裹 32 | 33 | 34 | 35 | 36 | // 切换 37 | setLocale = (lang) => { 38 | switch (lang) { 39 | case 'zh': { 40 | this.setState({ locale: 'zh' }); 41 | break; 42 | } 43 | case 'en': { 44 | this.setState({ locale: 'en' }); 45 | break; 46 | } 47 | default: { 48 | this.setState({ locale: 'zh' }); 49 | } 50 | } 51 | } 52 | 53 | // 用于 api 方式的文件 54 | import {defineMessages} from 'react-intl'; 55 | const Intlapi = defineMessages({ 56 | say_hello: { 57 | id: 'intl.say_hello', 58 | defaultMessage: '你好呀', 59 | }, 60 | }); 61 | export default Intlapi; 62 | 63 | // 子组件(被包裹) 64 | import React, { Component } from 'react'; 65 | import { FormattedMessage, injectIntl } from 'react-intl'; 66 | import Intlapi from './Intlapi'; 67 | 68 | class Intl extends Component { 69 | 70 | chooseZH = () => { 71 | this.props.handleSetLocale('zh'); 72 | } 73 | 74 | chooseEN = () => { 75 | this.props.handleSetLocale('en'); 76 | } 77 | 78 | render() { 79 | return ( 80 |
81 | 84 | 87 |
88 | 使用组件的方式: 89 | 96 |
97 |
98 | 使用API的方式: 99 | {this.props.intl.formatMessage(Intlapi.say_hello, {name: "Jay Lau"})} 100 |
101 |
102 | ); 103 | } 104 | } 105 | 106 | // 使用 injectIntl 注入,然后 this.props会得到一个 intl 对象,用于 api 方式 107 | export default injectIntl(Intl); 108 | ``` 109 | ### Demo 110 | ``` 111 | $ yarn install 112 | $ yarn start 113 | ``` -------------------------------------------------------------------------------- /react-intl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-intl", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "react": "^16.5.2", 7 | "react-dom": "^16.5.2", 8 | "react-intl": "^2.7.1", 9 | "react-scripts": "2.0.5" 10 | }, 11 | "scripts": { 12 | "start": "react-scripts start", 13 | "build": "react-scripts build", 14 | "test": "react-scripts test", 15 | "eject": "react-scripts eject" 16 | }, 17 | "eslintConfig": { 18 | "extends": "react-app" 19 | }, 20 | "browserslist": [ 21 | ">0.2%", 22 | "not dead", 23 | "not ie <= 11", 24 | "not op_mini all" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /react-intl/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayJay1024/Developer/b525d3364bc7fb0c0b351ba83c86e4cd1065f633/react-intl/public/favicon.ico -------------------------------------------------------------------------------- /react-intl/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 22 | React App 23 | 24 | 25 | 28 |
29 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /react-intl/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /react-intl/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 40vmin; 8 | } 9 | 10 | .App-header { 11 | background-color: #282c34; 12 | min-height: 100vh; 13 | display: flex; 14 | flex-direction: column; 15 | align-items: center; 16 | justify-content: center; 17 | font-size: calc(10px + 2vmin); 18 | color: white; 19 | } 20 | 21 | .App-link { 22 | color: #61dafb; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { 27 | transform: rotate(0deg); 28 | } 29 | to { 30 | transform: rotate(360deg); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /react-intl/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | // import logo from './logo.svg'; 3 | // import './App.css'; 4 | 5 | import Intl from './Intl/Intl'; 6 | 7 | // for locale 8 | import {addLocaleData, IntlProvider} from 'react-intl'; 9 | import en from 'react-intl/locale-data/en'; 10 | import zh from 'react-intl/locale-data/zh'; 11 | import zh_CN from './locale/zh_CN'; 12 | import en_US from './locale/en_US'; 13 | 14 | // for locale 15 | addLocaleData([...en, ...zh]); 16 | const arrLang = []; 17 | arrLang['zh'] = zh_CN; 18 | arrLang['en'] = en_US; 19 | 20 | class App extends Component { 21 | constructor(props) { 22 | super(props); 23 | 24 | this.state = { 25 | locale: 'zh', 26 | } 27 | } 28 | 29 | setLocale = (lang) => { 30 | switch (lang) { 31 | case 'zh': { 32 | this.setState({ locale: 'zh' }); 33 | break; 34 | } 35 | case 'en': { 36 | this.setState({ locale: 'en' }); 37 | break; 38 | } 39 | default: { 40 | this.setState({ locale: 'zh' }); 41 | } 42 | } 43 | } 44 | 45 | render() { 46 | return ( 47 | //
48 | //
49 | // logo 50 | //

51 | // Edit src/App.js and save to reload. 52 | //

53 | // 59 | // Learn React 60 | // 61 | //
62 | //
63 |
64 | 65 | 66 | 67 |
68 | ); 69 | } 70 | } 71 | 72 | export default App; 73 | -------------------------------------------------------------------------------- /react-intl/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /react-intl/src/Intl/Intl.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { FormattedMessage, injectIntl } from 'react-intl'; 3 | import Intlapi from './Intlapi'; 4 | 5 | class Intl extends Component { 6 | 7 | chooseZH = () => { 8 | this.props.handleSetLocale('zh'); 9 | } 10 | 11 | chooseEN = () => { 12 | this.props.handleSetLocale('en'); 13 | } 14 | 15 | render() { 16 | return ( 17 |
18 | 21 | 24 |
25 | 使用组件的方式: 26 | 33 |
34 |
35 | 使用API的方式: 36 | {this.props.intl.formatMessage(Intlapi.say_hello, {name: "Jay Lau"})} 37 |
38 |
39 | ); 40 | } 41 | } 42 | 43 | // 使用 injectIntl 注入,然后 this.props会得到一个 intl 对象,用于 api 方式 44 | export default injectIntl(Intl); 45 | -------------------------------------------------------------------------------- /react-intl/src/Intl/Intlapi.js: -------------------------------------------------------------------------------- 1 | import {defineMessages} from 'react-intl'; 2 | 3 | const Intlapi = defineMessages({ 4 | say_hello: { 5 | id: 'intl.say_hello', 6 | defaultMessage: '你好呀', 7 | }, 8 | }); 9 | 10 | export default Intlapi; -------------------------------------------------------------------------------- /react-intl/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 5 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 6 | sans-serif; 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | } 10 | 11 | code { 12 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 13 | monospace; 14 | } 15 | -------------------------------------------------------------------------------- /react-intl/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: http://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /react-intl/src/locale/en_US.js: -------------------------------------------------------------------------------- 1 | const en_US = { 2 | "intl.say_hello": "Hello, {name} !", 3 | } 4 | export default en_US; -------------------------------------------------------------------------------- /react-intl/src/locale/zh_CN.js: -------------------------------------------------------------------------------- 1 | const zh_CN = { 2 | "intl.say_hello": "您好,{name} !", 3 | } 4 | export default zh_CN; -------------------------------------------------------------------------------- /react-intl/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /react-intl/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read http://bit.ly/CRA-PWA. 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | installingWorker.onstatechange = () => { 64 | if (installingWorker.state === 'installed') { 65 | if (navigator.serviceWorker.controller) { 66 | // At this point, the updated precached content has been fetched, 67 | // but the previous service worker will still serve the older 68 | // content until all client tabs are closed. 69 | console.log( 70 | 'New content is available and will be used when all ' + 71 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.' 72 | ); 73 | 74 | // Execute callback 75 | if (config && config.onUpdate) { 76 | config.onUpdate(registration); 77 | } 78 | } else { 79 | // At this point, everything has been precached. 80 | // It's the perfect time to display a 81 | // "Content is cached for offline use." message. 82 | console.log('Content is cached for offline use.'); 83 | 84 | // Execute callback 85 | if (config && config.onSuccess) { 86 | config.onSuccess(registration); 87 | } 88 | } 89 | } 90 | }; 91 | }; 92 | }) 93 | .catch(error => { 94 | console.error('Error during service worker registration:', error); 95 | }); 96 | } 97 | 98 | function checkValidServiceWorker(swUrl, config) { 99 | // Check if the service worker can be found. If it can't reload the page. 100 | fetch(swUrl) 101 | .then(response => { 102 | // Ensure service worker exists, and that we really are getting a JS file. 103 | if ( 104 | response.status === 404 || 105 | response.headers.get('content-type').indexOf('javascript') === -1 106 | ) { 107 | // No service worker found. Probably a different app. Reload the page. 108 | navigator.serviceWorker.ready.then(registration => { 109 | registration.unregister().then(() => { 110 | window.location.reload(); 111 | }); 112 | }); 113 | } else { 114 | // Service worker found. Proceed as normal. 115 | registerValidSW(swUrl, config); 116 | } 117 | }) 118 | .catch(() => { 119 | console.log( 120 | 'No internet connection found. App is running in offline mode.' 121 | ); 122 | }); 123 | } 124 | 125 | export function unregister() { 126 | if ('serviceWorker' in navigator) { 127 | navigator.serviceWorker.ready.then(registration => { 128 | registration.unregister(); 129 | }); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /scatter交易missing-required-accounts/README.md: -------------------------------------------------------------------------------- 1 | ## 概述: 2 | 使用`scatter js sdk`发起一笔交易,请求`scatter`确认时,出现如下错误提示: 3 | ``` 4 | Missing required accounts, repull the identity 5 | ``` 6 | 7 | ## 解决: 8 | 需要添加权限选项`{ authorization: [account.name@account.authority] }`,比如 EOS 转账交易: 9 | ``` 10 | eos.contract('eosio.token').then(contract => { 11 | contract.transfer( 12 | 'fromaccount1', 13 | 'toaccount111', 14 | '1.0000 EOS', 15 | 'test', 16 | { authorization: ['fromaccount1@active'] } 17 | ); 18 | }); 19 | ``` 20 | -------------------------------------------------------------------------------- /transaction-declares-authority错误/README.md: -------------------------------------------------------------------------------- 1 | ## 概述: 2 | push action 或者 transaction 的时候,出现类似以下错误: 3 | ``` 4 | transaction declares authority '{"actor":"myaccount111","permission":"active"}', but does not have signatures for it under a provided delay of 0 ms, provided permissions [{"actor":"myaccount111","permission":"eosio.code"}], and provided keys [] 5 | ``` 6 | 7 | ## 原因: 8 | 检查部署`myaccount111`的合约代码,看看是不是使用了内联 action 或 defer ,这需要你的`myaccount111`具有`eosio.code`权限 9 | 10 | ## 解决: 11 | 给`myaccount111`赋予`eosio.code`权限 12 | ``` 13 | // 这里 EOS5RZcioUTeXNWCUehqtSHpzcXEj4auyRQiD3qwsjCQjWqmH8Qgs 是你 myaccount111 的公钥 14 | $: cleos set account permission myaccount111 active '{"threshold":1, "keys":[{"key":"EOS5RZcioUTeXNWCUehqtSHpzcXEj4auyRQiD3qwsjCQjWqmH8Qgs", "weight":1}], "accounts": [{"permission":{"actor":"myaccount111","permission":"eosio.code"},"weight":1}]}' owner -p myaccount111 15 | ``` 16 | -------------------------------------------------------------------------------- /节点rpc无法访问/README.md: -------------------------------------------------------------------------------- 1 | ## 概述: 2 | 你通过`config.ini`配置了`http-server-address = 0.0.0.0:8888`,并且配置了插件`plugin = eosio::http_plugin`,假设你的 server 的公开 ip 为`12.34.56.78`,氮素`cleos -u http://12.34.56.78:8888`仍然无法访问你的节点 rpc。 3 | 4 | ## 一些问题: 5 | - 看看你的 server 安全组有没有允许`8888`端口的访问 6 | - 在`config.ini`中配置`http-alias = 12.34.56.78:8888`试试看 7 | - 然后重启 nodeos 8 | -------------------------------------------------------------------------------- /获取eosio表的所有scope的表数据/README.md: -------------------------------------------------------------------------------- 1 | ## 背景 2 | `eosio`的多索引表,有`code`和`scope`两个角色。一张表只能有一个`code`,但是可以有多个`scope`,当然`code`和`scope`可以是同一个账号。根据`code`和`scope`可以唯一的确定一张数据表。 3 | 如果`code`和`scope`同一个,我们很容易获得表的数据,但是如果不同一个呢?现在`eosjs`这个库还不支持获取`scope`,但是`eosio`软件已经实现了这个接口了,所以思路是先获取所有的`scope`,然后结合`code`确定表的数据。 4 | 5 | ## 方法一 6 | 使用`js`封装 7 | ``` 8 | // 1. 获取scope 9 | fetchScopes = (upper = '') => { 10 | const data = { 11 | code: 'eosio.token', 12 | table: 'accounts', 13 | lower_bound: upper, // 从 upper 开始 14 | // upper_bound: '', 15 | limit: 6, // 表示每次获取6条记录 16 | }; 17 | const url = 'http://api-kylin.eoshenzhen.io:8890/v1/chain/get_table_by_scope'; 18 | 19 | fetch(url, { 20 | method: 'POST', // or 'PUT' 21 | body: JSON.stringify(data), // data can be `string` or {object}! 22 | headers: new Headers({ 23 | 'Content-Type': 'application/json' 24 | }) 25 | }) 26 | .then(response => { 27 | return response.json(); 28 | }) 29 | .then(myJson => { 30 | // miners: myJson.rows[0].scope, myJson.rows[1].scope, myJson.rows[2].scope, ... 31 | console.log( myJson ); 32 | if ( myJson.more && myJson.more.length > 0 ) { 33 | this.fetchTest( myJson.more ); 34 | } 35 | }) 36 | .catch(e => { 37 | console.error(e); 38 | }); 39 | } 40 | 41 | // 2. 拿到了scope,接下来按正常的用code和scope获取表就可以了 42 | ``` 43 | 44 | ## 方法二 45 | 如果你有一个节点,可以改造插件 46 | ``` 47 | // 1. 在chain_api_plugin.cpp的void chain_api_plugin::plugin_startup中,添加一个接口 48 | CHAIN_RO_CALL(get_currency_balance, 200), 49 | + CHAIN_RO_CALL(get_table_scopes_rows, 200), 50 | CHAIN_RO_CALL(get_currency_stats, 200), 51 | 52 | // 2. 在chain_plugin.hpp中,声明接口函数,定义参数、返回值类型 53 | vector get_currency_balance( const get_currency_balance_params& params )const; 54 | 55 | + struct get_table_scopes_rows_params { 56 | + bool json = false; 57 | + name code; 58 | + name table = 0; 59 | + string lower_bound; 60 | + string upper_bound; 61 | + uint32_t limit = 10; 62 | + }; 63 | + struct get_table_scopes_rows_result_scope { 64 | + name scope; 65 | + vector rows; 66 | + }; 67 | + struct get_table_scopes_rows_result { 68 | + vector scopes; 69 | + string more; 70 | + }; 71 | + get_table_scopes_rows_result get_table_scopes_rows( const get_table_scopes_rows_params& params )const; 72 | + 73 | struct get_currency_stats_params { 74 | name code; 75 | string symbol; 76 | 77 | // 按格式补充完整 78 | FC_REFLECT( eosio::chain_apis::read_only::get_currency_balance_params, (code)(account)(symbol)); 79 | +FC_REFLECT( eosio::chain_apis::read_only::get_table_scopes_rows_params, (json)(code)(table)(lower_bound)(upper_bound)(limit)); 80 | +FC_REFLECT( eosio::chain_apis::read_only::get_table_scopes_rows_result_scope, (scope)(rows)); 81 | +FC_REFLECT( eosio::chain_apis::read_only::get_table_scopes_rows_result, (scopes)(more)); 82 | FC_REFLECT( eosio::chain_apis::read_only::get_currency_stats_params, (code)(symbol)); 83 | 84 | 85 | // 3. 在chain_plugin.cpp中添加方法的实现 86 | return results; 87 | } 88 | 89 | +read_only::get_table_scopes_rows_result read_only::get_table_scopes_rows( const read_only::get_table_scopes_rows_params& params )const { 90 | + get_table_scopes_rows_result results; 91 | + 92 | + // 构造获取table scope的参数 93 | + const get_table_by_scope_params table_scope_params = get_table_by_scope_params { 94 | + .code = params.code, 95 | + .table = params.table, 96 | + .lower_bound = params.lower_bound, 97 | + .upper_bound = params.upper_bound, 98 | + .limit = params.limit, 99 | + }; 100 | + 101 | + // 获取table scope 102 | + const auto table_scope_result = get_table_by_scope( table_scope_params ); 103 | + 104 | + // 根据每一个scope,获取该scope所在的的table 105 | + for ( auto &table_scope : table_scope_result.rows ) { 106 | + 107 | + // 构造获取table的参数 108 | + const get_table_rows_params table_rows_params = get_table_rows_params { 109 | + .json = params.json, 110 | + .code = table_scope.code, 111 | + .scope = table_scope.scope.to_string(), 112 | + .table = table_scope.table, 113 | + }; 114 | + 115 | + // 获取当前scope所在的table 116 | + const auto table_rows_result = get_table_rows( table_rows_params ); 117 | + 118 | + get_table_scopes_rows_result_scope scope; 119 | + 120 | + for ( auto &row : table_rows_result.rows ) { 121 | + scope.rows.emplace_back( row ); 122 | + } 123 | + scope.scope = table_scope.scope; 124 | + 125 | + results.scopes.emplace_back( scope ); 126 | + } 127 | + 128 | + // 如果more不为空,调用get_table_scope_rows时设置lower_bound参数为该more数据,获取更多 129 | + results.more = table_scope_result.more; 130 | + 131 | + return results; 132 | +} 133 | + 134 | fc::variant read_only::get_currency_stats( const read_only::get_currency_stats_params& p )const { 135 | fc::mutable_variant_object results; 136 | ``` 137 | 138 | 改造完后,回到`eosio`源码根目录,执行`eosio_build`重新编译`nodeos`。开启`chain_api_plugin`插件,启动`nodeos`。 139 | 140 | #### 测试 141 | ``` 142 | 18:48:36 CryptoKylin $: curl http://127.0.0.1:8888/v1/chain/get_table_scopes_rows -X POST -d '{"code":"eosio.token","table":"accounts","json":true,"limit":5}' 143 | { 144 | "scopes":[ 145 | { 146 | "scope":"1234512345bb", 147 | "rows":[{"balance":"6.4945 EOS"}] 148 | },{ 149 | "scope":"eosasia11111", 150 | "rows":[{"balance":"1999799.8758 EOS"}] 151 | },{ 152 | "scope":"eosbixincool", 153 | "rows":[{"balance":"19999683.6871 EOS"}] 154 | },{ 155 | "scope":"eosecoeoseco", 156 | "rows":[{"balance":"80001720.6698 EOS"}] 157 | },{ 158 | "scope":"eoseekingapp", 159 | "rows":[{"balance":"1970.0000 EOS"}] 160 | } 161 | ], 162 | "more":"eosfaucet111" 163 | } 164 | 165 | 18:48:58 CryptoKylin $: curl http://127.0.0.1:8888/v1/chain/get_table_scopes_rows -X POST -d '{"code":"eosio.token","table":"accounts","json":true,"limit":5,"lower_bound":"eosfaucet111"}' 166 | { 167 | "scopes":[ 168 | { 169 | "scope":"eosfaucet111", 170 | "rows":[{"balance":"99996798.0156 EOS"}] 171 | },{ 172 | "scope":"eoshuobipool", 173 | "rows":[{"balance":"99981813.0324 EOS"}] 174 | },{ 175 | "scope":"eosio.bpay", 176 | "rows":[{"balance":"3114.8928 EOS"}] 177 | },{ 178 | "scope":"eosio.faucet", 179 | "rows":[{"balance":"199999730.0000 EOS"}] 180 | },{ 181 | "scope":"eosio.names", 182 | "rows":[{"balance":"1.0000 EOS"}] 183 | } 184 | ], 185 | "more":"eosio.ram" 186 | } 187 | ``` 188 | --------------------------------------------------------------------------------