├── playground ├── pet-shop-tutorial │ ├── img │ │ ├── .gitignore │ │ ├── 0.jpeg │ │ ├── 1.jpeg │ │ ├── 10.jpeg │ │ ├── 11.jpeg │ │ ├── 12.jpeg │ │ ├── 13.jpeg │ │ ├── 14.jpeg │ │ ├── 15.jpeg │ │ ├── 2.jpeg │ │ ├── 3.jpeg │ │ ├── 4.jpeg │ │ ├── 5.jpeg │ │ ├── 6.jpeg │ │ ├── 7.jpeg │ │ ├── 8.jpeg │ │ └── 9.jpeg │ ├── contracts │ │ ├── .gitkeep │ │ ├── Adoption.sol │ │ ├── Migrations.sol │ │ ├── SafeMath.sol │ │ └── QRC20Token.sol │ ├── .babelrc │ ├── icon.png │ ├── tile.png │ ├── favicon.ico │ ├── robots.txt │ ├── tile-wide.png │ ├── migrations │ │ ├── 3_deploy_token.js │ │ ├── 2_deploy_contracts.js │ │ └── 1_initial_migration.js │ ├── .editorconfig │ ├── Makefile │ ├── .gitignore │ ├── site.webmanifest │ ├── humans.txt │ ├── browserconfig.xml │ ├── js │ │ └── plugins.js │ ├── truffle-config.js │ ├── LICENSE.txt │ ├── 404.html │ ├── doc │ │ ├── js.md │ │ ├── css.md │ │ ├── TOC.md │ │ └── faq.md │ └── index.html ├── docker │ ├── env.list-example │ ├── .gitignore │ ├── Dockerfile │ ├── myaccounts.txt │ └── init-container.sh ├── deploy-myToken.sh ├── deploy-SimpleStore.sh ├── migrations │ ├── 1_initial_migration.js │ ├── 2_deploy_simpleStore.js │ └── 3_deploy_myToken.js ├── contracts │ ├── MyToken.sol │ ├── SimpleStore.sol │ └── openzeppelin-solidity │ │ └── contracts │ │ ├── token │ │ └── ERC20 │ │ │ ├── ERC20Basic.sol │ │ │ ├── ERC20.sol │ │ │ ├── CappedToken.sol │ │ │ ├── BasicToken.sol │ │ │ └── MintableToken.sol │ │ ├── math │ │ └── SafeMath.sol │ │ └── ownership │ │ └── Ownable.sol ├── node-myToken-commands.txt ├── package.json ├── truffle-myToken-commands.txt ├── truffle-test-simpleStore.js ├── Makefile ├── test-SimpleStore.js ├── .gitignore └── test │ ├── truffle-test-myToken.js │ └── truffle-test-simpleStore.js ├── testing ├── .dockerignore ├── web3 │ ├── .gitignore │ ├── package.json │ ├── truffle-config.js │ └── contracts │ │ └── ERC20Mock.sol ├── run-tests.sh ├── openzeppelin │ ├── trim-github-logs.sh │ ├── openzeppelin.Dockerfile │ ├── docker-compose-openzeppelin.yml │ ├── truffle-config.js │ └── run-openzeppelin-tests.sh ├── aave │ ├── .gitignore │ ├── tslint.json │ ├── tsconfig.json │ └── hardhat.config.ts ├── truffle-parser.Dockerfile ├── revert-reasons │ ├── truffle-config.js │ ├── contracts │ │ └── ERC20Mock.sol │ └── .gitignore ├── pull-dependencies.sh ├── Makefile └── .gitignore ├── docker ├── .gitignore ├── openssl.Dockerfile ├── populate_and_run.sh ├── unittests.Dockerfile ├── qtum-seeded.Dockerfile ├── spin_up.regtest.sh ├── spin_up.mainnet.sh ├── spin_up.testnet.sh ├── standalone │ └── myaccounts.txt ├── go-build.Dockerfile ├── configure_https.sh ├── quick_start │ ├── docker-compose.testnet.yml │ ├── docker-compose.mainnet.yml │ └── docker-compose.regtest.yml └── setup_self_signed_https.sh ├── metamask ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── views │ │ ├── About.vue │ │ └── Home.vue │ ├── App.vue │ ├── main.js │ ├── router │ │ └── index.js │ └── components │ │ └── HelloWorld.vue ├── .gitignore ├── package.json └── README.md ├── sha.sh ├── .dockerignore ├── .gitmodules ├── main.go ├── pkg ├── utils │ ├── utils.go │ ├── hex_test.go │ └── hex.go ├── transformer │ ├── notifier.go │ ├── type.go │ ├── eth_protocolVersion.go │ ├── eth_getCompilers.go │ ├── eth_getUncleCountByBlockHash.go │ ├── eth_getUncleCountByBlockNumber.go │ ├── eth_getUncleByBlockHashAndIndex.go │ ├── eth_personal_unlockAccount.go │ ├── eth_getCompilers_test.go │ ├── eth_getTransactionByBlockHashAndIndex_test.go │ ├── eth_protocolVersion_test.go │ ├── eth_getTransactionByBlockNumberAndIndex_test.go │ ├── eth_getUncleByBlockHashAndIndex_test.go │ ├── eth_chainId.go │ ├── log.go │ ├── eth_net_version.go │ ├── eth_net_listening.go │ ├── web3_clientVersion.go │ ├── eth_gasPrice_test.go │ ├── eth_getTransactionCount_test.go │ ├── eth_net_peerCount.go │ ├── eth_gasPrice.go │ ├── eth_mining.go │ ├── tests_common.go │ ├── web3_sha3.go │ ├── eth_accounts.go │ ├── eth_newBlockFilter.go │ ├── eth_mining_test.go │ ├── eth_hashrate.go │ ├── eth_getTransactionCount.go │ ├── eth_uninstallFilter.go │ ├── eth_getBlockByHash_test.go │ ├── eth_blockNumber_test.go │ ├── qtum_genericStringArguments.go │ ├── eth_net_listening_test.go │ ├── eth_getCode.go │ ├── eth_blockNumber.go │ ├── eth_hashrate_test.go │ ├── eth_subscribe.go │ ├── eth_unsubscribe.go │ ├── eth_net_peerCount_test.go │ ├── eth_chainId_test.go │ ├── eth_getFilterLogs.go │ ├── web3_sha3_test.go │ ├── eth_newFilter.go │ ├── eth_getBlockByNumber_test.go │ ├── eth_getTransactionByBlockHashAndIndex.go │ ├── eth_sendRawTransaction.go │ ├── eth_sign.go │ ├── eth_getTransactionByBlockNumberAndIndex.go │ ├── eth_getBalance.go │ ├── eth_getTransactionReceipt_test.go │ ├── eth_estimateGas.go │ ├── qtum_generate.go │ ├── eth_getStorageAt.go │ ├── eth_getBlockByNumber.go │ ├── eth_call.go │ └── eth_accounts_test.go ├── params │ └── version.go ├── server │ ├── pingpong.go │ └── myctx.go ├── eth │ ├── rpc_types_test.go │ ├── filter.go │ ├── eth_int.go │ ├── util.go │ ├── eth_address.go │ ├── eth.go │ └── errors.go ├── qtum │ ├── account.go │ └── client_test.go ├── notifier │ └── subscription_test.go ├── internal │ └── tests_transformer.go └── analytics │ └── analytics.go ├── myaccounts.txt ├── .gitignore ├── Dockerfile └── .github └── workflows ├── docker-unit-tests.yml └── docker-openzeppelin.yml /playground/pet-shop-tutorial/img/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/contracts/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /playground/docker/env.list-example: -------------------------------------------------------------------------------- 1 | #QTUM_NETWORK=auto 2 | -------------------------------------------------------------------------------- /testing/.dockerignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | openzeppelin-contracts/build -------------------------------------------------------------------------------- /testing/web3/.gitignore: -------------------------------------------------------------------------------- 1 | .txt 2 | /yarn.lock 3 | /package-lock.json 4 | node_modules/ -------------------------------------------------------------------------------- /docker/.gitignore: -------------------------------------------------------------------------------- 1 | /janus-linux-amd64 2 | /.qtum 3 | /supervisord.* 4 | /env.list 5 | -------------------------------------------------------------------------------- /docker/openssl.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.18-alpine 2 | 3 | RUN apk add --no-cache openssl 4 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"] 3 | } 4 | -------------------------------------------------------------------------------- /playground/docker/.gitignore: -------------------------------------------------------------------------------- 1 | /janus-linux-amd64 2 | /.qtum 3 | /supervisord.* 4 | /env.list 5 | -------------------------------------------------------------------------------- /docker/populate_and_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ./fill_user_account.sh& 3 | # run all command line arguments 4 | $@ -------------------------------------------------------------------------------- /metamask/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/metamask/public/favicon.ico -------------------------------------------------------------------------------- /playground/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM dcb9/qtumportal 2 | 3 | COPY janus-linux-amd64 /usr/local/bin/janus 4 | -------------------------------------------------------------------------------- /sha.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ -n "$GIT_SHA" ]; then 3 | echo $GIT_SHA 4 | else 5 | git rev-parse HEAD 6 | fi 7 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/icon.png -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/tile.png -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/favicon.ico -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/0.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/1.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/10.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/10.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/11.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/11.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/12.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/12.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/13.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/13.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/14.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/14.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/15.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/15.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/2.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/3.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/4.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/5.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/6.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/6.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/7.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/7.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/8.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/8.jpeg -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/img/9.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/img/9.jpeg -------------------------------------------------------------------------------- /metamask/src/views/About.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /playground/deploy-myToken.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -x 3 | solar deploy contracts/MyToken.sol --gasPrice=0.0000001 '[21000000]' --force 4 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | 3 | # Allow crawling of all content 4 | User-agent: * 5 | Disallow: 6 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/tile-wide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qtumproject/janus/HEAD/playground/pet-shop-tutorial/tile-wide.png -------------------------------------------------------------------------------- /playground/deploy-SimpleStore.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | solar deploy ./contracts/SimpleStore.sol '["1"]' --gasPrice=0.0000001 --force 4 | -------------------------------------------------------------------------------- /testing/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #Test openzeppelin integration 3 | make openzeppelin 4 | #Test Aave integration 5 | cd aave 6 | npm run test 7 | -------------------------------------------------------------------------------- /testing/openzeppelin/trim-github-logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # removes first 29 characters from file 3 | sed -i -r 's/.{29}//' truffle-expected-output.json 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | #ingore testing components 2 | /testing 3 | /playground 4 | /metamask 5 | /https 6 | /logs 7 | /.vscode 8 | /.idea 9 | janusLogs.txt 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "testing/openzeppelin-contracts"] 2 | path = testing/openzeppelin/openzeppelin-contracts 3 | url = https://github.com/OpenZeppelin/openzeppelin-contracts.git 4 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/migrations/3_deploy_token.js: -------------------------------------------------------------------------------- 1 | var QRC20 = artifacts.require("QRC20Token"); 2 | 3 | module.exports = async function(deployer) { 4 | await deployer.deploy(QRC20); 5 | }; -------------------------------------------------------------------------------- /playground/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = async function(deployer) { 4 | await deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var Adoption = artifacts.require("Adoption"); 2 | 3 | module.exports = async function(deployer) { 4 | await deployer.deploy(Adoption); 5 | }; -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/qtumproject/janus/cli" 7 | ) 8 | 9 | func main() { 10 | log.SetFlags(log.LstdFlags | log.Llongfile) 11 | cli.Run() 12 | } 13 | -------------------------------------------------------------------------------- /pkg/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | func InStrSlice(s []string, str string) bool { 4 | for _, v := range s { 5 | if v == str { 6 | return true 7 | } 8 | } 9 | 10 | return false 11 | } 12 | -------------------------------------------------------------------------------- /playground/migrations/2_deploy_simpleStore.js: -------------------------------------------------------------------------------- 1 | var SimpleStore = artifacts.require("./SimpleStore.sol"); 2 | 3 | module.exports = async function(deployer) { 4 | await deployer.deploy(SimpleStore, ["100"]); 5 | }; 6 | -------------------------------------------------------------------------------- /docker/unittests.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.18 2 | 3 | WORKDIR $GOPATH/src/github.com/qtumproject/janus 4 | COPY . $GOPATH/src/github.com/qtumproject/janus 5 | RUN go get -d ./... 6 | 7 | CMD [ "go", "test", "-v", "./..."] -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = async function(deployer) { 4 | await deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: deploy-contracts 3 | deploy-contracts: 4 | truffle migrate --reset 5 | cp ./build/contracts/*.json ./js 6 | 7 | .PHONY: serve-pet-shop 8 | serve-pet-shop: 9 | npm run dev 10 | -------------------------------------------------------------------------------- /docker/qtum-seeded.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM qtum/qtum 2 | 3 | COPY ./fill_user_account.sh ./ 4 | COPY ./populate_and_run.sh ./ 5 | RUN chmod +x ./fill_user_account.sh 6 | RUN chmod +x ./populate_and_run.sh 7 | 8 | ENTRYPOINT [ "./populate_and_run.sh" ] -------------------------------------------------------------------------------- /playground/contracts/MyToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | import "./openzeppelin-solidity/contracts/token/ERC20/CappedToken.sol"; 4 | 5 | contract MyToken is CappedToken { 6 | constructor(uint256 _cap) CappedToken(_cap) public {} 7 | } 8 | -------------------------------------------------------------------------------- /playground/migrations/3_deploy_myToken.js: -------------------------------------------------------------------------------- 1 | var MyToken = artifacts.require("./MyToken.sol"); 2 | 3 | module.exports = async function(deployer) { 4 | await deployer.deploy(MyToken, 9999999999999, {from: "0x7926223070547d2d15b2ef5e7383e541c338ffe9"}); 5 | }; 6 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/.gitignore: -------------------------------------------------------------------------------- 1 | # Include your project-specific ignores in this file 2 | # Read about how to use .gitignore: https://help.github.com/articles/ignoring-files 3 | # Useful .gitignore templates: https://github.com/github/gitignore 4 | node_modules 5 | dist 6 | .cache -------------------------------------------------------------------------------- /testing/aave/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .env 3 | #Buidler files 4 | cache 5 | artifacts 6 | node_modules 7 | dist/ 8 | build/ 9 | .vscode 10 | .idea 11 | /types 12 | 13 | deployed-contracts.json 14 | 15 | coverage 16 | .coverage_artifacts 17 | .coverage_cache 18 | .coverage_contracts 19 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "", 3 | "name": "", 4 | "icons": [{ 5 | "src": "icon.png", 6 | "type": "image/png", 7 | "sizes": "192x192" 8 | }], 9 | "start_url": "/?utm_source=homescreen", 10 | "background_color": "#fafafa", 11 | "theme_color": "#fafafa" 12 | } 13 | -------------------------------------------------------------------------------- /playground/node-myToken-commands.txt: -------------------------------------------------------------------------------- 1 | export ACC1="0x7926223070547d2d15b2ef5e7383e541c338ffe9" 2 | export ACC2="0x3a895d2af552600f1f585425318c13a5aa25f01a" 3 | 4 | node myToken.js mint ${ACC1} 100 5 | 6 | node myToken.js balance ${ACC1} 7 | 8 | node myToken.js transfer ${ACC1} ${ACC2} 1 9 | 10 | node myToken.js balance ${ACC2} 11 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/humans.txt: -------------------------------------------------------------------------------- 1 | # humanstxt.org/ 2 | # The humans responsible & technology colophon 3 | 4 | # TEAM 5 | 6 | -- -- 7 | 8 | # THANKS 9 | 10 | 11 | 12 | # TECHNOLOGY COLOPHON 13 | 14 | CSS3, HTML5 15 | Apache Server Configs, jQuery, Modernizr, Normalize.css 16 | -------------------------------------------------------------------------------- /myaccounts.txt: -------------------------------------------------------------------------------- 1 | cMbgxCJrTYUqgcmiC1berh5DFrtY1KeU4PXZ6NZxgenniF1mXCRk 2 | cRcG1jizfBzHxfwu68aMjhy78CpnzD9gJYZ5ggDbzfYD3EQfGUDZ 3 | cV79qBoCSA2NDrJz8S3T7J8f3zgkGfg4ua4hRRXfhbnq5VhXkukT 4 | cV93kaaV8hvNqZ711s2z9jVWLYEtwwsVpyFeEZCP6otiZgrCTiEW 5 | cVPHpTvmv3UjQsZfsMRrW5RrGCyTSAZ3MWs1f8R1VeKJSYxy5uac 6 | cTs5NqY4Ko9o6FESHGBDEG77qqz9me7cyYCoinHcWEiqMZgLC6XY 7 | -------------------------------------------------------------------------------- /docker/spin_up.regtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | docker-compose -f ${GOPATH}/src/github.com/qtumproject/janus/docker/quick_start/docker-compose.regtest.yml up -d 3 | sleep 3 #executing too fast causes some errors 4 | docker cp ${GOPATH}/src/github.com/qtumproject/janus/docker/fill_user_account.sh qtum_regtest:. 5 | docker exec qtum_regtest /bin/sh -c ./fill_user_account.sh -------------------------------------------------------------------------------- /metamask/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /docker/spin_up.mainnet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | docker-compose -f ${GOPATH}/src/github.com/qtumproject/janus/docker/quick_start/docker-compose.mainnet.yml up -d 3 | # sleep 3 #executing too fast causes some errors 4 | # docker cp ${GOPATH}/src/github.com/qtumproject/janus/docker/fill_user_account.sh qtum_testchain:. 5 | # docker exec qtum_mainnet /bin/sh -c ./fill_user_account.sh -------------------------------------------------------------------------------- /docker/spin_up.testnet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | docker-compose -f ${GOPATH}/src/github.com/qtumproject/janus/docker/quick_start/docker-compose.testnet.yml up -d 3 | # sleep 3 #executing too fast causes some errors 4 | # docker cp ${GOPATH}/src/github.com/qtumproject/janus/docker/fill_user_account.sh qtum_testchain:. 5 | # docker exec qtum_testnet /bin/sh -c ./fill_user_account.sh -------------------------------------------------------------------------------- /docker/standalone/myaccounts.txt: -------------------------------------------------------------------------------- 1 | cMbgxCJrTYUqgcmiC1berh5DFrtY1KeU4PXZ6NZxgenniF1mXCRk 2 | cRcG1jizfBzHxfwu68aMjhy78CpnzD9gJYZ5ggDbzfYD3EQfGUDZ 3 | cV79qBoCSA2NDrJz8S3T7J8f3zgkGfg4ua4hRRXfhbnq5VhXkukT 4 | cV93kaaV8hvNqZ711s2z9jVWLYEtwwsVpyFeEZCP6otiZgrCTiEW 5 | cVPHpTvmv3UjQsZfsMRrW5RrGCyTSAZ3MWs1f8R1VeKJSYxy5uac 6 | cTs5NqY4Ko9o6FESHGBDEG77qqz9me7cyYCoinHcWEiqMZgLC6XY -------------------------------------------------------------------------------- /testing/aave/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint-config-prettier"], 3 | "rulesDirectory": ["tslint-plugin-prettier"], 4 | "rules": { 5 | "prettier": true, 6 | "max-line-length": [true, 100], 7 | "import-name": false 8 | }, 9 | "linterOptions": { 10 | "exclude": ["src/migration/**", "src/contracts/ABI/**"] 11 | } 12 | } -------------------------------------------------------------------------------- /pkg/transformer/notifier.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/notifier" 6 | ) 7 | 8 | func getNotifier(c echo.Context) *notifier.Notifier { 9 | storedValue := c.Get("notifier") 10 | notifier, ok := storedValue.(*notifier.Notifier) 11 | if !ok { 12 | return nil 13 | } 14 | return notifier 15 | } 16 | -------------------------------------------------------------------------------- /testing/truffle-parser.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.14-alpine 2 | 3 | RUN echo $GOPATH 4 | RUN apk add --no-cache make gcc musl-dev git 5 | WORKDIR $GOPATH/src/github.com/qtumproject/truffle-parser 6 | COPY ./main.go $GOPATH/src/github.com/qtumproject/truffle-parser 7 | RUN go get -d ./... 8 | RUN go install github.com/qtumproject/truffle-parser/ 9 | 10 | ENTRYPOINT [ "truffle-parser" ] -------------------------------------------------------------------------------- /playground/docker/myaccounts.txt: -------------------------------------------------------------------------------- 1 | L42ijXgcx42jGGe8Ei2TazrMG3TWRBecBPUqqvE2qWgGVXFoFwZS 2 | cMbgxCJrTYUqgcmiC1berh5DFrtY1KeU4PXZ6NZxgenniF1mXCRk 3 | cRcG1jizfBzHxfwu68aMjhy78CpnzD9gJYZ5ggDbzfYD3EQfGUDZ 4 | cV79qBoCSA2NDrJz8S3T7J8f3zgkGfg4ua4hRRXfhbnq5VhXkukT 5 | cV93kaaV8hvNqZ711s2z9jVWLYEtwwsVpyFeEZCP6otiZgrCTiEW 6 | cVPHpTvmv3UjQsZfsMRrW5RrGCyTSAZ3MWs1f8R1VeKJSYxy5uac 7 | cTs5NqY4Ko9o6FESHGBDEG77qqz9me7cyYCoinHcWEiqMZgLC6XY -------------------------------------------------------------------------------- /pkg/transformer/type.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/labstack/echo" 7 | "github.com/qtumproject/janus/pkg/eth" 8 | ) 9 | 10 | var UnmarshalRequestErr = errors.New("Input is invalid") 11 | 12 | type Option func(*Transformer) error 13 | 14 | type ETHProxy interface { 15 | Request(*eth.JSONRPCRequest, echo.Context) (interface{}, eth.JSONRPCError) 16 | Method() string 17 | } 18 | -------------------------------------------------------------------------------- /docker/go-build.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG GO_VERSION=1.18 2 | ARG ALPINE_VERSION=3.16 3 | 4 | FROM golang:${GO_VERSION}-alpine as builder 5 | RUN apk add --no-cache make gcc musl-dev git 6 | 7 | WORKDIR $GOPATH/src/github.com/qtumproject/janus 8 | COPY go.mod go.sum $GOPATH/src/github.com/qtumproject/janus/ 9 | 10 | # Cache go modules 11 | RUN go mod download -x 12 | 13 | ARG GIT_SHA 14 | ENV CGO_ENABLED=0 15 | ENV GIT_SHA=$GIT_SH 16 | 17 | ENTRYPOINT [ "go" ] 18 | -------------------------------------------------------------------------------- /pkg/transformer/eth_protocolVersion.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | ) 7 | 8 | type ETHProtocolVersion struct { 9 | } 10 | 11 | func (p *ETHProtocolVersion) Method() string { 12 | return "eth_protocolVersion" 13 | } 14 | 15 | func (p *ETHProtocolVersion) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 16 | return "0x41", nil 17 | } 18 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/contracts/Adoption.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | 3 | contract Adoption { 4 | address[16] public adopters; 5 | 6 | function adopt(uint petId) public returns (uint) { 7 | require(petId >= 0 && petId <= 15); 8 | 9 | adopters[petId] = msg.sender; 10 | 11 | return petId; 12 | } 13 | 14 | function getAdopters() public view returns (address[16] memory) { 15 | return adopters; 16 | } 17 | } -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getCompilers.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | ) 7 | 8 | type ETHGetCompilers struct { 9 | } 10 | 11 | func (p *ETHGetCompilers) Method() string { 12 | return "eth_getCompilers" 13 | } 14 | 15 | func (p *ETHGetCompilers) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 16 | // hardcoded to empty 17 | return []string{}, nil 18 | } 19 | -------------------------------------------------------------------------------- /playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "ethers": "^5.2.0", 8 | "minimist": "^1.2.0", 9 | "ora": "^3.0.0", 10 | "qtumjs": "ceoimon/qtumjs-eth#master", 11 | "truffle": "^4.1.13", 12 | "truffle-contract": "^3.0.6", 13 | "truffle-require": "^1.0.7" 14 | }, 15 | "scripts": { 16 | "postinstall": "cd node_modules/qtumjs/ && yarn && yarn build ; cd ../../ " 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getUncleCountByBlockHash.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | ) 7 | 8 | type ETHGetUncleCountByBlockHash struct { 9 | } 10 | 11 | func (p *ETHGetUncleCountByBlockHash) Method() string { 12 | return "eth_getUncleCountByBlockHash" 13 | } 14 | 15 | func (p *ETHGetUncleCountByBlockHash) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 16 | // hardcoded to 0 17 | return 0, nil 18 | } 19 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getUncleCountByBlockNumber.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | ) 7 | 8 | type ETHGetUncleCountByBlockNumber struct { 9 | } 10 | 11 | func (p *ETHGetUncleCountByBlockNumber) Method() string { 12 | return "eth_getUncleCountByBlockNumber" 13 | } 14 | 15 | func (p *ETHGetUncleCountByBlockNumber) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 16 | // hardcoded to 0 17 | return "0x0", nil 18 | } 19 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getUncleByBlockHashAndIndex.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | ) 7 | 8 | type ETHGetUncleByBlockHashAndIndex struct { 9 | } 10 | 11 | func (p *ETHGetUncleByBlockHashAndIndex) Method() string { 12 | return "eth_getUncleByBlockHashAndIndex" 13 | } 14 | 15 | func (p *ETHGetUncleByBlockHashAndIndex) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 16 | // hardcoded to nil 17 | return nil, nil 18 | } 19 | -------------------------------------------------------------------------------- /playground/contracts/SimpleStore.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | contract SimpleStore { 3 | event UpdateValue( 4 | address from, 5 | uint _oldValue, 6 | uint indexed _newValue 7 | ); 8 | 9 | constructor(uint _value) public { 10 | value = _value; 11 | } 12 | 13 | function set(uint newValue) public { 14 | emit UpdateValue(msg.sender, value, newValue); 15 | value = newValue; 16 | } 17 | 18 | function get() public constant returns (uint) { 19 | return value; 20 | } 21 | 22 | uint value; 23 | } 24 | -------------------------------------------------------------------------------- /playground/contracts/openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | /** 5 | * @title ERC20Basic 6 | * @dev Simpler version of ERC20 interface 7 | * See https://github.com/ethereum/EIPs/issues/179 8 | */ 9 | contract ERC20Basic { 10 | function totalSupply() public view returns (uint256); 11 | function balanceOf(address who) public view returns (uint256); 12 | function transfer(address to, uint256 value) public returns (bool); 13 | event Transfer(address indexed from, address indexed to, uint256 value); 14 | } 15 | -------------------------------------------------------------------------------- /pkg/transformer/eth_personal_unlockAccount.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | ) 7 | 8 | // ProxyETHPersonalUnlockAccount implements ETHProxy 9 | type ProxyETHPersonalUnlockAccount struct{} 10 | 11 | func (p *ProxyETHPersonalUnlockAccount) Method() string { 12 | return "personal_unlockAccount" 13 | } 14 | 15 | func (p *ProxyETHPersonalUnlockAccount) Request(req *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 16 | return eth.PersonalUnlockAccountResponse(true), nil 17 | } 18 | -------------------------------------------------------------------------------- /testing/web3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@openzeppelin/contracts": "^3.4.0", 8 | "@openzeppelin/test-helpers": "^0.5.10", 9 | "chai": "^4.3.0", 10 | "minimist": "^1.2.0", 11 | "ora": "^3.0.0", 12 | "qtumjs": "ceoimon/qtumjs-eth#master", 13 | "truffle": "^4.1.13", 14 | "truffle-contract": "^3.0.6", 15 | "truffle-require": "^1.0.7" 16 | }, 17 | "scripts": { 18 | "postinstall": "cd node_modules/qtumjs/ && yarn && yarn build ; cd ../../ " 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /metamask/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metamask", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "bootstrap-vue": "^2.21.2", 11 | "vue": "^2.6.11", 12 | "vue-router": "^3.2.0", 13 | "web3": "^1.3.5" 14 | }, 15 | "devDependencies": { 16 | "@vue/cli-plugin-router": "~4.5.0", 17 | "@vue/cli-service": "~4.5.0", 18 | "vue-template-compiler": "^2.6.11" 19 | }, 20 | "browserslist": [ 21 | "> 1%", 22 | "last 2 versions", 23 | "not dead" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | constructor() public { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /metamask/src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 33 | -------------------------------------------------------------------------------- /metamask/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import Web3 from'web3' 5 | import { BootstrapVue } from 'bootstrap-vue' 6 | 7 | // Import Bootstrap an BootstrapVue CSS files (order is important) 8 | import 'bootstrap/dist/css/bootstrap.css' 9 | import 'bootstrap-vue/dist/bootstrap-vue.css' 10 | 11 | Vue.config.productionTip = false 12 | // Make BootstrapVue available throughout your project 13 | Vue.use(BootstrapVue) 14 | if (window.qtum) { 15 | Vue.prototype.Web3 = new Web3(window.qtum.currentProvider); 16 | } 17 | 18 | new Vue({ 19 | router, 20 | render: function (h) { return h(App) }, 21 | }).$mount('#app') 22 | -------------------------------------------------------------------------------- /testing/web3/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "127.0.0.1", 5 | port: 23888, //Switch to 23888 for local HTTP Server, look at Makefile run-janus 6 | network_id: "*", 7 | gasPrice: "0x64" 8 | }, 9 | ganache: { 10 | host: "127.0.0.1", 11 | port: 8545, 12 | network_id: "*" 13 | }, 14 | testnet: { 15 | host: "hk1.s.qtum.org", 16 | port: 23889, 17 | network_id: "*", 18 | from: "0x7926223070547d2d15b2ef5e7383e541c338ffe9", 19 | gasPrice: "0x64" 20 | } 21 | }, 22 | compilers: { 23 | solc: { 24 | version: "^0.6.12", 25 | } 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /metamask/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /playground/contracts/openzeppelin-solidity/contracts/token/ERC20/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./ERC20Basic.sol"; 4 | 5 | 6 | /** 7 | * @title ERC20 interface 8 | * @dev see https://github.com/ethereum/EIPs/issues/20 9 | */ 10 | contract ERC20 is ERC20Basic { 11 | function allowance(address owner, address spender) 12 | public view returns (uint256); 13 | 14 | function transferFrom(address from, address to, uint256 value) 15 | public returns (bool); 16 | 17 | function approve(address spender, uint256 value) public returns (bool); 18 | event Approval( 19 | address indexed owner, 20 | address indexed spender, 21 | uint256 value 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /testing/aave/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2019", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "outDir": "dist", 8 | "noImplicitAny": false, 9 | "resolveJsonModule": true 10 | }, 11 | "include": ["./scripts", "./test", "./tasks"], 12 | "files": [ 13 | "./modules/tenderly/tenderly.d.ts", 14 | "node_modules/@nomiclabs/buidler-ethers/src/type-extensions.d.ts", 15 | "node_modules/buidler-typechain/src/type-extensions.d.ts", 16 | "node_modules/@nomiclabs/buidler-waffle/src/type-extensions.d.ts", 17 | "node_modules/@nomiclabs/buidler-etherscan/src/type-extensions.d.ts" 18 | ] 19 | } -------------------------------------------------------------------------------- /pkg/transformer/eth_getCompilers_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | ) 9 | 10 | func TestGetCompilersReturnsEmptyArray(t *testing.T) { 11 | //preparing the request 12 | requestParams := []json.RawMessage{} //eth_getCompilers has no params 13 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | 18 | proxyEth := ETHGetCompilers{} 19 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 20 | if jsonErr != nil { 21 | t.Fatal(jsonErr) 22 | } 23 | 24 | want := []string{} 25 | 26 | internal.CheckTestResultDefault(want, got, t, false) 27 | } 28 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getTransactionByBlockHashAndIndex_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | "github.com/qtumproject/janus/pkg/qtum" 9 | ) 10 | 11 | func initializeProxyETHGetTransactionByBlockHashAndIndex(qtumClient *qtum.Qtum) ETHProxy { 12 | return &ProxyETHGetTransactionByBlockHashAndIndex{qtumClient} 13 | } 14 | 15 | func TestGetTransactionByBlockHashAndIndex(t *testing.T) { 16 | testETHProxyRequest( 17 | t, 18 | initializeProxyETHGetTransactionByBlockHashAndIndex, 19 | []json.RawMessage{[]byte(`"` + internal.GetTransactionByHashBlockHash + `"`), []byte(`"0x0"`)}, 20 | internal.GetTransactionByHashResponseData, 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/contracts/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | 3 | /* taking ideas from FirstBlood token */ 4 | contract SafeMath { 5 | 6 | constructor() { 7 | } 8 | 9 | function safeAdd(uint256 _x, uint256 _y) pure internal returns (uint256) { 10 | uint256 z = _x + _y; 11 | assert(z >= _x); 12 | return z; 13 | } 14 | 15 | function safeSub(uint256 _x, uint256 _y) pure internal returns (uint256) { 16 | assert(_x >= _y); 17 | return _x - _y; 18 | } 19 | 20 | function safeMul(uint256 _x, uint256 _y) pure internal returns (uint256) { 21 | uint256 z = _x * _y; 22 | assert(_x == 0 || z / _x == _y); 23 | return z; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /pkg/transformer/eth_protocolVersion_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | ) 9 | 10 | func TestProtocolVersionReturnsHardcodedValue(t *testing.T) { 11 | //preparing the request 12 | requestParams := []json.RawMessage{} //eth_protocolVersion has no params 13 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | 18 | proxyEth := ETHProtocolVersion{} 19 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 20 | if jsonErr != nil { 21 | t.Fatal(jsonErr) 22 | } 23 | 24 | want := "0x41" 25 | 26 | internal.CheckTestResultDefault(want, got, t, false) 27 | } 28 | -------------------------------------------------------------------------------- /testing/revert-reasons/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "127.0.0.1", 5 | port: 23888, //Switch to 23888 for local HTTP Server, look at Makefile run-janus 6 | network_id: "*", 7 | gasPrice: "0x64" 8 | }, 9 | ganache: { 10 | host: "127.0.0.1", 11 | port: 8545, 12 | network_id: "*" 13 | }, 14 | testnet: { 15 | host: "hk1.s.qtum.org", 16 | port: 23889, 17 | network_id: "*", 18 | from: "0x7926223070547d2d15b2ef5e7383e541c338ffe9", 19 | gasPrice: "0x64" 20 | } 21 | }, 22 | compilers: { 23 | solc: { 24 | version: "^0.6.12", 25 | } 26 | }, 27 | } -------------------------------------------------------------------------------- /pkg/transformer/eth_getTransactionByBlockNumberAndIndex_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | "github.com/qtumproject/janus/pkg/qtum" 9 | ) 10 | 11 | func initializeProxyETHGetTransactionByBlockNumberAndIndex(qtumClient *qtum.Qtum) ETHProxy { 12 | return &ProxyETHGetTransactionByBlockNumberAndIndex{qtumClient} 13 | } 14 | 15 | func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { 16 | testETHProxyRequest( 17 | t, 18 | initializeProxyETHGetTransactionByBlockNumberAndIndex, 19 | []json.RawMessage{[]byte(`"` + internal.GetTransactionByHashBlockNumberHex + `"`), []byte(`"0x0"`)}, 20 | internal.GetTransactionByHashResponseData, 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /metamask/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | import Home from '../views/Home.vue' 4 | 5 | Vue.use(VueRouter) 6 | 7 | const routes = [ 8 | { 9 | path: '/', 10 | name: 'Home', 11 | component: Home 12 | }, 13 | { 14 | path: '/about', 15 | name: 'About', 16 | // route level code-splitting 17 | // this generates a separate chunk (about.[hash].js) for this route 18 | // which is lazy-loaded when the route is visited. 19 | component: function () { 20 | return import(/* webpackChunkName: "about" */ '../views/About.vue') 21 | } 22 | } 23 | ] 24 | 25 | const router = new VueRouter({ 26 | mode: 'history', 27 | base: process.env.BASE_URL, 28 | routes 29 | }) 30 | 31 | export default router 32 | -------------------------------------------------------------------------------- /playground/truffle-myToken-commands.txt: -------------------------------------------------------------------------------- 1 | var token 2 | 3 | # qcli gethexaddress qUbxboqjBRp96j3La8D1RYkyqx5uQbJPoW 4 | # 7926223070547d2d15b2ef5e7383e541c338ffe9 5 | 6 | # qcli gethexaddress qLn9vqbr2Gx3TsVR9QyTVB5mrMoh4x43Uf 7 | # 2352be3db3177f0a07efbe6da5857615b8c9901d 8 | 9 | var acc1 = "0x7926223070547d2d15b2ef5e7383e541c338ffe9" 10 | var acc2 = "0x2352be3db3177f0a07efbe6da5857615b8c9901d" 11 | 12 | MyToken.deployed().then(function(i) { token = i }) 13 | 14 | token.totalSupply().then(function(res) { console.log(res.toNumber()) }) 15 | 16 | token.balanceOf(acc1).then(function(res) { console.log(res.toNumber()) }) 17 | 18 | token.balanceOf(acc2).then(function(res) { console.log(res.toNumber()) }) 19 | 20 | token.mint(acc1, 100) 21 | 22 | token.transfer(acc2, 10, {from: acc1}) 23 | -------------------------------------------------------------------------------- /pkg/params/version.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | import "fmt" 4 | 5 | const ( 6 | unstable = "unstable" 7 | stable = "stable" 8 | VersionMajor = 0 // Major version component of the current release 9 | VersionMinor = 4 // Minor version component of the current release 10 | VersionPatch = 2 // Patch version component of the current release 11 | VersionMeta = unstable // Version metadata to append to the version string 12 | ) 13 | 14 | var GitSha = "development" 15 | 16 | var Version = func() string { 17 | return fmt.Sprintf("%d.%d.%d", VersionMajor, VersionMinor, VersionPatch) 18 | }() 19 | 20 | var VersionWithGitSha = func() string { 21 | if len(GitSha) == 0 { 22 | GitSha = "unknown" 23 | } 24 | return fmt.Sprintf("%s-%s", Version, GitSha) 25 | }() 26 | -------------------------------------------------------------------------------- /docker/configure_https.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -f "/https/cert.pem" ]; then 4 | echo "cert.pem already exists" 5 | if [ ! -f "/https/key.pem" ]; then 6 | echo "key.pem does not exist, both are needed, please delete "`pwd`"/https/key.pem manually" 7 | exit 1 8 | fi 9 | exit 0 10 | fi 11 | 12 | mkdir -p /https 13 | if [ ! -d "/https" ]; then 14 | echo "Failed to mkdir -p /https" 15 | exit 1 16 | fi 17 | 18 | echo "Generating key.pem and cert.pem" 19 | openssl req -nodes -x509 -newkey rsa:4096 -keyout /https/key.pem -out /https/cert.pem -days 365 -subj "/C=US/ST=ST/L=L/O=Janus Self-signed https/OU=Janus Self-signed https/CN=Janus Self-signed https" 20 | if [ 0 -ne $? ]; then 21 | echo "Failed to generate server.key" 22 | exit $? 23 | fi 24 | 25 | exit 0 26 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getUncleByBlockHashAndIndex_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | ) 9 | 10 | func TestGetUncleByBlockHashAndIndexReturnsNil(t *testing.T) { 11 | // request body doesn't matter, there is no QTUM object to proxy calls to 12 | requestParams := []json.RawMessage{} 13 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | 18 | proxyEth := ETHGetUncleByBlockHashAndIndex{} 19 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 20 | if jsonErr != nil { 21 | t.Fatal(jsonErr) 22 | } 23 | 24 | want := interface{}(nil) 25 | 26 | internal.CheckTestResultEthRequestRPC(*request, want, got, t, false) 27 | } 28 | -------------------------------------------------------------------------------- /testing/openzeppelin/openzeppelin.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-bullseye 2 | 3 | RUN npm install -g truffle --loglevel verbose 4 | RUN npm install -g mocha-spec-json-output-reporter 5 | RUN mkdir -p openzeppelin-contracts 6 | WORKDIR /openzeppelin-contracts 7 | COPY ./openzeppelin-contracts/package.json /openzeppelin-contracts 8 | COPY ./openzeppelin-contracts/hardhat /openzeppelin-contracts/hardhat 9 | COPY ./openzeppelin-contracts/hardhat.config.js /openzeppelin-contracts 10 | RUN yarn install 11 | COPY ./openzeppelin-contracts/contracts /openzeppelin-contracts/contracts 12 | COPY ./truffle-config.js / 13 | RUN truffle compile 14 | COPY ./openzeppelin-contracts/scripts /openzeppelin-contracts/scripts 15 | COPY ./openzeppelin-contracts/ /openzeppelin-contracts 16 | COPY ./truffle-config.js / 17 | 18 | CMD [ "truffle", "test" ] 19 | -------------------------------------------------------------------------------- /pkg/transformer/eth_chainId.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/common/hexutil" 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | ) 11 | 12 | type ProxyETHChainId struct { 13 | *qtum.Qtum 14 | } 15 | 16 | func (p *ProxyETHChainId) Method() string { 17 | return "eth_chainId" 18 | } 19 | 20 | func (p *ProxyETHChainId) Request(req *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 21 | chainId, err := getChainId(p.Qtum) 22 | if err != nil { 23 | return nil, err 24 | } 25 | return eth.ChainIdResponse(hexutil.EncodeBig(chainId)), nil 26 | } 27 | 28 | func getChainId(p *qtum.Qtum) (*big.Int, eth.JSONRPCError) { 29 | return big.NewInt(int64(p.ChainId())), nil 30 | } 31 | -------------------------------------------------------------------------------- /pkg/transformer/log.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/go-kit/kit/log" 5 | "github.com/go-kit/kit/log/level" 6 | "github.com/qtumproject/janus/pkg/qtum" 7 | ) 8 | 9 | func GetLogger(proxy ETHProxy, q *qtum.Qtum) log.Logger { 10 | method := proxy.Method() 11 | logger := q.Client.GetLogger() 12 | return log.WithPrefix(level.Info(logger), method) 13 | } 14 | 15 | func GetLoggerFromETHCall(proxy *ProxyETHCall) log.Logger { 16 | return GetLogger(proxy, proxy.Qtum) 17 | } 18 | 19 | func GetDebugLogger(proxy ETHProxy, q *qtum.Qtum) log.Logger { 20 | method := proxy.Method() 21 | logger := q.Client.GetDebugLogger() 22 | return log.WithPrefix(level.Debug(logger), method) 23 | } 24 | 25 | func GetDebugLoggerFromETHCall(proxy *ProxyETHCall) log.Logger { 26 | return GetDebugLogger(proxy, proxy.Qtum) 27 | } 28 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/js/plugins.js: -------------------------------------------------------------------------------- 1 | // Avoid `console` errors in browsers that lack a console. 2 | (function() { 3 | var method; 4 | var noop = function () {}; 5 | var methods = [ 6 | 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 7 | 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 8 | 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', 9 | 'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn' 10 | ]; 11 | var length = methods.length; 12 | var console = (window.console = window.console || {}); 13 | 14 | while (length--) { 15 | method = methods[length]; 16 | 17 | // Only stub undefined methods. 18 | if (!console[method]) { 19 | console[method] = noop; 20 | } 21 | } 22 | }()); 23 | 24 | // Place any jQuery/helper plugins in here. 25 | -------------------------------------------------------------------------------- /pkg/transformer/eth_net_version.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common/hexutil" 5 | "github.com/labstack/echo" 6 | "github.com/qtumproject/janus/pkg/eth" 7 | "github.com/qtumproject/janus/pkg/qtum" 8 | ) 9 | 10 | // ProxyETHNetVersion implements ETHProxy 11 | type ProxyETHNetVersion struct { 12 | *qtum.Qtum 13 | } 14 | 15 | func (p *ProxyETHNetVersion) Method() string { 16 | return "net_version" 17 | } 18 | 19 | func (p *ProxyETHNetVersion) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 20 | return p.request() 21 | } 22 | 23 | func (p *ProxyETHNetVersion) request() (*eth.NetVersionResponse, eth.JSONRPCError) { 24 | networkID, err := getChainId(p.Qtum) 25 | if err != nil { 26 | return nil, err 27 | } 28 | response := eth.NetVersionResponse(hexutil.EncodeBig(networkID)) 29 | return &response, nil 30 | } 31 | -------------------------------------------------------------------------------- /pkg/transformer/eth_net_listening.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | "github.com/qtumproject/janus/pkg/qtum" 7 | ) 8 | 9 | // ProxyETHGetCode implements ETHProxy 10 | type ProxyNetListening struct { 11 | *qtum.Qtum 12 | } 13 | 14 | func (p *ProxyNetListening) Method() string { 15 | return "net_listening" 16 | } 17 | 18 | func (p *ProxyNetListening) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 19 | networkInfo, err := p.GetNetworkInfo(c.Request().Context()) 20 | if err != nil { 21 | p.GetDebugLogger().Log("method", p.Method(), "msg", "Failed to query network info", "err", err) 22 | return false, eth.NewCallbackError(err.Error()) 23 | } 24 | 25 | p.GetDebugLogger().Log("method", p.Method(), "network active", networkInfo.NetworkActive) 26 | return networkInfo.NetworkActive, nil 27 | } 28 | -------------------------------------------------------------------------------- /playground/contracts/openzeppelin-solidity/contracts/token/ERC20/CappedToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./MintableToken.sol"; 4 | 5 | 6 | /** 7 | * @title Capped token 8 | * @dev Mintable token with a token cap. 9 | */ 10 | contract CappedToken is MintableToken { 11 | 12 | uint256 public cap; 13 | 14 | constructor(uint256 _cap) public { 15 | require(_cap > 0); 16 | cap = _cap; 17 | } 18 | 19 | /** 20 | * @dev Function to mint tokens 21 | * @param _to The address that will receive the minted tokens. 22 | * @param _amount The amount of tokens to mint. 23 | * @return A boolean that indicates if the operation was successful. 24 | */ 25 | function mint( 26 | address _to, 27 | uint256 _amount 28 | ) 29 | public 30 | returns (bool) 31 | { 32 | require(totalSupply_.add(_amount) <= cap); 33 | 34 | return super.mint(_to, _amount); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /pkg/transformer/web3_clientVersion.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "runtime" 5 | 6 | "github.com/labstack/echo" 7 | "github.com/qtumproject/janus/pkg/eth" 8 | "github.com/qtumproject/janus/pkg/params" 9 | ) 10 | 11 | // Web3ClientVersion implements web3_clientVersion 12 | type Web3ClientVersion struct { 13 | // *qtum.Qtum 14 | } 15 | 16 | func (p *Web3ClientVersion) Method() string { 17 | return "web3_clientVersion" 18 | } 19 | 20 | func (p *Web3ClientVersion) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 21 | return "Janus/" + params.VersionWithGitSha + "/" + runtime.GOOS + "-" + runtime.GOARCH + "/" + runtime.Version(), nil 22 | } 23 | 24 | // func (p *Web3ClientVersion) ToResponse(ethresp *qtum.CallContractResponse) *eth.CallResponse { 25 | // data := utils.AddHexPrefix(ethresp.ExecutionResult.Output) 26 | // qtumresp := eth.CallResponse(data) 27 | // return &qtumresp 28 | // } 29 | -------------------------------------------------------------------------------- /testing/pull-dependencies.sh: -------------------------------------------------------------------------------- 1 | make init 2 | #Change directories and pull a different dependency 3 | cd aave/ 4 | # Initialize git repo for sparsecheckout 5 | git init 6 | # Add the desired repo to origin 7 | git remote add -f origin https://github.com/aave/protocol-v2.git 8 | # Configure sparsecheckout 9 | git config core.sparsecheckout true 10 | echo "test/*" >> .git/info/sparse-checkout 11 | echo "contracts/*" >> .git/info/sparse-checkout 12 | echo "helpers/*" >> .git/info/sparse-checkout 13 | echo "markets/*" >> .git/info/sparse-checkout 14 | echo "modules/*" >> .git/info/sparse-checkout 15 | echo "specs/*" >> .git/info/sparse-checkout 16 | echo "tasks/*" >> .git/info/sparse-checkout 17 | # Pull the desired subdirectories 18 | git pull origin master 19 | # Install dependencies 20 | sudo yarn install 21 | # Remove the git repo in order to keep track of changes outside of test/ and contracs/ 22 | rm -rf .git 23 | # Go back to /testing 24 | cd .. 25 | -------------------------------------------------------------------------------- /pkg/transformer/eth_gasPrice_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | ) 9 | 10 | func TestGasPriceRequest(t *testing.T) { 11 | //preparing request 12 | requestParams := []json.RawMessage{} 13 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | 18 | mockedClientDoer := internal.NewDoerMappedMock() 19 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 20 | if err != nil { 21 | t.Fatal(err) 22 | } 23 | 24 | //preparing proxy & executing request 25 | proxyEth := ProxyETHGasPrice{qtumClient} 26 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 27 | if jsonErr != nil { 28 | t.Fatal(jsonErr) 29 | } 30 | 31 | want := string("0x5d21dba000") //price is hardcoded inside the implement 32 | 33 | internal.CheckTestResultDefault(want, got, t, false) 34 | } 35 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // See 3 | // for more about customizing your Truffle configuration! 4 | networks: { 5 | development: { 6 | host: "127.0.0.1", 7 | port: 23889, 8 | network_id: "*", 9 | from: "0x7926223070547d2d15b2ef5e7383e541c338ffe9", 10 | gasPrice: "0x64" 11 | }, 12 | ganache: { 13 | host: "127.0.0.1", 14 | port: 8545, 15 | network_id: "*" 16 | }, 17 | testnet: { 18 | host: "hk1.s.qtum.org", 19 | port: 23889, 20 | network_id: "*", 21 | from: "0x7926223070547d2d15b2ef5e7383e541c338ffe9", 22 | gasPrice: "0x64" 23 | } 24 | }, 25 | compilers: { 26 | solc: { 27 | version: "^0.8.0", 28 | settings: { 29 | optimizer: { 30 | enabled: true, 31 | runs: 1, 32 | }, 33 | }, 34 | }, 35 | }, 36 | }; 37 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getTransactionCount_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | ) 9 | 10 | func TestGetTransactionCountRequest(t *testing.T) { 11 | //preparing request 12 | requestParams := []json.RawMessage{} 13 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | 18 | mockedClientDoer := internal.NewDoerMappedMock() 19 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 20 | if err != nil { 21 | t.Fatal(err) 22 | } 23 | 24 | //preparing proxy & executing request 25 | proxyEth := ProxyETHTxCount{qtumClient} 26 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 27 | if jsonErr != nil { 28 | t.Fatal(jsonErr) 29 | } 30 | 31 | want := string("0x1") //tx count is hardcoded inside the implement 32 | 33 | internal.CheckTestResultEthRequestRPC(*request, want, got, t, false) 34 | } 35 | -------------------------------------------------------------------------------- /pkg/transformer/eth_net_peerCount.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/dcb9/go-ethereum/common/hexutil" 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | ) 11 | 12 | // ProxyNetPeerCount implements ETHProxy 13 | type ProxyNetPeerCount struct { 14 | *qtum.Qtum 15 | } 16 | 17 | func (p *ProxyNetPeerCount) Method() string { 18 | return "net_peerCount" 19 | } 20 | 21 | func (p *ProxyNetPeerCount) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 22 | return p.request(c.Request().Context()) 23 | } 24 | 25 | func (p *ProxyNetPeerCount) request(ctx context.Context) (*eth.NetPeerCountResponse, eth.JSONRPCError) { 26 | peerInfos, err := p.GetPeerInfo(ctx) 27 | if err != nil { 28 | return nil, eth.NewCallbackError(err.Error()) 29 | } 30 | 31 | resp := eth.NetPeerCountResponse(hexutil.EncodeUint64(uint64(len(peerInfos)))) 32 | return &resp, nil 33 | } 34 | -------------------------------------------------------------------------------- /pkg/transformer/eth_gasPrice.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/common/hexutil" 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | ) 11 | 12 | // ProxyETHEstimateGas implements ETHProxy 13 | type ProxyETHGasPrice struct { 14 | *qtum.Qtum 15 | } 16 | 17 | func (p *ProxyETHGasPrice) Method() string { 18 | return "eth_gasPrice" 19 | } 20 | 21 | func (p *ProxyETHGasPrice) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 22 | qtumresp, err := p.Qtum.GetGasPrice(c.Request().Context()) 23 | if err != nil { 24 | return nil, eth.NewCallbackError(err.Error()) 25 | } 26 | 27 | // qtum res -> eth res 28 | return p.response(qtumresp), nil 29 | } 30 | 31 | func (p *ProxyETHGasPrice) response(qtumresp *big.Int) string { 32 | // 34 GWEI is the minimum price that QTUM will confirm tx with 33 | return hexutil.EncodeBig(convertFromSatoshiToWei(qtumresp)) 34 | } 35 | -------------------------------------------------------------------------------- /testing/web3/contracts/ERC20Mock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.6.0 <0.8.0; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | 7 | // mock class using ERC20 8 | contract ERC20Mock is ERC20 { 9 | constructor ( 10 | string memory name, 11 | string memory symbol, 12 | address initialAccount, 13 | uint256 initialBalance 14 | ) public payable ERC20(name, symbol) { 15 | _mint(initialAccount, initialBalance); 16 | } 17 | 18 | function mint(address account, uint256 amount) public { 19 | _mint(account, amount); 20 | } 21 | 22 | function burn(address account, uint256 amount) public { 23 | _burn(account, amount); 24 | } 25 | 26 | function transferInternal(address from, address to, uint256 value) public { 27 | _transfer(from, to, value); 28 | } 29 | 30 | function approveInternal(address owner, address spender, uint256 value) public { 31 | _approve(owner, spender, value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /testing/revert-reasons/contracts/ERC20Mock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.6.0 <0.8.0; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | 7 | // mock class using ERC20 8 | contract ERC20Mock is ERC20 { 9 | constructor ( 10 | string memory name, 11 | string memory symbol, 12 | address initialAccount, 13 | uint256 initialBalance 14 | ) public payable ERC20(name, symbol) { 15 | _mint(initialAccount, initialBalance); 16 | } 17 | 18 | function mint(address account, uint256 amount) public { 19 | _mint(account, amount); 20 | } 21 | 22 | function burn(address account, uint256 amount) public { 23 | _burn(account, amount); 24 | } 25 | 26 | function transferInternal(address from, address to, uint256 value) public { 27 | _transfer(from, to, value); 28 | } 29 | 30 | function approveInternal(address owner, address spender, uint256 value) public { 31 | _approve(owner, spender, value); 32 | } 33 | } -------------------------------------------------------------------------------- /pkg/server/pingpong.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | "time" 7 | 8 | "github.com/gorilla/websocket" 9 | ) 10 | 11 | const ( 12 | pongWait = 60 * time.Second 13 | pingPeriod = (pongWait * 9) / 10 14 | ) 15 | 16 | func pingPong(ctx context.Context, ws *websocket.Conn, writeMutex *sync.Mutex) func() { 17 | ws.SetReadDeadline(time.Now().Add(pongWait)) 18 | ws.SetPongHandler(func(string) error { 19 | ws.SetReadDeadline(time.Now().Add(pongWait)) 20 | return nil 21 | }) 22 | 23 | ticker := time.NewTicker(pingPeriod) 24 | 25 | go func(ctx context.Context, t *time.Ticker) { 26 | defer ticker.Stop() 27 | for { 28 | select { 29 | case <-ctx.Done(): 30 | return 31 | case <-t.C: 32 | writeMutex.Lock() 33 | ws.SetWriteDeadline(time.Now().Add(writeWait)) 34 | err := ws.WriteMessage(websocket.PingMessage, nil) 35 | writeMutex.Unlock() 36 | if err != nil { 37 | ws.Close() 38 | return 39 | } 40 | } 41 | } 42 | }(ctx, ticker) 43 | 44 | return ticker.Stop 45 | } 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | .idea 14 | 15 | .DS_Store 16 | build 17 | node_modules 18 | metamask/dist 19 | https 20 | janusLogs.txt 21 | 22 | # local env files 23 | .env.local 24 | .env.*.local 25 | 26 | # Log files 27 | npm-debug.log* 28 | yarn-debug.log* 29 | yarn-error.log* 30 | pnpm-debug.log* 31 | 32 | # Editor directories and files 33 | .idea 34 | .vscode 35 | *.suo 36 | *.ntvs* 37 | *.njsproj 38 | *.sln 39 | *.sw? 40 | 41 | # VS Code extension RestClient 42 | api.rest 43 | 44 | # Truffle test result files 45 | truffle-pruned-output.json 46 | truffle-result-output.json 47 | output.json 48 | testing/testing 49 | 50 | .parcel-cache 51 | playground/pet-shop-tutorial/dist 52 | playground/pet-shop-tutorial/js/Adoption.json 53 | playground/pet-shop-tutorial/js/Migrations.json 54 | playground/pet-shop-tutorial/js/QRC20Token.json 55 | 56 | -------------------------------------------------------------------------------- /pkg/transformer/eth_mining.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/labstack/echo" 7 | "github.com/qtumproject/janus/pkg/eth" 8 | "github.com/qtumproject/janus/pkg/qtum" 9 | ) 10 | 11 | //ProxyETHGetHashrate implements ETHProxy 12 | type ProxyETHMining struct { 13 | *qtum.Qtum 14 | } 15 | 16 | func (p *ProxyETHMining) Method() string { 17 | return "eth_mining" 18 | } 19 | 20 | func (p *ProxyETHMining) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 21 | return p.request(c.Request().Context()) 22 | } 23 | 24 | func (p *ProxyETHMining) request(ctx context.Context) (*eth.MiningResponse, eth.JSONRPCError) { 25 | qtumresp, err := p.Qtum.GetMining(ctx) 26 | if err != nil { 27 | return nil, eth.NewCallbackError(err.Error()) 28 | } 29 | 30 | // qtum res -> eth res 31 | return p.ToResponse(qtumresp), nil 32 | } 33 | 34 | func (p *ProxyETHMining) ToResponse(qtumresp *qtum.GetMiningResponse) *eth.MiningResponse { 35 | ethresp := eth.MiningResponse(qtumresp.Staking) 36 | return ðresp 37 | } 38 | -------------------------------------------------------------------------------- /playground/truffle-test-simpleStore.js: -------------------------------------------------------------------------------- 1 | const artifacts = require('./build/contracts/SimpleStore.json'); 2 | const contract = require('truffle-contract'); 3 | const SimpleStore = contract(artifacts); 4 | SimpleStore.setProvider(web3.currentProvider); 5 | 6 | function testGet(store) { 7 | return store.get().then(function(res) { 8 | console.log("exec: store.get()") 9 | console.log("value: ", res.toNumber()); 10 | }) 11 | } 12 | 13 | function testSet(store) { 14 | var newVal = Math.floor((Math.random() * 1000) + 1); 15 | console.log(`exec: store.set(${newVal})`) 16 | return store.set(newVal, {from: "0x7926223070547d2d15b2ef5e7383e541c338ffe9"}).then(function(res) { 17 | console.log("receipt: ", res) 18 | }).catch(function(e) { 19 | console.log(e) 20 | }) 21 | } 22 | 23 | var store; 24 | SimpleStore.deployed().then(function(i) { 25 | store = i; 26 | }).then(function() { 27 | return testGet(store) 28 | }).then(function() { 29 | return testSet(store) 30 | }).then(function() { 31 | return testGet(store) 32 | }).catch(function(e) { 33 | console.log(e) 34 | }) 35 | -------------------------------------------------------------------------------- /pkg/utils/hex_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | ) 7 | 8 | func TestConvertQtumAddress(t *testing.T) { 9 | bech32addressMainnet := "qc1q3422djj7p4mjsgn7m3k3kymd2s36jnrpzcn7xx" 10 | bech32addressTestnet := "tq1qxagv83u8vgg656de4aa04xvxe7jfzguwmg020n" 11 | legacyaddressMainnet := "QYmyzKNjoox5LkaiUvibZdM252bftQotDx" 12 | legacyAddressTesnet := "qUbxboqjBRp96j3La8D1RYkyqx5uQbJPoW" 13 | 14 | var tests = []struct { 15 | address string 16 | want string 17 | err error 18 | }{ 19 | {bech32addressMainnet, "", errors.New("invalid address")}, 20 | {bech32addressTestnet, "", errors.New("invalid address")}, 21 | {legacyaddressMainnet, "8585918c3ee7168ee9d79dd9b5883eb65d0e0db0", nil}, 22 | {legacyAddressTesnet, "7926223070547d2d15b2ef5e7383e541c338ffe9", nil}, 23 | } 24 | 25 | for _, tt := range tests { 26 | testname := tt.address 27 | t.Run(testname, func(t *testing.T) { 28 | got, _ := ConvertQtumAddress(tt.address) 29 | if got != tt.want { 30 | t.Errorf("got %s, want %s", got, tt.want) 31 | } 32 | }) 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG GO_VERSION=1.18 2 | ARG ALPINE_VERSION=3.16 3 | 4 | FROM golang:${GO_VERSION}-alpine as builder 5 | RUN apk add --no-cache make gcc musl-dev git 6 | 7 | WORKDIR $GOPATH/src/github.com/qtumproject/janus 8 | COPY go.mod go.sum $GOPATH/src/github.com/qtumproject/janus/ 9 | 10 | # Cache go modules 11 | RUN go mod download -x 12 | 13 | ARG GIT_SHA 14 | ENV CGO_ENABLED=0 15 | 16 | COPY ./ $GOPATH/src/github.com/qtumproject/janus 17 | 18 | ENV GIT_SHA=$GIT_SH 19 | 20 | RUN go build \ 21 | -ldflags \ 22 | "-X 'github.com/qtumproject/janus/pkg/params.GitSha=`./sha.sh`'" \ 23 | -o $GOPATH/bin $GOPATH/src/github.com/qtumproject/janus/... && \ 24 | rm -fr $GOPATH/src/github.com/qtumproject/janus/.git 25 | 26 | # Final stage 27 | FROM alpine:${ALPINE_VERSION} as base 28 | # Makefile supports generating ssl files from docker 29 | RUN apk add --no-cache openssl 30 | COPY --from=builder /go/bin/janus /janus 31 | 32 | ENV QTUM_RPC=http://qtum:testpasswd@localhost:3889 33 | ENV QTUM_NETWORK=auto 34 | 35 | EXPOSE 23889 36 | EXPOSE 23890 37 | 38 | ENTRYPOINT [ "/janus" ] -------------------------------------------------------------------------------- /playground/docker/init-container.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | while 3 | qcli help &> /dev/null 4 | rc=$?; if [[ $rc == 0 ]]; then break; fi 5 | do :; done 6 | 7 | balance=`qcli getbalance` 8 | if [ "${balance:0:1}" == "0" ] 9 | then 10 | set -x 11 | qcli generate 600 > /dev/null 12 | set - 13 | fi 14 | 15 | WALLETFILE=test-wallet 16 | LOCKFILE=${QTUM_DATADIR}/import-test-wallet.lock 17 | 18 | if [ ! -e $LOCKFILE ]; then 19 | while 20 | qcli getaddressesbyaccount "" &> /dev/null 21 | rc=$?; if [[ $rc != 0 ]]; then continue; fi 22 | 23 | set -x 24 | 25 | qcli importprivkey "cMbgxCJrTYUqgcmiC1berh5DFrtY1KeU4PXZ6NZxgenniF1mXCRk" # addr=qUbxboqjBRp96j3La8D1RYkyqx5uQbJPoW hdkeypath=m/88'/0'/1' 26 | qcli importprivkey "cRcG1jizfBzHxfwu68aMjhy78CpnzD9gJYZ5ggDbzfYD3EQfGUDZ" # addr=qLn9vqbr2Gx3TsVR9QyTVB5mrMoh4x43Uf hdkeypath=m/88'/0'/2' 27 | 28 | solar prefund qUbxboqjBRp96j3La8D1RYkyqx5uQbJPoW 500 29 | solar prefund qLn9vqbr2Gx3TsVR9QyTVB5mrMoh4x43Uf 500 30 | touch $LOCKFILE 31 | 32 | set - 33 | break 34 | do :; done 35 | fi 36 | -------------------------------------------------------------------------------- /pkg/transformer/tests_common.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | "github.com/qtumproject/janus/pkg/qtum" 9 | ) 10 | 11 | type ETHProxyInitializer = func(*qtum.Qtum) ETHProxy 12 | 13 | func testETHProxyRequest(t *testing.T, initializer ETHProxyInitializer, requestParams []json.RawMessage, want interface{}) { 14 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 15 | if err != nil { 16 | t.Fatal(err) 17 | } 18 | 19 | mockedClientDoer := internal.NewDoerMappedMock() 20 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 21 | 22 | internal.SetupGetBlockByHashResponses(t, mockedClientDoer) 23 | 24 | //preparing proxy & executing request 25 | proxyEth := initializer(qtumClient) 26 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 27 | if jsonErr != nil { 28 | t.Fatalf("Failed to process request on %T.Request(%s): %s", proxyEth, requestParams, jsonErr) 29 | } 30 | 31 | internal.CheckTestResultEthRequestRPC(*request, want, got, t, false) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/transformer/web3_sha3.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/ethereum/go-ethereum/common/hexutil" 7 | "github.com/ethereum/go-ethereum/crypto" 8 | "github.com/labstack/echo" 9 | "github.com/qtumproject/janus/pkg/eth" 10 | ) 11 | 12 | type Web3Sha3 struct{} 13 | 14 | func (p *Web3Sha3) Method() string { 15 | return "web3_sha3" 16 | } 17 | 18 | func (p *Web3Sha3) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 19 | var err error 20 | var req eth.Web3Sha3Request 21 | if err = json.Unmarshal(rawreq.Params, &req); err != nil { 22 | // TODO: Correct error code? 23 | return nil, eth.NewInvalidParamsError(err.Error()) 24 | } 25 | 26 | message := req.Message 27 | var decoded []byte 28 | // zero length should return "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" 29 | if len(message) != 0 { 30 | decoded, err = hexutil.Decode(string(message)) 31 | if err != nil { 32 | return nil, eth.NewCallbackError("Failed to decode") 33 | } 34 | } 35 | 36 | return hexutil.Encode(crypto.Keccak256(decoded)), nil 37 | } 38 | -------------------------------------------------------------------------------- /metamask/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 41 | -------------------------------------------------------------------------------- /pkg/eth/rpc_types_test.go: -------------------------------------------------------------------------------- 1 | package eth 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | ) 7 | 8 | func TestEthLogSubscriptionRequestSerialization(t *testing.T) { 9 | jsonValue := `["logs",{"address":"0x8320fe7702b96808f7bbc0d4a888ed1468216cfd","topics":["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"]}]` 10 | var request EthSubscriptionRequest 11 | err := json.Unmarshal([]byte(jsonValue), &request) 12 | if err != nil { 13 | t.Fatal(err) 14 | } 15 | asJson, err := json.Marshal(request) 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | if string(asJson) != jsonValue { 20 | t.Fatalf(`"%s" != "%s"\n`, string(asJson), jsonValue) 21 | } 22 | } 23 | 24 | func TestEthNewPendingTransactionsRequestSerialization(t *testing.T) { 25 | jsonValue := `["newPendingTransactions"]` 26 | var request EthSubscriptionRequest 27 | err := json.Unmarshal([]byte(jsonValue), &request) 28 | if err != nil { 29 | t.Fatal(err) 30 | } 31 | asJson, err := json.Marshal(request) 32 | if err != nil { 33 | t.Fatal(err) 34 | } 35 | if string(asJson) != jsonValue { 36 | t.Fatalf(`"%s" != "%s"\n`, string(asJson), jsonValue) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) HTML5 Boilerplate 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /pkg/transformer/eth_accounts.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | "github.com/qtumproject/janus/pkg/qtum" 7 | "github.com/qtumproject/janus/pkg/utils" 8 | ) 9 | 10 | // ProxyETHAccounts implements ETHProxy 11 | type ProxyETHAccounts struct { 12 | *qtum.Qtum 13 | } 14 | 15 | func (p *ProxyETHAccounts) Method() string { 16 | return "eth_accounts" 17 | } 18 | 19 | func (p *ProxyETHAccounts) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 20 | return p.request() 21 | } 22 | 23 | func (p *ProxyETHAccounts) request() (eth.AccountsResponse, eth.JSONRPCError) { 24 | var accounts eth.AccountsResponse 25 | 26 | for _, acc := range p.Accounts { 27 | acc := qtum.Account{acc} 28 | addr := acc.ToHexAddress() 29 | 30 | accounts = append(accounts, utils.AddHexPrefix(addr)) 31 | } 32 | 33 | return accounts, nil 34 | } 35 | 36 | func (p *ProxyETHAccounts) ToResponse(ethresp *qtum.CallContractResponse) *eth.CallResponse { 37 | data := utils.AddHexPrefix(ethresp.ExecutionResult.Output) 38 | qtumresp := eth.CallResponse(data) 39 | return &qtumresp 40 | } 41 | -------------------------------------------------------------------------------- /pkg/transformer/eth_newBlockFilter.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/ethereum/go-ethereum/common/hexutil" 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | ) 11 | 12 | // ProxyETHNewBlockFilter implements ETHProxy 13 | type ProxyETHNewBlockFilter struct { 14 | *qtum.Qtum 15 | filter *eth.FilterSimulator 16 | } 17 | 18 | func (p *ProxyETHNewBlockFilter) Method() string { 19 | return "eth_newBlockFilter" 20 | } 21 | 22 | func (p *ProxyETHNewBlockFilter) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 23 | return p.request(c.Request().Context()) 24 | } 25 | 26 | func (p *ProxyETHNewBlockFilter) request(ctx context.Context) (eth.NewBlockFilterResponse, eth.JSONRPCError) { 27 | blockCount, err := p.GetBlockCount(ctx) 28 | if err != nil { 29 | return "", eth.NewCallbackError(err.Error()) 30 | } 31 | 32 | filter := p.filter.New(eth.NewBlockFilterTy) 33 | filter.Data.Store("lastBlockNumber", blockCount.Uint64()) 34 | 35 | p.GenerateIfPossible() 36 | 37 | return eth.NewBlockFilterResponse(hexutil.EncodeUint64(filter.ID)), nil 38 | } 39 | -------------------------------------------------------------------------------- /pkg/transformer/eth_mining_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/eth" 8 | "github.com/qtumproject/janus/pkg/internal" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | ) 11 | 12 | func TestMiningRequest(t *testing.T) { 13 | //preparing the request 14 | requestParams := []json.RawMessage{} //eth_hashrate has no params 15 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | 20 | mockedClientDoer := internal.NewDoerMappedMock() 21 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 22 | if err != nil { 23 | t.Fatal(err) 24 | } 25 | 26 | getMiningResponse := qtum.GetMiningResponse{Staking: true} 27 | err = mockedClientDoer.AddResponse(qtum.MethodGetStakingInfo, getMiningResponse) 28 | if err != nil { 29 | t.Fatal(err) 30 | } 31 | 32 | proxyEth := ProxyETHMining{qtumClient} 33 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 34 | if jsonErr != nil { 35 | t.Fatal(jsonErr) 36 | } 37 | 38 | want := eth.MiningResponse(true) 39 | 40 | internal.CheckTestResultEthRequestRPC(*request, &want, got, t, false) 41 | } 42 | -------------------------------------------------------------------------------- /pkg/eth/filter.go: -------------------------------------------------------------------------------- 1 | package eth 2 | 3 | import ( 4 | "math/big" 5 | "sync" 6 | "sync/atomic" 7 | ) 8 | 9 | type FilterType int 10 | 11 | const ( 12 | NewFilterTy FilterType = iota 13 | NewBlockFilterTy 14 | NewPendingTransactionFilterTy 15 | ) 16 | 17 | type Filter struct { 18 | ID uint64 19 | Type FilterType 20 | Request interface{} 21 | LastBlockNum *big.Int 22 | Data sync.Map 23 | } 24 | 25 | type FilterSimulator struct { 26 | filters sync.Map 27 | maxFilterID *uint64 28 | } 29 | 30 | func NewFilterSimulator() *FilterSimulator { 31 | id := uint64(0) 32 | return &FilterSimulator{ 33 | maxFilterID: &id, 34 | } 35 | } 36 | 37 | func (f *FilterSimulator) New(ty FilterType, req ...interface{}) *Filter { 38 | id := atomic.AddUint64(f.maxFilterID, 1) 39 | filter := &Filter{ID: id, Type: ty} 40 | if ty == NewFilterTy { 41 | filter.Request = req[0] 42 | } 43 | 44 | f.filters.Store(id, filter) 45 | 46 | return filter 47 | } 48 | 49 | func (f *FilterSimulator) Uninstall(filterID uint64) { 50 | f.filters.Delete(filterID) 51 | } 52 | 53 | func (f *FilterSimulator) Filter(filterID uint64) (value interface{}, ok bool) { 54 | return f.filters.Load(filterID) 55 | } 56 | -------------------------------------------------------------------------------- /pkg/transformer/eth_hashrate.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | "math" 6 | 7 | "github.com/ethereum/go-ethereum/common/hexutil" 8 | "github.com/labstack/echo" 9 | "github.com/qtumproject/janus/pkg/eth" 10 | "github.com/qtumproject/janus/pkg/qtum" 11 | ) 12 | 13 | //ProxyETHGetHashrate implements ETHProxy 14 | type ProxyETHHashrate struct { 15 | *qtum.Qtum 16 | } 17 | 18 | func (p *ProxyETHHashrate) Method() string { 19 | return "eth_hashrate" 20 | } 21 | 22 | func (p *ProxyETHHashrate) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 23 | return p.request(c.Request().Context()) 24 | } 25 | 26 | func (p *ProxyETHHashrate) request(ctx context.Context) (*eth.HashrateResponse, eth.JSONRPCError) { 27 | qtumresp, err := p.Qtum.GetHashrate(ctx) 28 | if err != nil { 29 | return nil, eth.NewCallbackError(err.Error()) 30 | } 31 | 32 | // qtum res -> eth res 33 | return p.ToResponse(qtumresp), nil 34 | } 35 | 36 | func (p *ProxyETHHashrate) ToResponse(qtumresp *qtum.GetHashrateResponse) *eth.HashrateResponse { 37 | hexVal := hexutil.EncodeUint64(math.Float64bits(qtumresp.Difficulty)) 38 | ethresp := eth.HashrateResponse(hexVal) 39 | return ðresp 40 | } 41 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getTransactionCount.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/common/hexutil" 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | ) 11 | 12 | // ProxyETHEstimateGas implements ETHProxy 13 | type ProxyETHTxCount struct { 14 | *qtum.Qtum 15 | } 16 | 17 | func (p *ProxyETHTxCount) Method() string { 18 | return "eth_getTransactionCount" 19 | } 20 | 21 | func (p *ProxyETHTxCount) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 22 | 23 | /* not sure we need this. Need to figure out how to best unmarshal this in the future. For now this will work. 24 | var req eth.GetTransactionCountRequest 25 | if err := unmarshalRequest(rawreq.Params, &req); err != nil { 26 | return nil, err 27 | }*/ 28 | qtumresp, err := p.Qtum.GetTransactionCount(c.Request().Context(), "", "") 29 | if err != nil { 30 | return nil, eth.NewCallbackError(err.Error()) 31 | } 32 | 33 | // qtum res -> eth res 34 | return p.response(qtumresp), nil 35 | } 36 | 37 | func (p *ProxyETHTxCount) response(qtumresp *big.Int) string { 38 | return hexutil.EncodeBig(qtumresp) 39 | } 40 | -------------------------------------------------------------------------------- /playground/Makefile: -------------------------------------------------------------------------------- 1 | img_tag = "hayeah/qtumportal:testjanus" 2 | container_name = "qtumportal-testjanus" 3 | 4 | .PHONY: image 5 | image: 6 | GOOS=linux GOARCH=amd64 go build -o ./docker/janus-linux-amd64 github.com/qtumproject/janus/cli/janus 7 | docker build ./docker -t $(img_tag) 8 | 9 | .PHONY: run 10 | run: 11 | cd .. && make run-janus-https 12 | 13 | .PHONY: stop 14 | stop: 15 | docker stop $(container_name) 16 | 17 | .PHONY: exec 18 | exec: 19 | docker exec -it $(container_name) sh 20 | 21 | .PHONY: init-container 22 | init-container: 23 | docker exec -it qtumportal-testjanus sh init-container.sh 24 | 25 | .PHONY: logs 26 | logs: 27 | docker logs --tail 1000 -f $(container_name) 28 | 29 | .PHONY: clean-qtum-data 30 | clean-qtum-data: 31 | rm -rf ./docker/.qtum 32 | 33 | .PHONY: deploy-contracts 34 | deploy-contracts: 35 | cd pet-shop-tutorial && truffle migrate --reset 36 | cp pet-shop-tutorial/build/contracts/*.json pet-shop-tutorial/js 37 | 38 | .PHONY: serve-pet-shop 39 | serve-pet-shop: 40 | cd pet-shop-tutorial; yarn 41 | echo "Two prefund accounts you can login with: \n 0x7926223070547d2d15b2ef5e7383e541c338ffe9 \n 0x2352be3db3177f0a07efbe6da5857615b8c9901d" 42 | cd pet-shop-tutorial; yarn dev &> /dev/null 43 | -------------------------------------------------------------------------------- /pkg/transformer/eth_uninstallFilter.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common/hexutil" 5 | "github.com/labstack/echo" 6 | "github.com/qtumproject/janus/pkg/eth" 7 | "github.com/qtumproject/janus/pkg/qtum" 8 | ) 9 | 10 | // ProxyETHUninstallFilter implements ETHProxy 11 | type ProxyETHUninstallFilter struct { 12 | *qtum.Qtum 13 | filter *eth.FilterSimulator 14 | } 15 | 16 | func (p *ProxyETHUninstallFilter) Method() string { 17 | return "eth_uninstallFilter" 18 | } 19 | 20 | func (p *ProxyETHUninstallFilter) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 21 | var req eth.UninstallFilterRequest 22 | if err := unmarshalRequest(rawreq.Params, &req); err != nil { 23 | // TODO: Correct error code? 24 | return nil, eth.NewInvalidParamsError(err.Error()) 25 | } 26 | 27 | return p.request(&req) 28 | } 29 | 30 | func (p *ProxyETHUninstallFilter) request(ethreq *eth.UninstallFilterRequest) (eth.UninstallFilterResponse, eth.JSONRPCError) { 31 | id, err := hexutil.DecodeUint64(string(*ethreq)) 32 | if err != nil { 33 | return false, eth.NewInvalidParamsError(err.Error()) 34 | } 35 | 36 | // uninstall 37 | p.filter.Uninstall(id) 38 | 39 | return true, nil 40 | } 41 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getBlockByHash_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | "github.com/qtumproject/janus/pkg/qtum" 9 | "github.com/qtumproject/janus/pkg/utils" 10 | ) 11 | 12 | func initializeProxyETHGetBlockByHash(qtumClient *qtum.Qtum) ETHProxy { 13 | return &ProxyETHGetBlockByHash{qtumClient} 14 | } 15 | 16 | func TestGetBlockByHashRequestNonceLength(t *testing.T) { 17 | if len(utils.RemoveHexPrefix(internal.GetTransactionByHashResponse.Nonce)) != 16 { 18 | t.Errorf("Nonce test data should be zero left padded length 16") 19 | } 20 | } 21 | 22 | func TestGetBlockByHashRequest(t *testing.T) { 23 | testETHProxyRequest( 24 | t, 25 | initializeProxyETHGetBlockByHash, 26 | []json.RawMessage{[]byte(`"` + internal.GetTransactionByHashBlockHexHash + `"`), []byte(`false`)}, 27 | &internal.GetTransactionByHashResponse, 28 | ) 29 | } 30 | 31 | func TestGetBlockByHashTransactionsRequest(t *testing.T) { 32 | testETHProxyRequest( 33 | t, 34 | initializeProxyETHGetBlockByHash, 35 | []json.RawMessage{[]byte(`"` + internal.GetTransactionByHashBlockHexHash + `"`), []byte(`true`)}, 36 | &internal.GetTransactionByHashResponseWithTransactions, 37 | ) 38 | } 39 | -------------------------------------------------------------------------------- /.github/workflows/docker-unit-tests.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Unit tests 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | push: 9 | branches: [master] 10 | pull_request: 11 | branches: [master] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-latest 22 | 23 | # Steps represent a sequence of tasks that will be executed as part of the job 24 | steps: 25 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 26 | - uses: actions/checkout@v2 27 | 28 | # Runs a single command using the runners shell 29 | - name: Build docker image to run unit tests 30 | run: make docker-build-unit-tests 31 | 32 | # Runs a set of commands using the runners shell 33 | - name: Run unit tests in docker 34 | run: make docker-unit-tests 35 | -------------------------------------------------------------------------------- /.github/workflows/docker-openzeppelin.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Openzeppelin 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | push: 9 | branches: [master] 10 | pull_request: 11 | branches: [master] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-latest 22 | 23 | # Steps represent a sequence of tasks that will be executed as part of the job 24 | steps: 25 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 26 | - uses: actions/checkout@v2 27 | 28 | - name: Pull openzeppelin 29 | run: cd testing && make init 30 | 31 | - name: Build test harness 32 | run: cd testing && make build-openzeppelin 33 | 34 | # Runs a single command using the runners shell 35 | - name: Run openzeppelin truffle tests 36 | run: make openzeppelin-docker-compose 37 | -------------------------------------------------------------------------------- /pkg/transformer/eth_blockNumber_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "math/big" 6 | "testing" 7 | 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/internal" 10 | "github.com/qtumproject/janus/pkg/qtum" 11 | ) 12 | 13 | func TestBlockNumberRequest(t *testing.T) { 14 | //preparing request 15 | requestParams := []json.RawMessage{} 16 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 17 | if err != nil { 18 | t.Fatal(err) 19 | } 20 | 21 | mockedClientDoer := internal.NewDoerMappedMock() 22 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | 27 | //preparing client response 28 | getBlockCountResponse := qtum.GetBlockCountResponse{Int: big.NewInt(11284900)} 29 | err = mockedClientDoer.AddResponseWithRequestID(2, qtum.MethodGetBlockCount, getBlockCountResponse) 30 | if err != nil { 31 | t.Fatal(err) 32 | } 33 | 34 | //preparing proxy & executing request 35 | proxyEth := ProxyETHBlockNumber{qtumClient} 36 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 37 | if jsonErr != nil { 38 | t.Fatal(jsonErr) 39 | } 40 | 41 | want := eth.BlockNumberResponse("0xac31a4") 42 | 43 | internal.CheckTestResultEthRequestRPC(*request, &want, got, t, false) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/qtum/account.go: -------------------------------------------------------------------------------- 1 | package qtum 2 | 3 | import ( 4 | "encoding/hex" 5 | 6 | "github.com/btcsuite/btcd/chaincfg" 7 | "github.com/btcsuite/btcutil" 8 | ) 9 | 10 | type Accounts []*btcutil.WIF 11 | 12 | func (as Accounts) FindByHexAddress(addr string) *btcutil.WIF { 13 | for _, a := range as { 14 | acc := &Account{a} 15 | 16 | if addr == acc.ToHexAddress() { 17 | return a 18 | } 19 | } 20 | 21 | return nil 22 | } 23 | 24 | type Account struct { 25 | *btcutil.WIF 26 | } 27 | 28 | func (a *Account) ToHexAddress() string { 29 | // wif := (*btcutil.WIF)(a) 30 | 31 | keyid := btcutil.Hash160(a.SerializePubKey()) 32 | return hex.EncodeToString(keyid) 33 | } 34 | 35 | var qtumMainNetParams = chaincfg.MainNetParams 36 | var qtumTestNetParams = chaincfg.MainNetParams 37 | 38 | func init() { 39 | qtumMainNetParams.PubKeyHashAddrID = 58 40 | qtumMainNetParams.ScriptHashAddrID = 50 41 | 42 | qtumTestNetParams.PubKeyHashAddrID = 120 43 | qtumTestNetParams.ScriptHashAddrID = 110 44 | } 45 | 46 | func (a *Account) ToBase58Address(isMain bool) (string, error) { 47 | params := &qtumMainNetParams 48 | if !isMain { 49 | params = &qtumTestNetParams 50 | } 51 | 52 | addr, err := btcutil.NewAddressPubKey(a.SerializePubKey(), params) 53 | if err != nil { 54 | return "", err 55 | } 56 | 57 | return addr.AddressPubKeyHash().String(), nil 58 | } 59 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Page Not Found 7 | 8 | 54 | 55 | 56 | 57 |

Page Not Found

58 |

Sorry, but the page you were trying to view does not exist.

59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /pkg/transformer/qtum_genericStringArguments.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | "github.com/qtumproject/janus/pkg/qtum" 7 | ) 8 | 9 | type ProxyQTUMGenericStringArguments struct { 10 | *qtum.Qtum 11 | prefix string 12 | method string 13 | } 14 | 15 | var _ ETHProxy = (*ProxyQTUMGenericStringArguments)(nil) 16 | 17 | func (p *ProxyQTUMGenericStringArguments) Method() string { 18 | return p.prefix + "_" + p.method 19 | } 20 | 21 | func (p *ProxyQTUMGenericStringArguments) Request(req *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 22 | var params eth.StringsArguments 23 | if err := unmarshalRequest(req.Params, ¶ms); err != nil { 24 | // TODO: Correct error code? 25 | return nil, eth.NewInvalidParamsError("couldn't unmarshal request parameters") 26 | } 27 | 28 | if len(params) != 1 { 29 | return nil, eth.NewInvalidParamsError("require 1 argument: the base58 Qtum address") 30 | } 31 | 32 | return p.request(params) 33 | } 34 | 35 | func (p *ProxyQTUMGenericStringArguments) request(params eth.StringsArguments) (*string, eth.JSONRPCError) { 36 | var response string 37 | err := p.Client.Request(p.method, params, &response) 38 | if err != nil { 39 | return nil, eth.NewInvalidRequestError(err.Error()) 40 | } 41 | 42 | return &response, nil 43 | } 44 | -------------------------------------------------------------------------------- /testing/openzeppelin/docker-compose-openzeppelin.yml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | services: 3 | janus: 4 | image: qtum/janus:dev 5 | build: 6 | context: ../../ 7 | dockerfile: ./Dockerfile 8 | cache_from: 9 | - golang:3.16-alpine 10 | - qtum/janus:dev 11 | ports: 12 | - "23889:23889" 13 | environment: 14 | - QTUM_RPC=http://qtum:testpasswd@qtum:3889 15 | volumes: 16 | - ../../:/src:ro 17 | depends_on: 18 | - qtum 19 | command: --bind 0.0.0.0 --accounts /src/myaccounts.txt --dev 20 | qtum: 21 | ports: 22 | - "3889:3889" 23 | image: qtum/qtum-seeded 24 | build: 25 | context: ../../docker 26 | dockerfile: ./qtum-seeded.Dockerfile 27 | cache_from: 28 | - qtum/qtum-seeded 29 | container_name: qtum_seeded_testchain 30 | command: qtumd -regtest -addrindex -txindex -rpcbind=0.0.0.0:3889 -rpcallowip=0.0.0.0/0 -logevents -rpcuser=qtum -rpcpassword=testpasswd -deprecatedrpc=accounts -printtoconsole 31 | openzeppelin: 32 | image: qtum/janus-openzeppelin 33 | build: 34 | context: . 35 | dockerfile: ./openzeppelin.Dockerfile 36 | cache_from: 37 | - qtum/janus-openzeppelin 38 | environment: 39 | - GENERATE_TO_ADDRESS=qW28njWueNpBXYWj2KDmtFG2gbLeALeHfV 40 | depends_on: 41 | - janus 42 | command: truffle test --network docker 43 | -------------------------------------------------------------------------------- /playground/test-SimpleStore.js: -------------------------------------------------------------------------------- 1 | // YOUR_QTUM_ACCOUNT 2 | const url = require('url'); 3 | 4 | const rpcURL= process.env.ETH_RPC; 5 | const qtumAccount = url.parse(rpcURL).auth.split(":")[0] 6 | 7 | const qtum = require("qtumjs") 8 | const rpc = new qtum.EthRPC(rpcURL, qtumAccount) 9 | const repoData = require("./solar.development.json") 10 | const { 11 | sender, 12 | ...info 13 | } = repoData.contracts['./contracts/SimpleStore.sol'] 14 | const simpleStoreContract = new qtum.Contract(rpc, info) 15 | 16 | const opts = {gasPrice: 100} 17 | 18 | 19 | async function test() { 20 | console.log('exec: await simpleStoreContract.call("get", [], {gasPrice: 100})') 21 | console.log("call", await simpleStoreContract.call("get", [], opts)) 22 | console.log() 23 | 24 | const newVal = Math.floor((Math.random() * 100000000) + 1); 25 | console.log(`exec: await simpleStoreContract.send("set", [${newVal}], {gasPrice: 100})`) 26 | const tx = await simpleStoreContract.send("set", [newVal], opts) 27 | console.log("tx", tx) 28 | console.log() 29 | 30 | console.log('exec: await tx.confirm(0)') 31 | const receipt = await tx.confirm(0) 32 | console.log("receipt", receipt) 33 | console.log() 34 | 35 | console.log('exec: await simpleStoreContract.call("get", [], {gasPrice: 100})') 36 | console.log("call", await simpleStoreContract.call("get", [], opts)) 37 | console.log() 38 | } 39 | 40 | test() 41 | -------------------------------------------------------------------------------- /pkg/transformer/eth_net_listening_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | "github.com/qtumproject/janus/pkg/qtum" 9 | ) 10 | 11 | func TestNetListeningInactive(t *testing.T) { 12 | testNetListeningRequest(t, false) 13 | } 14 | 15 | func TestNetListeningActive(t *testing.T) { 16 | testNetListeningRequest(t, true) 17 | } 18 | 19 | func testNetListeningRequest(t *testing.T, active bool) { 20 | //preparing the request 21 | requestParams := []json.RawMessage{} //net_listening has no params 22 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | 27 | mockedClientDoer := internal.NewDoerMappedMock() 28 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | 33 | networkInfoResponse := qtum.NetworkInfoResponse{NetworkActive: active} 34 | err = mockedClientDoer.AddResponseWithRequestID(2, qtum.MethodGetNetworkInfo, networkInfoResponse) 35 | if err != nil { 36 | t.Fatal(err) 37 | } 38 | 39 | proxyEth := ProxyNetListening{qtumClient} 40 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 41 | if jsonErr != nil { 42 | t.Fatal(jsonErr) 43 | } 44 | 45 | want := active 46 | 47 | internal.CheckTestResultEthRequestRPC(*request, want, got, t, false) 48 | } 49 | -------------------------------------------------------------------------------- /docker/quick_start/docker-compose.testnet.yml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | networks: 4 | qtumd_testnet_network: 5 | volumes: 6 | qtumd_testnet_volume: 7 | 8 | services: 9 | janus_testnet: 10 | image: qtum/janus:dev 11 | container_name: janus_testchain 12 | build: 13 | context: ../../ 14 | cache_from: 15 | - golang:1.18-alpine 16 | ports: 17 | - "23889:23889" 18 | environment: 19 | - QTUM_RPC=http://qtum:testpasswd@qtum_testnet:3889 20 | - COMPOSE_PROJECT_NAME=testnet 21 | volumes: 22 | - ../standalone/myaccounts.txt:$GOPATH/github.com/qtumproject/janus/myaccounts.txt 23 | - ../../https:/https 24 | - ../../logs:/logs 25 | depends_on: 26 | - qtum_testnet 27 | command: --bind 0.0.0.0 --port 23889 --ignoreTransactions --accounts $GOPATH/github.com/qtumproject/janus/myaccounts.txt --dev --https-key /https/key.pem --https-cert /https/cert.pem 28 | networks: 29 | - qtumd_testnet_network 30 | 31 | qtum_testnet: 32 | ports: 33 | - "3889:3889" 34 | image: qtum/qtum 35 | container_name: qtum_testnet 36 | command: qtumd -testnet -txindex -addrindex=1 -rpcbind=0.0.0.0:3889 -rpcallowip=0.0.0.0/0 -logevents -rpcuser=qtum -rpcpassword=testpasswd -deprecatedrpc=accounts -printtoconsole 37 | volumes: 38 | - qtumd_testnet_volume:/root/.qtum 39 | networks: 40 | - qtumd_testnet_network 41 | -------------------------------------------------------------------------------- /pkg/notifier/subscription_test.go: -------------------------------------------------------------------------------- 1 | package notifier 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func TestRollingLimit(t *testing.T) { 9 | l := newRollingLimit(4) 10 | if l.oldest() != 1 { 11 | t.Fatalf("Expected oldest slot to be 1, not %d", l.oldest()) 12 | } 13 | if l.newest() != 0 { 14 | t.Fatalf("Expected newest slot to be 0, not %d", l.newest()) 15 | } 16 | now := time.Now() 17 | first := now.Add(-1 * time.Second) 18 | second := now 19 | third := now.Add(1 * time.Second) 20 | fourth := third.Add(1 * time.Second) 21 | 22 | l.Push(first) 23 | if l.oldest() != 2 { 24 | t.Fatalf("Expected oldest slot to be 2, not %d", l.oldest()) 25 | } 26 | if l.newest() != 1 { 27 | t.Fatalf("Expected newest slot to be 1, not %d", l.newest()) 28 | } 29 | 30 | l.Push(second) 31 | if l.oldest() != 3 { 32 | t.Fatalf("Expected oldest slot to be 3, not %d", l.oldest()) 33 | } 34 | if l.newest() != 2 { 35 | t.Fatalf("Expected newest slot to be 2, not %d", l.newest()) 36 | } 37 | 38 | l.Push(third) 39 | if l.oldest() != 0 { 40 | t.Fatalf("Expected oldest slot to be 0, not %d", l.oldest()) 41 | } 42 | if l.newest() != 3 { 43 | t.Fatalf("Expected newest slot to be 3, not %d", l.newest()) 44 | } 45 | 46 | l.Push(fourth) 47 | if l.oldest() != 1 { 48 | t.Fatalf("Expected oldest slot to be 1, not %d", l.oldest()) 49 | } 50 | if l.newest() != 0 { 51 | t.Fatalf("Expected newest slot to be 0, not %d", l.newest()) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /docker/quick_start/docker-compose.mainnet.yml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | networks: 4 | qtumd_mainnet_network: 5 | volumes: 6 | qtumd_mainnet_volume: 7 | 8 | services: 9 | janus_mainnet: 10 | image: qtum/janus:latest 11 | container_name: janus_mainnet 12 | build: 13 | context: ../../ 14 | cache_from: 15 | - golang:1.18-alpine 16 | ports: 17 | - "23890:23890" 18 | environment: 19 | - QTUM_RPC=http://qtum:testpasswd@qtum_mainnet:3890 20 | - COMPOSE_PROJECT_NAME=mainnet 21 | volumes: 22 | - ../standalone/myaccounts.txt:$GOPATH/github.com/qtumproject/janus/myaccounts.txt 23 | - ../../https:/https 24 | - ../../logs:/logs 25 | depends_on: 26 | - qtum_mainnet 27 | command: --bind 0.0.0.0 --port 23890 --ignoreTransactions --accounts $GOPATH/github.com/qtumproject/janus/myaccounts.txt --dev --https-key /https/key.pem --https-cert /https/cert.pem 28 | networks: 29 | - qtumd_mainnet_network 30 | 31 | qtum_mainnet: 32 | ports: 33 | - "3890:3890" 34 | image: qtum/qtum 35 | container_name: qtum_mainnet 36 | environment: 37 | - COMPOSE_PROJECT_NAME=mainnet 38 | command: qtumd -txindex -addrindex=1 -rpcbind=0.0.0.0:3890 -rpcallowip=0.0.0.0/0 -rpcuser=qtum -rpcpassword=testpasswd -deprecatedrpc=accounts 39 | volumes: 40 | - qtumd_mainnet_volume:/root/.qtum 41 | networks: 42 | - qtumd_mainnet_network 43 | -------------------------------------------------------------------------------- /docker/quick_start/docker-compose.regtest.yml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | networks: 4 | qtumd_regtest_network: 5 | volumes: 6 | qtumd_regtest_volume: 7 | 8 | services: 9 | janus_regtest: 10 | image: qtum/janus:dev 11 | container_name: janus_regtest 12 | build: 13 | context: ../../ 14 | cache_from: 15 | - golang:1.18-alpine 16 | ports: 17 | - "23889:23889" 18 | environment: 19 | - QTUM_RPC=http://qtum:testpasswd@qtum_regtest:3889 20 | - COMPOSE_PROJECT_NAME=regtest 21 | volumes: 22 | - ../standalone/myaccounts.txt:$GOPATH/github.com/qtumproject/janus/myaccounts.txt 23 | - ../../https:/https 24 | - ../../logs:/logs 25 | depends_on: 26 | - qtum_regtest 27 | command: --bind 0.0.0.0 --accounts $GOPATH/github.com/qtumproject/janus/myaccounts.txt --log-file /logs/janusLogs.txt --dev --https-key /https/key.pem --https-cert /https/cert.pem 28 | networks: 29 | - qtumd_regtest_network 30 | 31 | qtum_regtest: 32 | ports: 33 | - "3889:3889" 34 | image: qtum/qtum 35 | container_name: qtum_regtest 36 | command: qtumd -regtest -txindex -addrindex=1 -rpcbind=0.0.0.0:3889 -rpcallowip=0.0.0.0/0 -logevents -rpcuser=qtum -rpcpassword=testpasswd -deprecatedrpc=accounts -printtoconsole 37 | volumes: 38 | - qtumd_regtest_volume:/root/.qtum 39 | networks: 40 | - qtumd_regtest_network 41 | -------------------------------------------------------------------------------- /playground/.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 | solar*.json 75 | /yarn.lock 76 | /.boast.json 77 | /build 78 | /package-lock.json -------------------------------------------------------------------------------- /playground/contracts/openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | import "./ERC20Basic.sol"; 5 | import "../../math/SafeMath.sol"; 6 | 7 | 8 | /** 9 | * @title Basic token 10 | * @dev Basic version of StandardToken, with no allowances. 11 | */ 12 | contract BasicToken is ERC20Basic { 13 | using SafeMath for uint256; 14 | 15 | mapping(address => uint256) balances; 16 | 17 | uint256 totalSupply_; 18 | 19 | /** 20 | * @dev Total number of tokens in existence 21 | */ 22 | function totalSupply() public view returns (uint256) { 23 | return totalSupply_; 24 | } 25 | 26 | /** 27 | * @dev Transfer token for a specified address 28 | * @param _to The address to transfer to. 29 | * @param _value The amount to be transferred. 30 | */ 31 | function transfer(address _to, uint256 _value) public returns (bool) { 32 | require(_value <= balances[msg.sender]); 33 | require(_to != address(0)); 34 | 35 | balances[msg.sender] = balances[msg.sender].sub(_value); 36 | balances[_to] = balances[_to].add(_value); 37 | emit Transfer(msg.sender, _to, _value); 38 | return true; 39 | } 40 | 41 | /** 42 | * @dev Gets the balance of the specified address. 43 | * @param _owner The address to query the the balance of. 44 | * @return An uint256 representing the amount owned by the passed address. 45 | */ 46 | function balanceOf(address _owner) public view returns (uint256) { 47 | return balances[_owner]; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/doc/js.md: -------------------------------------------------------------------------------- 1 | [HTML5 Boilerplate homepage](https://html5boilerplate.com/) | [Documentation 2 | table of contents](TOC.md) 3 | 4 | # The JavaScript 5 | 6 | Information about the default JavaScript included in the project. 7 | 8 | ## main.js 9 | 10 | This file can be used to contain or reference your site/app JavaScript code. If 11 | you're working on something more advanced you might replace this file entirely. 12 | That's cool. 13 | 14 | ## plugins.js 15 | 16 | This file can be used to contain all your plugins, such as jQuery plugins and 17 | other 3rd party scripts for a simple site. 18 | 19 | One approach is to put jQuery plugins inside of a `(function($){ ...})(jQuery);` 20 | closure to make sure they're in the jQuery namespace safety blanket. Read more 21 | about [jQuery plugin authoring](https://learn.jquery.com/plugins/). 22 | 23 | By default the `plugins.js` file contains a small script to avoid `console` 24 | errors in browsers that lack a `console`. The script will make sure that, if a 25 | console method isn't available, that method will have the value of empty 26 | function, thus, preventing the browser from throwing an error. 27 | 28 | ## vendor 29 | 30 | This directory can be used to contain all 3rd party library code. 31 | 32 | Our custom build of the Modernizr library is included by 33 | default. You may wish to create your own [custom Modernizr build with the online 34 | builder](https://modernizr.com/download/) or [command line 35 | tool](https://modernizr.com/docs#command-line-config). 36 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getCode.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/labstack/echo" 7 | "github.com/qtumproject/janus/pkg/eth" 8 | "github.com/qtumproject/janus/pkg/qtum" 9 | "github.com/qtumproject/janus/pkg/utils" 10 | ) 11 | 12 | // ProxyETHGetCode implements ETHProxy 13 | type ProxyETHGetCode struct { 14 | *qtum.Qtum 15 | } 16 | 17 | func (p *ProxyETHGetCode) Method() string { 18 | return "eth_getCode" 19 | } 20 | 21 | func (p *ProxyETHGetCode) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 22 | var req eth.GetCodeRequest 23 | if err := unmarshalRequest(rawreq.Params, &req); err != nil { 24 | // TODO: Correct error code? 25 | return nil, eth.NewInvalidParamsError(err.Error()) 26 | } 27 | 28 | return p.request(c.Request().Context(), &req) 29 | } 30 | 31 | func (p *ProxyETHGetCode) request(ctx context.Context, ethreq *eth.GetCodeRequest) (eth.GetCodeResponse, eth.JSONRPCError) { 32 | qtumreq := qtum.GetAccountInfoRequest(utils.RemoveHexPrefix(ethreq.Address)) 33 | 34 | qtumresp, err := p.GetAccountInfo(ctx, &qtumreq) 35 | if err != nil { 36 | if err == qtum.ErrInvalidAddress { 37 | /** 38 | // correct response for an invalid address 39 | { 40 | "jsonrpc": "2.0", 41 | "id": 123, 42 | "result": "0x" 43 | } 44 | **/ 45 | return "0x", nil 46 | } else { 47 | return "", eth.NewCallbackError(err.Error()) 48 | } 49 | } 50 | 51 | // qtum res -> eth res 52 | return eth.GetCodeResponse(utils.AddHexPrefix(qtumresp.Code)), nil 53 | } 54 | -------------------------------------------------------------------------------- /pkg/eth/eth_int.go: -------------------------------------------------------------------------------- 1 | package eth 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/pkg/errors" 6 | "math/big" 7 | 8 | "github.com/ethereum/go-ethereum/common/hexutil" 9 | "github.com/qtumproject/janus/pkg/utils" 10 | ) 11 | 12 | type ETHInt struct { 13 | *big.Int 14 | } 15 | 16 | func (i *ETHInt) Hex() string { 17 | return hexutil.EncodeBig(i.Int) 18 | } 19 | 20 | func (i *ETHInt) MarshalJSON() ([]byte, error) { 21 | return json.Marshal(i.Int) 22 | } 23 | 24 | // UnmarshalJSON needs to be able to parse ETHInt from both hex string or number 25 | func (i *ETHInt) UnmarshalJSON(data []byte) (err error) { 26 | if len(data) == 0 { 27 | return errors.New("data must not be empty") 28 | } 29 | 30 | isNumber := func(data []byte) bool { 31 | return data[0] != '"' && data[len(data)-1] != '"' 32 | } 33 | 34 | if isNumber(data) { 35 | i.Int, err = bigIntFromNumber(data) 36 | return err 37 | } 38 | 39 | i.Int, err = bigIntFromHex(data) 40 | return err 41 | } 42 | 43 | func bigIntFromNumber(data json.RawMessage) (*big.Int, error) { 44 | var v *big.Int 45 | if err := json.Unmarshal(data, &v); err != nil { 46 | return nil, errors.Wrap(err, "json unmarshal") 47 | } 48 | return v, nil 49 | } 50 | 51 | func bigIntFromHex(data json.RawMessage) (*big.Int, error) { 52 | var val string 53 | 54 | if err := json.Unmarshal(data, &val); err != nil { 55 | return nil, errors.Wrap(err, "json unmarshal") 56 | } 57 | 58 | i, err := utils.DecodeBig(val) 59 | if err != nil { 60 | return nil, errors.Wrap(err, "decoding error") 61 | } 62 | return i, nil 63 | } 64 | -------------------------------------------------------------------------------- /testing/openzeppelin/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | test_directory: "./openzeppelin-contracts/test", 3 | migrations: "./openzeppelin-contracts/migrations", 4 | contracts_directory: "./openzeppelin-contracts/contracts", 5 | contracts_build_directory: "./openzeppelin-contracts/build/output", 6 | mocha: { 7 | reporter: "mocha-spec-json-output-reporter", 8 | reporterOptions: { 9 | fileName: "output.json", 10 | }, 11 | }, 12 | networks: { 13 | development: { 14 | host: "127.0.0.1", 15 | port: 23889, //Switch to 23888 for local HTTP Server, look at Makefile run-janus 16 | network_id: "*", 17 | gas: 3000000, 18 | gasPrice: "0x64", 19 | }, 20 | testing: { 21 | host: "127.0.0.1", 22 | port: 23888, 23 | network_id: "*", 24 | gas: 3000000, 25 | gasPrice: "0x64", 26 | }, 27 | docker: { 28 | host: "janus", 29 | port: 23889, 30 | network_id: "*", 31 | gas: 3000000, 32 | gasPrice: "0x64", 33 | }, 34 | ganache: { 35 | host: "127.0.0.1", 36 | port: 8545, 37 | network_id: "*", 38 | }, 39 | testnet: { 40 | host: "hk1.s.qtum.org", 41 | port: 23889, 42 | network_id: "*", 43 | from: "0x7926223070547d2d15b2ef5e7383e541c338ffe9", 44 | gasPrice: "0x64", 45 | }, 46 | }, 47 | compilers: { 48 | solc: { 49 | version: "0.8.3", 50 | settings: { 51 | optimizer: { 52 | enabled: true, 53 | runs: 1, 54 | }, 55 | }, 56 | }, 57 | }, 58 | }; 59 | -------------------------------------------------------------------------------- /pkg/transformer/eth_blockNumber.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "strings" 5 | "time" 6 | 7 | "github.com/ethereum/go-ethereum/common/hexutil" 8 | "github.com/labstack/echo" 9 | "github.com/qtumproject/janus/pkg/eth" 10 | "github.com/qtumproject/janus/pkg/qtum" 11 | ) 12 | 13 | // ProxyETHBlockNumber implements ETHProxy 14 | type ProxyETHBlockNumber struct { 15 | *qtum.Qtum 16 | } 17 | 18 | func (p *ProxyETHBlockNumber) Method() string { 19 | return "eth_blockNumber" 20 | } 21 | 22 | func (p *ProxyETHBlockNumber) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 23 | return p.request(c, 5) 24 | } 25 | 26 | func (p *ProxyETHBlockNumber) request(c echo.Context, retries int) (*eth.BlockNumberResponse, eth.JSONRPCError) { 27 | qtumresp, err := p.Qtum.GetBlockCount(c.Request().Context()) 28 | if err != nil { 29 | if retries > 0 && strings.Contains(err.Error(), qtum.ErrTryAgain.Error()) { 30 | ctx := c.Request().Context() 31 | t := time.NewTimer(500 * time.Millisecond) 32 | select { 33 | case <-ctx.Done(): 34 | return nil, eth.NewCallbackError(err.Error()) 35 | case <-t.C: 36 | // fallthrough 37 | } 38 | return p.request(c, retries-1) 39 | } 40 | return nil, eth.NewCallbackError(err.Error()) 41 | } 42 | 43 | // qtum res -> eth res 44 | return p.ToResponse(qtumresp), nil 45 | } 46 | 47 | func (p *ProxyETHBlockNumber) ToResponse(qtumresp *qtum.GetBlockCountResponse) *eth.BlockNumberResponse { 48 | hexVal := hexutil.EncodeBig(qtumresp.Int) 49 | ethresp := eth.BlockNumberResponse(hexVal) 50 | return ðresp 51 | } 52 | -------------------------------------------------------------------------------- /playground/contracts/openzeppelin-solidity/contracts/math/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | /** 5 | * @title SafeMath 6 | * @dev Math operations with safety checks that throw on error 7 | */ 8 | library SafeMath { 9 | 10 | /** 11 | * @dev Multiplies two numbers, throws on overflow. 12 | */ 13 | function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { 14 | // Gas optimization: this is cheaper than asserting 'a' not being zero, but the 15 | // benefit is lost if 'b' is also tested. 16 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 17 | if (a == 0) { 18 | return 0; 19 | } 20 | 21 | c = a * b; 22 | assert(c / a == b); 23 | return c; 24 | } 25 | 26 | /** 27 | * @dev Integer division of two numbers, truncating the quotient. 28 | */ 29 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 30 | // assert(b > 0); // Solidity automatically throws when dividing by 0 31 | // uint256 c = a / b; 32 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 33 | return a / b; 34 | } 35 | 36 | /** 37 | * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). 38 | */ 39 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 40 | assert(b <= a); 41 | return a - b; 42 | } 43 | 44 | /** 45 | * @dev Adds two numbers, throws on overflow. 46 | */ 47 | function add(uint256 a, uint256 b) internal pure returns (uint256 c) { 48 | c = a + b; 49 | assert(c >= a); 50 | return c; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pkg/transformer/eth_hashrate_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "math" 6 | "testing" 7 | 8 | "github.com/ethereum/go-ethereum/common/hexutil" 9 | "github.com/qtumproject/janus/pkg/eth" 10 | "github.com/qtumproject/janus/pkg/internal" 11 | "github.com/qtumproject/janus/pkg/qtum" 12 | ) 13 | 14 | func TestHashrateRequest(t *testing.T) { 15 | //preparing the request 16 | requestParams := []json.RawMessage{} //eth_hashrate has no params 17 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 18 | if err != nil { 19 | t.Fatal(err) 20 | } 21 | 22 | mockedClientDoer := internal.NewDoerMappedMock() 23 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 24 | if err != nil { 25 | t.Fatal(err) 26 | } 27 | 28 | exampleResponse := `{"enabled": true, "staking": false, "errors": "", "currentblocktx": 0, "pooledtx": 0, "difficulty": 4.656542373906925e-010, "search-interval": 0, "weight": 0, "netstakeweight": 0, "expectedtime": 0}` 29 | getHashrateResponse := qtum.GetHashrateResponse{} 30 | unmarshalRequest([]byte(exampleResponse), &getHashrateResponse) 31 | 32 | err = mockedClientDoer.AddResponse(qtum.MethodGetStakingInfo, getHashrateResponse) 33 | if err != nil { 34 | t.Fatal(err) 35 | } 36 | 37 | proxyEth := ProxyETHHashrate{qtumClient} 38 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 39 | if jsonErr != nil { 40 | t.Fatal(jsonErr) 41 | } 42 | 43 | expected := hexutil.EncodeUint64(math.Float64bits(4.656542373906925e-010)) 44 | want := eth.HashrateResponse(expected) 45 | 46 | internal.CheckTestResultEthRequestRPC(*request, &want, got, t, false) 47 | } 48 | -------------------------------------------------------------------------------- /pkg/transformer/eth_subscribe.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | "github.com/qtumproject/janus/pkg/notifier" 7 | "github.com/qtumproject/janus/pkg/qtum" 8 | ) 9 | 10 | // ETHSubscribe implements ETHProxy 11 | type ETHSubscribe struct { 12 | *qtum.Qtum 13 | *notifier.Agent 14 | } 15 | 16 | func (p *ETHSubscribe) Method() string { 17 | return "eth_subscribe" 18 | } 19 | 20 | func (p *ETHSubscribe) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 21 | notifier := getNotifier(c) 22 | if notifier == nil { 23 | p.GetLogger().Log("msg", "eth_subscribe only supported over websocket") 24 | /* 25 | // TODO 26 | { 27 | "jsonrpc": "2.0", 28 | "id": 580, 29 | "error": { 30 | "code": -32601, 31 | "message": "The method eth_subscribe does not exist/is not available" 32 | } 33 | } 34 | */ 35 | return nil, eth.NewMethodNotFoundError("eth_subscribe") 36 | } 37 | 38 | var req eth.EthSubscriptionRequest 39 | if err := unmarshalRequest(rawreq.Params, &req); err != nil { 40 | // TODO: Correct error code? 41 | return nil, eth.NewInvalidParamsError(err.Error()) 42 | } 43 | 44 | return p.request(&req, notifier) 45 | } 46 | 47 | func (p *ETHSubscribe) request(req *eth.EthSubscriptionRequest, notifier *notifier.Notifier) (*eth.EthSubscriptionResponse, eth.JSONRPCError) { 48 | notifier.ResponseRequired() 49 | id, err := p.NewSubscription(notifier, req) 50 | response := eth.EthSubscriptionResponse(id) 51 | if err == nil { 52 | return &response, nil 53 | } else { 54 | return &response, eth.NewCallbackError(err.Error()) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pkg/transformer/eth_unsubscribe.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/qtumproject/janus/pkg/eth" 6 | "github.com/qtumproject/janus/pkg/notifier" 7 | "github.com/qtumproject/janus/pkg/qtum" 8 | ) 9 | 10 | // ETHUnsubscribe implements ETHProxy 11 | type ETHUnsubscribe struct { 12 | *qtum.Qtum 13 | *notifier.Agent 14 | } 15 | 16 | func (p *ETHUnsubscribe) Method() string { 17 | return "eth_unsubscribe" 18 | } 19 | 20 | func (p *ETHUnsubscribe) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 21 | notifier := getNotifier(c) 22 | if notifier == nil { 23 | p.GetLogger().Log("msg", "eth_unsubscribe only supported over websocket") 24 | /* 25 | // TODO 26 | { 27 | "jsonrpc": "2.0", 28 | "id": 580, 29 | "error": { 30 | "code": -32601, 31 | "message": "The method eth_unsubscribe does not exist/is not available" 32 | } 33 | } 34 | */ 35 | return nil, eth.NewMethodNotFoundError("eth_subscribe") 36 | } 37 | 38 | var req eth.EthUnsubscribeRequest 39 | if err := unmarshalRequest(rawreq.Params, &req); err != nil { 40 | // TODO: Correct error code? 41 | return nil, eth.NewInvalidParamsError(err.Error()) 42 | } 43 | 44 | return p.request(&req, notifier) 45 | } 46 | 47 | func (p *ETHUnsubscribe) request(req *eth.EthUnsubscribeRequest, notifier *notifier.Notifier) (eth.EthUnsubscribeResponse, eth.JSONRPCError) { 48 | if len(*req) != 1 { 49 | // TODO: Correct error code? 50 | return false, eth.NewInvalidParamsError("requires one parameter") 51 | } 52 | param := (*req)[0] 53 | success := notifier.Unsubscribe(param) 54 | return eth.EthUnsubscribeResponse(success), nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/transformer/eth_net_peerCount_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "testing" 7 | 8 | "github.com/ethereum/go-ethereum/common/hexutil" 9 | "github.com/qtumproject/janus/pkg/eth" 10 | "github.com/qtumproject/janus/pkg/internal" 11 | "github.com/qtumproject/janus/pkg/qtum" 12 | ) 13 | 14 | func TestPeerCountRequest(t *testing.T) { 15 | for i := 0; i < 10; i++ { 16 | testDesc := fmt.Sprintf("#%d", i) 17 | t.Run(testDesc, func(t *testing.T) { 18 | testPeerCountRequest(t, i) 19 | }) 20 | } 21 | } 22 | 23 | func testPeerCountRequest(t *testing.T, clients int) { 24 | //preparing the request 25 | requestParams := []json.RawMessage{} //net_peerCount has no params 26 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 27 | if err != nil { 28 | t.Fatal(err) 29 | } 30 | 31 | mockedClientDoer := internal.NewDoerMappedMock() 32 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 33 | if err != nil { 34 | t.Fatal(err) 35 | } 36 | 37 | getPeerInfoResponse := []qtum.GetPeerInfoResponse{} 38 | for i := 0; i < clients; i++ { 39 | getPeerInfoResponse = append(getPeerInfoResponse, qtum.GetPeerInfoResponse{}) 40 | } 41 | err = mockedClientDoer.AddResponseWithRequestID(2, qtum.MethodGetPeerInfo, getPeerInfoResponse) 42 | if err != nil { 43 | t.Fatal(err) 44 | } 45 | 46 | proxyEth := ProxyNetPeerCount{qtumClient} 47 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 48 | if jsonErr != nil { 49 | t.Fatal(jsonErr) 50 | } 51 | 52 | want := eth.NetPeerCountResponse(hexutil.EncodeUint64(uint64(clients))) 53 | 54 | internal.CheckTestResultUnspecifiedInput(fmt.Sprint(clients), &want, got, t, false) 55 | } 56 | -------------------------------------------------------------------------------- /pkg/utils/hex.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "encoding/hex" 5 | "math/big" 6 | "strings" 7 | 8 | "github.com/btcsuite/btcutil/base58" 9 | // "github.com/decred/base58" 10 | "github.com/ethereum/go-ethereum/common" 11 | "github.com/ethereum/go-ethereum/common/hexutil" 12 | "github.com/pkg/errors" 13 | ) 14 | 15 | func RemoveHexPrefix(hex string) string { 16 | if strings.HasPrefix(hex, "0x") { 17 | return hex[2:] 18 | } 19 | return hex 20 | } 21 | 22 | func IsEthHexAddress(str string) bool { 23 | return strings.HasPrefix(str, "0x") || common.IsHexAddress("0x"+str) 24 | } 25 | 26 | func AddHexPrefix(hex string) string { 27 | if strings.HasPrefix(hex, "0x") { 28 | return hex 29 | } 30 | return "0x" + hex 31 | } 32 | 33 | func AddHexPrefixIfNotEmpty(hex string) string { 34 | if hex == "" { 35 | return hex 36 | } 37 | return AddHexPrefix(hex) 38 | } 39 | 40 | // DecodeBig decodes a hex string whether input is with 0x prefix or not. 41 | func DecodeBig(input string) (*big.Int, error) { 42 | input = AddHexPrefix(input) 43 | if input == "0x00" { 44 | return big.NewInt(0), nil 45 | } 46 | return hexutil.DecodeBig(input) 47 | } 48 | 49 | // Converts Qtum address to an Ethereum address 50 | func ConvertQtumAddress(address string) (ethAddress string, _ error) { 51 | if n := len(address); n < 22 { 52 | return "", errors.Errorf("invalid address: length is less than 22 bytes - %d", n) 53 | } 54 | 55 | _, _, err := base58.CheckDecode(address) 56 | if err != nil { 57 | return "", errors.Errorf("invalid address") 58 | } 59 | 60 | // Drop Qtum chain prefix and checksum suffix 61 | ethAddrBytes := base58.Decode(address)[1:21] 62 | 63 | return hex.EncodeToString(ethAddrBytes), nil 64 | } 65 | -------------------------------------------------------------------------------- /pkg/internal/tests_transformer.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/pkg/errors" 6 | "github.com/qtumproject/janus/pkg/eth" 7 | ) 8 | 9 | type ETHProxy interface { 10 | Request(*eth.JSONRPCRequest, echo.Context) (interface{}, eth.JSONRPCError) 11 | Method() string 12 | } 13 | 14 | type mockTransformer struct { 15 | proxies map[string]ETHProxy 16 | } 17 | 18 | func (t *mockTransformer) Transform(req *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 19 | proxy, ok := t.proxies[req.Method] 20 | if !ok { 21 | return nil, eth.NewCallbackError("couldn't get proxy") 22 | } 23 | resp, err := proxy.Request(req, c) 24 | if err != nil { 25 | return nil, eth.NewCallbackError(errors.WithMessagef(err.Error(), "couldn't proxy %s request", req.Method).Error()) 26 | } 27 | return resp, nil 28 | } 29 | 30 | func newTransformer(proxies []ETHProxy) *mockTransformer { 31 | t := &mockTransformer{ 32 | proxies: make(map[string]ETHProxy), 33 | } 34 | 35 | for _, proxy := range proxies { 36 | t.proxies[proxy.Method()] = proxy 37 | } 38 | 39 | return t 40 | } 41 | 42 | func NewMockTransformer(proxies []ETHProxy) *mockTransformer { 43 | return newTransformer(proxies) 44 | } 45 | 46 | type mockETHProxy struct { 47 | method string 48 | response interface{} 49 | } 50 | 51 | func NewMockETHProxy(method string, response interface{}) ETHProxy { 52 | return &mockETHProxy{ 53 | method: method, 54 | response: response, 55 | } 56 | } 57 | 58 | func (e *mockETHProxy) Request(*eth.JSONRPCRequest, echo.Context) (interface{}, eth.JSONRPCError) { 59 | return e.response, nil 60 | } 61 | 62 | func (e *mockETHProxy) Method() string { 63 | return e.method 64 | } 65 | -------------------------------------------------------------------------------- /metamask/README.md: -------------------------------------------------------------------------------- 1 | # Simple VUE project to switch to QTUM network via Metamask 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Customize configuration 19 | See [Configuration Reference](https://cli.vuejs.org/config/). 20 | 21 | ### wallet_addEthereumChain 22 | ``` 23 | // request account access 24 | window.qtum.request({ method: 'eth_requestAccounts' }) 25 | .then(() => { 26 | // add chain 27 | window.qtum.request({ 28 | method: "wallet_addEthereumChain", 29 | params: [{ 30 | { 31 | chainId: '0x22B9', 32 | chainName: 'Qtum Testnet', 33 | rpcUrls: ['https://localhost:23889'], 34 | blockExplorerUrls: ['https://testnet.qtum.info/'], 35 | iconUrls: [ 36 | 'https://qtum.info/images/metamask_icon.svg', 37 | 'https://qtum.info/images/metamask_icon.png', 38 | ], 39 | nativeCurrency: { 40 | decimals: 18, 41 | symbol: 'QTUM', 42 | }, 43 | } 44 | }], 45 | } 46 | }); 47 | ``` 48 | 49 | # Known issues 50 | - Metamask requires https for `rpcUrls` so that must be enabled 51 | - Either directly through Janus with `--https-key ./path --https-cert ./path2` see [SSL](../README.md#ssl) 52 | - Through the Makefile `make docker-configure-https && make run-janus-https` 53 | - Or do it yourself with a proxy (eg, nginx) 54 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/doc/css.md: -------------------------------------------------------------------------------- 1 | [HTML5 Boilerplate homepage](https://html5boilerplate.com/) | [Documentation 2 | table of contents](TOC.md) 3 | 4 | # The CSS 5 | 6 | HTML5 Boilerplate's CSS includes: 7 | 8 | * [Normalize.css](#normalizecss) 9 | * [main.css](#maincss) 10 | 11 | ## Normalize.css 12 | 13 | In order to make browsers render all elements more consistently and in line with 14 | modern standards, we include Normalize.css — a modern, HTML5-ready alternative 15 | to CSS resets. 16 | 17 | As opposed to CSS resets, Normalize.css: 18 | 19 | * targets only the styles that need normalizing 20 | * preserves useful browser defaults rather than erasing them 21 | * corrects bugs and common browser inconsistencies 22 | * improves usability with subtle improvements 23 | * doesn't clutter the debugging tools 24 | * has better documentation 25 | 26 | For more information about Normalize.css, please refer to its [project 27 | page](https://necolas.github.io/normalize.css/). 28 | 29 | ## main.css 30 | 31 | Several base styles are included that build upon `Normalize.css`. These styles: 32 | 33 | * provide basic typography settings that improve text readability 34 | * protect against unwanted `text-shadow` during text highlighting 35 | * tweak the default alignment of some elements (e.g.: `img`, `video`, 36 | `fieldset`, `textarea`) 37 | * style the prompt that is displayed to users using an outdated browser 38 | * and more... 39 | 40 | These styles are included in 41 | [main.css](https://github.com/h5bp/html5-boilerplate/blob/master/dist/css/main.css). 42 | See the [main.css](https://github.com/h5bp/main.css) project 43 | [documentation](https://github.com/h5bp/main.css/blob/master/README.md#features) 44 | for a full discussion of these styles. 45 | -------------------------------------------------------------------------------- /pkg/transformer/eth_chainId_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/eth" 8 | "github.com/qtumproject/janus/pkg/internal" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | ) 11 | 12 | func TestChainIdMainnet(t *testing.T) { 13 | testChainIdsImpl(t, "main", "0x51") 14 | } 15 | 16 | func TestChainIdTestnet(t *testing.T) { 17 | testChainIdsImpl(t, "test", "0x22b9") 18 | } 19 | 20 | func TestChainIdRegtest(t *testing.T) { 21 | testChainIdsImpl(t, "regtest", "0x22ba") 22 | } 23 | 24 | func TestChainIdUnknown(t *testing.T) { 25 | testChainIdsImpl(t, "???", "0x22ba") 26 | } 27 | 28 | func testChainIdsImpl(t *testing.T, chain string, expected string) { 29 | //preparing request 30 | requestParams := []json.RawMessage{} 31 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 32 | if err != nil { 33 | t.Fatal(err) 34 | } 35 | 36 | mockedClientDoer := internal.NewDoerMappedMock() 37 | 38 | //preparing client response 39 | getBlockCountResponse := qtum.GetBlockChainInfoResponse{Chain: chain} 40 | err = mockedClientDoer.AddResponseWithRequestID(2, qtum.MethodGetBlockChainInfo, getBlockCountResponse) 41 | if err != nil { 42 | t.Fatal(err) 43 | } 44 | 45 | qtumClient, err := internal.CreateMockedClientForNetwork(mockedClientDoer, qtum.ChainAuto) 46 | if err != nil { 47 | t.Fatal(err) 48 | } 49 | 50 | //preparing proxy & executing request 51 | proxyEth := ProxyETHChainId{qtumClient} 52 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 53 | if jsonErr != nil { 54 | t.Fatal(jsonErr) 55 | } 56 | 57 | want := eth.ChainIdResponse(expected) 58 | 59 | internal.CheckTestResultEthRequestRPC(*request, want, got, t, false) 60 | } 61 | -------------------------------------------------------------------------------- /playground/contracts/openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./StandardToken.sol"; 4 | import "../../ownership/Ownable.sol"; 5 | 6 | 7 | /** 8 | * @title Mintable token 9 | * @dev Simple ERC20 Token example, with mintable token creation 10 | * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol 11 | */ 12 | contract MintableToken is StandardToken, Ownable { 13 | event Mint(address indexed to, uint256 amount); 14 | event MintFinished(); 15 | 16 | bool public mintingFinished = false; 17 | 18 | 19 | modifier canMint() { 20 | require(!mintingFinished); 21 | _; 22 | } 23 | 24 | modifier hasMintPermission() { 25 | require(msg.sender == owner); 26 | _; 27 | } 28 | 29 | /** 30 | * @dev Function to mint tokens 31 | * @param _to The address that will receive the minted tokens. 32 | * @param _amount The amount of tokens to mint. 33 | * @return A boolean that indicates if the operation was successful. 34 | */ 35 | function mint( 36 | address _to, 37 | uint256 _amount 38 | ) 39 | hasMintPermission 40 | canMint 41 | public 42 | returns (bool) 43 | { 44 | totalSupply_ = totalSupply_.add(_amount); 45 | balances[_to] = balances[_to].add(_amount); 46 | emit Mint(_to, _amount); 47 | emit Transfer(address(0), _to, _amount); 48 | return true; 49 | } 50 | 51 | /** 52 | * @dev Function to stop minting new tokens. 53 | * @return True if the operation was successful. 54 | */ 55 | function finishMinting() onlyOwner canMint public returns (bool) { 56 | mintingFinished = true; 57 | emit MintFinished(); 58 | return true; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pkg/analytics/analytics.go: -------------------------------------------------------------------------------- 1 | package analytics 2 | 3 | import "sync" 4 | 5 | type Analytics struct { 6 | success int 7 | failures int 8 | lastRequest int 9 | lastRequests []bool 10 | totalRequests int 11 | 12 | mutex sync.RWMutex 13 | } 14 | 15 | func NewAnalytics(requests int) *Analytics { 16 | analytics := &Analytics{ 17 | success: 0, 18 | failures: 0, 19 | lastRequest: 0, 20 | lastRequests: make([]bool, requests), 21 | totalRequests: requests, 22 | } 23 | 24 | return analytics 25 | } 26 | 27 | func (a *Analytics) GetSuccessRate() float32 { 28 | a.mutex.RLock() 29 | defer a.mutex.RUnlock() 30 | 31 | total := a.success + a.failures 32 | 33 | if total != a.totalRequests { 34 | // if there are not enough requests, don't let the first request get reported as an alert 35 | return 1 36 | } 37 | 38 | return float32(a.success) / float32(total) 39 | } 40 | 41 | func (a *Analytics) Success() { 42 | a.bump(true) 43 | } 44 | 45 | func (a *Analytics) Failure() { 46 | a.bump(false) 47 | } 48 | 49 | func (a *Analytics) bump(success bool) { 50 | a.mutex.Lock() 51 | defer a.mutex.Unlock() 52 | 53 | total := a.success + a.failures 54 | 55 | if success { 56 | a.success++ 57 | } else { 58 | a.failures++ 59 | } 60 | 61 | if total >= a.totalRequests { 62 | // push the last request off 63 | if a.lastRequests[a.lastRequest] { 64 | a.success-- 65 | } else { 66 | a.failures-- 67 | } 68 | 69 | if a.success < 0 { 70 | panic("internal analytics success count is < 0") 71 | } 72 | 73 | if a.failures < 0 { 74 | panic("internal analytics failure count is < 0") 75 | } 76 | } 77 | 78 | a.lastRequests[a.lastRequest] = success 79 | a.lastRequest = (a.lastRequest + 1) % a.totalRequests 80 | } 81 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getFilterLogs.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | "math/big" 6 | 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | ) 10 | 11 | // ProxyETHGetFilterLogs implements ETHProxy 12 | type ProxyETHGetFilterLogs struct { 13 | *ProxyETHGetFilterChanges 14 | } 15 | 16 | func (p *ProxyETHGetFilterLogs) Method() string { 17 | return "eth_getFilterLogs" 18 | } 19 | 20 | func (p *ProxyETHGetFilterLogs) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 21 | 22 | filter, err := processFilter(p.ProxyETHGetFilterChanges, rawreq) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | switch filter.Type { 28 | case eth.NewFilterTy: 29 | return p.request(c.Request().Context(), filter) 30 | default: 31 | return nil, eth.NewInvalidParamsError("filter not found") 32 | } 33 | } 34 | 35 | func (p *ProxyETHGetFilterLogs) request(ctx context.Context, filter *eth.Filter) (qtumresp eth.GetFilterChangesResponse, err eth.JSONRPCError) { 36 | qtumresp = make(eth.GetFilterChangesResponse, 0) 37 | 38 | _lastBlockNumber, ok := filter.Data.Load("lastBlockNumber") 39 | if !ok { 40 | return qtumresp, eth.NewCallbackError("Could not get lastBlockNumber") 41 | } 42 | lastBlockNumber := _lastBlockNumber.(uint64) 43 | 44 | _toBlock, ok := filter.Data.Load("toBlock") 45 | if !ok { 46 | return qtumresp, eth.NewCallbackError("Could not get toBlock") 47 | } 48 | toBlock := _toBlock.(uint64) 49 | 50 | searchLogsReq, err := p.ProxyETHGetFilterChanges.toSearchLogsReq(filter, big.NewInt(int64(lastBlockNumber)), big.NewInt(int64(toBlock))) 51 | if err != nil { 52 | return nil, err 53 | } 54 | 55 | return p.ProxyETHGetFilterChanges.doSearchLogs(ctx, searchLogsReq) 56 | 57 | } 58 | -------------------------------------------------------------------------------- /pkg/transformer/web3_sha3_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/internal" 8 | ) 9 | 10 | func TestWeb3Sha3Request(t *testing.T) { 11 | values := make(map[string]string) 12 | values[""] = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" 13 | values["0x00"] = "0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a" 14 | values["0x68656c6c6f20776f726c64"] = "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad" 15 | 16 | for input, want := range values { 17 | requestParams := []json.RawMessage{[]byte(`"` + input + `"`)} 18 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 19 | if err != nil { 20 | t.Fatal(err) 21 | } 22 | 23 | web3Sha3 := Web3Sha3{} 24 | got, jsonErr := web3Sha3.Request(request, nil) 25 | if jsonErr != nil { 26 | t.Fatal(jsonErr) 27 | } 28 | 29 | internal.CheckTestResultUnspecifiedInput(input, want, got, t, false) 30 | } 31 | } 32 | 33 | func TestWeb3Sha3Errors(t *testing.T) { 34 | testWeb3Sha3Errors(t, []json.RawMessage{}, "missing value for required argument 0") 35 | testWeb3Sha3Errors(t, []json.RawMessage{[]byte(`"0x00"`), []byte(`"0x00"`)}, "too many arguments, want at most 1") 36 | } 37 | 38 | func testWeb3Sha3Errors(t *testing.T, input []json.RawMessage, want string) { 39 | requestParams := input 40 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 41 | if err != nil { 42 | t.Fatal(err) 43 | } 44 | 45 | web3Sha3 := Web3Sha3{} 46 | _, jsonErr := web3Sha3.Request(request, nil) 47 | got := jsonErr.Message() 48 | 49 | // TODO: Expand to also check for correct error code? 50 | internal.CheckTestResultUnspecifiedInputMarshal(input, want, got, t, false) 51 | } 52 | -------------------------------------------------------------------------------- /playground/test/truffle-test-myToken.js: -------------------------------------------------------------------------------- 1 | const MyToken = artifacts.require("MyToken"); 2 | 3 | contract("MyToken", async accounts => { 4 | 5 | it("Has been deployed", async () => { 6 | const myTokenDeployed = await MyToken.deployed(); 7 | assert(myTokenDeployed, "contract has been deployed"); 8 | console.log("Address is: ", myTokenDeployed.address) 9 | }); 10 | 11 | it("should perform transactions correctly", async () => { 12 | 13 | const acc1 = accounts[0]; 14 | console.log("acc1 address: ", acc1); 15 | const acc2 = accounts[1]; 16 | console.log("acc2 address: ", acc2); 17 | 18 | const amount = 10; 19 | 20 | const myToken = await MyToken.deployed(); 21 | 22 | let balance = await myToken.balanceOf(acc1); 23 | let acc1StartingBalance = balance.toNumber(); 24 | console.log("starting balance of acc1: ", acc1StartingBalance); 25 | 26 | balance = await myToken.balanceOf(acc2); 27 | let acc2StartingBalance = balance.toNumber(); 28 | console.log("starting balance of acc2: ", acc2StartingBalance); 29 | 30 | await myToken.mint(acc1, 100).then((receipt) => { console.log("receipt: ", receipt)}); 31 | balance = await myToken.balanceOf(acc1); 32 | let acc1Balance = balance.toNumber(); 33 | console.log("new balance of acc1: ", acc1Balance); 34 | 35 | await myToken.transfer(acc2, amount, {from: acc1}).then((receipt) => { console.log("receipt: ", receipt)}); 36 | balance = await myToken.balanceOf(acc2); 37 | let acc2Balance = balance.toNumber(); 38 | balance = await myToken.balanceOf(acc1); 39 | acc1Balance = balance.toNumber(); 40 | console.log("new balance of acc1 after transfer to acc2: ", acc1Balance); 41 | console.log("new balance of acc2 after transfer to acc1: ", acc2Balance); 42 | 43 | }); 44 | 45 | }); -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/doc/TOC.md: -------------------------------------------------------------------------------- 1 | [HTML5 Boilerplate homepage](https://html5boilerplate.com/) 2 | 3 | ## Getting started 4 | 5 | * [Usage](usage.md) — Overview of the project contents. 6 | * [FAQ](faq.md) — Frequently asked questions along with their answers. 7 | 8 | ## HTML5 Boilerplate core 9 | 10 | * [HTML](html.md) — Guide to the default HTML. 11 | * [CSS](css.md) — Guide to the default CSS. 12 | * [JavaScript](js.md) — Guide to the default JavaScript. 13 | * [Everything else](misc.md). 14 | 15 | ## Development 16 | 17 | * [Extending and customizing HTML5 Boilerplate](extend.md) — Going further with 18 | the boilerplate. 19 | 20 | ## Related projects 21 | 22 | The [H5BP organization](https://github.com/h5bp) maintains several projects that 23 | complement HTML5 Boilerplate, projects that can help you improve different 24 | aspects of your website/web app (e.g.: the performance, security, etc.). 25 | 26 | * [Server Configs](https://github.com/h5bp/server-configs) — Fast and smart 27 | configurations for web servers such as Apache and Nginx. 28 | * [Apache](https://github.com/h5bp/server-configs-apache) 29 | * [Google App Engine (GAE)](https://github.com/h5bp/server-configs-gae) 30 | * [Internet Information Services 31 | (IIS)](https://github.com/h5bp/server-configs-iis) 32 | * [lighttpd](https://github.com/h5bp/server-configs-lighttpd) 33 | * [Nginx](https://github.com/h5bp/server-configs-nginx) 34 | * [Node.js](https://github.com/h5bp/server-configs-node) 35 | * [Front-end Developer Interview Questions](https://github.com/h5bp/Front-end-Developer-Interview-Questions) 36 | * [create-html5-boilerplate](https://github.com/h5bp/create-html5-boilerplate) — Quick start HTML5 Boilerplate development 37 | * [main.css](https://github.com/h5bp/main.css) — the main.css file included with HTML5 Boilerplate 38 | -------------------------------------------------------------------------------- /pkg/transformer/eth_newFilter.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | 7 | "github.com/dcb9/go-ethereum/common/hexutil" 8 | "github.com/labstack/echo" 9 | "github.com/qtumproject/janus/pkg/eth" 10 | "github.com/qtumproject/janus/pkg/qtum" 11 | ) 12 | 13 | // ProxyETHNewFilter implements ETHProxy 14 | type ProxyETHNewFilter struct { 15 | *qtum.Qtum 16 | filter *eth.FilterSimulator 17 | } 18 | 19 | func (p *ProxyETHNewFilter) Method() string { 20 | return "eth_newFilter" 21 | } 22 | 23 | func (p *ProxyETHNewFilter) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 24 | var req eth.NewFilterRequest 25 | if err := json.Unmarshal(rawreq.Params, &req); err != nil { 26 | // TODO: Correct error code? 27 | return nil, eth.NewInvalidParamsError(err.Error()) 28 | } 29 | 30 | return p.request(c.Request().Context(), &req) 31 | } 32 | 33 | func (p *ProxyETHNewFilter) request(ctx context.Context, ethreq *eth.NewFilterRequest) (*eth.NewFilterResponse, eth.JSONRPCError) { 34 | 35 | from, err := getBlockNumberByRawParam(ctx, p.Qtum, ethreq.FromBlock, true) 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | to, err := getBlockNumberByRawParam(ctx, p.Qtum, ethreq.ToBlock, true) 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | filter := p.filter.New(eth.NewFilterTy, ethreq) 46 | filter.Data.Store("lastBlockNumber", from.Uint64()) 47 | 48 | filter.Data.Store("toBlock", to.Uint64()) 49 | 50 | if len(ethreq.Topics) > 0 { 51 | topics, err := eth.TranslateTopics(ethreq.Topics) 52 | if err != nil { 53 | return nil, eth.NewCallbackError(err.Error()) 54 | } 55 | filter.Data.Store("topics", qtum.NewSearchLogsTopics(topics)) 56 | } 57 | resp := eth.NewFilterResponse(hexutil.EncodeUint64(filter.ID)) 58 | return &resp, nil 59 | } 60 | -------------------------------------------------------------------------------- /testing/revert-reasons/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | .idea 14 | 15 | .DS_Store 16 | build 17 | 18 | # Logs 19 | logs 20 | *.log 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | .txt 25 | 26 | # Runtime data 27 | pids 28 | *.pid 29 | *.seed 30 | *.pid.lock 31 | 32 | # Directory for instrumented libs generated by jscoverage/JSCover 33 | lib-cov 34 | 35 | # Coverage directory used by tools like istanbul 36 | coverage 37 | 38 | # nyc test coverage 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 42 | .grunt 43 | 44 | # Bower dependency directory (https://bower.io/) 45 | bower_components 46 | 47 | # node-waf configuration 48 | .lock-wscript 49 | 50 | # Compiled binary addons (https://nodejs.org/api/addons.html) 51 | build/Release 52 | 53 | # Dependency directories 54 | node_modules/ 55 | jspm_packages/ 56 | 57 | # TypeScript v1 declaration files 58 | typings/ 59 | 60 | # Optional npm cache directory 61 | .npm 62 | 63 | # Optional eslint cache 64 | .eslintcache 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variables file 76 | .env 77 | 78 | # parcel-bundler cache (https://parceljs.org/) 79 | .cache 80 | 81 | # next.js build output 82 | .next 83 | 84 | # nuxt.js build output 85 | .nuxt 86 | 87 | # vuepress build output 88 | .vuepress/dist 89 | 90 | # Serverless directories 91 | .serverless 92 | solar*.json 93 | /yarn.lock 94 | /.boast.json 95 | /build 96 | /package-lock.json 97 | /package.json 98 | *.txt -------------------------------------------------------------------------------- /testing/aave/hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import fs from 'fs'; 3 | import { HardhatUserConfig } from 'hardhat/types'; 4 | // @ts-ignore 5 | 6 | require('dotenv').config(); 7 | 8 | import '@nomiclabs/hardhat-ethers'; 9 | import '@nomiclabs/hardhat-waffle'; 10 | import 'hardhat-gas-reporter'; 11 | import 'hardhat-typechain'; 12 | import '@tenderly/hardhat-tenderly'; 13 | 14 | const SKIP_LOAD = true; 15 | 16 | // Prevent to load scripts before compilation and typechain 17 | if (!SKIP_LOAD) { 18 | ['misc', 'migrations', 'dev', 'full', 'verifications', 'deployments', 'helpers'].forEach( 19 | (folder) => { 20 | const tasksPath = path.join(__dirname, 'tasks', folder); 21 | fs.readdirSync(tasksPath) 22 | .filter((pth) => pth.includes('.ts')) 23 | .forEach((task) => { 24 | require(`${tasksPath}/${task}`); 25 | }); 26 | } 27 | ); 28 | } 29 | 30 | require(`${path.join(__dirname, 'tasks/misc')}/set-bre.ts`); 31 | 32 | 33 | const buidlerConfig: HardhatUserConfig = { 34 | solidity: { 35 | version: '0.6.12', 36 | settings: { 37 | optimizer: {enabled: true, runs: 1}, 38 | }, 39 | }, 40 | typechain: { 41 | outDir: 'types', 42 | target: 'ethers-v5', 43 | }, 44 | mocha: { 45 | timeout: 0, 46 | }, 47 | defaultNetwork: "development", 48 | networks: { 49 | development: { 50 | url: "http://127.0.0.1:23889", 51 | gas: "auto", 52 | gasPrice: "auto", 53 | timeout: 600000 54 | }, 55 | ganache: { 56 | url: "http://127.0.0.1:8545", 57 | gas: "auto", 58 | }, 59 | testnet: { 60 | url: "http://hk1.s.qtum.org:23889", 61 | from: "0x7926223070547d2d15b2ef5e7383e541c338ffe9", 62 | gas: "auto", 63 | gasPrice: "auto" 64 | }, 65 | }, 66 | }; 67 | 68 | export default buidlerConfig; 69 | -------------------------------------------------------------------------------- /pkg/eth/util.go: -------------------------------------------------------------------------------- 1 | package eth 2 | 3 | import ( 4 | "github.com/pkg/errors" 5 | "github.com/qtumproject/janus/pkg/utils" 6 | ) 7 | 8 | var ErrInvalidTopics = errors.New("Invalid topics") 9 | 10 | /** 11 | translateTopics takes in an ethReq's topics field and translates it to a it's equivalent QtumReq 12 | topics (optional) has a max lenght of 4 13 | 14 | Topics are order-dependent. A transaction with a log with topics [A, B] will be matched by the following topic filters: 15 | 16 | [] “anything” 17 | [A] “A in first position (and anything after)” 18 | [null, B] “anything in first position AND B in second position (and anything after)” 19 | [A, B] “A in first position AND B in second position (and anything after)” 20 | [[A, B], [A, B]] “(A OR B) in first position AND (A OR B) in second position (and anything after)” 21 | */ 22 | func TranslateTopics(ethTopics []interface{}) ([][]string, error) { 23 | 24 | var topics [][]string 25 | nilCount := 0 26 | 27 | for _, topic := range ethTopics { 28 | switch topic.(type) { 29 | case []string: 30 | stringTopics := []string{} 31 | for _, t := range topic.([]string) { 32 | stringTopics = append(stringTopics, utils.RemoveHexPrefix(t)) 33 | } 34 | topics = append(topics, stringTopics) 35 | case string: 36 | topics = append(topics, []string{utils.RemoveHexPrefix(topic.(string))}) 37 | case nil: 38 | nilCount++ 39 | topics = append(topics, nil) 40 | case []interface{}: 41 | stringTopics := []string{} 42 | for _, t := range topic.([]interface{}) { 43 | if stringTopic, ok := t.(string); ok { 44 | stringTopics = append(stringTopics, utils.RemoveHexPrefix(stringTopic)) 45 | } else { 46 | return nil, ErrInvalidTopics 47 | } 48 | } 49 | topics = append(topics, stringTopics) 50 | } 51 | } 52 | 53 | return topics, nil 54 | 55 | } 56 | -------------------------------------------------------------------------------- /pkg/qtum/client_test.go: -------------------------------------------------------------------------------- 1 | package qtum 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func TestComputeBackoff(t *testing.T) { 9 | backoffOne := computeBackoff(0, false) 10 | if backoffOne != 250*time.Millisecond { 11 | t.Errorf("Unexpected backoff time %d != %d", backoffOne.Milliseconds(), (250 * time.Millisecond).Milliseconds()) 12 | } 13 | backoffTwo := computeBackoff(1, false) 14 | if backoffTwo != 500*time.Millisecond { 15 | t.Errorf("Unexpected backoff time %d != %d", backoffTwo.Milliseconds(), (500 * time.Millisecond).Milliseconds()) 16 | } 17 | backoffThree := computeBackoff(2, false) 18 | if backoffThree != 1000*time.Millisecond { 19 | t.Errorf("Unexpected backoff time %d != %d", backoffThree.Milliseconds(), (1000 * time.Millisecond).Milliseconds()) 20 | } 21 | maxBackoff := computeBackoff(10, false) 22 | if maxBackoff != 2000*time.Millisecond { 23 | t.Errorf("Unexpected backoff time %d != %d", maxBackoff.Milliseconds(), (2000 * time.Millisecond).Milliseconds()) 24 | } 25 | overflow := computeBackoff(1000000, false) 26 | if overflow != 2000*time.Millisecond { 27 | t.Errorf("Unexpected backoff time %d != %d", overflow.Milliseconds(), (2000 * time.Millisecond).Milliseconds()) 28 | } 29 | } 30 | 31 | func TestComputeBackoffWithRandom(t *testing.T) { 32 | randomRange := time.Duration(250) 33 | for i := 0; i < 10000; i++ { 34 | backoff := computeBackoff(0, true) 35 | min := (250 - randomRange) * time.Millisecond 36 | max := (250 + randomRange) * time.Millisecond 37 | if backoff < min || backoff > max { 38 | t.Fatalf("Unexpected backoff time %d <= (%d) <= %d", min, backoff.Milliseconds(), max) 39 | } 40 | } 41 | 42 | overflow := computeBackoff(1000000, true) 43 | if overflow != 2000*time.Millisecond { 44 | t.Fatalf("Unexpected backoff time %d != %d", overflow.Milliseconds(), (2000 * time.Millisecond).Milliseconds()) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /pkg/eth/eth_address.go: -------------------------------------------------------------------------------- 1 | package eth 2 | 3 | import ( 4 | "encoding/json" 5 | "strings" 6 | 7 | "github.com/pkg/errors" 8 | 9 | "github.com/ethereum/go-ethereum/common/hexutil" 10 | ) 11 | 12 | var ErrNoHexPrefix = errors.New("Missing 0x prefix") 13 | var ErrInvalidLength = errors.New("Invalid length") 14 | 15 | type ETHAddress struct { 16 | address string 17 | } 18 | 19 | func NewETHAddress(address string) (ETHAddress, error) { 20 | var ethAddress ETHAddress 21 | if !strings.HasPrefix(address, `"`) { 22 | address = `"` + address 23 | } 24 | 25 | if !strings.HasSuffix(address, `"`) { 26 | address = address + `"` 27 | } 28 | 29 | err := json.Unmarshal([]byte(address), ðAddress) 30 | if err != nil { 31 | return ethAddress, err 32 | } 33 | return ethAddress, nil 34 | } 35 | 36 | func (addr *ETHAddress) String() string { 37 | return addr.address 38 | } 39 | 40 | func (addr ETHAddress) MarshalJSON() ([]byte, error) { 41 | if err := validateAddress(addr.address); err != nil { 42 | return []byte{}, err 43 | } 44 | 45 | return json.Marshal(addr.address) 46 | } 47 | 48 | // UnmarshalJSON needs to be able to parse ETHAddress from both hex string or number 49 | func (addr *ETHAddress) UnmarshalJSON(data []byte) (err error) { 50 | asString := string(data) 51 | if strings.HasPrefix(asString, `"`) && strings.HasSuffix(asString, `"`) { 52 | asString = asString[1 : len(asString)-1] 53 | } 54 | if err := validateAddress(asString); err != nil { 55 | return err 56 | } 57 | 58 | addr.address = asString 59 | return nil 60 | } 61 | 62 | func validateAddress(address string) error { 63 | if !strings.HasPrefix(address, "0x") { 64 | return ErrNoHexPrefix 65 | } 66 | 67 | if len(address) != 42 { 68 | return ErrInvalidLength 69 | } 70 | 71 | _, err := hexutil.Decode(address) 72 | if err != nil { 73 | return errors.Wrap(err, "Invalid hexadecimal") 74 | } 75 | 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /playground/contracts/openzeppelin-solidity/contracts/ownership/Ownable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | /** 5 | * @title Ownable 6 | * @dev The Ownable contract has an owner address, and provides basic authorization control 7 | * functions, this simplifies the implementation of "user permissions". 8 | */ 9 | contract Ownable { 10 | address public owner; 11 | 12 | 13 | event OwnershipRenounced(address indexed previousOwner); 14 | event OwnershipTransferred( 15 | address indexed previousOwner, 16 | address indexed newOwner 17 | ); 18 | 19 | 20 | /** 21 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 22 | * account. 23 | */ 24 | constructor() public { 25 | owner = msg.sender; 26 | } 27 | 28 | /** 29 | * @dev Throws if called by any account other than the owner. 30 | */ 31 | modifier onlyOwner() { 32 | require(msg.sender == owner); 33 | _; 34 | } 35 | 36 | /** 37 | * @dev Allows the current owner to relinquish control of the contract. 38 | * @notice Renouncing to ownership will leave the contract without an owner. 39 | * It will not be possible to call the functions with the `onlyOwner` 40 | * modifier anymore. 41 | */ 42 | function renounceOwnership() public onlyOwner { 43 | emit OwnershipRenounced(owner); 44 | owner = address(0); 45 | } 46 | 47 | /** 48 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 49 | * @param _newOwner The address to transfer ownership to. 50 | */ 51 | function transferOwnership(address _newOwner) public onlyOwner { 52 | _transferOwnership(_newOwner); 53 | } 54 | 55 | /** 56 | * @dev Transfers control of the contract to a newOwner. 57 | * @param _newOwner The address to transfer ownership to. 58 | */ 59 | function _transferOwnership(address _newOwner) internal { 60 | require(_newOwner != address(0)); 61 | emit OwnershipTransferred(owner, _newOwner); 62 | owner = _newOwner; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getBlockByNumber_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/eth" 8 | "github.com/qtumproject/janus/pkg/internal" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | ) 11 | 12 | func initializeProxyETHGetBlockByNumber(qtumClient *qtum.Qtum) ETHProxy { 13 | return &ProxyETHGetBlockByNumber{qtumClient} 14 | } 15 | 16 | func TestGetBlockByNumberRequest(t *testing.T) { 17 | testETHProxyRequest( 18 | t, 19 | initializeProxyETHGetBlockByNumber, 20 | []json.RawMessage{[]byte(`"` + internal.GetTransactionByHashBlockNumberHex + `"`), []byte(`false`)}, 21 | &internal.GetTransactionByHashResponse, 22 | ) 23 | } 24 | 25 | func TestGetBlockByNumberWithTransactionsRequest(t *testing.T) { 26 | testETHProxyRequest( 27 | t, 28 | initializeProxyETHGetBlockByNumber, 29 | []json.RawMessage{[]byte(`"` + internal.GetTransactionByHashBlockNumberHex + `"`), []byte(`true`)}, 30 | &internal.GetTransactionByHashResponseWithTransactions, 31 | ) 32 | } 33 | 34 | func TestGetBlockByNumberUnknownBlockRequest(t *testing.T) { 35 | requestParams := []json.RawMessage{[]byte(`"` + internal.GetTransactionByHashBlockNumberHex + `"`), []byte(`true`)} 36 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 37 | if err != nil { 38 | t.Fatal(err) 39 | } 40 | 41 | mockedClientDoer := internal.NewDoerMappedMock() 42 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 43 | 44 | unknownBlockResponse := qtum.GetErrorResponse(qtum.ErrInvalidParameter) 45 | err = mockedClientDoer.AddError(qtum.MethodGetBlockHash, unknownBlockResponse) 46 | if err != nil { 47 | t.Fatal(err) 48 | } 49 | 50 | //preparing proxy & executing request 51 | proxyEth := ProxyETHGetBlockByNumber{qtumClient} 52 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 53 | if jsonErr != nil { 54 | t.Fatal(jsonErr) 55 | } 56 | 57 | want := (*eth.GetBlockByNumberResponse)(nil) 58 | 59 | internal.CheckTestResultDefault(want, got, t, false) 60 | } 61 | -------------------------------------------------------------------------------- /testing/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build build-openzeppelin openzeppelin 2 | build: build-openzeppelin 3 | 4 | # Build openzeppelin docker files with docker-compose 5 | openzeppelin-docker-compose: 6 | cd openzeppelin && ./run-openzeppelin-tests.sh 7 | 8 | build-openzeppelin: build-truffle-parser-docker build-openzeppelin-docker 9 | 10 | build-truffle-parser-docker: 11 | docker build -t qtum/janus-truffle-parser -f ./truffle-parser.Dockerfile . 12 | 13 | build-openzeppelin-docker: 14 | cd openzeppelin && docker build -t qtum/janus-openzeppelin -f ./openzeppelin.Dockerfile . 15 | 16 | init: 17 | git submodule init 18 | git submodule update 19 | cd openzeppelin/openzeppelin-contracts && yarn install 20 | cd openzeppelin/openzeppelin-contracts && yarn add mocha-spec-json-output-reporter 21 | 22 | openzeppelin: 23 | cd openzeppelin/openzeppelin-contracts && truffle test --network testing 24 | 25 | openzeppelin-development: 26 | cd openzeppelin/openzeppelin-contracts && truffle test --network development 27 | 28 | openzeppelin-docker: build 29 | docker run --rm qtum/janus-openzeppelin 30 | 31 | github-action-openzeppelin: 32 | docker logs ci_openzeppelin_1 | sed -n 's/.* \([0-9]\{1,\}\) passing.*/::set-output name=PASSING=::\1/p' 33 | docker logs ci_openzeppelin_1 | sed -n 's/.* \([0-9]\{1,\}\) pending.*/::set-output name=PENDING=::\1/p' 34 | docker logs ci_openzeppelin_1 | sed -n 's/.* \([0-9]\{1,\}\) failing.*/::set-output name=FAILING=::\1/p' 35 | 36 | openzeppelin-truffle-parser-docker: 37 | cd openzeppelin && make -f ../Makefile truffle-parser-docker 38 | 39 | truffle-parser-extract-result-docker: 40 | docker cp ${CONTAINER}:${INPUT} ./truffle-result-output.json 41 | 42 | truffle-parser-docker: 43 | echo ================================== 44 | cat ./truffle-result-output.json 45 | echo ================================== 46 | docker run --rm -v `pwd`:/output qtum/janus-truffle-parser \ 47 | --expected /output/truffle-expected-output.json \ 48 | --input /output/truffle-result-output.json \ 49 | --output /output/truffle-pruned-output.json -------------------------------------------------------------------------------- /pkg/eth/eth.go: -------------------------------------------------------------------------------- 1 | package eth 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | var EmptyLogsBloom = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 8 | var DefaultSha3Uncles = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" 9 | 10 | const ( 11 | RPCVersion = "2.0" 12 | ) 13 | 14 | type JSONRPCRequest struct { 15 | JSONRPC string `json:"jsonrpc"` 16 | Method string `json:"method"` 17 | ID json.RawMessage `json:"id"` 18 | Params json.RawMessage `json:"params"` 19 | } 20 | 21 | type JSONRPCResult struct { 22 | JSONRPC string `json:"jsonrpc"` 23 | RawResult json.RawMessage `json:"result,omitempty"` 24 | Error JSONRPCError `json:"error,omitempty"` 25 | ID json.RawMessage `json:"id,omitempty"` 26 | } 27 | 28 | func NewJSONRPCResult(id json.RawMessage, res interface{}) (*JSONRPCResult, error) { 29 | rawResult, err := json.Marshal(res) 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | return &JSONRPCResult{ 35 | JSONRPC: RPCVersion, 36 | ID: id, 37 | RawResult: rawResult, 38 | }, nil 39 | } 40 | 41 | type JSONRPCNotification struct { 42 | JSONRPC string `json:"jsonrpc"` 43 | Method string `json:"method,omitempty"` 44 | Params json.RawMessage `json:"params"` 45 | } 46 | 47 | func NewJSONRPCNotification(method string, params interface{}) (*JSONRPCNotification, error) { 48 | rawParams, err := json.Marshal(params) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | return &JSONRPCNotification{ 54 | JSONRPC: RPCVersion, 55 | Method: method, 56 | Params: rawParams, 57 | }, nil 58 | } 59 | -------------------------------------------------------------------------------- /playground/test/truffle-test-simpleStore.js: -------------------------------------------------------------------------------- 1 | /*const artifacts = require('./build/contracts/SimpleStore.json'); 2 | const contract = require('truffle-contract');*/ 3 | const SimpleStore = artifacts.require("SimpleStore"); 4 | 5 | contract("SimpleStore", async accounts => { 6 | 7 | it("Has been deployed", async () => { 8 | const simpleStoreDeployed = await SimpleStore.deployed(); 9 | assert(simpleStoreDeployed, "contract has been deployed"); 10 | console.log("Address is: ", simpleStoreDeployed.address) 11 | }); 12 | 13 | it("should return 100", async () => { 14 | const instance = await SimpleStore.deployed(); 15 | console.log("executing: get(): "); 16 | const balance = await instance.get(); 17 | assert.equal(balance.toNumber(), 100); 18 | console.log("value: ", balance.toNumber()) 19 | }); 20 | 21 | it("should return 184", async () => { 22 | const instance = await SimpleStore.deployed(); 23 | console.log("executing: set(150): "); 24 | await instance.set(184).then((receipt) => { console.log("receipt: ", receipt)}); 25 | const balance = await instance.get(); 26 | assert.equal(balance.toNumber(), 184); 27 | console.log("value: ", balance.toNumber()) 28 | 29 | 30 | }) 31 | 32 | 33 | }); 34 | /* 35 | function testGet(store) { 36 | return store.get().then(function(res) { 37 | console.log("exec: store.get()") 38 | console.log("value: ", res.toNumber()); 39 | }) 40 | } 41 | 42 | function testSet(store) { 43 | var newVal = Math.floor((Math.random() * 1000) + 1); 44 | console.log(`exec: store.set(${newVal})`) 45 | return store.set(newVal, {from: "0x7926223070547d2d15b2ef5e7383e541c338ffe9"}).then(function(res) { 46 | console.log("receipt: ", res) 47 | }).catch(function(e) { 48 | console.log(e) 49 | }) 50 | } 51 | 52 | var store; 53 | SimpleStore.deployed().then(function(i) { 54 | store = i; 55 | }).then(function() { 56 | return testGet(store) 57 | }).then(function() { 58 | return testSet(store) 59 | }).then(function() { 60 | return testGet(store) 61 | }).catch(function(e) { 62 | console.log(e) 63 | })*/ 64 | -------------------------------------------------------------------------------- /metamask/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 40 | 41 | 42 | 58 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getTransactionByBlockHashAndIndex.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | 7 | "github.com/ethereum/go-ethereum/common/hexutil" 8 | "github.com/labstack/echo" 9 | "github.com/qtumproject/janus/pkg/eth" 10 | "github.com/qtumproject/janus/pkg/qtum" 11 | ) 12 | 13 | // ProxyETHGetTransactionByBlockHashAndIndex implements ETHProxy 14 | type ProxyETHGetTransactionByBlockHashAndIndex struct { 15 | *qtum.Qtum 16 | } 17 | 18 | func (p *ProxyETHGetTransactionByBlockHashAndIndex) Method() string { 19 | return "eth_getTransactionByBlockHashAndIndex" 20 | } 21 | 22 | func (p *ProxyETHGetTransactionByBlockHashAndIndex) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 23 | var req eth.GetTransactionByBlockHashAndIndex 24 | if err := json.Unmarshal(rawreq.Params, &req); err != nil { 25 | // TODO: Correct error code? 26 | return nil, eth.NewInvalidParamsError(err.Error()) 27 | } 28 | if req.BlockHash == "" { 29 | // TODO: Correct error code? 30 | return nil, eth.NewInvalidParamsError("invalid argument 0: empty hex string") 31 | } 32 | 33 | return p.request(c.Request().Context(), &req) 34 | } 35 | 36 | func (p *ProxyETHGetTransactionByBlockHashAndIndex) request(ctx context.Context, req *eth.GetTransactionByBlockHashAndIndex) (interface{}, eth.JSONRPCError) { 37 | transactionIndex, err := hexutil.DecodeUint64(req.TransactionIndex) 38 | if err != nil { 39 | // TODO: Correct error code? 40 | return nil, eth.NewInvalidParamsError("invalid argument 1") 41 | } 42 | 43 | // Proxy eth_getBlockByHash and return the transaction at requested index 44 | getBlockByNumber := ProxyETHGetBlockByHash{p.Qtum} 45 | blockByNumber, jsonErr := getBlockByNumber.request(ctx, ð.GetBlockByHashRequest{BlockHash: req.BlockHash, FullTransaction: true}) 46 | 47 | if jsonErr != nil { 48 | return nil, jsonErr 49 | } 50 | 51 | if blockByNumber == nil { 52 | return nil, nil 53 | } 54 | 55 | if len(blockByNumber.Transactions) <= int(transactionIndex) { 56 | return nil, nil 57 | } 58 | 59 | return blockByNumber.Transactions[int(transactionIndex)], nil 60 | } 61 | -------------------------------------------------------------------------------- /docker/setup_self_signed_https.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -f "./https/cert.pem" ]; then 4 | echo "cert.pem already exists" 5 | if [ ! -f "./https/key.pem" ]; then 6 | echo "key.pem does not exist, both are needed, please delete "`pwd`"/https/key.pem manually" 7 | exit 1 8 | fi 9 | exit 0 10 | fi 11 | 12 | mkdir -p ./https 13 | if [ ! -d "./https" ]; then 14 | echo "Failed to mkdir -p ./https" 15 | exit 1 16 | fi 17 | 18 | echo "Generating key.pem and cert.pem" 19 | docker run -v `pwd`/https:/https qtum/openssl.janus openssl req -nodes -x509 -newkey rsa:4096 -keyout /https/key.pem -out /https/cert.pem -days 365 -subj "/C=US/ST=ST/L=L/O=Janus Self-signed https/OU=Janus Self-signed https/CN=Janus Self-signed https" 20 | if [ 0 -ne $? ]; then 21 | echo "Failed to generate server.key" 22 | exit $? 23 | fi 24 | 25 | if [ ! -r ./https/key.key ]; then 26 | echo "Generated files have wrong owner, chowning them" 27 | sudo chown `id -u`:`id -g` ./https/key.pem ./https/cert.pem 28 | if [ ! -r ./https/key.pem ]; then 29 | echo "Failed to chown on generated files, do it manually in "`pwd`"/https" 30 | echo "\"sudo chown `id -u`:`id -g` ./https/key.pem ./https/cert.pem\"" 31 | exit 1 32 | else 33 | echo "Successfully chown'd generated files are now readable" 34 | fi 35 | fi 36 | 37 | exit 0 38 | 39 | echo "Generating server.key" 40 | docker run -v `pwd`/https:/https qtum/openssl.janus openssl genrsa -out /https/server.key 2048 41 | if [ 0 -ne $? ]; then 42 | echo "Failed to generate server.key" 43 | exit $? 44 | fi 45 | docker run -v `pwd`/https:/https qtum/openssl.janus openssl ecparam -genkey -name secp384r1 -out /https/server.key 46 | if [ 0 -ne $? ]; then 47 | echo "Failed to generate sever.key" 48 | exit $? 49 | fi 50 | echo "Generating server.crt" 51 | docker run -v `pwd`/https:/https qtum/openssl.janus openssl req -nodes -new -x509 -sha256 -key /https/server.key -out /https/server.crt -days 3650 -subj "/C=US/ST=ST/L=L/O=Janus Self-signed https/OU=Janus Self-signed https/CN=Janus Self-signed https" 52 | if [ 0 -ne $? ]; then 53 | echo "Failed to generate server.crt" 54 | exit $? 55 | fi 56 | 57 | 58 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/doc/faq.md: -------------------------------------------------------------------------------- 1 | [HTML5 Boilerplate homepage](https://html5boilerplate.com/) | [Documentation 2 | table of contents](TOC.md) 3 | 4 | # Frequently asked questions 5 | 6 | * [Why is the Google Analytics code at the bottom? Google recommends it be 7 | placed in the 8 | ``.](#why-is-the-google-analytics-code-at-the-bottom-google-recommends-it-be-placed-in-the-head) 9 | * [Do I need to upgrade my site each time a new version of HTML5 Boilerplate is 10 | released?](#do-i-need-to-upgrade-my-site-each-time-a-new-version-of-html5-boilerplate-is-released) 11 | * [Where can I get help with support 12 | questions?](#where-can-i-get-help-with-support-questions) 13 | 14 | --- 15 | 16 | ## Why is the Google Analytics code at the bottom? Google recommends it be placed in the ``. 17 | 18 | The main advantage of placing it in the `` is that you will track the 19 | user's `pageview` even if they leave the page before it has been fully loaded. 20 | 21 | Here's a handy quote from [Mathias 22 | Bynens](https://mathiasbynens.be/notes/async-analytics-snippet#comment-50) about 23 | our placement choice. 24 | >I should point out that it’s Google — not me — recommending to place this 25 | script before all other scripts in the document. The only real advantage is to 26 | catch a pageView call if your page fails to load completely (for example, if the 27 | user aborts loading, or quickly closes the page, etc.). Personally, I wouldn’t 28 | count that as a page view, so I actually prefer to place this script at the 29 | bottom, after all other scripts. This keeps all the scripts together and 30 | reinforces that scripts at the bottom are the right move. (Usually I concatenate 31 | and minify all my scripts into one .js file — the GA snippet being the suffix.) 32 | 33 | ## Do I need to upgrade my site each time a new version of HTML5 Boilerplate is released? 34 | 35 | No, just as you don't normally replace the foundation of a house once it was 36 | built. However, there is nothing stopping you from trying to work in the latest 37 | changes, but you'll have to assess the costs/benefits of doing so. 38 | 39 | ## Where can I get help with support questions? 40 | 41 | Please ask for help on 42 | [StackOverflow](https://stackoverflow.com/questions/tagged/html5boilerplate). 43 | -------------------------------------------------------------------------------- /testing/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | .idea 14 | 15 | .DS_Store 16 | build 17 | 18 | # Logs 19 | logs 20 | *.log 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | *.txt 25 | 26 | # Runtime data 27 | pids 28 | *.pid 29 | *.seed 30 | *.pid.lock 31 | 32 | # Directory for instrumented libs generated by jscoverage/JSCover 33 | lib-cov 34 | 35 | # Coverage directory used by tools like istanbul 36 | coverage 37 | 38 | # nyc test coverage 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 42 | .grunt 43 | 44 | # Bower dependency directory (https://bower.io/) 45 | bower_components 46 | 47 | # node-waf configuration 48 | .lock-wscript 49 | 50 | # Compiled binary addons (https://nodejs.org/api/addons.html) 51 | build/Release 52 | 53 | # Dependency directories 54 | node_modules/ 55 | jspm_packages/ 56 | 57 | # TypeScript v1 declaration files 58 | typings/ 59 | 60 | # Optional npm cache directory 61 | .npm 62 | 63 | # Optional eslint cache 64 | .eslintcache 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variables file 76 | .env 77 | 78 | # parcel-bundler cache (https://parceljs.org/) 79 | .cache 80 | 81 | # next.js build output 82 | .next 83 | 84 | # nuxt.js build output 85 | .nuxt 86 | 87 | # vuepress build output 88 | .vuepress/dist 89 | 90 | # Serverless directories 91 | .serverless 92 | solar*.json 93 | /yarn.lock 94 | /.boast.json 95 | /build 96 | /package-lock.json 97 | 98 | #non-commit integration testing files 99 | /openzeppelin/test 100 | /openzeppelin/contracts 101 | /openzeppelin/node_modules 102 | /openzeppelin/revision-logs 103 | /aave/test 104 | /aave/contracts 105 | /aave/revision-logs 106 | /aave/node_modules 107 | /aave/artifacts 108 | /aave/cache 109 | /aave/helpers 110 | /aave/markets 111 | /aave/modules 112 | /aave/node_modules 113 | /aave/specs 114 | /aave/tasks 115 | /aave/types 116 | .txt 117 | -------------------------------------------------------------------------------- /pkg/transformer/eth_sendRawTransaction.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/labstack/echo" 7 | "github.com/qtumproject/janus/pkg/eth" 8 | "github.com/qtumproject/janus/pkg/qtum" 9 | "github.com/qtumproject/janus/pkg/utils" 10 | ) 11 | 12 | // ProxyETHSendRawTransaction implements ETHProxy 13 | type ProxyETHSendRawTransaction struct { 14 | *qtum.Qtum 15 | } 16 | 17 | var _ ETHProxy = (*ProxyETHSendRawTransaction)(nil) 18 | 19 | func (p *ProxyETHSendRawTransaction) Method() string { 20 | return "eth_sendRawTransaction" 21 | } 22 | 23 | func (p *ProxyETHSendRawTransaction) Request(req *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 24 | var params eth.SendRawTransactionRequest 25 | if err := unmarshalRequest(req.Params, ¶ms); err != nil { 26 | // TODO: Correct error code? 27 | return nil, eth.NewInvalidParamsError(err.Error()) 28 | } 29 | if params[0] == "" { 30 | // TODO: Correct error code? 31 | return nil, eth.NewInvalidParamsError("invalid parameter: raw transaction hexed string is empty") 32 | } 33 | 34 | return p.request(c.Request().Context(), params) 35 | } 36 | 37 | func (p *ProxyETHSendRawTransaction) request(ctx context.Context, params eth.SendRawTransactionRequest) (eth.SendRawTransactionResponse, eth.JSONRPCError) { 38 | var ( 39 | qtumHexedRawTx = utils.RemoveHexPrefix(params[0]) 40 | req = qtum.SendRawTransactionRequest([1]string{qtumHexedRawTx}) 41 | ) 42 | 43 | qtumresp, err := p.Qtum.SendRawTransaction(ctx, &req) 44 | if err != nil { 45 | if err == qtum.ErrVerifyAlreadyInChain { 46 | // already committed 47 | // we need to send back the tx hash 48 | rawTx, err := p.Qtum.DecodeRawTransaction(ctx, qtumHexedRawTx) 49 | if err != nil { 50 | p.GetErrorLogger().Log("msg", "Error decoding raw transaction for duplicate raw transaction", "err", err) 51 | return eth.SendRawTransactionResponse(""), eth.NewCallbackError(err.Error()) 52 | } 53 | qtumresp = &qtum.SendRawTransactionResponse{Result: rawTx.Hash} 54 | } else { 55 | return eth.SendRawTransactionResponse(""), eth.NewCallbackError(err.Error()) 56 | } 57 | } else { 58 | p.GenerateIfPossible() 59 | } 60 | 61 | resp := *qtumresp 62 | ethHexedTxHash := utils.AddHexPrefix(resp.Result) 63 | return eth.SendRawTransactionResponse(ethHexedTxHash), nil 64 | } 65 | -------------------------------------------------------------------------------- /pkg/transformer/eth_sign.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "encoding/hex" 7 | "fmt" 8 | 9 | "github.com/btcsuite/btcd/btcec" 10 | "github.com/btcsuite/btcd/chaincfg/chainhash" 11 | "github.com/labstack/echo" 12 | "github.com/qtumproject/janus/pkg/eth" 13 | "github.com/qtumproject/janus/pkg/qtum" 14 | "github.com/qtumproject/janus/pkg/utils" 15 | ) 16 | 17 | // ProxyETHGetLogs implements ETHProxy 18 | type ProxyETHSign struct { 19 | *qtum.Qtum 20 | } 21 | 22 | func (p *ProxyETHSign) Method() string { 23 | return "eth_sign" 24 | } 25 | 26 | func (p *ProxyETHSign) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 27 | var req eth.SignRequest 28 | if err := unmarshalRequest(rawreq.Params, &req); err != nil { 29 | p.GetDebugLogger().Log("method", p.Method(), "error", err) 30 | // TODO: Correct error code? 31 | return nil, eth.NewInvalidParamsError(err.Error()) 32 | } 33 | 34 | addr := utils.RemoveHexPrefix(req.Account) 35 | 36 | acc := p.Qtum.Accounts.FindByHexAddress(addr) 37 | if acc == nil { 38 | p.GetDebugLogger().Log("method", p.Method(), "account", addr, "msg", "Unknown account") 39 | return nil, eth.NewInvalidParamsError(fmt.Sprintf("No such account: %s", addr)) 40 | } 41 | 42 | sig, err := signMessage(acc.PrivKey, req.Message) 43 | if err != nil { 44 | p.GetDebugLogger().Log("method", p.Method(), "msg", "Failed to sign message", "error", err) 45 | return nil, eth.NewCallbackError(err.Error()) 46 | } 47 | 48 | p.GetDebugLogger().Log("method", p.Method(), "msg", "Successfully signed message") 49 | 50 | return eth.SignResponse("0x" + hex.EncodeToString(sig)), nil 51 | } 52 | 53 | func signMessage(key *btcec.PrivateKey, msg []byte) ([]byte, error) { 54 | msghash := chainhash.DoubleHashB(paddedMessage(msg)) 55 | 56 | secp256k1 := btcec.S256() 57 | 58 | return btcec.SignCompact(secp256k1, key, msghash, true) 59 | } 60 | 61 | var qtumSignMessagePrefix = []byte("\u0015Qtum Signed Message:\n") 62 | 63 | func paddedMessage(msg []byte) []byte { 64 | var wbuf bytes.Buffer 65 | 66 | wbuf.Write(qtumSignMessagePrefix) 67 | 68 | var msglenbuf [binary.MaxVarintLen64]byte 69 | msglen := binary.PutUvarint(msglenbuf[:], uint64(len(msg))) 70 | 71 | wbuf.Write(msglenbuf[:msglen]) 72 | wbuf.Write(msg) 73 | 74 | return wbuf.Bytes() 75 | } 76 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getTransactionByBlockNumberAndIndex.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | 7 | "github.com/ethereum/go-ethereum/common/hexutil" 8 | "github.com/labstack/echo" 9 | "github.com/qtumproject/janus/pkg/eth" 10 | "github.com/qtumproject/janus/pkg/qtum" 11 | ) 12 | 13 | // ProxyETHGetTransactionByBlockNumberAndIndex implements ETHProxy 14 | type ProxyETHGetTransactionByBlockNumberAndIndex struct { 15 | *qtum.Qtum 16 | } 17 | 18 | func (p *ProxyETHGetTransactionByBlockNumberAndIndex) Method() string { 19 | return "eth_getTransactionByBlockNumberAndIndex" 20 | } 21 | 22 | func (p *ProxyETHGetTransactionByBlockNumberAndIndex) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 23 | var req eth.GetTransactionByBlockNumberAndIndex 24 | if err := json.Unmarshal(rawreq.Params, &req); err != nil { 25 | // TODO: Correct error code? 26 | return nil, eth.NewInvalidParamsError("couldn't unmarshal request") 27 | } 28 | if req.BlockNumber == "" { 29 | // TODO: Correct error code? 30 | return nil, eth.NewInvalidParamsError("invalid argument 0: empty hex string") 31 | } 32 | 33 | return p.request(c.Request().Context(), &req) 34 | } 35 | 36 | func (p *ProxyETHGetTransactionByBlockNumberAndIndex) request(ctx context.Context, req *eth.GetTransactionByBlockNumberAndIndex) (interface{}, eth.JSONRPCError) { 37 | // Decoded by ProxyETHGetTransactionByBlockHashAndIndex, quickly decode so we can fail cheaply without making any calls 38 | _, decodeErr := hexutil.DecodeUint64(req.TransactionIndex) 39 | if decodeErr != nil { 40 | return nil, eth.NewInvalidParamsError("invalid argument 1") 41 | } 42 | 43 | blockNum, err := getBlockNumberByParam(ctx, p.Qtum, req.BlockNumber, false) 44 | if err != nil { 45 | return nil, eth.NewCallbackError("couldn't get block number by parameter") 46 | } 47 | 48 | blockHash, err := proxyETHGetBlockByHash(ctx, p, p.Qtum, blockNum) 49 | if err != nil { 50 | return nil, err 51 | } 52 | if blockHash == nil { 53 | return nil, nil 54 | } 55 | 56 | var ( 57 | getBlockByHashReq = ð.GetTransactionByBlockHashAndIndex{ 58 | BlockHash: string(*blockHash), 59 | TransactionIndex: req.TransactionIndex, 60 | } 61 | proxy = &ProxyETHGetTransactionByBlockHashAndIndex{Qtum: p.Qtum} 62 | ) 63 | return proxy.request(ctx, getBlockByHashReq) 64 | } 65 | -------------------------------------------------------------------------------- /pkg/eth/errors.go: -------------------------------------------------------------------------------- 1 | package eth 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | // unknown service 9 | // return fmt.Sprintf("The method %s%s%s does not exist/is not available", e.service, serviceMethodSeparator, e.method) 10 | var MethodNotFoundErrorCode = -32601 11 | 12 | // invalid request 13 | var InvalidRequestErrorCode = -32600 14 | var InvalidMessageErrorCode = -32700 15 | var InvalidParamsErrorCode = -32602 16 | 17 | // logic error 18 | var CallbackErrorCode = -32000 19 | 20 | // shutdown error 21 | // "server is shutting down" 22 | var ShutdownErrorCode = -32000 23 | var ShutdownError = NewJSONRPCError(ShutdownErrorCode, "server is shutting down", nil) 24 | 25 | func NewMethodNotFoundError(method string) JSONRPCError { 26 | return NewJSONRPCError( 27 | MethodNotFoundErrorCode, 28 | fmt.Sprintf("The method %s does not exist/is not available", method), 29 | nil, 30 | ) 31 | } 32 | 33 | func NewInvalidRequestError(message string) JSONRPCError { 34 | return NewJSONRPCError(InvalidRequestErrorCode, message, nil) 35 | } 36 | 37 | func NewInvalidMessageError(message string) JSONRPCError { 38 | return NewJSONRPCError(InvalidMessageErrorCode, message, nil) 39 | } 40 | 41 | func NewInvalidParamsError(message string) JSONRPCError { 42 | return NewJSONRPCError(InvalidParamsErrorCode, message, nil) 43 | } 44 | 45 | func NewCallbackError(message string) JSONRPCError { 46 | return NewJSONRPCError(CallbackErrorCode, message, nil) 47 | } 48 | 49 | type JSONRPCError interface { 50 | Code() int 51 | Message() string 52 | Error() error 53 | } 54 | 55 | func NewJSONRPCError(code int, message string, err error) JSONRPCError { 56 | return &GenericJSONRPCError{ 57 | code: code, 58 | message: message, 59 | err: err, 60 | } 61 | } 62 | 63 | // JSONRPCError contains the message and code for an ETH RPC error 64 | type GenericJSONRPCError struct { 65 | code int 66 | message string 67 | err error 68 | } 69 | 70 | func (err *GenericJSONRPCError) Code() int { 71 | return err.code 72 | } 73 | 74 | func (err *GenericJSONRPCError) Message() string { 75 | return err.message 76 | } 77 | 78 | func (err *GenericJSONRPCError) Error() error { 79 | return err.err 80 | } 81 | 82 | func (err *GenericJSONRPCError) MarshalJSON() ([]byte, error) { 83 | return json.Marshal(struct { 84 | Code int `json:"code"` 85 | Message string `json:"message"` 86 | }{ 87 | Code: err.code, 88 | Message: err.message, 89 | }) 90 | } 91 | -------------------------------------------------------------------------------- /pkg/server/myctx.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | "net/http" 7 | 8 | "github.com/go-kit/kit/log" 9 | "github.com/go-kit/kit/log/level" 10 | "github.com/labstack/echo" 11 | "github.com/qtumproject/janus/pkg/analytics" 12 | "github.com/qtumproject/janus/pkg/blockhash" 13 | "github.com/qtumproject/janus/pkg/eth" 14 | "github.com/qtumproject/janus/pkg/transformer" 15 | ) 16 | 17 | type myCtx struct { 18 | echo.Context 19 | rpcReq *eth.JSONRPCRequest 20 | logWriter io.Writer 21 | logger log.Logger 22 | transformer *transformer.Transformer 23 | blockHash *blockhash.BlockHash 24 | qtumAnalytics *analytics.Analytics 25 | ethAnalytics *analytics.Analytics 26 | } 27 | 28 | func (c *myCtx) GetJSONRPCResult(result interface{}) (*eth.JSONRPCResult, error) { 29 | return eth.NewJSONRPCResult(c.rpcReq.ID, result) 30 | } 31 | 32 | func (c *myCtx) JSONRPCResult(result interface{}) error { 33 | response, err := c.GetJSONRPCResult(result) 34 | if err != nil { 35 | return err 36 | } 37 | 38 | return c.JSON(http.StatusOK, response) 39 | } 40 | 41 | func (c *myCtx) GetJSONRPCError(err eth.JSONRPCError) *eth.JSONRPCResult { 42 | var id json.RawMessage 43 | if c.rpcReq != nil && c.rpcReq.ID != nil { 44 | id = c.rpcReq.ID 45 | } 46 | return ð.JSONRPCResult{ 47 | ID: id, 48 | Error: err, 49 | JSONRPC: eth.RPCVersion, 50 | } 51 | } 52 | 53 | func (c *myCtx) JSONRPCError(err eth.JSONRPCError) error { 54 | resp := c.GetJSONRPCError(err) 55 | 56 | if !c.Response().Committed { 57 | err := c.JSON(http.StatusOK, resp) 58 | c.logger.Log("Internal server error", err) 59 | return err 60 | } 61 | 62 | return nil 63 | } 64 | 65 | func (c *myCtx) SetLogWriter(logWriter io.Writer) { 66 | c.logWriter = logWriter 67 | } 68 | 69 | func (c *myCtx) GetLogWriter() io.Writer { 70 | return c.logWriter 71 | } 72 | 73 | func (c *myCtx) SetLogger(l log.Logger) { 74 | c.logger = log.WithPrefix(l, "component", "context") 75 | } 76 | 77 | func (c *myCtx) GetLogger() log.Logger { 78 | return c.logger 79 | } 80 | 81 | func (c *myCtx) GetDebugLogger() log.Logger { 82 | if !c.IsDebugEnabled() { 83 | return log.NewNopLogger() 84 | } 85 | return log.With(level.Debug(c.logger)) 86 | } 87 | 88 | func (c *myCtx) GetErrorLogger() log.Logger { 89 | return log.With(level.Error(c.logger)) 90 | } 91 | 92 | func (c *myCtx) IsDebugEnabled() bool { 93 | return c.transformer.IsDebugEnabled() 94 | } 95 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getBalance.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/common/hexutil" 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | "github.com/qtumproject/janus/pkg/utils" 11 | ) 12 | 13 | // ProxyETHGetBalance implements ETHProxy 14 | type ProxyETHGetBalance struct { 15 | *qtum.Qtum 16 | } 17 | 18 | func (p *ProxyETHGetBalance) Method() string { 19 | return "eth_getBalance" 20 | } 21 | 22 | func (p *ProxyETHGetBalance) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 23 | var req eth.GetBalanceRequest 24 | if err := unmarshalRequest(rawreq.Params, &req); err != nil { 25 | // TODO: Correct error code? 26 | return nil, eth.NewInvalidParamsError(err.Error()) 27 | } 28 | 29 | addr := utils.RemoveHexPrefix(req.Address) 30 | { 31 | // is address a contract or an account? 32 | qtumreq := qtum.GetAccountInfoRequest(addr) 33 | qtumresp, err := p.GetAccountInfo(c.Request().Context(), &qtumreq) 34 | 35 | // the address is a contract 36 | if err == nil { 37 | // the unit of the balance Satoshi 38 | p.GetDebugLogger().Log("method", p.Method(), "address", req.Address, "msg", "is a contract") 39 | return hexutil.EncodeUint64(uint64(qtumresp.Balance)), nil 40 | } 41 | } 42 | 43 | { 44 | // try account 45 | base58Addr, err := p.FromHexAddress(addr) 46 | if err != nil { 47 | p.GetDebugLogger().Log("method", p.Method(), "address", req.Address, "msg", "error parsing address", "error", err) 48 | return nil, eth.NewCallbackError(err.Error()) 49 | } 50 | 51 | qtumreq := qtum.GetAddressBalanceRequest{ 52 | Addresses: []string{base58Addr}, 53 | } 54 | qtumresp, err := p.GetAddressBalance(c.Request().Context(), &qtumreq) 55 | if err != nil { 56 | if err == qtum.ErrInvalidAddress { 57 | // invalid address should return 0x0 58 | return "0x0", nil 59 | } 60 | p.GetDebugLogger().Log("method", p.Method(), "address", req.Address, "msg", "error getting address balance", "error", err) 61 | return nil, eth.NewCallbackError(err.Error()) 62 | } 63 | 64 | // 1 QTUM = 10 ^ 8 Satoshi 65 | balance := new(big.Int).SetUint64(qtumresp.Balance) 66 | 67 | //Balance for ETH response is represented in Weis (1 QTUM Satoshi = 10 ^ 10 Wei) 68 | balance = balance.Mul(balance, big.NewInt(10000000000)) 69 | 70 | return hexutil.EncodeBig(balance), nil 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getTransactionReceipt_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/qtumproject/janus/pkg/eth" 8 | "github.com/qtumproject/janus/pkg/internal" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | "github.com/qtumproject/janus/pkg/utils" 11 | ) 12 | 13 | func TestGetTransactionReceiptForNonVMTransaction(t *testing.T) { 14 | //preparing request 15 | requestParams := []json.RawMessage{[]byte(`"0x8fcd819194cce6a8454b2bec334d3448df4f097e9cdc36707bfd569900268950"`)} 16 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 17 | if err != nil { 18 | t.Fatal(err) 19 | } 20 | 21 | mockedClientDoer := internal.NewDoerMappedMock() 22 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | 27 | //preparing client response 28 | err = mockedClientDoer.AddResponseWithRequestID(2, qtum.MethodGetTransactionReceipt, []byte("[]")) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | 33 | rawTransactionResponse := &qtum.GetRawTransactionResponse{ 34 | BlockHash: internal.GetTransactionByHashBlockHash, 35 | } 36 | err = mockedClientDoer.AddResponseWithRequestID(3, qtum.MethodGetRawTransaction, rawTransactionResponse) 37 | if err != nil { 38 | t.Fatal(err) 39 | } 40 | 41 | err = mockedClientDoer.AddResponseWithRequestID(4, qtum.MethodGetBlock, internal.GetBlockResponse) 42 | if err != nil { 43 | t.Fatal(err) 44 | } 45 | 46 | //preparing proxy & executing request 47 | proxyEth := ProxyETHGetTransactionReceipt{qtumClient} 48 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 49 | if jsonErr != nil { 50 | t.Fatal(jsonErr) 51 | } 52 | 53 | want := eth.GetTransactionReceiptResponse{ 54 | TransactionHash: "0x8fcd819194cce6a8454b2bec334d3448df4f097e9cdc36707bfd569900268950", 55 | TransactionIndex: "0x1", 56 | BlockHash: "0xbba11e1bacc69ba535d478cf1f2e542da3735a517b0b8eebaf7e6bb25eeb48c5", 57 | BlockNumber: "0xf8f", 58 | GasUsed: NonContractVMGasLimit, 59 | Logs: []eth.Log{}, 60 | EffectiveGasPrice: "0x0", 61 | CumulativeGasUsed: NonContractVMGasLimit, 62 | To: utils.AddHexPrefix(qtum.ZeroAddress), 63 | From: utils.AddHexPrefix(qtum.ZeroAddress), 64 | LogsBloom: eth.EmptyLogsBloom, 65 | Status: STATUS_SUCCESS, 66 | } 67 | 68 | internal.CheckTestResultEthRequestRPC(*request, &want, got, t, false) 69 | } 70 | -------------------------------------------------------------------------------- /pkg/transformer/eth_estimateGas.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common/hexutil" 5 | "github.com/labstack/echo" 6 | "github.com/pkg/errors" 7 | "github.com/qtumproject/janus/pkg/eth" 8 | "github.com/qtumproject/janus/pkg/qtum" 9 | ) 10 | 11 | // 22000 12 | var NonContractVMGasLimit = "0x55f0" 13 | var ErrExecutionReverted = errors.New("execution reverted") 14 | 15 | // 10% isn't enough in some cases, neither is 15%, 20% works 16 | var GAS_BUFFER = 1.20 17 | 18 | // ProxyETHEstimateGas implements ETHProxy 19 | type ProxyETHEstimateGas struct { 20 | *ProxyETHCall 21 | } 22 | 23 | func (p *ProxyETHEstimateGas) Method() string { 24 | return "eth_estimateGas" 25 | } 26 | 27 | func (p *ProxyETHEstimateGas) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 28 | var ethreq eth.CallRequest 29 | if jsonErr := unmarshalRequest(rawreq.Params, ðreq); jsonErr != nil { 30 | // TODO: Correct error code? 31 | return nil, eth.NewInvalidParamsError(jsonErr.Error()) 32 | } 33 | 34 | if ethreq.Data == "" { 35 | response := eth.EstimateGasResponse(NonContractVMGasLimit) 36 | return &response, nil 37 | } 38 | 39 | // when supplying this parameter to callcontract to estimate gas in the qtum api 40 | // if there isn't enough gas specified here, the result will be an exception 41 | // Excepted = "OutOfGasIntrinsic" 42 | // Gas = "the supplied value" 43 | // this is different from geth's behavior 44 | // which will return a used gas value that is higher than the incoming gas parameter 45 | // so we set this to nil so that callcontract will return the actual gas estimate 46 | ethreq.Gas = nil 47 | 48 | // eth req -> qtum req 49 | qtumreq, jsonErr := p.ToRequest(ðreq) 50 | if jsonErr != nil { 51 | return nil, jsonErr 52 | } 53 | 54 | // qtum [code: -5] Incorrect address occurs here 55 | qtumresp, err := p.CallContract(c.Request().Context(), qtumreq) 56 | if err != nil { 57 | return nil, eth.NewCallbackError(err.Error()) 58 | } 59 | 60 | return p.toResp(qtumresp) 61 | } 62 | 63 | func (p *ProxyETHEstimateGas) toResp(qtumresp *qtum.CallContractResponse) (*eth.EstimateGasResponse, eth.JSONRPCError) { 64 | if qtumresp.ExecutionResult.Excepted != "None" { 65 | return nil, eth.NewCallbackError(ErrExecutionReverted.Error()) 66 | } 67 | gas := eth.EstimateGasResponse(hexutil.EncodeUint64(uint64(float64(qtumresp.ExecutionResult.GasUsed) * GAS_BUFFER))) 68 | p.GetDebugLogger().Log(p.Method(), gas) 69 | return &gas, nil 70 | } 71 | -------------------------------------------------------------------------------- /pkg/transformer/qtum_generate.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "reflect" 5 | "strconv" 6 | 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | "github.com/qtumproject/janus/pkg/utils" 11 | ) 12 | 13 | type ProxyQTUMGenerateToAddress struct { 14 | *qtum.Qtum 15 | } 16 | 17 | var _ ETHProxy = (*ProxyQTUMGenerateToAddress)(nil) 18 | 19 | func (p *ProxyQTUMGenerateToAddress) Method() string { 20 | return "dev_generatetoaddress" 21 | } 22 | 23 | func (p *ProxyQTUMGenerateToAddress) Request(req *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 24 | if !p.CanGenerate() { 25 | return nil, eth.NewInvalidRequestError("Can only generate on regtest") 26 | } 27 | 28 | var params []interface{} 29 | if err := unmarshalRequest(req.Params, ¶ms); err != nil { 30 | // TODO: Correct error code? 31 | return nil, eth.NewInvalidParamsError("couldn't unmarshal request parameters") 32 | } 33 | 34 | if len(params) != 2 { 35 | return nil, eth.NewInvalidParamsError("require 2 arguments: blocks, the base58/hex address to mine rewards to") 36 | } 37 | 38 | return p.request(params) 39 | } 40 | 41 | func (p *ProxyQTUMGenerateToAddress) request(params []interface{}) (*[]string, eth.JSONRPCError) { 42 | blocks := params[0] 43 | generateTo, ok := params[1].(string) 44 | if !ok { 45 | return nil, eth.NewInvalidParamsError("second paramter must be string") 46 | } 47 | 48 | var blocksInteger int64 49 | var err error 50 | 51 | if blocksString, ok := blocks.(string); ok { 52 | blocksInteger, err = strconv.ParseInt(blocksString, 10, 64) 53 | if err != nil { 54 | return nil, eth.NewInvalidParamsError("Couldn't parse blocks") 55 | } 56 | } else if blocksNumber, ok := blocks.(float64); ok { 57 | blocksInteger = int64(blocksNumber) 58 | } else { 59 | return nil, eth.NewInvalidParamsError("Unknown blocks type: " + reflect.TypeOf(blocks).String()) 60 | } 61 | 62 | if blocksInteger <= 0 { 63 | return nil, eth.NewInvalidParamsError("Blocks to generate must be > 0") 64 | } 65 | 66 | hex := utils.RemoveHexPrefix(generateTo) 67 | base58Address, err := p.FromHexAddress(hex) 68 | if err != nil { 69 | // already base58? 70 | base58Address = generateTo 71 | } 72 | 73 | var response []string 74 | err = p.Client.Request(qtum.MethodGenerateToAddress, []interface{}{blocksInteger, base58Address}, &response) 75 | if err != nil { 76 | return nil, eth.NewInvalidRequestError(err.Error()) 77 | } 78 | 79 | return &response, nil 80 | } 81 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getStorageAt.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | "github.com/qtumproject/janus/pkg/utils" 11 | ) 12 | 13 | // ProxyETHGetStorageAt implements ETHProxy 14 | type ProxyETHGetStorageAt struct { 15 | *qtum.Qtum 16 | } 17 | 18 | func (p *ProxyETHGetStorageAt) Method() string { 19 | return "eth_getStorageAt" 20 | } 21 | 22 | func (p *ProxyETHGetStorageAt) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 23 | var req eth.GetStorageRequest 24 | if err := unmarshalRequest(rawreq.Params, &req); err != nil { 25 | // TODO: Correct error code? 26 | return nil, eth.NewInvalidParamsError(err.Error()) 27 | } 28 | 29 | qtumAddress := utils.RemoveHexPrefix(req.Address) 30 | blockNumber, err := getBlockNumberByParam(c.Request().Context(), p.Qtum, req.BlockNumber, false) 31 | if err != nil { 32 | p.GetDebugLogger().Log("msg", fmt.Sprintf("Failed to get block number by param for '%s'", req.BlockNumber), "err", err) 33 | return nil, err 34 | } 35 | 36 | return p.request( 37 | c.Request().Context(), 38 | &qtum.GetStorageRequest{ 39 | Address: qtumAddress, 40 | BlockNumber: blockNumber, 41 | }, 42 | utils.RemoveHexPrefix(req.Index), 43 | ) 44 | } 45 | 46 | func (p *ProxyETHGetStorageAt) request(ctx context.Context, ethreq *qtum.GetStorageRequest, index string) (*eth.GetStorageResponse, eth.JSONRPCError) { 47 | qtumresp, err := p.Qtum.GetStorage(ctx, ethreq) 48 | if err != nil { 49 | return nil, eth.NewCallbackError(err.Error()) 50 | } 51 | 52 | // qtum res -> eth res 53 | return p.ToResponse(qtumresp, index), nil 54 | } 55 | 56 | func (p *ProxyETHGetStorageAt) ToResponse(qtumresp *qtum.GetStorageResponse, slot string) *eth.GetStorageResponse { 57 | // the value for unknown anything 58 | storageData := eth.GetStorageResponse("0x0000000000000000000000000000000000000000000000000000000000000000") 59 | if len(slot) != 64 { 60 | slot = leftPadStringWithZerosTo64Bytes(slot) 61 | } 62 | for _, outerValue := range *qtumresp { 63 | qtumStorageData, ok := outerValue[slot] 64 | if ok { 65 | storageData = eth.GetStorageResponse(utils.AddHexPrefix(qtumStorageData)) 66 | return &storageData 67 | } 68 | } 69 | 70 | return &storageData 71 | } 72 | 73 | // left pad a string with leading zeros to fit 64 bytes 74 | func leftPadStringWithZerosTo64Bytes(hex string) string { 75 | return fmt.Sprintf("%064v", hex) 76 | } 77 | -------------------------------------------------------------------------------- /pkg/transformer/eth_getBlockByNumber.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | "math/big" 6 | 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | ) 11 | 12 | // ProxyETHGetBlockByNumber implements ETHProxy 13 | type ProxyETHGetBlockByNumber struct { 14 | *qtum.Qtum 15 | } 16 | 17 | func (p *ProxyETHGetBlockByNumber) Method() string { 18 | return "eth_getBlockByNumber" 19 | } 20 | 21 | func (p *ProxyETHGetBlockByNumber) Request(rpcReq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 22 | req := new(eth.GetBlockByNumberRequest) 23 | if err := unmarshalRequest(rpcReq.Params, req); err != nil { 24 | // TODO: Correct error code? 25 | return nil, eth.NewInvalidParamsError(err.Error()) 26 | } 27 | return p.request(c.Request().Context(), req) 28 | } 29 | 30 | func (p *ProxyETHGetBlockByNumber) request(ctx context.Context, req *eth.GetBlockByNumberRequest) (*eth.GetBlockByNumberResponse, eth.JSONRPCError) { 31 | blockNum, err := getBlockNumberByRawParam(ctx, p.Qtum, req.BlockNumber, false) 32 | if err != nil { 33 | return nil, eth.NewCallbackError("couldn't get block number by parameter") 34 | } 35 | 36 | blockHash, jsonErr := proxyETHGetBlockByHash(ctx, p, p.Qtum, blockNum) 37 | if jsonErr != nil { 38 | return nil, jsonErr 39 | } 40 | if blockHash == nil { 41 | return nil, nil 42 | } 43 | 44 | var ( 45 | getBlockByHashReq = ð.GetBlockByHashRequest{ 46 | BlockHash: string(*blockHash), 47 | FullTransaction: req.FullTransaction, 48 | } 49 | proxy = &ProxyETHGetBlockByHash{Qtum: p.Qtum} 50 | ) 51 | block, jsonErr := proxy.request(ctx, getBlockByHashReq) 52 | if jsonErr != nil { 53 | p.GetDebugLogger().Log("function", p.Method(), "msg", "couldn't get block by hash", "err", err) 54 | return nil, eth.NewCallbackError("couldn't get block by hash") 55 | } 56 | if blockNum != nil { 57 | p.GetDebugLogger().Log("function", p.Method(), "request", string(req.BlockNumber), "msg", "Successfully got block by number", "result", blockNum.String()) 58 | } 59 | return block, nil 60 | } 61 | 62 | // Properly handle unknown blocks 63 | func proxyETHGetBlockByHash(ctx context.Context, p ETHProxy, q *qtum.Qtum, blockNum *big.Int) (*qtum.GetBlockHashResponse, eth.JSONRPCError) { 64 | resp, err := q.GetBlockHash(ctx, blockNum) 65 | if err != nil { 66 | if err == qtum.ErrInvalidParameter { 67 | // block doesn't exist, ETH rpc returns null 68 | /** 69 | { 70 | "jsonrpc": "2.0", 71 | "id": 1234, 72 | "result": null 73 | } 74 | **/ 75 | q.GetDebugLogger().Log("function", p.Method(), "request", blockNum.String(), "msg", "Unknown block") 76 | return nil, nil 77 | } 78 | return nil, eth.NewCallbackError("couldn't get block hash") 79 | } 80 | return &resp, nil 81 | } 82 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 |
29 |
30 |
31 |
32 |

Pete's Pet Shop

33 |
34 |
35 |
36 |
37 | 38 |
39 | 40 |
41 |
42 | 43 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /pkg/transformer/eth_call.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "context" 5 | "math/big" 6 | 7 | "github.com/labstack/echo" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/qtum" 10 | "github.com/qtumproject/janus/pkg/utils" 11 | ) 12 | 13 | // ProxyETHCall implements ETHProxy 14 | type ProxyETHCall struct { 15 | *qtum.Qtum 16 | } 17 | 18 | func (p *ProxyETHCall) Method() string { 19 | return "eth_call" 20 | } 21 | 22 | func (p *ProxyETHCall) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, eth.JSONRPCError) { 23 | var req eth.CallRequest 24 | if err := unmarshalRequest(rawreq.Params, &req); err != nil { 25 | // TODO: Is this correct error code? 26 | return nil, eth.NewInvalidParamsError(err.Error()) 27 | } 28 | 29 | return p.request(c.Request().Context(), &req) 30 | } 31 | 32 | func (p *ProxyETHCall) request(ctx context.Context, ethreq *eth.CallRequest) (interface{}, eth.JSONRPCError) { 33 | // eth req -> qtum req 34 | qtumreq, jsonErr := p.ToRequest(ethreq) 35 | if jsonErr != nil { 36 | return nil, jsonErr 37 | } 38 | if qtumreq.GasLimit != nil && qtumreq.GasLimit.Cmp(big.NewInt(40000000)) > 0 { 39 | qtumresp := eth.CallResponse("0x") 40 | p.Qtum.GetLogger().Log("msg", "Caller gas above allowance, capping", "requested", qtumreq.GasLimit.Int64(), "cap", "40,000,000") 41 | return &qtumresp, nil 42 | } 43 | 44 | qtumresp, err := p.CallContract(ctx, qtumreq) 45 | if err != nil { 46 | if err == qtum.ErrInvalidAddress { 47 | qtumresp := eth.CallResponse("0x") 48 | return &qtumresp, nil 49 | } 50 | 51 | return nil, eth.NewCallbackError(err.Error()) 52 | } 53 | 54 | // qtum res -> eth res 55 | return p.ToResponse(qtumresp), nil 56 | } 57 | 58 | func (p *ProxyETHCall) ToRequest(ethreq *eth.CallRequest) (*qtum.CallContractRequest, eth.JSONRPCError) { 59 | from := ethreq.From 60 | var err error 61 | if utils.IsEthHexAddress(from) { 62 | from, err = p.FromHexAddress(from) 63 | if err != nil { 64 | return nil, eth.NewCallbackError(err.Error()) 65 | } 66 | } 67 | 68 | var gasLimit *big.Int 69 | if ethreq.Gas != nil { 70 | gasLimit = ethreq.Gas.Int 71 | } 72 | 73 | if gasLimit != nil && gasLimit.Int64() < MinimumGasLimit { 74 | p.GetLogger().Log("msg", "Gas limit is too low", "gasLimit", gasLimit.String()) 75 | } 76 | 77 | return &qtum.CallContractRequest{ 78 | To: ethreq.To, 79 | From: from, 80 | Data: ethreq.Data, 81 | GasLimit: gasLimit, 82 | }, nil 83 | } 84 | 85 | func (p *ProxyETHCall) ToResponse(qresp *qtum.CallContractResponse) interface{} { 86 | if qresp.ExecutionResult.Output == "" { 87 | return eth.NewJSONRPCError( 88 | -32000, 89 | "Revert: executionResult output is empty", 90 | nil, 91 | ) 92 | } 93 | 94 | data := utils.AddHexPrefix(qresp.ExecutionResult.Output) 95 | qtumresp := eth.CallResponse(data) 96 | return &qtumresp 97 | 98 | } 99 | -------------------------------------------------------------------------------- /playground/pet-shop-tutorial/contracts/QRC20Token.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | import './SafeMath.sol'; 3 | 4 | 5 | /** 6 | QRC20Token Standard Token implementation 7 | */ 8 | contract QRC20Token is SafeMath { 9 | string public constant standard = 'Token 0.1'; 10 | uint8 public constant decimals = 8; // it's recommended to set decimals to 8 in QTUM 11 | 12 | // you need change the following three values 13 | string public constant name = 'QRC TEST'; 14 | string public constant symbol = 'QTC'; 15 | //Default assumes totalSupply can't be over max (2^256 - 1). 16 | //you need multiply 10^decimals by your real total supply. 17 | uint256 public totalSupply = 10**9 * 10**uint256(decimals); 18 | 19 | mapping (address => uint256) public balanceOf; 20 | mapping (address => mapping (address => uint256)) public allowance; 21 | 22 | event Transfer(address indexed _from, address indexed _to, uint256 _value); 23 | event Approval(address indexed _owner, address indexed _spender, uint256 _value); 24 | 25 | constructor() { 26 | balanceOf[msg.sender] = totalSupply; 27 | } 28 | 29 | // validates an address - currently only checks that it isn't null 30 | modifier validAddress(address _address) { 31 | require(_address != address(0x0)); 32 | _; 33 | } 34 | 35 | function transfer(address _to, uint256 _value) 36 | public 37 | validAddress(_to) 38 | returns (bool success) 39 | { 40 | balanceOf[msg.sender] = safeSub(balanceOf[msg.sender], _value); 41 | balanceOf[_to] = safeAdd(balanceOf[_to], _value); 42 | emit Transfer(msg.sender, _to, _value); 43 | return true; 44 | } 45 | 46 | function transferFrom(address _from, address _to, uint256 _value) 47 | public 48 | validAddress(_from) 49 | validAddress(_to) 50 | returns (bool success) 51 | { 52 | allowance[_from][msg.sender] = safeSub(allowance[_from][msg.sender], _value); 53 | balanceOf[_from] = safeSub(balanceOf[_from], _value); 54 | balanceOf[_to] = safeAdd(balanceOf[_to], _value); 55 | emit Transfer(_from, _to, _value); 56 | return true; 57 | } 58 | 59 | function approve(address _spender, uint256 _value) 60 | public 61 | validAddress(_spender) 62 | returns (bool success) 63 | { 64 | // To change the approve amount you first have to reduce the addresses` 65 | // allowance to zero by calling `approve(_spender, 0)` if it is not 66 | // already 0 to mitigate the race condition described here: 67 | // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 68 | require(_value == 0 || allowance[msg.sender][_spender] == 0); 69 | allowance[msg.sender][_spender] = _value; 70 | emit Approval(msg.sender, _spender, _value); 71 | return true; 72 | } 73 | 74 | // disable pay QTUM to this contract 75 | receive() external payable { 76 | revert(); 77 | } 78 | } -------------------------------------------------------------------------------- /testing/openzeppelin/run-openzeppelin-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | EXPECTED_OUTPUT=truffle-expected-output.json 3 | RESULT_OUTPUT=truffle-result-output.json 4 | PRUNED_OUTPUT=truffle-pruned-output.json 5 | 6 | doGithubWorkflowProcessing () { 7 | if [ "" != "$GITHUB_ACTION" ] ; then 8 | echo "Running within github actions... processing output file" 9 | # running in a github action, output results for next workflow action 10 | make -f ../Makefile github-action-openzeppelin || exit 1 11 | 12 | if [ ! -f $EXPECTED_OUTPUT ] ; then 13 | echo "Expected output not found -" $EXPECTED_OUTPUT 14 | doGithubWorkflowProcessingResult=1 15 | return 16 | fi 17 | 18 | if [ -e $RESULT_OUTPUT ] ; then 19 | echo Successfully copied output results from docker container 20 | make -f ../Makefile truffle-parser-docker 21 | else 22 | echo "Failed to find output results in docker container" 23 | doGithubWorkflowProcessingResult=-1 24 | return 25 | fi 26 | 27 | doGithubWorkflowProcessingResult=$? 28 | else 29 | echo "Not running within github actions, skipping processing of output results" 30 | fi 31 | } 32 | cleanupDocker () { 33 | echo Shutting down docker-compose containers 34 | docker-compose -f docker-compose-openzeppelin.yml -p ci kill 35 | docker-compose -f docker-compose-openzeppelin.yml -p ci rm -f 36 | } 37 | trap 'cleanupDocker ; echo "Tests Failed For Unexpected Reasons"' HUP INT QUIT PIPE TERM 38 | docker-compose -p ci -f docker-compose-openzeppelin.yml build && docker-compose -p ci -f docker-compose-openzeppelin.yml up -d 39 | if [ $? -ne 0 ] ; then 40 | echo "Docker Compose Failed" 41 | exit 1 42 | fi 43 | # docker logs qtum_seeded_testchain -f& 44 | # docker logs ci_janus_1 -f& 45 | docker logs ci_openzeppelin_1 -f& 46 | EXIT_CODE=`docker wait ci_openzeppelin_1` 47 | echo "Processing openzeppelin test results with exit code of:" $EXIT_CODE 48 | doGithubWorkflowProcessingResult=$EXIT_CODE 49 | 50 | if [ -e $RESULT_OUTPUT ] ; then 51 | echo "Deleting existing output results" 52 | rm $RESULT_OUTPUT 53 | fi 54 | 55 | echo "Copying output results from docker container to local filesystem" 56 | CONTAINER=ci_openzeppelin_1 INPUT=/openzeppelin-contracts/output.json make -f ../Makefile truffle-parser-extract-result-docker || exit 1 57 | echo "Successfully copied output results from docker container to local filesystem" 58 | 59 | doGithubWorkflowProcessing 60 | EXIT_CODE=$doGithubWorkflowProcessingResult 61 | if [ -z ${EXIT_CODE+z} ] || [ -z ${EXIT_CODE} ] || ([ "0" != "$EXIT_CODE" ] && [ "" != "$EXIT_CODE" ]) ; then 62 | # TODO: is it even worth outputting the logs? they will overflow the actual results 63 | # these logs are so large we can't print them out into github actions 64 | # docker logs qtum_seeded_testchain 65 | # docker logs ci_janus_1 66 | # docker logs ci_openzeppelin_1 67 | echo "Tests Failed - Exit Code: $EXIT_CODE (truffle exit code indicates how many tests failed)" 68 | else 69 | echo "Tests Passed" 70 | fi 71 | cleanupDocker 72 | exit $EXIT_CODE 73 | -------------------------------------------------------------------------------- /pkg/transformer/eth_accounts_test.go: -------------------------------------------------------------------------------- 1 | package transformer 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/btcsuite/btcutil" 8 | "github.com/qtumproject/janus/pkg/eth" 9 | "github.com/qtumproject/janus/pkg/internal" 10 | "github.com/qtumproject/janus/pkg/qtum" 11 | ) 12 | 13 | func TestAccountRequest(t *testing.T) { 14 | requestParams := []json.RawMessage{} 15 | request, err := internal.PrepareEthRPCRequest(1, requestParams) 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | 20 | mockedClientDoer := internal.NewDoerMappedMock() 21 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 22 | if err != nil { 23 | t.Fatal(err) 24 | } 25 | 26 | exampleAcc1, err := btcutil.DecodeWIF("5JK4Gu9nxCvsCxiq9Zf3KdmA9ACza6dUn5BRLVWAYEtQabdnJ89") 27 | if err != nil { 28 | t.Fatal(err) 29 | } 30 | exampleAcc2, err := btcutil.DecodeWIF("5JwvXtv6YCa17XNDHJ6CJaveg4mrpqFvcjdrh9FZWZEvGFpUxec") 31 | if err != nil { 32 | t.Fatal(err) 33 | } 34 | 35 | qtumClient.Accounts = append(qtumClient.Accounts, exampleAcc1, exampleAcc2) 36 | 37 | //preparing proxy & executing request 38 | proxyEth := ProxyETHAccounts{qtumClient} 39 | got, jsonErr := proxyEth.Request(request, internal.NewEchoContext()) 40 | if jsonErr != nil { 41 | t.Fatal(jsonErr.Error()) 42 | } 43 | 44 | want := eth.AccountsResponse{"0x6d358cf96533189dd5a602d0937fddf0888ad3ae", "0x7e22630f90e6db16283af2c6b04f688117a55db4"} 45 | 46 | internal.CheckTestResultEthRequestRPC(*request, want, got, t, false) 47 | } 48 | 49 | func TestAccountMethod(t *testing.T) { 50 | mockedClientDoer := internal.NewDoerMappedMock() 51 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 52 | if err != nil { 53 | t.Fatal(err) 54 | } 55 | //preparing proxy & executing request 56 | proxyEth := ProxyETHAccounts{qtumClient} 57 | got := proxyEth.Method() 58 | 59 | want := string("eth_accounts") 60 | 61 | internal.CheckTestResultDefault(want, got, t, false) 62 | } 63 | func TestAccountToResponse(t *testing.T) { 64 | mockedClientDoer := internal.NewDoerMappedMock() 65 | qtumClient, err := internal.CreateMockedClient(mockedClientDoer) 66 | if err != nil { 67 | t.Fatal(err) 68 | } 69 | proxyEth := ProxyETHAccounts{qtumClient} 70 | callResponse := qtum.CallContractResponse{ 71 | ExecutionResult: struct { 72 | GasUsed int `json:"gasUsed"` 73 | Excepted string `json:"excepted"` 74 | ExceptedMessage string `json:"exceptedMessage"` 75 | NewAddress string `json:"newAddress"` 76 | Output string `json:"output"` 77 | CodeDeposit int `json:"codeDeposit"` 78 | GasRefunded int `json:"gasRefunded"` 79 | DepositSize int `json:"depositSize"` 80 | GasForDeposit int `json:"gasForDeposit"` 81 | }{ 82 | Output: "0x0000000000000000000000000000000000000000000000000000000000000002", 83 | }, 84 | } 85 | 86 | got := *proxyEth.ToResponse(&callResponse) 87 | want := eth.CallResponse("0x0000000000000000000000000000000000000000000000000000000000000002") 88 | 89 | internal.CheckTestResultDefault(want, got, t, false) 90 | } 91 | --------------------------------------------------------------------------------