├── 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 | 
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 | //
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 |
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 | //
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 |
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 |
--------------------------------------------------------------------------------