diff --git a/clients/README.md b/clients/README.md new file mode 100644 index 0000000..f7d2384 --- /dev/null +++ b/clients/README.md @@ -0,0 +1,7 @@ +# Client-side helpers + +These are just examples of how clients can use Cyphernode in their code. + +# Contributing + +You are welcome to add more languages and/or improve current code. diff --git a/clients/javascript/cyphernode-client.js b/clients/javascript/cyphernode-client.js index e69de29..c93506c 100644 --- a/clients/javascript/cyphernode-client.js +++ b/clients/javascript/cyphernode-client.js @@ -0,0 +1,77 @@ +CyphernodeClient = function(is_prod) { + this.baseURL = is_prod ? 'https://cyphernode:443' : 'https://cyphernode-dev:443' +}; + +CyphernodeClient.prototype._post = function(url, postdata, cb) { + let urlr = this.baseURL + url; + + let h64 = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9Cg==' + let current = Math.round(new Date().getTime/1000) + 10 + let p64 = btoa('{"id":"${id}","exp":' + current + '}') + let api_key = Meteor.settings.CYPHERNODE.api_key + let s = CryptoJS.HmacSHA256(p64, api_key).toString() + let token = h64 + '.' + p64 + '.' + s + + HTTP.post( + urlr, + { + data: postdata, + headers: {'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + token}, + }, function (err, resp) { + cb(err, resp.data) + } + ) +}; + +CyphernodeClient.prototype._get = function(url, cb) { + let urlr = this.baseURL + url; + + let h64 = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9Cg==' + let current = Math.round(new Date().getTime/1000) + 10 + let p64 = btoa('{"id":"${id}","exp":' + current + '}') + let api_key = Meteor.settings.CYPHERNODE.api_key + let s = CryptoJS.HmacSHA256(p64, api_key).toString() + let token = h64 + '.' + p64 + '.' + s + + HTTP.get(urlr, {headers: {'Authorization': 'Bearer ' + token}}, function (err, resp) { + cb(err, resp.data) + }) +}; + +CyphernodeClient.prototype.watch = function(btcaddr, cb0conf, cb1conf, cbreply) { + // BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","unconfirmedCallbackURL":"192.168.122.233:1111/callback0conf","confirmedCallbackURL":"192.168.122.233:1111/callback1conf"} + let data = { address: btcaddr, unconfirmedCallbackURL: cb0conf, confirmedCallbackURL: cb1conf } + this._post('/watch', data, cbreply); +}; + +CyphernodeClient.prototype.unwatch = function(btcaddr, cbreply) { + // 192.168.122.152:8080/unwatch/2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp + this._get('/unwatch/' + btcaddr, cbreply); +}; + +CyphernodeClient.prototype.getActiveWatches = function(cbreply) { + // 192.168.122.152:8080/getactivewatches + this._get('/getactivewatches', cbreply); +}; + +CyphernodeClient.prototype.getTransaction = function(txid, cbreply) { + // http://192.168.122.152:8080/gettransaction/af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648 + this._get('/gettransaction/' + txid, cbreply); +}; + +CyphernodeClient.prototype.spend = function(btcaddr, amnt, cbreply) { + // BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","amount":0.00233} + let data = { address: btcaddr, amount: amnt } + this._post('/spend', data, cbreply); +}; + +CyphernodeClient.prototype.getBalance = function(cbreply) { + // http://192.168.122.152:8080/getbalance + this._get('/getbalance', cbreply); +}; + +CyphernodeClient.prototype.getNewAddress = function(cbreply) { + // http://192.168.122.152:8080/getnewaddress + this._get('/getnewaddress', cbreply); +}; diff --git a/clients/shell/cyphernode-client.sh b/clients/shell/cyphernode-client.sh index dc62791..9d1312b 100644 --- a/clients/shell/cyphernode-client.sh +++ b/clients/shell/cyphernode-client.sh @@ -1,6 +1,77 @@ +#!/bin/sh -invoke_cyphernode +. .cyphernode.conf + +invoke_cyphernode() { - id="001";h64=$(echo "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo "{\"id\":\"$id\",\"exp\":$((`date +\"%s\"`+10))}" | base64);k="2df1eeea370eacdc5cf7e96c2d82140d1568079a5d4d87006ec8718a98883b36";s=$(echo "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";curl -v -H "Authorization: Bearer $token" localhost/getbestblockhash + local action=${1} + local post=${2} + local h64=$(echo "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64) + local p64=$(echo "{\"id\":\"${id}\",\"exp\":$((`date +"%s"`+10))}" | base64) + local s=$(echo "$h64.$p64" | openssl dgst -hmac "$key" -sha256 -r | cut -sd ' ' -f1) + local token="$h64.$p64.$s" + + if [ -n "${post}" ]; then + echo $(curl -v -H "Authorization: Bearer $token" -d "${post}" -k "https://cyphernode/${action}") + return $? + else + echo $(curl -v -H "Authorization: Bearer $token" -k "https://cyphernode/${action}") + return $? + fi +} + +watch() +{ + # BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","unconfirmedCallbackURL":"192.168.122.233:1111/callback0conf","confirmedCallbackURL":"192.168.122.233:1111/callback1conf"} + local btcaddr=${1} + local cb0conf=${2} + local cb1conf=${3} + local post="{\"address\":\"${btcaddr}\",\"unconfirmedCallbackURL\":\"${cb0conf}\",\"confirmedCallbackURL\":\"${cb1conf}\"}" + + echo $(invoke_cyphernode "watch" ${post}) +} + +unwatch() +{ + # 192.168.122.152:8080/unwatch/2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp + local btcaddr=${1} + + echo $(invoke_cyphernode "unwatch/${btcaddr}") +} + +getactivewatches() +{ + # 192.168.122.152:8080/getactivewatches + echo $(invoke_cyphernode "getactivewatches") +} + +gettransaction() +{ + # http://192.168.122.152:8080/gettransaction/af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648 + local txid=${1} + + echo $(invoke_cyphernode "gettransaction/${txid}") +} + +spend() +{ + # BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","amount":0.00233} + local btcaddr=${1} + local amount=${2} + local post="{\"address\":\"${btcaddr}\",\"amount\":\"${amount}\"}" + + echo $(invoke_cyphernode "spend" ${post}) +} + +getbalance() +{ + # http://192.168.122.152:8080/getbalance + echo $(invoke_cyphernode "getbalance") +} + +getnewaddress() +{ + # http://192.168.122.152:8080/getnewaddress + echo $(invoke_cyphernode "getnewaddress") } diff --git a/clients/shell/cyphernode.conf b/clients/shell/cyphernode.conf new file mode 100644 index 0000000..d19bf3d --- /dev/null +++ b/clients/shell/cyphernode.conf @@ -0,0 +1,3 @@ +# Provided by cyphernode, see api_auth_docker/README.md +id=001 +key=2df1eeea370eacdc5cf7e96c2d82140d1568079a5d4d87006ec8718a98883b36 diff --git a/doc/INSTALL-MANUAL-STEPS.md b/doc/INSTALL-MANUAL-STEPS.md index 4a5d3fb..a95161c 100644 --- a/doc/INSTALL-MANUAL-STEPS.md +++ b/doc/INSTALL-MANUAL-STEPS.md @@ -45,6 +45,9 @@ vi pycoin_docker/env.properties ```shell sudo useradd cyphernode mkdir ~/btcproxydb ; sudo chown -R cyphernode:debian ~/btcproxydb ; sudo chmod g+ws ~/btcproxydb +mkdir -p ~/cyphernode-ssl/certs ~/cyphernode-ssl/private +openssl req -subj '/CN=localhost' -x509 -newkey rsa:4096 -nodes -keyout ~/cyphernode-ssl/private/key.pem -out ~/cyphernode-ssl/certs/cert.pem -days 365 +docker build -t authapi api_auth_docker/. docker build -t proxycronimg cron_docker/. docker build -t btcproxyimg proxy_docker/. docker build -t pycoinimg pycoin_docker/. diff --git a/docker-compose.yml b/docker-compose.yml index e354c0f..3138639 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,8 +21,6 @@ services: env_file: - proxy_docker/env.properties image: btcproxyimg -# ports: -# - "8888:8888" volumes: # Variable substitutions don't work # Match with DB_PATH in proxy_docker/env.properties @@ -52,8 +50,6 @@ services: env_file: - pycoin_docker/env.properties image: pycoinimg -# ports: -# - "7777:7777" # deploy: # placement: # constraints: [node.hostname==dev] @@ -80,10 +76,8 @@ services: image: btcnode # ports: # - "18333:18333" -# - "18332:18332" # - "29000:29000" # - "8333:8333" -# - "8332:8332" volumes: - "~/btcdata:/.bitcoin" command: $USER bitcoind