├── .npmignore
├── .prettierrc
├── template
├── state.json
├── blockchain.json
└── message.json
├── test
├── init.json
├── scilla
│ ├── chain-call-balance-c.scilla
│ ├── chain-call-balance-b.scilla
│ ├── chain-call-balance-a.scilla
│ └── mining.scilla
├── scripts
│ ├── HelloWorld.scilla
│ └── testblockchain.js
├── account-fixtures.json
├── sample-export.json
├── mining.test.js
├── multicontract.test.js
└── server.test.js
├── .travis.yml
├── src
├── components
│ ├── scilla
│ │ ├── stdlib
│ │ │ ├── PairUtils.scillib
│ │ │ ├── BoolUtils.scillib
│ │ │ ├── NatUtils.scillib
│ │ │ ├── IntUtils.scillib
│ │ │ └── ListUtils.scillib
│ │ └── scilla.js
│ ├── blockchain.js
│ ├── CustomErrors.js
│ └── wallet
│ │ └── wallet.js
├── server.js
├── argv.js
├── config.js
├── provider.js
├── utilities.js
├── app.js
└── logic.js
├── .github
├── CODEOWNERS
└── PULL_REQUEST_TEMPLATE.md
├── .eslintrc.json
├── jest.config.js
├── package.json
├── .gitignore
├── README.md
└── LICENSE
/.npmignore:
--------------------------------------------------------------------------------
1 | .npmignore
2 | .vscode
3 | .travis.yml
4 | .eslintrc.js
5 | *.log
6 | data
7 | ROADMAP
8 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "parser": "flow",
4 | "semi": true,
5 | "trailingComma": "es5"
6 | }
--------------------------------------------------------------------------------
/template/state.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "vname": "_balance",
4 | "type" : "Uint128",
5 | "value": "0"
6 | }
7 | ]
--------------------------------------------------------------------------------
/template/blockchain.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "vname": "BLOCKNUMBER",
4 | "type": "BNum",
5 | "value": "100"
6 | }
7 | ]
--------------------------------------------------------------------------------
/test/init.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "vname" : "owner",
4 | "type" : "Address",
5 | "value" : "0x1234567890123456789012345678901234567890"
6 | }
7 | ]
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | sudo: true
3 | dist: trusty
4 | node_js:
5 | - 10
6 | install:
7 | - npm install
8 | script:
9 | - npm run test
10 | branches:
11 | only:
12 | - /.*/
13 | cache:
14 | directories:
15 | - $HOME/.npm
16 |
--------------------------------------------------------------------------------
/template/message.json:
--------------------------------------------------------------------------------
1 | {
2 | "_tag": "setHello",
3 | "_amount": "0",
4 | "_sender" : "0x1234567890123456789012345678901234567890",
5 | "params": [
6 | {
7 | "vname": "msg",
8 | "type": "String",
9 | "value": "Hello World"
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/src/components/scilla/stdlib/PairUtils.scillib:
--------------------------------------------------------------------------------
1 | library PairUtils
2 |
3 | let fst =
4 | tfun 'A =>
5 | tfun 'B =>
6 | fun (p : Pair ('A) ('B)) =>
7 | match p with
8 | | Pair a b => a
9 | end
10 |
11 | let snd =
12 | tfun 'A =>
13 | tfun 'B =>
14 | fun (p : Pair ('A) ('B)) =>
15 | match p with
16 | | Pair a b => b
17 | end
18 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | ########## Global owners ##########
2 |
3 | * @edisonljh @AmritKumar
4 |
5 | ########## Source Code ##########
6 |
7 | *.js @edisonljh
8 |
9 | ########## Documentation ##########
10 |
11 | /README.md @edisonljh @evesnow91 @AmritKumar
12 |
13 | ########## GitHub metadata, including this file ##########
14 |
15 | /.github/ @edisonljh @AmritKumar
16 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 |
4 |
5 |
6 | ## Review Suggestion
7 |
8 |
9 |
10 | ## Status
11 |
12 | ### Implementation
13 |
14 | - [ ] **ready for review**
15 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "rules": {
4 | "no-console": 0,
5 | "no-underscore-dangle": 0,
6 | "no-return-assign": 0,
7 | "no-extend-native": 0,
8 | "no-lonely-if": 0,
9 | "prefer-destructuring": 0,
10 | "no-multi-assign": 0,
11 | "import/no-extraneous-dependencies": 0
12 | },
13 | "env": {
14 | "es6": true,
15 | "node": true
16 | },
17 | "extends": [
18 | "airbnb-base"
19 | ],
20 | "overrides": [
21 | {
22 | "files": ["*.test.js"],
23 | "env": {
24 | "jest": true
25 | }
26 | }
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/test/scilla/chain-call-balance-c.scilla:
--------------------------------------------------------------------------------
1 | scilla_version 0
2 |
3 | library Test
4 |
5 | let one_msg =
6 | fun (msg : Message) =>
7 | let nil_msg = Nil {Message} in
8 | Cons {Message} msg nil_msg
9 |
10 | contract Test
11 | ()
12 |
13 | field last_amount: Uint128 = Uint128 0
14 |
15 | (* Do not accept _amount. Emit event. *)
16 | transition noAcceptC ()
17 | last_amount := _amount;
18 |
19 | e = {_eventname: "C"};
20 | event e
21 | end
22 |
23 | transition simplyAccept ()
24 | accept;
25 |
26 | last_amount := _amount;
27 |
28 | e = {_eventname: "C"};
29 | event e
30 | end
31 |
--------------------------------------------------------------------------------
/test/scilla/chain-call-balance-b.scilla:
--------------------------------------------------------------------------------
1 | scilla_version 0
2 |
3 | library Test
4 |
5 | let one_msg =
6 | fun (msg : Message) =>
7 | let nil_msg = Nil {Message} in
8 | Cons {Message} msg nil_msg
9 |
10 | contract Test
11 | ()
12 |
13 | field last_amount: Uint128 = Uint128 0
14 |
15 | (* Call contrC. Also pass on _amount. Emit event. *)
16 | transition acceptBAndTransferToC (addrC : ByStr20)
17 | accept;
18 |
19 | last_amount := _amount;
20 |
21 | e = {_eventname: "B"};
22 | event e;
23 |
24 | msg = { _tag : "simplyAccept"; _amount : _amount; _recipient : addrC };
25 | msgs = one_msg msg;
26 | send msgs
27 | end
28 |
29 | transition simplyAccept ()
30 | accept;
31 |
32 | last_amount := _amount;
33 |
34 | e = {_eventname: "B"};
35 | event e
36 | end
37 |
--------------------------------------------------------------------------------
/src/components/scilla/stdlib/BoolUtils.scillib:
--------------------------------------------------------------------------------
1 | library BoolUtils
2 |
3 | let andb =
4 | fun (b : Bool) =>
5 | fun (c : Bool) =>
6 | match b with
7 | | False => False
8 | | True =>
9 | match c with
10 | | False => False
11 | | True => True
12 | end
13 | end
14 |
15 | let orb =
16 | fun (b : Bool) => fun (c : Bool) =>
17 | match b with
18 | | True => True
19 | | False =>
20 | match c with
21 | | False => False
22 | | True => True
23 | end
24 | end
25 |
26 | let negb = fun (b : Bool) =>
27 | match b with
28 | | True => False
29 | | False => True
30 | end
31 |
32 | let bool_to_string = fun (flag: Bool) =>
33 | match flag with
34 | | True => "True"
35 | | False => "False"
36 | end
37 |
--------------------------------------------------------------------------------
/test/scilla/chain-call-balance-a.scilla:
--------------------------------------------------------------------------------
1 | scilla_version 0
2 |
3 | library Test
4 |
5 | let one_msg =
6 | fun (msg : Message) =>
7 | let nil_msg = Nil {Message} in
8 | Cons {Message} msg nil_msg
9 |
10 | contract Test
11 | ()
12 |
13 | field last_amount: Uint128 = Uint128 0
14 |
15 | (* Call contrB, passing contrC to it. Also pass on _amount. Emit event. *)
16 | transition acceptAAndTransferToBAndCallC (addrB : ByStr20, addrC : ByStr20)
17 | accept;
18 |
19 | last_amount := _amount;
20 |
21 | e = {_eventname: "A"};
22 | event e;
23 |
24 | msg = { _tag : "acceptBAndTransferToC"; _amount : _amount; _recipient : addrB; addrC : addrC };
25 | msgs = one_msg msg;
26 | send msgs
27 | end
28 |
29 | transition simplyAccept ()
30 | accept;
31 |
32 | last_amount := _amount;
33 |
34 | e = {_eventname: "B"};
35 | event e
36 | end
37 |
--------------------------------------------------------------------------------
/test/scilla/mining.scilla:
--------------------------------------------------------------------------------
1 | scilla_version 0
2 |
3 | import BoolUtils
4 |
5 | library MiningTest
6 |
7 | let success_block_count = Uint32 3
8 |
9 | (* Contract starts timer based on block number. *)
10 | contract MiningTest
11 | ()
12 |
13 | field timer_start: BNum = BNum 0
14 |
15 | transition startTimer ()
16 | accept;
17 | blk <- & BLOCKNUMBER;
18 | timer_start := blk
19 | end
20 |
21 | (* Emit "success" if timer is complete. Emit "pending" if not. *)
22 | transition checkTimer ()
23 | accept;
24 | blk <- & BLOCKNUMBER;
25 | start_blk <- timer_start;
26 | success_blk = builtin badd start_blk success_block_count;
27 | success_is_current = builtin eq success_blk blk;
28 | success_is_passed = builtin blt success_blk blk;
29 |
30 | is_success = orb success_is_current success_is_passed;
31 | match is_success with
32 | | False =>
33 | e = {_eventname: "pending"};
34 | event e
35 | | True =>
36 | e = {_eventname: "success"};
37 | event e
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/src/components/blockchain.js:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of kaya.
3 | Copyright (c) 2018 - present Zilliqa Research Pte. Ltd.
4 |
5 | kaya is free software: you can redistribute it and/or modify it under the
6 | terms of the GNU General Public License as published by the Free Software
7 | Foundation, either version 3 of the License, or (at your option) any later
8 | version.
9 |
10 | kaya is distributed in the hope that it will be useful, but WITHOUT ANY
11 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 | A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License along with
15 | kaya. If not, see .
16 | */
17 |
18 | const config = require('../config');
19 |
20 | let bnum = config.blockchain.blockStart;
21 |
22 | function addBnum() {
23 | bnum += 1;
24 | return bnum;
25 | }
26 |
27 | // blockinterval is duration for each block number increment
28 | if (config.blockchain.blockInterval > 0) setInterval(addBnum, config.blockchain.blockInterval);
29 |
30 | module.exports = {
31 | getBlockNum: () => bnum,
32 | addBnum,
33 | };
34 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | This file is part of kaya.
3 | Copyright (c) 2018 - present Zilliqa Research Pte. Ltd.
4 |
5 | kaya is free software: you can redistribute it and/or modify it under the
6 | terms of the GNU General Public License as published by the Free Software
7 | Foundation, either version 3 of the License, or (at your option) any later
8 | version.
9 |
10 | kaya is distributed in the hope that it will be useful, but WITHOUT ANY
11 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 | A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License along with
15 | kaya. If not, see .
16 | **/
17 |
18 | const config = {
19 | verbose: true,
20 | collectCoverage: true,
21 | collectCoverageFrom: [
22 | '**/*.{js,jsx}',
23 | '!**/node_modules/**',
24 | '!**/vendor/**',
25 | '!**/coverage/**',
26 | '!**/test/**',
27 | ],
28 |
29 | // coverageThreshold: {
30 | // "global": {
31 | // "branches": 80,
32 | // "functions": 80,
33 | // "lines": 80,
34 | // "statements": 80
35 | // }
36 | // }
37 | };
38 | module.exports = config;
39 |
--------------------------------------------------------------------------------
/src/components/CustomErrors.js:
--------------------------------------------------------------------------------
1 | const zCore = require('@zilliqa-js/core');
2 |
3 | const errorCodes = zCore.RPCErrorCode;
4 |
5 | class InterpreterError extends Error {
6 | constructor(message) {
7 | super(message);
8 | this.name = 'InterpreterError';
9 | }
10 | }
11 |
12 | class BalanceError extends Error {
13 | constructor(message) {
14 | super(message);
15 | this.name = 'BalanceError';
16 | this.code = errorCodes.RPC_INVALID_ADDRESS_OR_KEY;
17 | this.data = null;
18 | }
19 | }
20 |
21 | // Cast all RPC errors to this error class
22 | // Reference: https://github.com/Zilliqa/Zilliqa/blob/master/src/libServer/Server.cpp
23 | class RPCError extends Error {
24 | constructor(message, errCode, errData) {
25 | super(message);
26 | this.name = 'RPCError';
27 | this.code = errCode;
28 | this.data = errData;
29 | }
30 | }
31 |
32 | class MultiContractError extends Error {
33 | constructor(message) {
34 | super(message);
35 | this.name = 'MulticontractError';
36 | }
37 | }
38 |
39 | class InsufficientGasError extends Error {
40 | constructor(message) {
41 | super(message);
42 | this.name = 'InsufficientGasError';
43 | }
44 | }
45 |
46 | module.exports = {
47 | InterpreterError,
48 | BalanceError,
49 | MultiContractError,
50 | InsufficientGasError,
51 | RPCError,
52 | };
53 |
--------------------------------------------------------------------------------
/test/scripts/HelloWorld.scilla:
--------------------------------------------------------------------------------
1 | scilla_version 0
2 |
3 | (* HelloWorld contract *)
4 |
5 | import ListUtils
6 |
7 | (***************************************************)
8 | (* Associated library *)
9 | (***************************************************)
10 | library HelloWorld
11 |
12 | let one_msg =
13 | fun (msg : Message) =>
14 | let nil_msg = Nil {Message} in
15 | Cons {Message} msg nil_msg
16 |
17 | let not_owner_code = Int32 1
18 | let set_hello_code = Int32 2
19 |
20 | (***************************************************)
21 | (* The contract definition *)
22 | (***************************************************)
23 |
24 | contract HelloWorld
25 | (owner: ByStr20)
26 |
27 | field welcome_msg : String = ""
28 |
29 | transition setHello (msg : String)
30 | is_owner = builtin eq owner _sender;
31 | match is_owner with
32 | | False =>
33 | e = {_eventname : "setHello()"; code : not_owner_code};
34 | event e
35 | | True =>
36 | welcome_msg := msg;
37 | e = {_eventname : "setHello()"; code : set_hello_code};
38 | event e
39 | end
40 | end
41 |
42 |
43 | transition getHello ()
44 | r <- welcome_msg;
45 | e = {_eventname: "getHello()"; msg: r};
46 | event e
47 | end
48 |
49 | transition multipleMsgs()
50 | msg1 = {_tag : ""; _recipient : _sender; _amount : Uint128 0};
51 | msg2 = {_tag : ""; _recipient : _sender; _amount : Uint128 0};
52 | msgs1 = one_msg msg1;
53 | msgs2 = Cons {Message} msg2 msgs1;
54 | send msgs2
55 | end
56 |
57 | transition contrAddr()
58 | msg1 = {_eventname : "ContractAddress"; addr : _this_address };
59 | event msg1
60 | end
61 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kaya-cli",
3 | "version": "0.2.9",
4 | "description": "Zilliqa's RPC Server",
5 | "main": "src/server.js",
6 | "scripts": {
7 | "test": "jest -c jest.config.js",
8 | "dev": "cross-env NODE_ENV=dev node src/server.js",
9 | "start": "node src/server.js",
10 | "start:fixtures": "node src/server.js --f test/account-fixtures.json",
11 | "debug": "node src/server.js -v",
12 | "debug:fixtures": "node src/server.js -f test/account-fixtures.json -v"
13 | },
14 | "author": "Edison Lim",
15 | "license": "GPL-3.0-or-later",
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/Zilliqa/kaya"
19 | },
20 | "bin": {
21 | "kaya-cli": "./src/server.js"
22 | },
23 | "devDependencies": {
24 | "babel-cli": "^6.26.0",
25 | "babel-preset-env": "^1.7.0",
26 | "cross-env": "^5.2.0",
27 | "eslint": "^5.15.0",
28 | "eslint-config-airbnb-base": "^13.1.0",
29 | "eslint-config-prettier": "^4.1.0",
30 | "eslint-plugin-import": "^2.14.0",
31 | "eslint-plugin-prettier": "^3.0.1",
32 | "jest": "^24.1.0",
33 | "prettier": "^1.14.2",
34 | "superagent": "^4.1.0",
35 | "supertest": "^3.1.0",
36 | "tslib": "^1.9.3"
37 | },
38 | "dependencies": {
39 | "@zilliqa-js/zilliqa": "^0.8.1",
40 | "bn.js": "^4.11.8",
41 | "body-parser": "^1.18.3",
42 | "colors": "^1.3.0",
43 | "cors": "^2.8.4",
44 | "es6-promise": "^4.2.4",
45 | "express": "^4.16.3",
46 | "glob": "^7.1.3",
47 | "hash.js": "^1.1.5",
48 | "isomorphic-fetch": "^2.2.1",
49 | "moment": "^2.22.2",
50 | "node-fs": "^0.1.7",
51 | "request": "^2.88.0",
52 | "request-promise": "^4.2.2",
53 | "rimraf": "^2.6.2",
54 | "yargs": "^13.2.1"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # parcel-bundler cache (https://parceljs.org/)
61 | .cache
62 |
63 | # next.js build output
64 | .next
65 |
66 | # nuxt.js build output
67 | .nuxt
68 |
69 | # vuepress build output
70 | .vuepress/dist
71 |
72 | # Serverless directories
73 | .serverless
74 |
75 | # Custom files
76 | saved/
77 | tmp/
78 | data/
79 | *scilla-runner
80 | *scilla-checker
81 |
82 | # Swap
83 | [._]*.s[a-v][a-z]
84 | [._]*.sw[a-p]
85 | [._]s[a-rt-v][a-z]
86 | [._]ss[a-gi-z]
87 | [._]sw[a-p]
88 |
89 | # # Session
90 | Session.vim
91 |
92 | # Temporary
93 | .netrwhist
94 | *~
95 | # Auto-generated tag files
96 | tags
97 | # Persistent undo
98 | [._]*.un~
99 |
--------------------------------------------------------------------------------
/src/server.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | /*
3 | This file is part of kaya.
4 | Copyright (c) 2018 - present Zilliqa Research Pte. Ltd.
5 |
6 | kaya is free software: you can redistribute it and/or modify it under the
7 | terms of the GNU General Public License as published by the Free Software
8 | Foundation, either version 3 of the License, or (at your option) any later
9 | version.
10 |
11 | kaya is distributed in the hope that it will be useful, but WITHOUT ANY
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 | A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License along with
16 | kaya. If not, see .
17 | */
18 |
19 | const yargs = require('yargs');
20 |
21 | const config = require('./config');
22 | const initArgv = require('./argv');
23 |
24 | let serverPort;
25 | let argv;
26 | if (process.env.NODE_ENV !== 'test') {
27 | argv = initArgv(yargs).argv;
28 | serverPort = argv.p ? argv.p : config.port;
29 | } else {
30 | console.log('-------- TEST MODE -------------');
31 | argv = config.testconfigs.args;
32 | }
33 |
34 | /* Information about Kaya RPC Server */
35 |
36 | console.log(`ZILLIQA KAYA RPC SERVER (ver: ${config.version})`);
37 | console.log(`Server listening on 127.0.0.1:${serverPort}`);
38 |
39 | const app = require('./app');
40 |
41 | const server = app.expressjs.listen(serverPort, (err) => {
42 | if (err) {
43 | process.exit(1);
44 | }
45 | });
46 |
47 | // Listener for connections opening on the server
48 | let connections = [];
49 | server.on('connection', (connection) => {
50 | connections.push(connection);
51 | connection.on(
52 | 'close',
53 | () => (connections = connections.filter(curr => curr !== connection)),
54 | );
55 | });
56 |
--------------------------------------------------------------------------------
/src/components/scilla/stdlib/NatUtils.scillib:
--------------------------------------------------------------------------------
1 | library NatUtils
2 |
3 | (* Nat -> Option Nat *)
4 | let nat_prev = fun (n: Nat) =>
5 | match n with
6 | | Succ n1 => Some {Nat} n1
7 | | Zero => None {Nat}
8 | end
9 |
10 | (* Nat -> Bool *)
11 | let is_some_zero = fun (n: Nat) =>
12 | match n with
13 | | Zero => True
14 | | _ => False
15 | end
16 |
17 | (* Nat -> Nat -> Bool *)
18 | let nat_eq = fun (n : Nat) => fun (m : Nat) =>
19 | let z = Some {Nat} m in
20 | let f = fun (res : Option Nat) => fun (n : Nat) =>
21 | match res with
22 | | None => None {Nat}
23 | | Some m1 => nat_prev m1
24 | end in
25 | let folder = @nat_fold (Option Nat) in
26 | let e = folder f z n in
27 | match e with
28 | | Some Zero => True
29 | | _ => False
30 | end
31 |
32 | (* Nat -> Uint32 *)
33 | let nat_to_int =
34 | fun (n : Nat) =>
35 | let f =
36 | fun (z : Uint32) =>
37 | fun (n : Nat) =>
38 | match n with
39 | | _ =>
40 | let one_int = Uint32 1 in
41 | builtin add z one_int
42 | end
43 | in
44 | let folder = @nat_fold Uint32 in
45 | let zero_int = Uint32 0 in
46 | folder f zero_int n
47 |
48 | let uint32_to_nat_helper =
49 | fun (m : Option Uint32) =>
50 | match m with
51 | | Some x =>
52 | let res = builtin to_nat x in
53 | Some {Nat} res
54 | | None => None {Nat}
55 | end
56 |
57 | (* UintX/IntX -> Option Nat *)
58 | let uint32_to_nat =
59 | fun (n : Uint32) =>
60 | let m = builtin to_uint32 n in
61 | uint32_to_nat_helper m
62 |
63 | let uint64_to_nat =
64 | fun (n : Uint64) =>
65 | let m = builtin to_uint32 n in
66 | uint32_to_nat_helper m
67 |
68 | let uint128_to_nat =
69 | fun (n : Uint128) =>
70 | let m = builtin to_uint32 n in
71 | uint32_to_nat_helper m
72 |
73 | let int32_to_nat =
74 | fun (n : Int32) =>
75 | let m = builtin to_uint32 n in
76 | uint32_to_nat_helper m
77 |
78 | let int64_to_nat =
79 | fun (n : Int64) =>
80 | let m = builtin to_uint32 n in
81 | uint32_to_nat_helper m
82 |
83 | let int128_to_nat =
84 | fun (n : Int128) =>
85 | let m = builtin to_uint32 n in
86 | uint32_to_nat_helper m
87 |
88 |
--------------------------------------------------------------------------------
/test/account-fixtures.json:
--------------------------------------------------------------------------------
1 | {
2 | "7bb3b0e8a59f3f61d9bff038f4aeb42cae2ecce8": {
3 | "privateKey": "db11cfa086b92497c8ed5a4cc6edb3a5bfe3a640c43ffb9fc6aa0873c56f2ee3",
4 | "amount": "1000000000000000000",
5 | "nonce": 0
6 | },
7 | "d90f2e538ce0df89c8273cad3b63ec44a3c4ed82": {
8 | "privateKey": "e53d1c3edaffc7a7bab5418eb836cf75819a82872b4a1a0f1c7fcf5c3e020b89",
9 | "amount": "1000000000000000000",
10 | "nonce": 0
11 | },
12 | "381f4008505e940ad7681ec3468a719060caf796": {
13 | "privateKey": "d96e9eb5b782a80ea153c937fa83e5948485fbfc8b7e7c069d7b914dbc350aba",
14 | "amount": "1000000000000000000",
15 | "nonce": 0
16 | },
17 | "b028055ea3bc78d759d10663da40d171dec992aa": {
18 | "privateKey": "e7f59a4beb997a02a13e0d5e025b39a6f0adc64d37bb1e6a849a4863b4680411",
19 | "amount": "1000000000000000000",
20 | "nonce": 0
21 | },
22 | "f6dad9e193fa2959a849b81caf9cb6ecde466771": {
23 | "privateKey": "589417286a3213dceb37f8f89bd164c3505a4cec9200c61f7c6db13a30a71b45",
24 | "amount": "1000000000000000000",
25 | "nonce": 0
26 | },
27 | "10200e3da08ee88729469d6eabc055cb225821e7": {
28 | "privateKey": "5430365143ce0154b682301d0ab731897221906a7054bbf5bd83c7663a6cbc40",
29 | "amount": "1000000000000000000",
30 | "nonce": 0
31 | },
32 | "ac941274c3b6a50203cc5e7939b7dad9f32a0c12": {
33 | "privateKey": "1080d2cca18ace8225354ac021f9977404cee46f1d12e9981af8c36322eac1a4",
34 | "amount": "1000000000000000000",
35 | "nonce": 0
36 | },
37 | "ec902fe17d90203d0bddd943d97b29576ece3177": {
38 | "privateKey": "254d9924fc1dcdca44ce92d80255c6a0bb690f867abde80e626fbfef4d357004",
39 | "amount": "1000000000000000000",
40 | "nonce": 0
41 | },
42 | "c2035715831ab100ec42e562ce341b834bed1f4c": {
43 | "privateKey": "b8fc4e270594d87d3f728d0873a38fb0896ea83bd6f96b4f3c9ff0a29122efe4",
44 | "amount": "1000000000000000000",
45 | "nonce": 0
46 | },
47 | "6cd3667ba79310837e33f0aecbe13688a6cbca32": {
48 | "privateKey": "b87f4ba7dcd6e60f2cca8352c89904e3993c5b2b0b608d255002edcda6374de4",
49 | "amount": "1000000000000000000",
50 | "nonce": 0
51 | }
52 | }
--------------------------------------------------------------------------------
/src/argv.js:
--------------------------------------------------------------------------------
1 | const config = require('./config');
2 |
3 | module.exports = exports = (yargs) => {
4 | const yargsOptions = yargs
5 | .strict()
6 | .usage('Usage: node $0 [options]')
7 | .example('node server.js -f -v', 'Starts server based on predefined wallet files with verbose mode')
8 | .option('p', {
9 | group: 'Network',
10 | alias: 'port',
11 | type: 'number',
12 | default: config.port,
13 | describe: 'Port number to listen',
14 | })
15 | .option('d', {
16 | group: 'Blockchain',
17 | alias: 'data',
18 | type: 'string',
19 | default: config.dataPath,
20 | describe: 'Relative path where state data will be stored. Creates directory if path does not exists',
21 | })
22 | .option('r', {
23 | group: 'Blockchain',
24 | alias: 'remote',
25 | type: 'boolean',
26 | default: config.scilla.remote,
27 | describe: 'Option to use remote interpreter or local interpreter. True = remote',
28 | })
29 | .option('f', {
30 | group: 'Other',
31 | alias: 'fixtures',
32 | type: 'string',
33 | default: null,
34 | describe: 'Path to JSON file which contains the private keys to predefined set of wallets',
35 | })
36 | .option('n', {
37 | group: 'Other',
38 | alias: 'numAccounts',
39 | type: 'number',
40 | default: config.wallet.numAccounts,
41 | describe: 'Number of accounts to load at start up. Only used if fixtures file is not defined.',
42 | })
43 | .option('l', {
44 | group: 'Other',
45 | alias: 'load',
46 | type: 'string',
47 | default: null,
48 | describe: 'Load data files from a path',
49 | })
50 | .option('s', {
51 | group: 'Other',
52 | alias: 'save',
53 | type: 'boolean',
54 | default: null,
55 | describe: 'Saves data by the end of the session',
56 | })
57 | .option('v', {
58 | group: 'Other',
59 | alias: 'verbose',
60 | type: 'boolean',
61 | default: false,
62 | describe: 'Log messages to console to stdout',
63 | })
64 | .showHelpOnFail(false, 'Specify --help for available options')
65 | .help('help')
66 | .alias('help', '?')
67 | .version(config.version);
68 |
69 | return yargsOptions;
70 | };
71 |
--------------------------------------------------------------------------------
/test/sample-export.json:
--------------------------------------------------------------------------------
1 | {
2 | "transactions": {},
3 | "createdContractsByUsers": {},
4 | "accounts": {
5 | "7bb3b0e8a59f3f61d9bff038f4aeb42cae2ecce8": {
6 | "privateKey": "db11cfa086b92497c8ed5a4cc6edb3a5bfe3a640c43ffb9fc6aa0873c56f2ee3",
7 | "amount": 100000,
8 | "nonce": 0
9 | },
10 | "d90f2e538ce0df89c8273cad3b63ec44a3c4ed82": {
11 | "privateKey": "e53d1c3edaffc7a7bab5418eb836cf75819a82872b4a1a0f1c7fcf5c3e020b89",
12 | "amount": 100000,
13 | "nonce": 0
14 | },
15 | "c2035715831ab100ec42e562ce341b834bed1f4c": {
16 | "privateKey": "b8fc4e270594d87d3f728d0873a38fb0896ea83bd6f96b4f3c9ff0a29122efe4",
17 | "amount": 100000,
18 | "nonce": 0
19 | },
20 | "6cd3667ba79310837e33f0aecbe13688a6cbca32": {
21 | "privateKey": "b87f4ba7dcd6e60f2cca8352c89904e3993c5b2b0b608d255002edcda6374de4",
22 | "amount": 50000,
23 | "nonce": 0
24 | }
25 | },
26 | "states": {
27 | "cef48d2ec4086bd5799b659261948daab02b760d_state.json": [
28 | {
29 | "vname": "_balance",
30 | "type": "Uint128",
31 | "value": "0"
32 | }
33 | ]
34 | },
35 | "init": {
36 | "cef48d2ec4086bd5799b659261948daab02b760d_init.json": [
37 | {
38 | "vname": "owner",
39 | "type": "ByStr20",
40 | "value": "0x7bb3b0e8a59f3f61d9bff038f4aeb42cae2ecce8"
41 | },
42 | {
43 | "vname": "_creation_block",
44 | "type": "BNum",
45 | "value": "100"
46 | }
47 | ]
48 | },
49 | "codes": {
50 | "cef48d2ec4086bd5799b659261948daab02b760d_code.scilla": " import ListUtils library HelloWorld let one_msg = fun (msg : Message) => let nil_msg = Nil {Message} in Cons {Message} msg nil_msg let not_owner_code = Int32 1 let set_hello_code = Int32 2 contract HelloWorld (owner: ByStr20) field welcome_msg : String = \"\" transition setHello (msg : String) is_owner = builtin eq owner _sender; match is_owner with | False => msg = {_tag : \"Main\"; _recipient : _sender; _amount : Uint128 0; code : not_owner_code}; msgs = one_msg msg; send msgs | True => welcome_msg := msg; msg = {_tag : \"Main\"; _recipient : _sender; _amount : Uint128 0; code : set_hello_code}; msgs = one_msg msg; send msgs end end transition getHello () r <- welcome_msg; msg = {_tag : \"Main\"; _recipient : _sender; _amount : Uint128 0; msg : r}; msgs = one_msg msg; send msgs end"
51 | }
52 | }
--------------------------------------------------------------------------------
/test/scripts/testblockchain.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const { BN, Long, bytes } = require('@zilliqa-js/util');
3 | const { Zilliqa } = require('@zilliqa-js/zilliqa');
4 |
5 | const zilliqa = new Zilliqa('http://localhost:4200');
6 |
7 | const CHAIN_ID = 111;
8 | const MSG_VERSION = 1;
9 | const VERSION = bytes.pack(CHAIN_ID, MSG_VERSION);
10 |
11 | // Populate the wallet with an account
12 | zilliqa.wallet.addByPrivateKey(
13 | 'db11cfa086b92497c8ed5a4cc6edb3a5bfe3a640c43ffb9fc6aa0873c56f2ee3',
14 | );
15 |
16 | async function testBlockchain() {
17 | try {
18 | // Send a transaction to the network
19 | const tx = await zilliqa.blockchain.createTransaction(
20 | zilliqa.transactions.new({
21 | version: VERSION,
22 | toAddr: 'd90f2e538ce0df89c8273cad3b63ec44a3c4ed82',
23 | amount: new BN(888),
24 | // gasPrice must be >= minGasPrice
25 | gasPrice: new BN('1_000_000_000'),
26 | // can be `number` if size is <= 2^53 (i.e., window.MAX_SAFE_INTEGER)
27 | gasLimit: Long.fromNumber(10),
28 | }),
29 | );
30 | console.log(tx);
31 |
32 | console.log('Deploying a contract now');
33 | // Deploy a contract
34 | const code = fs.readFileSync('HelloWorld.scilla', 'utf-8');
35 | const init = [
36 | {
37 | vname: '_scilla_version',
38 | type: 'Uint32',
39 | value: '0',
40 | },
41 | {
42 | vname: 'owner',
43 | type: 'ByStr20',
44 | // NOTE: all byte strings passed to Scilla contracts _must_ be
45 | // prefixed with 0x. Failure to do so will result in the network
46 | // rejecting the transaction while consuming gas!
47 | value: '0x7bb3b0e8a59f3f61d9bff038f4aeb42cae2ecce8',
48 | },
49 | ];
50 |
51 | // instance of class Contract
52 | const contract = zilliqa.contracts.new(code, init);
53 |
54 | const [deployTx, hello] = await contract.deploy({
55 | version: VERSION,
56 | gasPrice: new BN('1_000_000_000'),
57 | gasLimit: Long.fromNumber(5000),
58 | });
59 |
60 | // Introspect the state of the underlying transaction
61 | console.log('Deployment Transaction ID: ', deployTx.id);
62 | console.log('Deployment Transaction Receipt: ', deployTx.txParams.receipt);
63 |
64 | const callTx = await hello.call('setHello', [
65 | {
66 | vname: 'msg',
67 | type: 'String',
68 | value: 'Hello World',
69 | }],
70 | {
71 | version: VERSION,
72 | amount: new BN(0),
73 | gasPrice: new BN('1_000_000_000'),
74 | gasLimit: Long.fromNumber(5000),
75 | });
76 | const { receipt } = callTx.txParams;
77 | console.log(receipt);
78 | const state = await hello.getState();
79 | console.log(state);
80 | } catch (err) {
81 | console.log('Blockchain Error');
82 | console.log(err);
83 | }
84 | }
85 |
86 | testBlockchain();
87 |
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of kaya.
3 | Copyright (c) 2018 - present Zilliqa Research Pte. Ltd.
4 |
5 | kaya is free software: you can redistribute it and/or modify it under the
6 | terms of the GNU General Public License as published by the Free Software
7 | Foundation, either version 3 of the License, or (at your option) any later
8 | version.
9 |
10 | kaya is distributed in the hope that it will be useful, but WITHOUT ANY
11 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 | A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License along with
15 | kaya. If not, see .
16 | */
17 |
18 | /* Configuration file */
19 | /* Feel free to add more things to this file that will help you in development */
20 | const { BN } = require('@zilliqa-js/util');
21 |
22 | const packagejs = require('../package.json');
23 |
24 | module.exports = {
25 | port: 4200,
26 | version: packagejs.version,
27 | dataPath: '../data/',
28 | savedFilesDir: '../saved/',
29 | chainId: 111,
30 | msgVersion: 1,
31 | // blockchain specific configuration
32 | blockchain: {
33 | // sets timer for the block confirmation
34 | blockInterval: 0, // automatic block confirmation time in ms, 0 disables automatic confirmation
35 | blockStart: 0,
36 | minimumGasPrice: new BN('1000000000'),
37 | transferGasCost: 1, // Amount of gas consumed for each transfer
38 | },
39 |
40 | wallet: {
41 | numAccounts: 10, // number of default accounts
42 | defaultAmt: new BN('1000000000000000000'), // default amount of zils assigned to each wallet
43 | defaultNonce: 0,
44 | },
45 |
46 | // Relevant constants config copied from core zilliqa repo (constants.xml)
47 | constants: {
48 | gas: {
49 | CONTRACT_CREATE_GAS: 50,
50 | CONTRACT_INVOKE_GAS: 10,
51 | NORMAL_TRAN_GAS: 1,
52 | },
53 | smart_contract: {
54 | SCILLA_RUNNER: `${__dirname}/components/scilla/scilla-runner`,
55 | SCILLA_CHECKER: `${__dirname}/components/scilla/scilla-checker`,
56 | SCILLA_LIB: `${__dirname}/components/scilla/stdlib`,
57 | },
58 | },
59 |
60 | /*
61 | Settings for the scilla interpreter
62 | - runner-path: Relative path to your scilla-runner
63 | - remote: Use the remote scilla interpreter. (Default: True). False: Use local scilla interpreter
64 | - url: URL to the remote scilla interpreter
65 | */
66 | scilla: {
67 | remote: true,
68 | CHECKER_URL: 'https://scilla-runner.zilliqa.com/contract/check',
69 | RUNNER_URL: 'https://scilla-runner.zilliqa.com/contract/call',
70 | },
71 |
72 | testconfigs: {
73 | gasPrice: '1_000_000_000',
74 | gasLimit: 10,
75 | transferAmt: 100,
76 | args: {
77 | r: true,
78 | remote: true,
79 | s: null,
80 | save: null,
81 | v: true,
82 | verbose: true,
83 | version: false,
84 | f: 'test/account-fixtures.json',
85 | fixtures: 'test/account-fixtures.json',
86 | p: 4200,
87 | port: 4200,
88 | d: 'data/',
89 | data: 'data/',
90 | n: 10,
91 | numAccounts: 10,
92 | l: null,
93 | load: null,
94 | $0: 'server.js',
95 | },
96 | },
97 | };
98 |
--------------------------------------------------------------------------------
/src/provider.js:
--------------------------------------------------------------------------------
1 | const zCore = require('@zilliqa-js/core');
2 | const logic = require('./logic');
3 | const wallet = require('./components/wallet/wallet');
4 | const config = require('./config');
5 | const { RPCError } = require('./components/CustomErrors');
6 | const { addBnum, getBlockNum } = require('./components/blockchain');
7 |
8 | const errorCodes = zCore.RPCErrorCode;
9 |
10 | class Provider {
11 | constructor(options) {
12 | this.options = options;
13 | this.middleware = {
14 | request: {
15 | use: () => {},
16 | },
17 | response: {
18 | use: () => {},
19 | },
20 | };
21 | }
22 |
23 | /**
24 | * Process the JSON RPC call
25 | * @async
26 | * @param { String } method - Zilliqa RPC method name
27 | * @param { Array } params - Zilliqa RPC method parameters
28 | * @returns { Promise