mirror of
https://github.com/aljazceru/cyphernode.git
synced 2025-12-19 05:35:17 +01:00
@@ -70,7 +70,9 @@ The core component of cyphernode is a request handler which exposes HTTP endpoin
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
* Read the API docs here: https://github.com/SatoshiPortal/cyphernode/blob/master/doc/API.md
|
* Read the API docs here:
|
||||||
|
* API v0 (Current): https://github.com/SatoshiPortal/cyphernode/blob/master/doc/API.v0.md
|
||||||
|
* API v1 (RESTful): https://github.com/SatoshiPortal/cyphernode/blob/master/doc/API.v1.md
|
||||||
* Installation documentation: https://github.com/SatoshiPortal/cyphernode/blob/master/doc/INSTALL.md
|
* Installation documentation: https://github.com/SatoshiPortal/cyphernode/blob/master/doc/INSTALL.md
|
||||||
* Step-by-step manual install (deprecated): https://github.com/SatoshiPortal/cyphernode/blob/master/doc/INSTALL-MANUAL-STEPS.md
|
* Step-by-step manual install (deprecated): https://github.com/SatoshiPortal/cyphernode/blob/master/doc/INSTALL-MANUAL-STEPS.md
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ action_getactivewatchesbylabel=watcher
|
|||||||
action_getactivexpubwatches=watcher
|
action_getactivexpubwatches=watcher
|
||||||
action_watchtxid=watcher
|
action_watchtxid=watcher
|
||||||
action_getactivewatches=watcher
|
action_getactivewatches=watcher
|
||||||
|
action_get_txns_by_watchlabel=watcher
|
||||||
|
action_get_unused_addresses_by_watchlabel=watcher
|
||||||
action_getbestblockhash=watcher
|
action_getbestblockhash=watcher
|
||||||
action_getbestblockinfo=watcher
|
action_getbestblockinfo=watcher
|
||||||
action_getblockinfo=watcher
|
action_getblockinfo=watcher
|
||||||
@@ -28,6 +30,7 @@ action_ln_getconnectionstring=watcher
|
|||||||
action_ln_decodebolt11=watcher
|
action_ln_decodebolt11=watcher
|
||||||
|
|
||||||
# Spender can do what the watcher can do, plus:
|
# Spender can do what the watcher can do, plus:
|
||||||
|
action_getxnslist=spender
|
||||||
action_getbalance=spender
|
action_getbalance=spender
|
||||||
action_getbalances=spender
|
action_getbalances=spender
|
||||||
action_getbalancebyxpub=spender
|
action_getbalancebyxpub=spender
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
"lightning_nodecolor": "LN nodes have colors. Choose the <font underline='true'>color you want</font> for yours in RGB format (RRGGBB). For example, pure red would be <font color='#ff0000'>ff0000</font>.",
|
"lightning_nodecolor": "LN nodes have colors. Choose the <font underline='true'>color you want</font> for yours in RGB format (RRGGBB). For example, pure red would be <font color='#ff0000'>ff0000</font>.",
|
||||||
"lightning_datapath": "<font underline='true'>Path name</font> to where LN's data files are stored. This directory will be mounted into the LN node's container. <font color='#ff0000'>If running on OSX, check mountable directories in Docker's File Sharing configs.</font>",
|
"lightning_datapath": "<font underline='true'>Path name</font> to where LN's data files are stored. This directory will be mounted into the LN node's container. <font color='#ff0000'>If running on OSX, check mountable directories in Docker's File Sharing configs.</font>",
|
||||||
"lightning_datapath_custom": " ",
|
"lightning_datapath_custom": " ",
|
||||||
"lightning_expose": "By default, LN node port will be <font underline='true'>published</font> outside of Docker. Do you want to hide it so that your node can't be accessed from outside of the Docker network?",
|
"lightning_expose": "By default, LN node port will be <font underline='true'>published</font> outside of Docker. Do you want to expose it so that your node can be accessed from outside of the Docker network?",
|
||||||
"otsclient_datapath": "<font underline='true'>Full path</font> where the OTS files will be stored. This path will be mounted into the otsclient container which will create the OTS files when <font color='#00ff00'>stamping</font> and update them when <font color='#00ff00'>upgrading</font> stamps. It will also be mounted to the proxy container so that it can serve the <font color='#00ff00'>ots_getfile</font> and send the OTS files to clients. <font color='#ff0000'>If running on OSX, check mountable directories in Docker's File Sharing configs.</font>",
|
"otsclient_datapath": "<font underline='true'>Full path</font> where the OTS files will be stored. This path will be mounted into the otsclient container which will create the OTS files when <font color='#00ff00'>stamping</font> and update them when <font color='#00ff00'>upgrading</font> stamps. It will also be mounted to the proxy container so that it can serve the <font color='#00ff00'>ots_getfile</font> and send the OTS files to clients. <font color='#ff0000'>If running on OSX, check mountable directories in Docker's File Sharing configs.</font>",
|
||||||
"otsclient_datapath_custom": " ",
|
"otsclient_datapath_custom": " ",
|
||||||
"installer_mode": "Only one <font underline='true'>installation mode</font> is supported, right now: <font color='#0000ff'>local docker (self-hosted)</font>. Choose wisely ;-)",
|
"installer_mode": "Only one <font underline='true'>installation mode</font> is supported, right now: <font color='#0000ff'>local docker (self-hosted)</font>. Choose wisely ;-)",
|
||||||
|
|||||||
@@ -149,6 +149,11 @@ module.exports = class App {
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
if( !fs.existsSync(this.destinationPath(configArchiveFileName)) ) {
|
if( !fs.existsSync(this.destinationPath(configArchiveFileName)) ) {
|
||||||
|
if( this.sessionData.noWizard ) {
|
||||||
|
console.log(chalk.bold.red('Unable to run in no wizard mode without a config.7z')+'\n');
|
||||||
|
process.exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
let r = {};
|
let r = {};
|
||||||
process.stdout.write(ansi.clear+ansi.reset);
|
process.stdout.write(ansi.clear+ansi.reset);
|
||||||
while( !r.password0 || !r.password1 || r.password0 !== r.password1 ) {
|
while( !r.password0 || !r.password1 || r.password0 !== r.password1 ) {
|
||||||
@@ -449,7 +454,7 @@ module.exports = class App {
|
|||||||
name: 'MQ broker',
|
name: 'MQ broker',
|
||||||
label: 'broker',
|
label: 'broker',
|
||||||
host: 'broker',
|
host: 'broker',
|
||||||
networks: ['cyphernodenet'],
|
networks: ['cyphernodenet', 'cyphernodeappsnet'],
|
||||||
docker: 'eclipse-mosquitto:'+this.config.docker_versions['eclipse-mosquitto']
|
docker: 'eclipse-mosquitto:'+this.config.docker_versions['eclipse-mosquitto']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
cyphernodeconf_docker/package-lock.json
generated
12
cyphernodeconf_docker/package-lock.json
generated
@@ -2451,9 +2451,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"handlebars": {
|
"handlebars": {
|
||||||
"version": "4.1.2",
|
"version": "4.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
|
||||||
"integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
|
"integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"neo-async": "^2.6.0",
|
"neo-async": "^2.6.0",
|
||||||
@@ -3721,9 +3721,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"mixin-deep": {
|
"mixin-deep": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
|
||||||
"integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
|
"integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"for-in": "^1.0.2",
|
"for-in": "^1.0.2",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ action_helloworld=stats
|
|||||||
action_getblockchaininfo=stats
|
action_getblockchaininfo=stats
|
||||||
action_installation_info=stats
|
action_installation_info=stats
|
||||||
action_getmempoolinfo=stats
|
action_getmempoolinfo=stats
|
||||||
|
action_getblockhash=stats
|
||||||
|
|
||||||
# Watcher can:
|
# Watcher can:
|
||||||
action_watch=watcher
|
action_watch=watcher
|
||||||
@@ -18,6 +19,8 @@ action_unwatchxpubbylabel=watcher
|
|||||||
action_getactivewatchesbyxpub=watcher
|
action_getactivewatchesbyxpub=watcher
|
||||||
action_getactivewatchesbylabel=watcher
|
action_getactivewatchesbylabel=watcher
|
||||||
action_getactivexpubwatches=watcher
|
action_getactivexpubwatches=watcher
|
||||||
|
action_get_txns_by_watchlabel=watcher
|
||||||
|
action_get_unused_addresses_by_watchlabel=watcher
|
||||||
action_watchtxid=watcher
|
action_watchtxid=watcher
|
||||||
action_getactivewatches=watcher
|
action_getactivewatches=watcher
|
||||||
action_getbestblockhash=watcher
|
action_getbestblockhash=watcher
|
||||||
@@ -32,6 +35,7 @@ action_ln_getconnectionstring=watcher
|
|||||||
action_ln_decodebolt11=watcher
|
action_ln_decodebolt11=watcher
|
||||||
|
|
||||||
# Spender can do what the watcher can do, plus:
|
# Spender can do what the watcher can do, plus:
|
||||||
|
action_get_txns_spending=spender
|
||||||
action_getbalance=spender
|
action_getbalance=spender
|
||||||
action_getbalances=spender
|
action_getbalances=spender
|
||||||
action_getbalancebyxpub=spender
|
action_getbalancebyxpub=spender
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ services:
|
|||||||
image: eclipse-mosquitto:1.6
|
image: eclipse-mosquitto:1.6
|
||||||
networks:
|
networks:
|
||||||
- cyphernodenet
|
- cyphernodenet
|
||||||
|
- cyphernodeappsnet
|
||||||
restart: always
|
restart: always
|
||||||
# deploy:
|
# deploy:
|
||||||
# placement:
|
# placement:
|
||||||
@@ -165,7 +166,7 @@ services:
|
|||||||
<% } %>
|
<% } %>
|
||||||
volumes:
|
volumes:
|
||||||
- "<%= otsclient_datapath %>:/otsfiles"
|
- "<%= otsclient_datapath %>:/otsfiles"
|
||||||
- "<%= bitcoin_datapath %>/bitcoin-client.conf:/.bitcoin/bitcoin.conf"
|
- "<%= bitcoin_datapath %>/bitcoin-client.conf:/.bitcoin/bitcoin.conf:ro"
|
||||||
command: $USER /script/startotsclient.sh
|
command: $USER /script/startotsclient.sh
|
||||||
networks:
|
networks:
|
||||||
- cyphernodenet
|
- cyphernodenet
|
||||||
@@ -190,8 +191,8 @@ services:
|
|||||||
- "<%= gatekeeper_port %>:<%= gatekeeper_port %>"
|
- "<%= gatekeeper_port %>:<%= gatekeeper_port %>"
|
||||||
<% } %>
|
<% } %>
|
||||||
volumes:
|
volumes:
|
||||||
- "<%= gatekeeper_datapath %>/certs:/etc/ssl/certs"
|
- "<%= gatekeeper_datapath %>/certs:/etc/ssl/certs:ro"
|
||||||
- "<%= gatekeeper_datapath %>/private:/etc/ssl/private"
|
- "<%= gatekeeper_datapath %>/private:/etc/ssl/private:ro"
|
||||||
- "<%= gatekeeper_datapath %>/keys.properties:/etc/nginx/conf.d/keys.properties"
|
- "<%= gatekeeper_datapath %>/keys.properties:/etc/nginx/conf.d/keys.properties"
|
||||||
- "<%= gatekeeper_datapath %>/api.properties:/etc/nginx/conf.d/api.properties"
|
- "<%= gatekeeper_datapath %>/api.properties:/etc/nginx/conf.d/api.properties"
|
||||||
- "<%= gatekeeper_datapath %>/default.conf:/etc/nginx/conf.d/default.conf"
|
- "<%= gatekeeper_datapath %>/default.conf:/etc/nginx/conf.d/default.conf"
|
||||||
@@ -220,9 +221,9 @@ services:
|
|||||||
- 443:443
|
- 443:443
|
||||||
volumes:
|
volumes:
|
||||||
- "/var/run/docker.sock:/var/run/docker.sock"
|
- "/var/run/docker.sock:/var/run/docker.sock"
|
||||||
- "<%= traefik_datapath%>/traefik.toml:/traefik.toml"
|
- "<%= traefik_datapath%>/traefik.toml:/traefik.toml:ro"
|
||||||
- "<%= traefik_datapath%>/acme.json:/acme.json"
|
- "<%= traefik_datapath%>/acme.json:/acme.json"
|
||||||
- "<%= traefik_datapath%>/htpasswd:/htpasswd/htpasswd"
|
- "<%= traefik_datapath%>/htpasswd:/htpasswd/htpasswd:ro"
|
||||||
networks:
|
networks:
|
||||||
- cyphernodeappsnet
|
- cyphernodeappsnet
|
||||||
restart: always
|
restart: always
|
||||||
@@ -246,7 +247,7 @@ services:
|
|||||||
<% } %>
|
<% } %>
|
||||||
volumes:
|
volumes:
|
||||||
- "<%= lightning_datapath %>:/.lightning"
|
- "<%= lightning_datapath %>:/.lightning"
|
||||||
- "<%= bitcoin_datapath %>/bitcoin-client.conf:/.bitcoin/bitcoin.conf"
|
- "<%= bitcoin_datapath %>/bitcoin-client.conf:/.bitcoin/bitcoin.conf:ro"
|
||||||
- bitcoin_monitor:/bitcoin_monitor:ro
|
- bitcoin_monitor:/bitcoin_monitor:ro
|
||||||
networks:
|
networks:
|
||||||
- cyphernodenet
|
- cyphernodenet
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ EXIT_STATUS=$(($? | ${EXIT_STATUS}))
|
|||||||
printf "\r\n\e[1;32mTests finished.\e[0m\n"
|
printf "\r\n\e[1;32mTests finished.\e[0m\n"
|
||||||
|
|
||||||
if [ "$EXIT_STATUS" -ne "0" ]; then
|
if [ "$EXIT_STATUS" -ne "0" ]; then
|
||||||
printf "\r\n\033[1;31mThere was an error during cyphernode installation. Please see Docker's logs for more information. Run ./testdeployment.sh to rerun the tests. Run ./stop.sh to stop cyphernode.\r\n\r\n\033[0m"
|
printf "\r\n\033[1;31mThere was an error during cyphernode installation. full logs: docker ps -q | xargs -L 1 docker logs , Containers logs: docker logs <containerid> , list containers: docker ps .Please see Docker's logs for more information. Run ./testdeployment.sh to rerun the tests. Run ./stop.sh to stop cyphernode.\r\n\r\n\033[0m"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
8
dist/setup.sh
vendored
8
dist/setup.sh
vendored
@@ -437,12 +437,6 @@ install_docker() {
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
elif [[ $cmpStatus == 'incompatible' ]]; then
|
|
||||||
copy_file $cyphernodeconf_filepath/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf.cyphernode 0 $SUDO_REQUIRED
|
|
||||||
copy_file $cyphernodeconf_filepath/bitcoin/bitcoin-client.conf $BITCOIN_DATAPATH/bitcoin-client.conf.cyphernode 0 $SUDO_REQUIRED
|
|
||||||
echo " [31mBlockchain data is not compatible, due to misconfigured nets.[0m"
|
|
||||||
echo " [31mYour cyphernode installation is most likely broken.[0m"
|
|
||||||
echo " [31mPlease check bitcoin.conf.cyphernode on how to repair it manually.[0m"
|
|
||||||
else
|
else
|
||||||
if [[ $cmpStatus == 'reindex' ]]; then
|
if [[ $cmpStatus == 'reindex' ]]; then
|
||||||
echo " [33mWarning[0m Reindexing will take some time."
|
echo " [33mWarning[0m Reindexing will take some time."
|
||||||
@@ -698,9 +692,11 @@ sanity_checks_pre_install() {
|
|||||||
|
|
||||||
install_apps() {
|
install_apps() {
|
||||||
if [ ! -d "$current_path/apps" ]; then
|
if [ ! -d "$current_path/apps" ]; then
|
||||||
|
local user=$(id -u $RUN_AS_USER):$(id -g $RUN_AS_USER)
|
||||||
local apps_repo="https://github.com/SatoshiPortal/cypherapps.git"
|
local apps_repo="https://github.com/SatoshiPortal/cypherapps.git"
|
||||||
echo " [32mclone[0m $apps_repo into apps"
|
echo " [32mclone[0m $apps_repo into apps"
|
||||||
docker run --rm -v "$current_path":/git --entrypoint git cyphernode/cyphernodeconf:$CONF_VERSION clone --single-branch -b ${CYPHERAPPS_VERSION} "$apps_repo" /git/apps > /dev/null 2>&1
|
docker run --rm -v "$current_path":/git --entrypoint git cyphernode/cyphernodeconf:$CONF_VERSION clone --single-branch -b ${CYPHERAPPS_VERSION} "$apps_repo" /git/apps > /dev/null 2>&1
|
||||||
|
sudo_if_required chown -R $user $current_path/apps
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
### Watch a Bitcoin Address (called by application)
|
### Watch a Bitcoin Address (called by application)
|
||||||
|
|
||||||
Inserts the address and callbacks in the DB and imports the address to the Watching wallet.
|
Inserts the address and callbacks in the DB and imports the address to the Watching wallet. The callback URLs and event message are optional. If eventMessage is not supplied, tx_confirmation for that watch will not be published. Event message should be in base64 format to avoid dealing with escaping special characters.
|
||||||
|
|
||||||
```http
|
```http
|
||||||
POST http://cyphernode:8888/watch
|
POST http://cyphernode:8888/watch
|
||||||
with body...
|
with body...
|
||||||
{"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","unconfirmedCallbackURL":"192.168.111.233:1111/callback0conf","confirmedCallbackURL":"192.168.111.233:1111/callback1conf"}
|
{"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","unconfirmedCallbackURL":"192.168.111.233:1111/callback0conf","confirmedCallbackURL":"192.168.111.233:1111/callback1conf","eventMessage":"eyJib3VuY2VfYWRkcmVzcyI6IjJNdkEzeHIzOHIxNXRRZWhGblBKMVhBdXJDUFR2ZTZOamNGIiwibmJfY29uZiI6MH0K"}
|
||||||
```
|
```
|
||||||
|
|
||||||
Proxy response:
|
Proxy response:
|
||||||
@@ -26,7 +26,8 @@ Proxy response:
|
|||||||
"estimatesmartfee2blocks": "0.000010",
|
"estimatesmartfee2blocks": "0.000010",
|
||||||
"estimatesmartfee6blocks": "0.000010",
|
"estimatesmartfee6blocks": "0.000010",
|
||||||
"estimatesmartfee36blocks": "0.000010",
|
"estimatesmartfee36blocks": "0.000010",
|
||||||
"estimatesmartfee144blocks": "0.000010"
|
"estimatesmartfee144blocks": "0.000010",
|
||||||
|
"eventMessage": "eyJib3VuY2VfYWRkcmVzcyI6IjJNdkEzeHIzOHIxNXRRZWhGblBKMVhBdXJDUFR2ZTZOamNGIiwibmJfY29uZiI6MH0K"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -66,7 +67,8 @@ Proxy response:
|
|||||||
"imported":"1",
|
"imported":"1",
|
||||||
"unconfirmedCallbackURL":"192.168.133.233:1111/callback0conf",
|
"unconfirmedCallbackURL":"192.168.133.233:1111/callback0conf",
|
||||||
"confirmedCallbackURL":"192.168.133.233:1111/callback1conf",
|
"confirmedCallbackURL":"192.168.133.233:1111/callback1conf",
|
||||||
"watching_since":"2018-09-06 21:14:03"}
|
"watching_since":"2018-09-06 21:14:03",
|
||||||
|
"eventMessage":"eyJib3VuY2VfYWRkcmVzcyI6IjJNdkEzeHIzOHIxNXRRZWhGblBKMVhBdXJDUFR2ZTZOamNGIiwibmJfY29uZiI6MH0K"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -619,12 +621,14 @@ Proxy response:
|
|||||||
|
|
||||||
### Spend coins from spending wallet (called by application)
|
### Spend coins from spending wallet (called by application)
|
||||||
|
|
||||||
Calls sendtoaddress RPC on the spending wallet with supplied info.
|
Calls sendtoaddress RPC on the spending wallet with supplied info. Can supply an eventMessage to be published on successful spending. eventMessage should be base64 encoded to avoid dealing with escaping special characters.
|
||||||
|
|
||||||
```http
|
```http
|
||||||
POST http://cyphernode:8888/spend
|
POST http://cyphernode:8888/spend
|
||||||
with body...
|
with body...
|
||||||
{"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","amount":0.00233}
|
{"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","amount":0.00233}
|
||||||
|
or
|
||||||
|
{"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","amount":0.00233,"eventMessage":"eyJ3aGF0ZXZlciI6MTIzfQo="}
|
||||||
```
|
```
|
||||||
|
|
||||||
Proxy response:
|
Proxy response:
|
||||||
@@ -782,12 +786,14 @@ Proxy response:
|
|||||||
|
|
||||||
### Create a Lightning Network invoice (called by application)
|
### Create a Lightning Network invoice (called by application)
|
||||||
|
|
||||||
Returns a LN invoice. Label must be unique. Description will be used by your user for payment. Expiry is in seconds.
|
Returns a LN invoice. Label must be unique. Description will be used by your user for payment. Expiry is in seconds and optional. If msatoshi is not supplied, will use "any" (ie donation invoice). callbackUrl is optional.
|
||||||
|
|
||||||
```http
|
```http
|
||||||
POST http://cyphernode:8888/ln_create_invoice
|
POST http://cyphernode:8888/ln_create_invoice
|
||||||
with body...
|
with body...
|
||||||
{"msatoshi":10000,"label":"koNCcrSvhX3dmyFhW","description":"Bylls order #10649","expiry":900}
|
{"msatoshi":10000,"label":"koNCcrSvhX3dmyFhW","description":"Bylls order #10649","expiry":900,"callbackUrl":"https://thesite/lnwebhook/9d8sa98yd"}
|
||||||
|
or
|
||||||
|
{"label":"koNCcrSvhX3dmyFhW","description":"Bylls order #10649","expiry":900}
|
||||||
```
|
```
|
||||||
|
|
||||||
Proxy response:
|
Proxy response:
|
||||||
@@ -802,7 +808,7 @@ Proxy response:
|
|||||||
|
|
||||||
### Pay a Lightning Network invoice (called by application)
|
### Pay a Lightning Network invoice (called by application)
|
||||||
|
|
||||||
Make a LN payment. expected_msatoshi and expected_description are respectively the amount and description you gave your user for her to create the invoice; they must match the given bolt11 invoice supplied by your user.
|
Make a LN payment. expected_msatoshi and expected_description are respectively the amount and description you gave your user for her to create the invoice; they must match the given bolt11 invoice supplied by your user. If the bolt11 invoice doesn't contain an amount, then the expected_msatoshi supplied here will be used as the paid amount.
|
||||||
|
|
||||||
```http
|
```http
|
||||||
POST http://cyphernode:8888/ln_pay
|
POST http://cyphernode:8888/ln_pay
|
||||||
|
|||||||
BIN
doc/CN-Arch.jpg
BIN
doc/CN-Arch.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 76 KiB |
@@ -50,8 +50,6 @@ paths:
|
|||||||
type: "object"
|
type: "object"
|
||||||
required:
|
required:
|
||||||
- "address"
|
- "address"
|
||||||
- "confirmedCallbackURL"
|
|
||||||
- "unconfirmedCallbackURL"
|
|
||||||
properties:
|
properties:
|
||||||
address:
|
address:
|
||||||
$ref: '#/components/schemas/TypeAddressString'
|
$ref: '#/components/schemas/TypeAddressString'
|
||||||
@@ -61,6 +59,9 @@ paths:
|
|||||||
confirmedCallbackURL:
|
confirmedCallbackURL:
|
||||||
type: "string"
|
type: "string"
|
||||||
format: "url"
|
format: "url"
|
||||||
|
eventMessage:
|
||||||
|
description: "Will be part of the published message on confirmations"
|
||||||
|
type: "string"
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: "successfully created"
|
description: "successfully created"
|
||||||
@@ -350,6 +351,276 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ApiResponseTemporarilyUnavailable'
|
$ref: '#/components/schemas/ApiResponseTemporarilyUnavailable'
|
||||||
|
/get_txns_by_watchlabel/{label}:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- in: "path"
|
||||||
|
name: "label"
|
||||||
|
description: "Xpub label"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "string"
|
||||||
|
tags:
|
||||||
|
- "transactions"
|
||||||
|
- "core features"
|
||||||
|
summary: "Get list of upto 10 transactions observed for addreses belonging to this label"
|
||||||
|
description: "Get list of transactions observed for addreses belonging to this label"
|
||||||
|
operationId: "get_txns_by_watchlabel"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: "successful operation"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: "object"
|
||||||
|
required:
|
||||||
|
- "label_txns"
|
||||||
|
properties:
|
||||||
|
watches:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/WatchXPubTxn'
|
||||||
|
'403':
|
||||||
|
$ref: '#/components/schemas/ApiResponseNotAllowed'
|
||||||
|
'503':
|
||||||
|
description: "Resource temporarily unavailable"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponseTemporarilyUnavailable'
|
||||||
|
/get_txns_by_watchlabel/{label}/{count}:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- in: "path"
|
||||||
|
name: "label"
|
||||||
|
description: "Xpub label"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "string"
|
||||||
|
- in: "path"
|
||||||
|
name: "count"
|
||||||
|
description: "Number of transactions to return"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "number"
|
||||||
|
tags:
|
||||||
|
- "transactions"
|
||||||
|
- "core features"
|
||||||
|
summary: "Get list of transactions observed for addreses belonging to this label"
|
||||||
|
description: "Get list of upto count number of transactions observed for addreses belonging to this label"
|
||||||
|
operationId: "get_txns_by_watchlabel_count"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: "successful operation"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: "object"
|
||||||
|
required:
|
||||||
|
- "label_txns"
|
||||||
|
properties:
|
||||||
|
watches:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/WatchXPubTxn'
|
||||||
|
'403':
|
||||||
|
$ref: '#/components/schemas/ApiResponseNotAllowed'
|
||||||
|
'503':
|
||||||
|
description: "Resource temporarily unavailable"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponseTemporarilyUnavailable'
|
||||||
|
/get_txns_spending:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- "transactions"
|
||||||
|
- "core features"
|
||||||
|
summary: "Get list of upto 10 spending wallet transactions"
|
||||||
|
description: "Get list of upto 10 spending wallet transactions"
|
||||||
|
operationId: "get_txns_spending"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: "successful operation"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: "object"
|
||||||
|
required:
|
||||||
|
- "txns"
|
||||||
|
properties:
|
||||||
|
watches:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/TransactionsSpending'
|
||||||
|
'403':
|
||||||
|
$ref: '#/components/schemas/ApiResponseNotAllowed'
|
||||||
|
'503':
|
||||||
|
description: "Resource temporarily unavailable"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponseTemporarilyUnavailable'
|
||||||
|
/get_txns_spending/{count}/:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- in: "path"
|
||||||
|
name: "count"
|
||||||
|
description: "Number of txns to return"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "integer"
|
||||||
|
tags:
|
||||||
|
- "transactions"
|
||||||
|
- "core features"
|
||||||
|
summary: "Get list of upto count spending wallet transactions"
|
||||||
|
description: "Get list of upto count wallets transactions"
|
||||||
|
operationId: "get_txns_spending_count"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: "successful operation"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: "object"
|
||||||
|
required:
|
||||||
|
- "txns"
|
||||||
|
properties:
|
||||||
|
watches:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/TransactionsSpending'
|
||||||
|
'403':
|
||||||
|
$ref: '#/components/schemas/ApiResponseNotAllowed'
|
||||||
|
'503':
|
||||||
|
description: "Resource temporarily unavailable"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponseTemporarilyUnavailable'
|
||||||
|
/get_txns_spending/{count}/{skip}:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- in: "path"
|
||||||
|
name: "count"
|
||||||
|
description: "Number of txns to return"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "integer"
|
||||||
|
- in: "path"
|
||||||
|
name: "skip"
|
||||||
|
description: "Number of txns to skip (start from)"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "integer"
|
||||||
|
tags:
|
||||||
|
- "transactions"
|
||||||
|
- "core features"
|
||||||
|
summary: "Get list of upto count spending wallet transactions, skipping over the first {skip} number of transactions"
|
||||||
|
description: "Get list of upto count spending wallet transactions, skipping over the first {skip} number of transactions"
|
||||||
|
operationId: "get_txns_spending_count_skip"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: "successful operation"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: "object"
|
||||||
|
required:
|
||||||
|
- "txns"
|
||||||
|
properties:
|
||||||
|
watches:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/TransactionsSpending'
|
||||||
|
'403':
|
||||||
|
$ref: '#/components/schemas/ApiResponseNotAllowed'
|
||||||
|
'503':
|
||||||
|
description: "Resource temporarily unavailable"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponseTemporarilyUnavailable'
|
||||||
|
/get_unused_addresses_by_watchlabel/{label}/:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- in: "path"
|
||||||
|
name: "label"
|
||||||
|
description: "Xpub label"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "string"
|
||||||
|
tags:
|
||||||
|
- "watching addresses"
|
||||||
|
- "core features"
|
||||||
|
summary: "Get list of upto 10 unused derived addreses belonging to this label"
|
||||||
|
description: "Gets an unused subset of addreses from the set of derived addresses belonging to this label"
|
||||||
|
operationId: "get_unused_addresses_by_watchlabel"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: "successful operation"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: "object"
|
||||||
|
required:
|
||||||
|
- "label_unused_addresses"
|
||||||
|
properties:
|
||||||
|
watches:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/UnusedWatchXPubAddress'
|
||||||
|
'403':
|
||||||
|
$ref: '#/components/schemas/ApiResponseNotAllowed'
|
||||||
|
'503':
|
||||||
|
description: "Resource temporarily unavailable"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponseTemporarilyUnavailable'
|
||||||
|
/get_unused_addresses_by_watchlabel/{label}/{count}:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- in: "path"
|
||||||
|
name: "label"
|
||||||
|
description: "Xpub label"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "string"
|
||||||
|
- in: "path"
|
||||||
|
name: "count"
|
||||||
|
description: "Number of addresses to return"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "integer"
|
||||||
|
tags:
|
||||||
|
- "watching addresses"
|
||||||
|
- "core features"
|
||||||
|
summary: "Get list of unused upto to {count} derived addreses belonging to this label"
|
||||||
|
description: "Get list of unused upto to {count} derived addreses belonging to this label"
|
||||||
|
operationId: "get_unused_addresses_by_watchlabel_count"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: "successful operation"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: "object"
|
||||||
|
required:
|
||||||
|
- "label_unused_addresses"
|
||||||
|
properties:
|
||||||
|
watches:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/UnusedWatchXPubAddress'
|
||||||
|
'403':
|
||||||
|
$ref: '#/components/schemas/ApiResponseNotAllowed'
|
||||||
|
'503':
|
||||||
|
description: "Resource temporarily unavailable"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponseTemporarilyUnavailable'
|
||||||
/getactivexpubwatches:
|
/getactivexpubwatches:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@@ -796,6 +1067,9 @@ paths:
|
|||||||
$ref: '#/components/schemas/TypeAddressString'
|
$ref: '#/components/schemas/TypeAddressString'
|
||||||
amount:
|
amount:
|
||||||
type: "number"
|
type: "number"
|
||||||
|
eventMessage:
|
||||||
|
description: "Will be part of the published message on spend"
|
||||||
|
type: "string"
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: "operation successful"
|
description: "operation successful"
|
||||||
@@ -1113,10 +1387,8 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: "object"
|
type: "object"
|
||||||
required:
|
required:
|
||||||
- "msatoshi"
|
|
||||||
- "label"
|
- "label"
|
||||||
- "description"
|
- "description"
|
||||||
- "expiry"
|
|
||||||
properties:
|
properties:
|
||||||
msatoshi:
|
msatoshi:
|
||||||
type: "integer"
|
type: "integer"
|
||||||
@@ -1126,6 +1398,9 @@ paths:
|
|||||||
type: "string"
|
type: "string"
|
||||||
expiry:
|
expiry:
|
||||||
type: "integer"
|
type: "integer"
|
||||||
|
callbackUrl:
|
||||||
|
type: "string"
|
||||||
|
format: "url"
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: "successful operation"
|
description: "successful operation"
|
||||||
@@ -1166,7 +1441,6 @@ paths:
|
|||||||
required:
|
required:
|
||||||
- "bolt11"
|
- "bolt11"
|
||||||
- "expected_msatoshi"
|
- "expected_msatoshi"
|
||||||
- "expected_description"
|
|
||||||
properties:
|
properties:
|
||||||
bolt11:
|
bolt11:
|
||||||
type: "string"
|
type: "string"
|
||||||
@@ -1543,6 +1817,7 @@ components:
|
|||||||
- "address"
|
- "address"
|
||||||
- "unconfirmedCallbackURL"
|
- "unconfirmedCallbackURL"
|
||||||
- "confirmedCallbackURL"
|
- "confirmedCallbackURL"
|
||||||
|
- "eventMessage"
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
type: "string"
|
type: "string"
|
||||||
@@ -1574,6 +1849,8 @@ components:
|
|||||||
type: "string"
|
type: "string"
|
||||||
watching_since:
|
watching_since:
|
||||||
type: "string"
|
type: "string"
|
||||||
|
eventMessage:
|
||||||
|
type: "string"
|
||||||
WatchedByXpubAddress:
|
WatchedByXpubAddress:
|
||||||
type: "object"
|
type: "object"
|
||||||
required:
|
required:
|
||||||
@@ -1607,6 +1884,109 @@ components:
|
|||||||
type: "string"
|
type: "string"
|
||||||
pub32_index:
|
pub32_index:
|
||||||
type: "string"
|
type: "string"
|
||||||
|
UnusedWatchXPubAddress:
|
||||||
|
type: "object"
|
||||||
|
required:
|
||||||
|
- "pub32_watch_id"
|
||||||
|
- "pub32_label"
|
||||||
|
- "pub32"
|
||||||
|
- "address_pub32_index"
|
||||||
|
- "address"
|
||||||
|
properties:
|
||||||
|
pub32_watch_id:
|
||||||
|
type: "string"
|
||||||
|
address:
|
||||||
|
$ref: '#/components/schemas/TypeAddressString'
|
||||||
|
pub32:
|
||||||
|
$ref: '#/components/schemas/TypeXpubString'
|
||||||
|
pub32_label:
|
||||||
|
type: "string"
|
||||||
|
address_pub32_index:
|
||||||
|
type: "string"
|
||||||
|
TransactionsSpending:
|
||||||
|
type: "object"
|
||||||
|
required:
|
||||||
|
- "address"
|
||||||
|
- "category"
|
||||||
|
- "amount"
|
||||||
|
- "label"
|
||||||
|
- "vout"
|
||||||
|
- "fee"
|
||||||
|
- "confirmations"
|
||||||
|
- "blockhash"
|
||||||
|
- "blockindex"
|
||||||
|
- "blocktime"
|
||||||
|
- "txid"
|
||||||
|
- "time"
|
||||||
|
- "timereceived"
|
||||||
|
- "comment"
|
||||||
|
- "bip125-replaceable"
|
||||||
|
- "abandoned"
|
||||||
|
properties:
|
||||||
|
address:
|
||||||
|
$ref: '#/components/schemas/TypeAddressString'
|
||||||
|
category:
|
||||||
|
$ref: 'string'
|
||||||
|
amount:
|
||||||
|
type: "number"
|
||||||
|
label:
|
||||||
|
type: "string"
|
||||||
|
vout:
|
||||||
|
type: "integer"
|
||||||
|
fee:
|
||||||
|
type: "fee"
|
||||||
|
confirmations:
|
||||||
|
type: "integer"
|
||||||
|
blockhash:
|
||||||
|
$ref: '#/components/schemas/TypeHashString'
|
||||||
|
blockindex:
|
||||||
|
$ref: 'number'
|
||||||
|
blocktime:
|
||||||
|
type: "number"
|
||||||
|
txid:
|
||||||
|
$ref: '#/components/schemas/TypeHashString'
|
||||||
|
time:
|
||||||
|
type: "number"
|
||||||
|
timereceived:
|
||||||
|
type: "number"
|
||||||
|
comment:
|
||||||
|
type: "string"
|
||||||
|
bip125-replaceable:
|
||||||
|
type: "string"
|
||||||
|
abandoned:
|
||||||
|
type: "boolean"
|
||||||
|
WatchXPubTxn:
|
||||||
|
type: "object"
|
||||||
|
required:
|
||||||
|
- "label"
|
||||||
|
- "address"
|
||||||
|
- "txid"
|
||||||
|
- "confirmations"
|
||||||
|
- "blockheight"
|
||||||
|
- "v_out"
|
||||||
|
- "amount"
|
||||||
|
- "blockhash"
|
||||||
|
- "blocktime"
|
||||||
|
- "timereceived"
|
||||||
|
properties:
|
||||||
|
label:
|
||||||
|
type: "string"
|
||||||
|
address:
|
||||||
|
$ref: '#/components/schemas/TypeAddressString'
|
||||||
|
txid:
|
||||||
|
$ref: '#/components/schemas/TypeHashString'
|
||||||
|
confirmations:
|
||||||
|
type: "integer"
|
||||||
|
v_out:
|
||||||
|
type: "integer"
|
||||||
|
amount:
|
||||||
|
type: "number"
|
||||||
|
blockhash:
|
||||||
|
$ref: '#/components/schemas/TypeHashString'
|
||||||
|
blocktime:
|
||||||
|
type: "number"
|
||||||
|
timereceived:
|
||||||
|
type: "number"
|
||||||
WatchedXpub:
|
WatchedXpub:
|
||||||
type: "object"
|
type: "object"
|
||||||
required:
|
required:
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ CREATE TABLE watching (
|
|||||||
imported INTEGER DEFAULT FALSE,
|
imported INTEGER DEFAULT FALSE,
|
||||||
watching_by_pub32_id INTEGER REFERENCES watching_by_pub32,
|
watching_by_pub32_id INTEGER REFERENCES watching_by_pub32,
|
||||||
pub32_index INTEGER,
|
pub32_index INTEGER,
|
||||||
|
event_message TEXT,
|
||||||
inserted_ts INTEGER DEFAULT CURRENT_TIMESTAMP
|
inserted_ts INTEGER DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
14
proxy_docker/app/data/sqlmigrate20191127_0.2.4-0.3.0.sh
Normal file
14
proxy_docker/app/data/sqlmigrate20191127_0.2.4-0.3.0.sh
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Checking for watching event support in DB..."
|
||||||
|
count=$(sqlite3 $DB_FILE "select count(*) from pragma_table_info('watching') where name='event_message'")
|
||||||
|
if [ "${count}" -eq "0" ]; then
|
||||||
|
# event_message not there, we have to migrate
|
||||||
|
echo "Migrating database for event triggered on watch notif..."
|
||||||
|
echo "Backing up current DB..."
|
||||||
|
cp $DB_FILE $DB_FILE-sqlmigrate20191127_0.2.4-0.3.0
|
||||||
|
echo "Altering DB..."
|
||||||
|
cat sqlmigrate20191127_0.2.4-0.3.0.sql | sqlite3 $DB_FILE
|
||||||
|
else
|
||||||
|
echo "Database watching event support migration already done, skipping!"
|
||||||
|
fi
|
||||||
1
proxy_docker/app/data/sqlmigrate20191127_0.2.4-0.3.0.sql
Normal file
1
proxy_docker/app/data/sqlmigrate20191127_0.2.4-0.3.0.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE watching ADD COLUMN event_message TEXT;
|
||||||
@@ -20,6 +20,11 @@ ln_create_invoice() {
|
|||||||
trace "[ln_create_invoice] expiry=${expiry}"
|
trace "[ln_create_invoice] expiry=${expiry}"
|
||||||
local callback_url=$(echo "${request}" | jq -r ".callbackUrl")
|
local callback_url=$(echo "${request}" | jq -r ".callbackUrl")
|
||||||
trace "[ln_create_invoice] callback_url=${callback_url}"
|
trace "[ln_create_invoice] callback_url=${callback_url}"
|
||||||
|
if [ "${callback_url}" != "null" ]; then
|
||||||
|
# If not null, let's add double-quotes so we don't need to add the double-quotes in the sql insert,
|
||||||
|
# so if it's null, it will insert the actual sql NULL value.
|
||||||
|
callback_url="\"${callback_url}\""
|
||||||
|
fi
|
||||||
|
|
||||||
#/proxy $ ./lightning-cli invoice 10000 "t1" "t1d" 60
|
#/proxy $ ./lightning-cli invoice 10000 "t1" "t1d" 60
|
||||||
#{
|
#{
|
||||||
@@ -28,8 +33,13 @@ ln_create_invoice() {
|
|||||||
# "bolt11": "lnbc100n1pwzllqgpp55a8xen9sdcntehwr93pkwnuu8nmtqx9yew0flalcxhx9nvy34crqdq9wsckgxqzpucqp2rzjqt04ll5ft3mcuy8hws4xcku2pnhma9r9mavtjtadawyrw5kgzp7g7zr745qq3mcqqyqqqqlgqqqqqzsqpcr85k33shzaxscpj29fadmjmfej6y2p380x9w4kxydqpxq87l6lshy69fry9q2yrtu037nt44x77uhzkdyn8043n5yj8tqgluvmcl69cquaxr68"
|
# "bolt11": "lnbc100n1pwzllqgpp55a8xen9sdcntehwr93pkwnuu8nmtqx9yew0flalcxhx9nvy34crqdq9wsckgxqzpucqp2rzjqt04ll5ft3mcuy8hws4xcku2pnhma9r9mavtjtadawyrw5kgzp7g7zr745qq3mcqqyqqqqlgqqqqqzsqpcr85k33shzaxscpj29fadmjmfej6y2p380x9w4kxydqpxq87l6lshy69fry9q2yrtu037nt44x77uhzkdyn8043n5yj8tqgluvmcl69cquaxr68"
|
||||||
#}
|
#}
|
||||||
|
|
||||||
trace "[ln_create_invoice] ./lightning-cli invoice ${msatoshi} \"${label}\" \"${description}\" ${expiry}"
|
if [ "${msatoshi}" = "null" ]; then
|
||||||
result=$(./lightning-cli invoice ${msatoshi} "${label}" "${description}" ${expiry})
|
trace "[ln_create_invoice] ./lightning-cli invoice \"any\" \"${label}\" \"${description}\" ${expiry}"
|
||||||
|
result=$(./lightning-cli invoice "any" "${label}" "${description}" ${expiry})
|
||||||
|
else
|
||||||
|
trace "[ln_create_invoice] ./lightning-cli invoice ${msatoshi} \"${label}\" \"${description}\" ${expiry}"
|
||||||
|
result=$(./lightning-cli invoice ${msatoshi} "${label}" "${description}" ${expiry})
|
||||||
|
fi
|
||||||
returncode=$?
|
returncode=$?
|
||||||
trace_rc ${returncode}
|
trace_rc ${returncode}
|
||||||
trace "[ln_create_invoice] result=${result}"
|
trace "[ln_create_invoice] result=${result}"
|
||||||
@@ -47,7 +57,11 @@ ln_create_invoice() {
|
|||||||
# Let's get the connect string if provided in configuration
|
# Let's get the connect string if provided in configuration
|
||||||
local connectstring=$(get_connection_string)
|
local connectstring=$(get_connection_string)
|
||||||
|
|
||||||
sql "INSERT OR IGNORE INTO ln_invoice (label, bolt11, callback_url, payment_hash, expires_at, msatoshi, description, status) VALUES (\"${label}\", \"${bolt11}\", \"${callback_url}\", \"${payment_hash}\", ${expires_at}, ${msatoshi}, \"${description}\", \"unpaid\")"
|
if [ "${msatoshi}" = "null" ]; then
|
||||||
|
sql "INSERT OR IGNORE INTO ln_invoice (label, bolt11, callback_url, payment_hash, expires_at, description, status) VALUES (\"${label}\", \"${bolt11}\", ${callback_url}, \"${payment_hash}\", ${expires_at}, \"${description}\", \"unpaid\")"
|
||||||
|
else
|
||||||
|
sql "INSERT OR IGNORE INTO ln_invoice (label, bolt11, callback_url, payment_hash, expires_at, msatoshi, description, status) VALUES (\"${label}\", \"${bolt11}\", ${callback_url}, \"${payment_hash}\", ${expires_at}, ${msatoshi}, \"${description}\", \"unpaid\")"
|
||||||
|
fi
|
||||||
trace_rc $?
|
trace_rc $?
|
||||||
id=$(sql "SELECT id FROM ln_invoice WHERE bolt11=\"${bolt11}\"")
|
id=$(sql "SELECT id FROM ln_invoice WHERE bolt11=\"${bolt11}\"")
|
||||||
trace_rc $?
|
trace_rc $?
|
||||||
@@ -58,9 +72,13 @@ ln_create_invoice() {
|
|||||||
if [ -n "${connectstring}" ]; then
|
if [ -n "${connectstring}" ]; then
|
||||||
data="${data}\"connectstring\":\"${connectstring}\","
|
data="${data}\"connectstring\":\"${connectstring}\","
|
||||||
fi
|
fi
|
||||||
data="${data}\"callback_url\":\"${callback_url}\","
|
if [ "${callback_url}" != "null" ]; then
|
||||||
|
data="${data}\"callbackUrl\":${callback_url},"
|
||||||
|
fi
|
||||||
data="${data}\"payment_hash\":\"${payment_hash}\","
|
data="${data}\"payment_hash\":\"${payment_hash}\","
|
||||||
data="${data}\"msatoshi\":${msatoshi},"
|
if [ "${msatoshi}" != "null" ]; then
|
||||||
|
data="${data}\"msatoshi\":${msatoshi},"
|
||||||
|
fi
|
||||||
data="${data}\"status\":\"unpaid\","
|
data="${data}\"status\":\"unpaid\","
|
||||||
data="${data}\"description\":\"${description}\","
|
data="${data}\"description\":\"${description}\","
|
||||||
data="${data}\"expires_at\":${expires_at}}"
|
data="${data}\"expires_at\":${expires_at}}"
|
||||||
@@ -306,21 +324,31 @@ ln_pay() {
|
|||||||
local invoice_description=$(echo "${result}" | jq ".description")
|
local invoice_description=$(echo "${result}" | jq ".description")
|
||||||
trace "[ln_pay] invoice_description=${invoice_description}"
|
trace "[ln_pay] invoice_description=${invoice_description}"
|
||||||
|
|
||||||
# The amount must match
|
# The amount must match if not "any"
|
||||||
if [ "${expected_msatoshi}" != "${invoice_msatoshi}" ]; then
|
# If the amount is not in the invoice and not supplied as expected_msatoshi, then both will be null, that's ok!
|
||||||
|
# Same thing goes for the description.
|
||||||
|
if [ "${expected_msatoshi}" != "${invoice_msatoshi}" ] && [ "${invoice_msatoshi}" != "null" ]; then
|
||||||
|
# If invoice_msatoshi is null, that means "any" was supplied, so the amounts don't have to match!
|
||||||
result="{\"result\":\"error\",\"expected_msatoshi\":${expected_msatoshi},\"invoice_msatoshi\":${invoice_msatoshi}}"
|
result="{\"result\":\"error\",\"expected_msatoshi\":${expected_msatoshi},\"invoice_msatoshi\":${invoice_msatoshi}}"
|
||||||
returncode=1
|
returncode=1
|
||||||
elif [ "${expected_description}" != '""' ] && [ "${expected_description}" != "${invoice_description}" ]; then
|
elif [ -n "${expected_description}" ] && [ "${expected_description}" != "null" ] && [ "${expected_description}" != "${invoice_description}" ]; then
|
||||||
# If expected description is empty, we accept any description on the invoice. Amount is the important thing.
|
# If expected description is not empty but doesn't correspond to invoice_description, there'a problem.
|
||||||
|
# (we don't care about the description if expected description is empty. Amount is the most important thing)
|
||||||
|
|
||||||
result="{\"result\":\"error\",\"expected_description\":${expected_description},\"invoice_description\":${invoice_description}}"
|
result="{\"result\":\"error\",\"expected_description\":${expected_description},\"invoice_description\":${invoice_description}}"
|
||||||
returncode=1
|
returncode=1
|
||||||
else
|
else
|
||||||
# Amount and description is as expected, let's pay!
|
# Amount and description are as expected (or empty description), let's pay!
|
||||||
trace "[ln_pay] Amount and description are as expected, let's try to pay!"
|
trace "[ln_pay] Amount and description are as expected, let's try to pay!"
|
||||||
|
|
||||||
trace "[ln_pay] ./lightning-cli pay -k bolt11=${bolt11} retry_for=15"
|
if [ "${invoice_msatoshi}" = "null" ]; then
|
||||||
result=$(./lightning-cli pay -k bolt11=${bolt11} retry_for=15)
|
# "any" amount on the invoice, we force paying the expected_msatoshi provided to ln_pay by the user
|
||||||
|
trace "[ln_pay] ./lightning-cli pay -k bolt11=${bolt11} msatoshi=${expected_msatoshi} retry_for=15"
|
||||||
|
result=$(./lightning-cli pay -k bolt11=${bolt11} msatoshi=${expected_msatoshi} retry_for=15)
|
||||||
|
else
|
||||||
|
trace "[ln_pay] ./lightning-cli pay -k bolt11=${bolt11} retry_for=15"
|
||||||
|
result=$(./lightning-cli pay -k bolt11=${bolt11} retry_for=15)
|
||||||
|
fi
|
||||||
returncode=$?
|
returncode=$?
|
||||||
trace_rc ${returncode}
|
trace_rc ${returncode}
|
||||||
trace "[ln_pay] result=${result}"
|
trace "[ln_pay] result=${result}"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ do_callbacks() {
|
|||||||
trace "Entering do_callbacks()..."
|
trace "Entering do_callbacks()..."
|
||||||
|
|
||||||
# Let's fetch all the watching addresses still being watched but not called back
|
# Let's fetch all the watching addresses still being watched but not called back
|
||||||
local callbacks=$(sql 'SELECT DISTINCT w.callback0conf, address, txid, vout, amount, confirmations, timereceived, fee, size, vsize, blockhash, blockheight, blocktime, w.id, is_replaceable, pub32_index, pub32, label, derivation_path FROM watching w LEFT JOIN watching_tx ON w.id = watching_id LEFT JOIN tx ON tx.id = tx_id LEFT JOIN watching_by_pub32 w32 ON watching_by_pub32_id = w32.id WHERE NOT calledback0conf AND watching_id NOT NULL AND w.callback0conf NOT NULL AND w.watching')
|
local callbacks=$(sql 'SELECT DISTINCT w.callback0conf, address, txid, vout, amount, confirmations, timereceived, fee, size, vsize, blockhash, blockheight, blocktime, w.id, is_replaceable, pub32_index, pub32, label, derivation_path, event_message FROM watching w LEFT JOIN watching_tx ON w.id = watching_id LEFT JOIN tx ON tx.id = tx_id LEFT JOIN watching_by_pub32 w32 ON watching_by_pub32_id = w32.id WHERE NOT calledback0conf AND watching_id NOT NULL AND w.callback0conf NOT NULL AND w.watching')
|
||||||
trace "[do_callbacks] callbacks0conf=${callbacks}"
|
trace "[do_callbacks] callbacks0conf=${callbacks}"
|
||||||
|
|
||||||
local returncode
|
local returncode
|
||||||
@@ -30,7 +30,7 @@ do_callbacks() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
callbacks=$(sql 'SELECT DISTINCT w.callback1conf, address, txid, vout, amount, confirmations, timereceived, fee, size, vsize, blockhash, blockheight, blocktime, w.id, is_replaceable, pub32_index, pub32, label, derivation_path FROM watching w, watching_tx wt, tx t LEFT JOIN watching_by_pub32 w32 ON watching_by_pub32_id = w32.id WHERE w.id = watching_id AND tx_id = t.id AND NOT calledback1conf AND confirmations>0 AND w.callback1conf NOT NULL AND w.watching')
|
callbacks=$(sql 'SELECT DISTINCT w.callback1conf, address, txid, vout, amount, confirmations, timereceived, fee, size, vsize, blockhash, blockheight, blocktime, w.id, is_replaceable, pub32_index, pub32, label, derivation_path, event_message FROM watching w, watching_tx wt, tx t LEFT JOIN watching_by_pub32 w32 ON watching_by_pub32_id = w32.id WHERE w.id = watching_id AND tx_id = t.id AND NOT calledback1conf AND confirmations>0 AND w.callback1conf NOT NULL AND w.watching')
|
||||||
trace "[do_callbacks] callbacks1conf=${callbacks}"
|
trace "[do_callbacks] callbacks1conf=${callbacks}"
|
||||||
|
|
||||||
for row in ${callbacks}
|
for row in ${callbacks}
|
||||||
@@ -64,12 +64,21 @@ ln_manage_callback() {
|
|||||||
|
|
||||||
local id=$(echo "${row}" | cut -d '|' -f1)
|
local id=$(echo "${row}" | cut -d '|' -f1)
|
||||||
trace "[ln_manage_callback] id=${id}"
|
trace "[ln_manage_callback] id=${id}"
|
||||||
|
local callback_url=$(echo "${row}" | cut -d '|' -f4)
|
||||||
|
trace "[ln_manage_callback] callback_url=${callback_url}"
|
||||||
|
|
||||||
|
if [ -z "${callback_url}" ]; then
|
||||||
|
# No callback url provided for that invoice
|
||||||
|
trace "[ln_manage_callback] No callback url provided for that invoice"
|
||||||
|
sql "UPDATE ln_invoice SET calledback=1 WHERE id=\"${id}\""
|
||||||
|
trace_rc $?
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
local label=$(echo "${row}" | cut -d '|' -f2)
|
local label=$(echo "${row}" | cut -d '|' -f2)
|
||||||
trace "[ln_manage_callback] label=${label}"
|
trace "[ln_manage_callback] label=${label}"
|
||||||
local bolt11=$(echo "${row}" | cut -d '|' -f3)
|
local bolt11=$(echo "${row}" | cut -d '|' -f3)
|
||||||
trace "[ln_manage_callback] bolt11=${bolt11}"
|
trace "[ln_manage_callback] bolt11=${bolt11}"
|
||||||
local callback_url=$(echo "${row}" | cut -d '|' -f4)
|
|
||||||
trace "[ln_manage_callback] callback_url=${callback_url}"
|
|
||||||
local payment_hash=$(echo "${row}" | cut -d '|' -f5)
|
local payment_hash=$(echo "${row}" | cut -d '|' -f5)
|
||||||
trace "[ln_manage_callback] payment_hash=${payment_hash}"
|
trace "[ln_manage_callback] payment_hash=${payment_hash}"
|
||||||
local msatoshi=$(echo "${row}" | cut -d '|' -f6)
|
local msatoshi=$(echo "${row}" | cut -d '|' -f6)
|
||||||
@@ -88,13 +97,6 @@ ln_manage_callback() {
|
|||||||
trace "[ln_manage_callback] expires_at=${expires_at}"
|
trace "[ln_manage_callback] expires_at=${expires_at}"
|
||||||
local returncode
|
local returncode
|
||||||
|
|
||||||
if [ -z "${callback_url}" ]; then
|
|
||||||
# No callback url provided for that invoice
|
|
||||||
sql "UPDATE ln_invoice SET calledback=1 WHERE id=\"${id}\""
|
|
||||||
trace_rc $?
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
data="{\"id\":\"${id}\","
|
data="{\"id\":\"${id}\","
|
||||||
data="${data}\"label\":\"${label}\","
|
data="${data}\"label\":\"${label}\","
|
||||||
data="${data}\"bolt11\":\"${bolt11}\","
|
data="${data}\"bolt11\":\"${bolt11}\","
|
||||||
@@ -149,13 +151,22 @@ build_callback() {
|
|||||||
local label
|
local label
|
||||||
local derivation_path
|
local derivation_path
|
||||||
|
|
||||||
# callback0conf, address, txid, vout, amount, confirmations, timereceived, fee, size, vsize, blockhash, blockheight, blocktime, w.id
|
local event_message
|
||||||
|
|
||||||
|
# w.callback0conf, address, txid, vout, amount, confirmations, timereceived, fee, size, vsize, blockhash, blockheight, blocktime,
|
||||||
|
# w.id, is_replaceable, pub32_index, pub32, label, derivation_path, event_message
|
||||||
|
|
||||||
|
url=$(echo "${row}" | cut -d '|' -f1)
|
||||||
|
trace "[build_callback] url=${url}"
|
||||||
|
if [ -z "${url}" ]; then
|
||||||
|
# No callback url provided for that watch
|
||||||
|
trace "[build_callback] No callback url provided for that watch, skipping webhook call"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
trace "[build_callback] row=${row}"
|
trace "[build_callback] row=${row}"
|
||||||
id=$(echo "${row}" | cut -d '|' -f14)
|
id=$(echo "${row}" | cut -d '|' -f14)
|
||||||
trace "[build_callback] id=${id}"
|
trace "[build_callback] id=${id}"
|
||||||
url=$(echo "${row}" | cut -d '|' -f1)
|
|
||||||
trace "[build_callback] url=${url}"
|
|
||||||
address=$(echo "${row}" | cut -d '|' -f2)
|
address=$(echo "${row}" | cut -d '|' -f2)
|
||||||
trace "[build_callback] address=${address}"
|
trace "[build_callback] address=${address}"
|
||||||
txid=$(echo "${row}" | cut -d '|' -f3)
|
txid=$(echo "${row}" | cut -d '|' -f3)
|
||||||
@@ -199,6 +210,8 @@ build_callback() {
|
|||||||
derivation_path=$(echo "${row}" | cut -d '|' -f19)
|
derivation_path=$(echo "${row}" | cut -d '|' -f19)
|
||||||
trace "[build_callback] derivation_path=${derivation_path}"
|
trace "[build_callback] derivation_path=${derivation_path}"
|
||||||
fi
|
fi
|
||||||
|
event_message=$(echo "${row}" | cut -d '|' -f20)
|
||||||
|
trace "[build_callback] event_message=${event_message}"
|
||||||
|
|
||||||
data="{\"id\":\"${id}\","
|
data="{\"id\":\"${id}\","
|
||||||
data="${data}\"address\":\"${address}\","
|
data="${data}\"address\":\"${address}\","
|
||||||
@@ -212,19 +225,19 @@ build_callback() {
|
|||||||
if [ -n "${fee}" ]; then
|
if [ -n "${fee}" ]; then
|
||||||
data="${data}\"fees\":${fee},"
|
data="${data}\"fees\":${fee},"
|
||||||
fi
|
fi
|
||||||
data="${data}\"is_replaceable\":${is_replaceable}"
|
data="${data}\"is_replaceable\":${is_replaceable},"
|
||||||
if [ -n "${blocktime}" ]; then
|
if [ -n "${blocktime}" ]; then
|
||||||
data="${data},\"blockhash\":\"${blockhash}\","
|
data="${data}\"blockhash\":\"${blockhash}\","
|
||||||
data="${data}\"blocktime\":\"$(date -Is -d @${blocktime})\","
|
data="${data}\"blocktime\":\"$(date -Is -d @${blocktime})\","
|
||||||
data="${data}\"blockheight\":${blockheight}"
|
data="${data}\"blockheight\":${blockheight},"
|
||||||
fi
|
fi
|
||||||
if [ -n "${pub32_index}" ]; then
|
if [ -n "${pub32_index}" ]; then
|
||||||
data="${data}\"pub32\":\"${pub32}\","
|
data="${data}\"pub32\":\"${pub32}\","
|
||||||
data="${data}\"pub32_label\":\"${label}\","
|
data="${data}\"pub32_label\":\"${label}\","
|
||||||
derivation_path=$(echo -e $derivation_path | sed -En "s/n/${pub32_index}/p")
|
derivation_path=$(echo -e $derivation_path | sed -En "s/n/${pub32_index}/p")
|
||||||
data="${data}\"pub32_derivation_path\":\"${derivation_path}\""
|
data="${data}\"pub32_derivation_path\":\"${derivation_path}\","
|
||||||
fi
|
fi
|
||||||
data="${data}}"
|
data="${data}\"eventMessage\":\"${event_message}\"}"
|
||||||
trace "[build_callback] data=${data}"
|
trace "[build_callback] data=${data}"
|
||||||
|
|
||||||
curl_callback "${url}" "${data}"
|
curl_callback "${url}" "${data}"
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ confirmation() {
|
|||||||
local returncode
|
local returncode
|
||||||
local txid=${1}
|
local txid=${1}
|
||||||
local tx_details
|
local tx_details
|
||||||
tx_details=$(get_transaction ${txid})
|
tx_details="$(get_transaction ${txid})"
|
||||||
returncode=$?
|
returncode=$?
|
||||||
trace_rc ${returncode}
|
trace_rc ${returncode}
|
||||||
trace "[confirmation] tx_details=${tx_details}"
|
trace "[confirmation] tx_details=${tx_details}"
|
||||||
@@ -38,7 +38,6 @@ confirmation() {
|
|||||||
trace "[confirmation] Transaction not in watcher, exiting."
|
trace "[confirmation] Transaction not in watcher, exiting."
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
########################################################################################################
|
########################################################################################################
|
||||||
# First of all, let's make sure we're working on watched addresses...
|
# First of all, let's make sure we're working on watched addresses...
|
||||||
local address
|
local address
|
||||||
@@ -58,7 +57,7 @@ confirmation() {
|
|||||||
notfirst=true
|
notfirst=true
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
local rows=$(sql "SELECT id, address, watching_by_pub32_id, pub32_index FROM watching WHERE address IN (${addresseswhere}) AND watching")
|
local rows=$(sql "SELECT id, address, watching_by_pub32_id, pub32_index, event_message FROM watching WHERE address IN (${addresseswhere}) AND watching")
|
||||||
if [ ${#rows} -eq 0 ]; then
|
if [ ${#rows} -eq 0 ]; then
|
||||||
trace "[confirmation] No watched address in this tx!"
|
trace "[confirmation] No watched address in this tx!"
|
||||||
return 0
|
return 0
|
||||||
@@ -68,7 +67,7 @@ confirmation() {
|
|||||||
local tx=$(sql "SELECT id FROM tx WHERE txid=\"${txid}\"")
|
local tx=$(sql "SELECT id FROM tx WHERE txid=\"${txid}\"")
|
||||||
local id_inserted
|
local id_inserted
|
||||||
local tx_raw_details=$(get_rawtransaction ${txid})
|
local tx_raw_details=$(get_rawtransaction ${txid})
|
||||||
local tx_nb_conf=$(echo "${tx_details}" | jq '.result.confirmations')
|
local tx_nb_conf=$(echo "${tx_details}" | jq -r '.result.confirmations // 0')
|
||||||
|
|
||||||
# Sometimes raw tx are too long to be passed as paramater, so let's write
|
# Sometimes raw tx are too long to be passed as paramater, so let's write
|
||||||
# it to a temp file for it to be read by sqlite3 and then delete the file
|
# it to a temp file for it to be read by sqlite3 and then delete the file
|
||||||
@@ -137,45 +136,62 @@ confirmation() {
|
|||||||
rm rawtx-${txid}.blob
|
rm rawtx-${txid}.blob
|
||||||
|
|
||||||
########################################################################################################
|
########################################################################################################
|
||||||
# Let's now insert in the join table if not already done
|
|
||||||
|
local event_message
|
||||||
|
local watching_id
|
||||||
|
|
||||||
|
# Let's see if we need to insert tx in the join table
|
||||||
tx=$(sql "SELECT tx_id FROM watching_tx WHERE tx_id=\"${tx}\"")
|
tx=$(sql "SELECT tx_id FROM watching_tx WHERE tx_id=\"${tx}\"")
|
||||||
|
|
||||||
if [ -z "${tx}" ]; then
|
|
||||||
trace "[confirmation] For this tx, there's no watching_tx row, let's create it"
|
|
||||||
local watching_id
|
|
||||||
|
|
||||||
# If the tx is batched and pays multiple watched addresses, we have to insert
|
|
||||||
# those additional addresses in watching_tx!
|
|
||||||
for row in ${rows}
|
|
||||||
do
|
|
||||||
watching_id=$(echo "${row}" | cut -d '|' -f1)
|
|
||||||
address=$(echo "${row}" | cut -d '|' -f2)
|
|
||||||
# In the case of us spending to a watched address, the address appears twice in the details,
|
|
||||||
# once on the spend side (negative amount) and once on the receiving side (positive amount)
|
|
||||||
tx_vout_n=$(echo "${tx_details}" | jq ".result.details | map(select(.address==\"${address}\"))[0] | .vout")
|
|
||||||
tx_vout_amount=$(echo "${tx_details}" | jq ".result.details | map(select(.address==\"${address}\"))[0] | .amount | fabs" | awk '{ printf "%.8f", $0 }')
|
|
||||||
sql "INSERT OR IGNORE INTO watching_tx (watching_id, tx_id, vout, amount) VALUES (${watching_id}, ${id_inserted}, ${tx_vout_n}, ${tx_vout_amount})"
|
|
||||||
trace_rc $?
|
|
||||||
done
|
|
||||||
else
|
|
||||||
trace "[confirmation] For this tx, there's already watching_tx rows"
|
|
||||||
fi
|
|
||||||
########################################################################################################
|
|
||||||
|
|
||||||
########################################################################################################
|
|
||||||
# Let's now grow the watch window in the case of a xpub watcher...
|
|
||||||
trace "[confirmation] Let's now grow the watch window in the case of a xpub watcher"
|
|
||||||
|
|
||||||
for row in ${rows}
|
for row in ${rows}
|
||||||
do
|
do
|
||||||
|
|
||||||
|
address=$(echo "${row}" | cut -d '|' -f2)
|
||||||
|
tx_vout_amount=$(echo "${tx_details}" | jq ".result.details | map(select(.address==\"${address}\"))[0] | .amount | fabs" | awk '{ printf "%.8f", $0 }')
|
||||||
|
# In the case of us spending to a watched address, the address appears twice in the details,
|
||||||
|
# once on the spend side (negative amount) and once on the receiving side (positive amount)
|
||||||
|
tx_vout_n=$(echo "${tx_details}" | jq ".result.details | map(select(.address==\"${address}\"))[0] | .vout")
|
||||||
|
|
||||||
|
########################################################################################################
|
||||||
|
# Let's now insert in the join table if not already done
|
||||||
|
if [ -z "${tx}" ]; then
|
||||||
|
trace "[confirmation] For this tx, there's no watching_tx row, let's create it"
|
||||||
|
|
||||||
|
# If the tx is batched and pays multiple watched addresses, we have to insert
|
||||||
|
# those additional addresses in watching_tx!
|
||||||
|
watching_id=$(echo "${row}" | cut -d '|' -f1)
|
||||||
|
sql "INSERT OR IGNORE INTO watching_tx (watching_id, tx_id, vout, amount) VALUES (${watching_id}, ${id_inserted}, ${tx_vout_n}, ${tx_vout_amount})"
|
||||||
|
trace_rc $?
|
||||||
|
else
|
||||||
|
trace "[confirmation] For this tx, there's already watching_tx rows"
|
||||||
|
fi
|
||||||
|
########################################################################################################
|
||||||
|
|
||||||
|
########################################################################################################
|
||||||
|
# Let's now grow the watch window in the case of a xpub watcher...
|
||||||
watching_by_pub32_id=$(echo "${row}" | cut -d '|' -f3)
|
watching_by_pub32_id=$(echo "${row}" | cut -d '|' -f3)
|
||||||
pub32_index=$(echo "${row}" | cut -d '|' -f4)
|
|
||||||
if [ -n "${watching_by_pub32_id}" ]; then
|
if [ -n "${watching_by_pub32_id}" ]; then
|
||||||
|
trace "[confirmation] Let's now grow the watch window in the case of a xpub watcher"
|
||||||
|
|
||||||
|
pub32_index=$(echo "${row}" | cut -d '|' -f4)
|
||||||
extend_watchers ${watching_by_pub32_id} ${pub32_index}
|
extend_watchers ${watching_by_pub32_id} ${pub32_index}
|
||||||
fi
|
fi
|
||||||
done
|
########################################################################################################
|
||||||
|
|
||||||
########################################################################################################
|
########################################################################################################
|
||||||
|
# Let's publish the event if needed
|
||||||
|
event_message=$(echo "${row}" | cut -d '|' -f5)
|
||||||
|
if [ -n "${event_message}" ]; then
|
||||||
|
# There's an event message, let's publish it!
|
||||||
|
|
||||||
|
trace "[confirmation] mosquitto_pub -h broker -t tx_confirmation -m \"{\"txid\":\"${txid}\",\"address\":\"${address}\",\"vout_n\":${tx_vout_n},\"amount\":${tx_vout_amount},\"confirmations\":${tx_nb_conf},\"eventMessage\":\"${event_message}\"}\""
|
||||||
|
response=$(mosquitto_pub -h broker -t tx_confirmation -m "{\"txid\":\"${txid}\",\"address\":\"${address}\",\"vout_n\":${tx_vout_n},\"amount\":${tx_vout_amount},\"confirmations\":${tx_nb_conf},\"eventMessage\":\"${event_message}\"}")
|
||||||
|
returncode=$?
|
||||||
|
trace_rc ${returncode}
|
||||||
|
fi
|
||||||
|
########################################################################################################
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
) 201>./.confirmation.lock
|
) 201>./.confirmation.lock
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,64 @@
|
|||||||
. ./trace.sh
|
. ./trace.sh
|
||||||
. ./sql.sh
|
. ./sql.sh
|
||||||
|
|
||||||
|
get_txns_by_watchlabel(){
|
||||||
|
trace "Entering get_txns_by_watchlabel() for label ${1}..."
|
||||||
|
local label_txns
|
||||||
|
query=$(cat <<-HERE
|
||||||
|
SELECT w32.label, w.address, tx.txid, tx.confirmations,tx.blockheight, wtxn.vout, wtxn.amount, tx.blockhash, tx.blocktime, tx.timereceived
|
||||||
|
FROM watching_by_pub32 as w32
|
||||||
|
INNER JOIN watching AS w ON w32.id = w.watching_by_pub32_id
|
||||||
|
INNER JOIN watching_tx AS wtxn ON w.id = wtxn.watching_id
|
||||||
|
INNER JOIN tx AS tx ON wtxn.tx_id = tx.id
|
||||||
|
WHERE w32.label="$1"
|
||||||
|
LIMIT 0,${2-10}
|
||||||
|
HERE
|
||||||
|
)
|
||||||
|
label_txns=$(sql "$query")
|
||||||
|
returncode=$?
|
||||||
|
trace_rc ${returncode}
|
||||||
|
label_txns_json=$(echo "$label_txns" | jq -Rcsn '
|
||||||
|
{"label_txns":
|
||||||
|
[inputs
|
||||||
|
| . / "\n"
|
||||||
|
| (.[] | select(length > 0) | . / "|") as $input
|
||||||
|
| {"label": $input[0], "address": $input[1], "txid": $input[2], "confirmations": $input[3], "blockheight": $input[4], "v_out": $input[5], "amount": $input[6], "blockhash": $input[7], "blocktime": $input[8], "timereceived": $input[9]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
')
|
||||||
|
echo "$label_txns_json"
|
||||||
|
return ${returncode}
|
||||||
|
}
|
||||||
|
get_unused_addresses_by_watchlabel(){
|
||||||
|
trace "Entering get_unused_addresses_by_watchlabel() for label ${1}..."
|
||||||
|
local label_unused_addrs
|
||||||
|
query=$(cat <<-HERE
|
||||||
|
SELECT w32.id, w32.label, w32.pub32, w.pub32_index, w.address
|
||||||
|
FROM watching as w
|
||||||
|
INNER JOIN watching_by_pub32 AS w32 ON w.watching_by_pub32_id = w32.id
|
||||||
|
WHERE w32.label="$1"
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM watching_tx WHERE watching_id = w.id
|
||||||
|
)
|
||||||
|
ORDER BY w.pub32_index ASC
|
||||||
|
LIMIT 0,${2-10}
|
||||||
|
HERE
|
||||||
|
)
|
||||||
|
label_unused_addrs=$(sql "$query")
|
||||||
|
returncode=$?
|
||||||
|
trace_rc ${returncode}
|
||||||
|
label_unused_addrs_json=$(echo "$label_unused_addrs" | jq -Rcsn '
|
||||||
|
{"label_unused_addresses":
|
||||||
|
[inputs
|
||||||
|
| . / "\n"
|
||||||
|
| (.[] | select(length > 0) | . / "|") as $input
|
||||||
|
| {"pub32_watch_id": $input[0], "pub32_label": $input[1], "pub32" : $input[2], "address_pub32_index": $input[3], "address": $input[4]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
')
|
||||||
|
echo "$label_unused_addrs_json"
|
||||||
|
return ${returncode}
|
||||||
|
}
|
||||||
getactivewatches() {
|
getactivewatches() {
|
||||||
trace "Entering getactivewatches()..."
|
trace "Entering getactivewatches()..."
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
. ./trace.sh
|
. ./trace.sh
|
||||||
. ./callbacks_txid.sh
|
. ./callbacks_txid.sh
|
||||||
|
. ./blockchainrpc.sh
|
||||||
|
|
||||||
newblock() {
|
newblock() {
|
||||||
trace "Entering newblock()..."
|
trace "Entering newblock()..."
|
||||||
@@ -9,5 +10,16 @@ newblock() {
|
|||||||
local request=${1}
|
local request=${1}
|
||||||
local blockhash=$(echo "${request}" | cut -d ' ' -f2 | cut -d '/' -f3)
|
local blockhash=$(echo "${request}" | cut -d ' ' -f2 | cut -d '/' -f3)
|
||||||
|
|
||||||
|
local blockinfo
|
||||||
|
blockinfo=$(get_block_info ${blockhash})
|
||||||
|
|
||||||
|
local blockheight
|
||||||
|
blockheight=$(echo ${blockinfo} | jq -r ".result.height")
|
||||||
|
|
||||||
|
trace "[newblock] mosquitto_pub -h broker -t newblock -m \"{\"blockhash\":\"${blockhash}\",\"blockheight\":\"${blockheight}\"}\""
|
||||||
|
response=$(mosquitto_pub -h broker -t newblock -m "{\"blockhash\":\"${blockhash}\",\"blockheight\":\"${blockheight}\"}")
|
||||||
|
returncode=$?
|
||||||
|
trace_rc ${returncode}
|
||||||
|
|
||||||
do_callbacks_txid
|
do_callbacks_txid
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ main() {
|
|||||||
watch)
|
watch)
|
||||||
# POST http://192.168.111.152:8080/watch
|
# POST http://192.168.111.152:8080/watch
|
||||||
# BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","unconfirmedCallbackURL":"192.168.111.233:1111/callback0conf","confirmedCallbackURL":"192.168.111.233:1111/callback1conf"}
|
# BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","unconfirmedCallbackURL":"192.168.111.233:1111/callback0conf","confirmedCallbackURL":"192.168.111.233:1111/callback1conf"}
|
||||||
|
# BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","confirmedCallbackURL":"192.168.111.233:1111/callback1conf","eventMessage":"eyJib3VuY2VfYWRkcmVzcyI6IjJNdkEzeHIzOHIxNXRRZWhGblBKMVhBdXJDUFR2ZTZOamNGIiwibmJfY29uZiI6MH0K"}
|
||||||
|
|
||||||
response=$(watchrequest "${line}")
|
response=$(watchrequest "${line}")
|
||||||
response_to_client "${response}" ${?}
|
response_to_client "${response}" ${?}
|
||||||
@@ -161,6 +162,18 @@ main() {
|
|||||||
response_to_client "${response}" ${?}
|
response_to_client "${response}" ${?}
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
|
get_txns_by_watchlabel)
|
||||||
|
# curl (GET) 192.168.111.152:8080/get_txns_by_watchlabel/<label>/<count>
|
||||||
|
response=$(get_txns_by_watchlabel $(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3) $(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f4))
|
||||||
|
response_to_client "${response}" ${?}
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
get_unused_addresses_by_watchlabel)
|
||||||
|
# curl (GET) 192.168.111.152:8080/get_unused_addresses_by_watchlabel/<label>/<count>
|
||||||
|
response=$(get_unused_addresses_by_watchlabel $(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3) $(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f4))
|
||||||
|
response_to_client "${response}" ${?}
|
||||||
|
break
|
||||||
|
;;
|
||||||
conf)
|
conf)
|
||||||
# curl (GET) 192.168.111.152:8080/conf/b081ca7724386f549cf0c16f71db6affeb52ff7a0d9b606fb2e5c43faffd3387
|
# curl (GET) 192.168.111.152:8080/conf/b081ca7724386f549cf0c16f71db6affeb52ff7a0d9b606fb2e5c43faffd3387
|
||||||
|
|
||||||
@@ -225,6 +238,13 @@ main() {
|
|||||||
response_to_client "${response}" ${?}
|
response_to_client "${response}" ${?}
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
|
get_txns_spending)
|
||||||
|
# curl (GET) http://192.168.111.152:8080/get_txns_spending/20/10
|
||||||
|
|
||||||
|
response=$(get_txns_spending $(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3) $(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f4))
|
||||||
|
response_to_client "${response}" ${?}
|
||||||
|
break
|
||||||
|
;;
|
||||||
getbalance)
|
getbalance)
|
||||||
# curl (GET) http://192.168.111.152:8080/getbalance
|
# curl (GET) http://192.168.111.152:8080/getbalance
|
||||||
|
|
||||||
@@ -263,7 +283,7 @@ main() {
|
|||||||
;;
|
;;
|
||||||
spend)
|
spend)
|
||||||
# POST http://192.168.111.152:8080/spend
|
# POST http://192.168.111.152:8080/spend
|
||||||
# BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","amount":0.00233}
|
# BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","amount":0.00233,"eventMessage":"eyJ3aGF0ZXZlciI6MTIzfQo="}
|
||||||
|
|
||||||
response=$(spend "${line}")
|
response=$(spend "${line}")
|
||||||
response_to_client "${response}" ${?}
|
response_to_client "${response}" ${?}
|
||||||
|
|||||||
@@ -4,18 +4,18 @@
|
|||||||
|
|
||||||
send_to_watcher_node() {
|
send_to_watcher_node() {
|
||||||
trace "Entering send_to_watcher_node()..."
|
trace "Entering send_to_watcher_node()..."
|
||||||
send_to_bitcoin_node ${WATCHER_NODE_RPC_URL}/${WATCHER_BTC_NODE_DEFAULT_WALLET} ${WATCHER_NODE_RPC_CFG} $@
|
local node_payload
|
||||||
|
node_payload="$(send_to_bitcoin_node ${WATCHER_NODE_RPC_URL}/${WATCHER_BTC_NODE_DEFAULT_WALLET} ${WATCHER_NODE_RPC_CFG} $@)"
|
||||||
local returncode=$?
|
local returncode=$?
|
||||||
trace_rc ${returncode}
|
trace_rc ${returncode}
|
||||||
|
|
||||||
if [ "${returncode}" -ne 0 ]; then
|
if [ "${returncode}" -ne 0 ]; then
|
||||||
# Ok, since we now have multiple watching wallets, we need to try them all if it fails
|
# Ok, since we now have multiple watching wallets, we need to try them all if it fails
|
||||||
# We have 2 right now: watching and watching-for-xpubs
|
# We have 2 right now: watching and watching-for-xpubs
|
||||||
send_to_watcher_node_wallet ${WATCHER_BTC_NODE_XPUB_WALLET} $@
|
node_payload="$(send_to_watcher_node_wallet ${WATCHER_BTC_NODE_XPUB_WALLET} $@)"
|
||||||
returncode=$?
|
returncode=$?
|
||||||
trace_rc ${returncode}
|
trace_rc ${returncode}
|
||||||
fi
|
fi
|
||||||
|
echo "$node_payload"
|
||||||
return ${returncode}
|
return ${returncode}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ ln_waitanyinvoice() {
|
|||||||
paid_at=$(echo "${result}" | jq -r ".paid_at")
|
paid_at=$(echo "${result}" | jq -r ".paid_at")
|
||||||
|
|
||||||
sql "UPDATE ln_invoice SET status=\"${status}\", pay_index=${pay_index}, msatoshi_received=${msatoshi_received}, paid_at=${paid_at} WHERE bolt11=\"${bolt11}\""
|
sql "UPDATE ln_invoice SET status=\"${status}\", pay_index=${pay_index}, msatoshi_received=${msatoshi_received}, paid_at=${paid_at} WHERE bolt11=\"${bolt11}\""
|
||||||
row=$(sql "SELECT id, label, bolt11, callback_url, payment_hash, msatoshi, status, pay_index, msatoshi_received, paid_at, description, expires_at FROM ln_invoice WHERE NOT calledback AND bolt11=\"${bolt11}\"")
|
row=$(sql "SELECT id, label, bolt11, callback_url, payment_hash, msatoshi, status, pay_index, msatoshi_received, paid_at, description, expires_at FROM ln_invoice WHERE callback_url<>\"\" AND NOT calledback AND bolt11=\"${bolt11}\"")
|
||||||
|
|
||||||
if [ -n "${row}" ]; then
|
if [ -n "${row}" ]; then
|
||||||
ln_manage_callback ${row}
|
ln_manage_callback ${row}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ spend() {
|
|||||||
local request=${1}
|
local request=${1}
|
||||||
local address=$(echo "${request}" | jq -r ".address")
|
local address=$(echo "${request}" | jq -r ".address")
|
||||||
trace "[spend] address=${address}"
|
trace "[spend] address=${address}"
|
||||||
local amount=$(echo "${request}" | jq ".amount" | awk '{ printf "%.8f", $0 }')
|
local amount=$(echo "${request}" | jq -r ".amount" | awk '{ printf "%.8f", $0 }')
|
||||||
trace "[spend] amount=${amount}"
|
trace "[spend] amount=${amount}"
|
||||||
local response
|
local response
|
||||||
local id_inserted
|
local id_inserted
|
||||||
@@ -39,10 +39,30 @@ spend() {
|
|||||||
local tx_replaceable=$(echo "${tx_details}" | jq '.result."bip125-replaceable"')
|
local tx_replaceable=$(echo "${tx_details}" | jq '.result."bip125-replaceable"')
|
||||||
tx_replaceable=$([ ${tx_replaceable} = "yes" ] && echo 1 || echo 0)
|
tx_replaceable=$([ ${tx_replaceable} = "yes" ] && echo 1 || echo 0)
|
||||||
local fees=$(echo "${tx_details}" | jq '.result.fee | fabs' | awk '{ printf "%.8f", $0 }')
|
local fees=$(echo "${tx_details}" | jq '.result.fee | fabs' | awk '{ printf "%.8f", $0 }')
|
||||||
local rawtx=$(echo "${tx_details}" | jq '.result.hex')
|
# Sometimes raw tx are too long to be passed as paramater, so let's write
|
||||||
|
# it to a temp file for it to be read by sqlite3 and then delete the file
|
||||||
|
echo "${tx_raw_details}" > rawtx-${txid}.blob
|
||||||
|
|
||||||
|
########################################################################################################
|
||||||
|
# Let's publish the event if needed
|
||||||
|
local event_message
|
||||||
|
event_message=$(echo "${request}" | jq -er ".eventMessage")
|
||||||
|
if [ "$?" -ne "0" ]; then
|
||||||
|
# event_message tag null, so there's no event_message
|
||||||
|
trace "[spend] event_message="
|
||||||
|
event_message=
|
||||||
|
else
|
||||||
|
# There's an event message, let's publish it!
|
||||||
|
|
||||||
|
trace "[spend] mosquitto_pub -h broker -t spend -m \"{\"txid\":\"${txid}\",\"address\":\"${address}\",\"amount\":${tx_amount},\"eventMessage\":\"${event_message}\"}\""
|
||||||
|
response=$(mosquitto_pub -h broker -t spend -m "{\"txid\":\"${txid}\",\"address\":\"${address}\",\"amount\":${tx_amount},\"eventMessage\":\"${event_message}\"}")
|
||||||
|
returncode=$?
|
||||||
|
trace_rc ${returncode}
|
||||||
|
fi
|
||||||
|
########################################################################################################
|
||||||
|
|
||||||
# Let's insert the txid in our little DB -- then we'll already have it when receiving confirmation
|
# Let's insert the txid in our little DB -- then we'll already have it when receiving confirmation
|
||||||
sql "INSERT OR IGNORE INTO tx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, raw_tx) VALUES (\"${txid}\", ${tx_hash}, 0, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${rawtx})"
|
sql "INSERT OR IGNORE INTO tx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, raw_tx) VALUES (\"${txid}\", ${tx_hash}, 0, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, readfile('rawtx-${txid}.blob'))"
|
||||||
trace_rc $?
|
trace_rc $?
|
||||||
id_inserted=$(sql "SELECT id FROM tx WHERE txid=\"${txid}\"")
|
id_inserted=$(sql "SELECT id FROM tx WHERE txid=\"${txid}\"")
|
||||||
trace_rc $?
|
trace_rc $?
|
||||||
@@ -51,6 +71,9 @@ spend() {
|
|||||||
|
|
||||||
data="{\"status\":\"accepted\""
|
data="{\"status\":\"accepted\""
|
||||||
data="${data},\"hash\":\"${txid}\"}"
|
data="${data},\"hash\":\"${txid}\"}"
|
||||||
|
|
||||||
|
# Delete the temp file containing the raw tx (see above)
|
||||||
|
rm rawtx-${txid}.blob
|
||||||
else
|
else
|
||||||
local message=$(echo "${response}" | jq -e ".error.message")
|
local message=$(echo "${response}" | jq -e ".error.message")
|
||||||
data="{\"message\":${message}}"
|
data="{\"message\":${message}}"
|
||||||
@@ -100,6 +123,32 @@ bumpfee() {
|
|||||||
return ${returncode}
|
return ${returncode}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_txns_spending() {
|
||||||
|
trace "Entering get_txns_spending()... with count: $1 , skip: $2"
|
||||||
|
local count="$1"
|
||||||
|
local skip="$2"
|
||||||
|
local response
|
||||||
|
local data="{\"method\":\"listtransactions\",\"params\":[\"*\",${count:-10},${skip:-0}]}"
|
||||||
|
response=$(send_to_spender_node "${data}")
|
||||||
|
local returncode=$?
|
||||||
|
trace_rc ${returncode}
|
||||||
|
trace "[get_txns_spending] response=${response}"
|
||||||
|
|
||||||
|
if [ "${returncode}" -eq 0 ]; then
|
||||||
|
local txns=$(echo ${response} | jq -rc ".result")
|
||||||
|
trace "[get_txns_spending] txns=${txns}"
|
||||||
|
|
||||||
|
data="{\"txns\":${txns}}"
|
||||||
|
else
|
||||||
|
trace "[get_txns_spending] Coudn't get txns!"
|
||||||
|
data=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
trace "[get_txns_spending] responding=${data}"
|
||||||
|
echo "${data}"
|
||||||
|
|
||||||
|
return ${returncode}
|
||||||
|
}
|
||||||
getbalance() {
|
getbalance() {
|
||||||
trace "Entering getbalance()..."
|
trace "Entering getbalance()..."
|
||||||
|
|
||||||
@@ -185,24 +234,22 @@ getbalancebyxpub() {
|
|||||||
local returncode
|
local returncode
|
||||||
|
|
||||||
# addresses=$(./bitcoin-cli -rpcwallet=xpubwatching01.dat getaddressesbylabel upub5GtUcgGed1aGH4HKQ3vMYrsmLXwmHhS1AeX33ZvDgZiyvkGhNTvGd2TA5Lr4v239Fzjj4ZY48t6wTtXUy2yRgapf37QHgt6KWEZ6bgsCLpb | jq "keys" | tr -d '\n ')
|
# addresses=$(./bitcoin-cli -rpcwallet=xpubwatching01.dat getaddressesbylabel upub5GtUcgGed1aGH4HKQ3vMYrsmLXwmHhS1AeX33ZvDgZiyvkGhNTvGd2TA5Lr4v239Fzjj4ZY48t6wTtXUy2yRgapf37QHgt6KWEZ6bgsCLpb | jq "keys" | tr -d '\n ')
|
||||||
data="{\"method\":\"getaddressesbylabel\",\"params\":[${xpub}]}"
|
data="{\"method\":\"getaddressesbylabel\",\"params\":[\"${xpub}\"]}"
|
||||||
trace "[getbalancebyxpub] data=${data}"
|
trace "[getbalancebyxpub] data=${data}"
|
||||||
addresses=$(send_to_xpub_watcher_wallet ${data} | jq "keys" | tr -d '\n ')
|
addresses=$(send_to_xpub_watcher_wallet ${data} | jq ".result | keys" | tr -d '\n ')
|
||||||
|
|
||||||
# ./bitcoin-cli -rpcwallet=xpubwatching01.dat listunspent 0 9999999 "$addresses" | jq "[.[].amount] | add"
|
# ./bitcoin-cli -rpcwallet=xpubwatching01.dat listunspent 0 9999999 "$addresses" | jq "[.[].amount] | add"
|
||||||
|
data="{\"method\":\"listunspent\",\"params\":[0,9999999,${addresses}]}"
|
||||||
data="{\"method\":\"listunspent\",\"params\":[0, 9999999, \"${addresses}\"]}"
|
|
||||||
trace "[getbalancebyxpub] data=${data}"
|
trace "[getbalancebyxpub] data=${data}"
|
||||||
balance=$(send_to_xpub_watcher_wallet ${data} | jq "[.[].amount] | add | . * 100000000 | trunc | . / 100000000")
|
balance=$(send_to_xpub_watcher_wallet ${data} | jq "[.result[].amount // 0 ] | add | . * 100000000 | trunc | . / 100000000")
|
||||||
returncode=$?
|
returncode=$?
|
||||||
trace_rc ${returncode}
|
trace_rc ${returncode}
|
||||||
trace "[getbalancebyxpub] balance=${balance}"
|
trace "[getbalancebyxpub] balance=${balance}"
|
||||||
|
|
||||||
data="{\"event\":\"${event}\",\"xpub\":\"${xpub}\",\"balance\":${balance}}"
|
data="{\"event\":\"${event}\",\"xpub\":\"${xpub}\",\"balance\":${balance:-0}}"
|
||||||
|
|
||||||
echo "${data}"
|
echo "${data}"
|
||||||
|
|
||||||
return ${returncode}
|
return "${returncode}"
|
||||||
}
|
}
|
||||||
|
|
||||||
getnewaddress() {
|
getnewaddress() {
|
||||||
@@ -315,10 +362,12 @@ batchspend() {
|
|||||||
local tx_replaceable=$(echo "${tx_details}" | jq '.result."bip125-replaceable"')
|
local tx_replaceable=$(echo "${tx_details}" | jq '.result."bip125-replaceable"')
|
||||||
tx_replaceable=$([ ${tx_replaceable} = "yes" ] && echo 1 || echo 0)
|
tx_replaceable=$([ ${tx_replaceable} = "yes" ] && echo 1 || echo 0)
|
||||||
local fees=$(echo "${tx_details}" | jq '.result.fee | fabs' | awk '{ printf "%.8f", $0 }')
|
local fees=$(echo "${tx_details}" | jq '.result.fee | fabs' | awk '{ printf "%.8f", $0 }')
|
||||||
local rawtx=$(echo "${tx_details}" | jq '.result.hex')
|
# Sometimes raw tx are too long to be passed as paramater, so let's write
|
||||||
|
# it to a temp file for it to be read by sqlite3 and then delete the file
|
||||||
|
echo "${tx_raw_details}" > rawtx-${txid}.blob
|
||||||
|
|
||||||
# Let's insert the txid in our little DB -- then we'll already have it when receiving confirmation
|
# Let's insert the txid in our little DB -- then we'll already have it when receiving confirmation
|
||||||
sql "INSERT OR IGNORE INTO tx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, raw_tx) VALUES (\"${txid}\", ${tx_hash}, 0, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${rawtx})"
|
sql "INSERT OR IGNORE INTO tx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, raw_tx) VALUES (\"${txid}\", ${tx_hash}, 0, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, readfile('rawtx-${txid}.blob'))"
|
||||||
returncode=$?
|
returncode=$?
|
||||||
trace_rc ${returncode}
|
trace_rc ${returncode}
|
||||||
if [ "${returncode}" -eq 0 ]; then
|
if [ "${returncode}" -eq 0 ]; then
|
||||||
@@ -330,6 +379,9 @@ batchspend() {
|
|||||||
|
|
||||||
data="{\"status\":\"accepted\""
|
data="{\"status\":\"accepted\""
|
||||||
data="${data},\"hash\":\"${txid}\"}"
|
data="${data},\"hash\":\"${txid}\"}"
|
||||||
|
|
||||||
|
# Delete the temp file containing the raw tx (see above)
|
||||||
|
rm rawtx-${txid}.blob
|
||||||
else
|
else
|
||||||
local message=$(echo "${response}" | jq -e ".error.message")
|
local message=$(echo "${response}" | jq -e ".error.message")
|
||||||
data="{\"message\":${message}}"
|
data="{\"message\":${message}}"
|
||||||
|
|||||||
@@ -11,14 +11,33 @@ watchrequest() {
|
|||||||
|
|
||||||
local returncode
|
local returncode
|
||||||
local request=${1}
|
local request=${1}
|
||||||
local address=$(echo "${request}" | jq -r ".address")
|
local address=$(echo "${request}" | jq -er ".address")
|
||||||
local cb0conf_url=$(echo "${request}" | jq -r ".unconfirmedCallbackURL")
|
local cb0conf_url
|
||||||
local cb1conf_url=$(echo "${request}" | jq -r ".confirmedCallbackURL")
|
cb0conf_url=$(echo "${request}" | jq -er ".unconfirmedCallbackURL")
|
||||||
|
if [ "$?" -ne "0" ]; then
|
||||||
|
# unconfirmedCallbackURL tag null, so there's no unconfirmedCallbackURL
|
||||||
|
trace "[watchrequest] unconfirmedCallbackURL="
|
||||||
|
unconfirmedCallbackURL=
|
||||||
|
fi
|
||||||
|
local cb1conf_url
|
||||||
|
cb1conf_url=$(echo "${request}" | jq -er ".confirmedCallbackURL")
|
||||||
|
if [ "$?" -ne "0" ]; then
|
||||||
|
# confirmedCallbackURL tag null, so there's no confirmedCallbackURL
|
||||||
|
trace "[watchrequest] confirmedCallbackURL="
|
||||||
|
confirmedCallbackURL=
|
||||||
|
fi
|
||||||
|
local event_message
|
||||||
|
event_message=$(echo "${request}" | jq -er ".eventMessage")
|
||||||
|
if [ "$?" -ne "0" ]; then
|
||||||
|
# event_message tag null, so there's no event_message
|
||||||
|
trace "[watchrequest] event_message="
|
||||||
|
event_message=
|
||||||
|
fi
|
||||||
local imported
|
local imported
|
||||||
local inserted
|
local inserted
|
||||||
local id_inserted
|
local id_inserted
|
||||||
local result
|
local result
|
||||||
trace "[watchrequest] Watch request on address (${address}), cb 0-conf (${cb0conf_url}), cb 1-conf (${cb1conf_url})"
|
trace "[watchrequest] Watch request on address (${address}), cb 0-conf (${cb0conf_url}), cb 1-conf (${cb1conf_url}) with event_message=${event_message}"
|
||||||
|
|
||||||
result=$(importaddress_rpc "${address}")
|
result=$(importaddress_rpc "${address}")
|
||||||
returncode=$?
|
returncode=$?
|
||||||
@@ -29,7 +48,7 @@ watchrequest() {
|
|||||||
imported=0
|
imported=0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sql "INSERT OR REPLACE INTO watching (address, watching, callback0conf, callback1conf, imported) VALUES (\"${address}\", 1, \"${cb0conf_url}\", \"${cb1conf_url}\", ${imported})"
|
sql "INSERT OR REPLACE INTO watching (address, watching, callback0conf, callback1conf, imported, event_message) VALUES (\"${address}\", 1, \"${cb0conf_url}\", \"${cb1conf_url}\", ${imported}, '${event_message}')"
|
||||||
returncode=$?
|
returncode=$?
|
||||||
trace_rc ${returncode}
|
trace_rc ${returncode}
|
||||||
if [ "${returncode}" -eq 0 ]; then
|
if [ "${returncode}" -eq 0 ]; then
|
||||||
@@ -63,7 +82,8 @@ watchrequest() {
|
|||||||
\"estimatesmartfee2blocks\":\"${fees2blocks}\",
|
\"estimatesmartfee2blocks\":\"${fees2blocks}\",
|
||||||
\"estimatesmartfee6blocks\":\"${fees6blocks}\",
|
\"estimatesmartfee6blocks\":\"${fees6blocks}\",
|
||||||
\"estimatesmartfee36blocks\":\"${fees36blocks}\",
|
\"estimatesmartfee36blocks\":\"${fees36blocks}\",
|
||||||
\"estimatesmartfee144blocks\":\"${fees144blocks}\"}"
|
\"estimatesmartfee144blocks\":\"${fees144blocks}\",
|
||||||
|
\"eventMessage\":\"${event_message}\"}"
|
||||||
trace "[watchrequest] responding=${data}"
|
trace "[watchrequest] responding=${data}"
|
||||||
|
|
||||||
echo "${data}"
|
echo "${data}"
|
||||||
|
|||||||
Reference in New Issue
Block a user