mirror of
https://github.com/aljazceru/cyphernode.git
synced 2025-12-17 04:35:14 +01:00
Migrated to postgres and added pub32 tests
This commit is contained in:
@@ -17,6 +17,9 @@
|
||||
"gatekeeper_edit_apiproperties": "If you know what you are doing, it is possible to manually edit the API endpoints/groups authorization. (Not recommended)",
|
||||
"gatekeeper_apiproperties": "You are about to edit the api.properties file. The format of the file is pretty simple: for each action, you will find what access group can access it. <font color='# 0000ff'>Admin</font> group can do what <font color='# 0000ff'>Spender</font> group can, and <font color='# 0000ff'>Spender</font> group can do what <font color='# 0000ff'>Watcher</font> group can. <font color='# 0000ff'>Internal</font> group is for the endpoints accessible only within the Docker network, like the backoffice tasks used by the Cron container. The access groups for each API id/key are found in the <font color='# 0000ff'>keys.properties</font> file.",
|
||||
"gatekeeper_cns": "I use <font underline='true'>domain names</font> and/or <font underline='true'>IP addresses</font> to create valid TLS certificates. For example, if <font color='# 0000ff'>https://cyphernodehost/getbestblockhash</font> and <font color='# 0000ff'>https://192.168.7.44/getbestblockhash</font> will be used, enter <font color='# 0000ff'>cyphernodehost, 192.168.7.44</font> as a possible domains. <font color='# 0000ff'>127.0.0.1, localhost, gatekeeper</font> will be automatically added to your list. Make sure the provided domain names are in your DNS or client's hosts file and is reachable.",
|
||||
"postgres_datapath": "The Cyphernode's Postgres files will be stored in a container's mounted directory. Please provide the <font underline='true'>local mounted path</font> to that directory. <font color='#ff0000'>If running on OSX, check mountable directories in Docker's File Sharing configs.</font>",
|
||||
"postgres_datapath_custom": "Provide the <font underline='true'>full path name</font> where Postgres files will be saved.",
|
||||
"postgres_password": "PostgreSQL cyphernode's <font underline='true'>password</font> used by Cyphernode when calling the database.",
|
||||
"logs_datapath": "The Cyphernode's log files will be stored in a container's mounted directory. Please provide the <font underline='true'>local mounted path</font> to that directory. <font color='#ff0000'>If running on OSX, check mountable directories in Docker's File Sharing configs.</font>",
|
||||
"logs_datapath_custom": "Provide the <font underline='true'>full path name</font> where Cyphernodes log files will be saved.",
|
||||
"traefik_datapath": "The Traefik's files will be stored in a container's mounted directory. Please provide the <font underline='true'>local mounted path</font> to that directory. <font color='#ff0000'>If running on OSX, check mountable directories in Docker's File Sharing configs.</font>",
|
||||
|
||||
@@ -87,6 +87,7 @@ module.exports = class App {
|
||||
proxy_version: process.env.PROXY_VERSION,
|
||||
proxycron_version: process.env.PROXYCRON_VERSION,
|
||||
pycoin_version: process.env.PYCOIN_VERSION,
|
||||
postgres_version: process.env.POSTGRES_VERSION,
|
||||
traefik_version: process.env.TRAEFIK_VERSION,
|
||||
mosquitto_version: process.env.MOSQUITTO_VERSION,
|
||||
otsclient_version: process.env.OTSCLIENT_VERSION,
|
||||
@@ -148,6 +149,7 @@ module.exports = class App {
|
||||
'cyphernode/proxy': this.sessionData.proxy_version,
|
||||
'cyphernode/proxycron': this.sessionData.proxycron_version,
|
||||
'cyphernode/pycoin': this.sessionData.pycoin_version,
|
||||
'cyphernode/postgres': this.sessionData.postgres_version,
|
||||
'cyphernode/otsclient': this.sessionData.otsclient_version,
|
||||
'traefik': this.sessionData.traefik_version,
|
||||
'cyphernode/clightning': this.sessionData.lightning_version,
|
||||
@@ -359,6 +361,7 @@ module.exports = class App {
|
||||
|
||||
const pathProps = [
|
||||
'gatekeeper_datapath',
|
||||
'postgres_datapath',
|
||||
'logs_datapath',
|
||||
'traefik_datapath',
|
||||
'tor_datapath',
|
||||
@@ -483,6 +486,13 @@ module.exports = class App {
|
||||
networks: ['cyphernodenet'],
|
||||
docker: 'cyphernode/pycoin:'+this.config.docker_versions['cyphernode/pycoin']
|
||||
},
|
||||
{
|
||||
name: 'Postgres',
|
||||
label: 'postgres',
|
||||
host: 'postgres',
|
||||
networks: ['cyphernodenet'],
|
||||
docker: 'postgres:'+this.config.docker_versions['cyphernode/postgres']
|
||||
},
|
||||
{
|
||||
name: 'Notifier',
|
||||
label: 'notifier',
|
||||
|
||||
@@ -12,10 +12,11 @@ const schemas = {
|
||||
'0.2.2': require('../schema/config-v0.2.2.json'),
|
||||
'0.2.3': require('../schema/config-v0.2.3.json'),
|
||||
'0.2.4': require('../schema/config-v0.2.4.json'),
|
||||
'0.2.5': require('../schema/config-v0.2.5.json')
|
||||
'0.2.5': require('../schema/config-v0.2.5.json'),
|
||||
'0.2.6': require('../schema/config-v0.2.6.json')
|
||||
};
|
||||
|
||||
const versionHistory = [ '0.1.0', '0.2.0', '0.2.2', '0.2.3', '0.2.4', '0.2.5' ];
|
||||
const versionHistory = [ '0.1.0', '0.2.0', '0.2.2', '0.2.3', '0.2.4', '0.2.5', '0.2.6' ];
|
||||
const defaultSchemaVersion=versionHistory[0];
|
||||
const latestSchemaVersion=versionHistory[versionHistory.length-1];
|
||||
|
||||
@@ -46,7 +47,8 @@ module.exports = class Config {
|
||||
'0.2.0->0.2.2': this.migrate_0_2_0_to_0_2_2,
|
||||
'0.2.2->0.2.3': this.migrate_0_2_2_to_0_2_3,
|
||||
'0.2.3->0.2.4': this.migrate_0_2_3_to_0_2_4,
|
||||
'0.2.4->0.2.5': this.migrate_0_2_4_to_0_2_5
|
||||
'0.2.4->0.2.5': this.migrate_0_2_4_to_0_2_5,
|
||||
'0.2.5->0.2.6': this.migrate_0_2_5_to_0_2_6
|
||||
};
|
||||
|
||||
this.setData( { schema_version: latestSchemaVersion } );
|
||||
@@ -247,4 +249,12 @@ module.exports = class Config {
|
||||
this.data.schema_version = '0.2.5';
|
||||
}
|
||||
|
||||
async migrate_0_2_5_to_0_2_6() {
|
||||
const currentVersion = this.data.schema_version;
|
||||
if( currentVersion != '0.2.5' ) {
|
||||
return;
|
||||
}
|
||||
this.data.schema_version = '0.2.6';
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
30
cyphernodeconf_docker/prompters/200_postgres.js
Normal file
30
cyphernodeconf_docker/prompters/200_postgres.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const chalk = require('chalk');
|
||||
|
||||
const name = 'postgres';
|
||||
|
||||
const capitalise = function( txt ) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
||||
};
|
||||
|
||||
const prefix = function() {
|
||||
return chalk.green(capitalise(name)+': ');
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
name: function() {
|
||||
return name;
|
||||
},
|
||||
prompts: function( utils ) {
|
||||
return [
|
||||
{
|
||||
type: 'password',
|
||||
name: 'postgres_password',
|
||||
default: utils.getDefault( 'postgres_password' ),
|
||||
message: prefix()+'Password of Postgres cyphernode user?'+utils.getHelp('postgres_password'),
|
||||
filter: utils.trimFilter,
|
||||
}];
|
||||
},
|
||||
templates: function( props ) {
|
||||
return ['pgpass'];
|
||||
}
|
||||
};
|
||||
@@ -30,6 +30,44 @@ module.exports = {
|
||||
value: "docker"
|
||||
}]
|
||||
},
|
||||
{
|
||||
when: installerDocker,
|
||||
type: 'list',
|
||||
name: 'postgres_datapath',
|
||||
default: utils.getDefault( 'postgres_datapath' ),
|
||||
choices: [
|
||||
{
|
||||
name: utils.setupDir()+"/cyphernode/postgres",
|
||||
value: utils.setupDir()+"/cyphernode/postgres"
|
||||
},
|
||||
{
|
||||
name: utils.defaultDataDirBase()+"/cyphernode/postgres",
|
||||
value: utils.defaultDataDirBase()+"/cyphernode/postgres"
|
||||
},
|
||||
{
|
||||
name: utils.defaultDataDirBase()+"/.cyphernode/postgres",
|
||||
value: utils.defaultDataDirBase()+"/.cyphernode/postgres"
|
||||
},
|
||||
{
|
||||
name: utils.defaultDataDirBase()+"/postgres",
|
||||
value: utils.defaultDataDirBase()+"/postgres"
|
||||
},
|
||||
{
|
||||
name: "Custom path",
|
||||
value: "_custom"
|
||||
}
|
||||
],
|
||||
message: prefix()+'Where do you want to store your Postgres files?'+utils.getHelp('postgres_datapath'),
|
||||
},
|
||||
{
|
||||
when: (props)=>{ return installerDocker(props) && (props.postgres_datapath === '_custom') },
|
||||
type: 'input',
|
||||
name: 'postgres_datapath_custom',
|
||||
default: utils.getDefault( 'postgres_datapath_custom' ),
|
||||
filter: utils.trimFilter,
|
||||
validate: utils.pathValidator,
|
||||
message: prefix()+'Custom path for Postgres files?'+utils.getHelp('postgres_datapath_custom'),
|
||||
},
|
||||
{
|
||||
when: installerDocker,
|
||||
type: 'list',
|
||||
|
||||
726
cyphernodeconf_docker/schema/config-v0.2.6.json
Normal file
726
cyphernodeconf_docker/schema/config-v0.2.6.json
Normal file
@@ -0,0 +1,726 @@
|
||||
{
|
||||
"definitions": {},
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "http://cyphernode.io/config-v0.2.6.json",
|
||||
"type": "object",
|
||||
"title": "Cyphernode config file structure v0.2.6",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_version",
|
||||
"setup_version",
|
||||
"features",
|
||||
"net",
|
||||
"use_xpub",
|
||||
"installer_mode",
|
||||
"run_as_different_user",
|
||||
"docker_mode",
|
||||
"docker_versions",
|
||||
"adminhash",
|
||||
"bitcoin_rpcuser",
|
||||
"bitcoin_rpcpassword",
|
||||
"bitcoin_prune",
|
||||
"bitcoin_datapath",
|
||||
"bitcoin_mode",
|
||||
"bitcoin_expose",
|
||||
"gatekeeper_expose",
|
||||
"gatekeeper_keys",
|
||||
"gatekeeper_sslcert",
|
||||
"gatekeeper_sslkey",
|
||||
"gatekeeper_cns",
|
||||
"gatekeeper_clientkeyspassword",
|
||||
"gatekeeper_datapath",
|
||||
"gatekeeper_port",
|
||||
"proxy_datapath",
|
||||
"postgres_password",
|
||||
"postgres_datapath",
|
||||
"logs_datapath",
|
||||
"traefik_datapath",
|
||||
"traefik_http_port",
|
||||
"traefik_https_port"
|
||||
],
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"run_as_different_user": {
|
||||
"enum": [
|
||||
true
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"username"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"use_xpub": {
|
||||
"enum": [
|
||||
true
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"xpub",
|
||||
"derivation_path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"bitcoin_prune": {
|
||||
"enum": [
|
||||
true
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"bitcoin_prune_size"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"features": {
|
||||
"contains": {
|
||||
"enum": [
|
||||
"tor"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"tor_datapath",
|
||||
"torifyables",
|
||||
"clearnet"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"features": {
|
||||
"contains": {
|
||||
"enum": [
|
||||
"lightning"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"lightning_announce",
|
||||
"lightning_expose",
|
||||
"lightning_implementation",
|
||||
"lightning_datapath",
|
||||
"lightning_nodename",
|
||||
"lightning_nodecolor"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"features": {
|
||||
"contains": {
|
||||
"enum": [
|
||||
"otsclient"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"otsclient_datapath"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"0.2.5"
|
||||
],
|
||||
"default": "0.3.0",
|
||||
"examples": [
|
||||
"0.2.5"
|
||||
]
|
||||
},
|
||||
"setup_version": {
|
||||
"type": "string",
|
||||
"examples": [
|
||||
"v0.2.0"
|
||||
]
|
||||
},
|
||||
"docker_versions": {
|
||||
"$id": "#/properties/dockerVersions",
|
||||
"type": "object",
|
||||
"title": "All versions of the docker containers",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"$id": "#/properties/features",
|
||||
"type": "array",
|
||||
"title": "The optional features of this cyphernode",
|
||||
"default": ["specter"],
|
||||
"items": {
|
||||
"$id": "#/properties/features/items",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"tor",
|
||||
"lightning",
|
||||
"otsclient",
|
||||
"batcher",
|
||||
"specter"
|
||||
],
|
||||
"title": "The feature",
|
||||
"default": "",
|
||||
"examples": [
|
||||
"tor",
|
||||
"lightning",
|
||||
"otsclient",
|
||||
"batcher",
|
||||
"specter"
|
||||
]
|
||||
}
|
||||
},
|
||||
"torifyables": {
|
||||
"$id": "#/properties/torifyables",
|
||||
"type": "array",
|
||||
"title": "The Torified features of this cyphernode",
|
||||
"default": [],
|
||||
"items": {
|
||||
"$id": "#/properties/torifyables/items",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"tor_traefik",
|
||||
"tor_bitcoin",
|
||||
"tor_lightning",
|
||||
"tor_otsoperations",
|
||||
"tor_otswebhooks",
|
||||
"tor_addrwatcheswebhooks",
|
||||
"tor_txidwatcheswebhooks"
|
||||
],
|
||||
"title": "The Torified feature",
|
||||
"default": "",
|
||||
"examples": [
|
||||
"tor_traefik",
|
||||
"tor_bitcoin",
|
||||
"tor_lightning",
|
||||
"tor_otsoperations",
|
||||
"tor_otswebhooks",
|
||||
"tor_addrwatcheswebhooks",
|
||||
"tor_txidwatcheswebhooks"
|
||||
]
|
||||
}
|
||||
},
|
||||
"clearnet": {
|
||||
"$id": "#/properties/clearnet",
|
||||
"type": "array",
|
||||
"title": "The clearnet-allowed Torified features of this cyphernode",
|
||||
"default": [],
|
||||
"items": {
|
||||
"$id": "#/properties/clearnet/items",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"clearnet_bitcoin",
|
||||
"clearnet_lightning"
|
||||
],
|
||||
"title": "The clearnet-allowed Torified feature",
|
||||
"default": "",
|
||||
"examples": [
|
||||
"clearnet_bitcoin",
|
||||
"clearnet_lightning"
|
||||
]
|
||||
}
|
||||
},
|
||||
"net": {
|
||||
"$id": "#/properties/net",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"testnet",
|
||||
"mainnet",
|
||||
"regtest"
|
||||
],
|
||||
"title": "The net cyphernode is running on",
|
||||
"default": "testnet",
|
||||
"examples": [
|
||||
"testnet"
|
||||
]
|
||||
},
|
||||
"use_xpub": {
|
||||
"$id": "#/properties/use_xpub",
|
||||
"type": "boolean",
|
||||
"title": "Use xpub key?",
|
||||
"default": false,
|
||||
"examples": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"xpub": {
|
||||
"$id": "#/properties/xpub",
|
||||
"type": "string",
|
||||
"title": "Default xpub to derive addresses from",
|
||||
"pattern": "^(\\w+)$"
|
||||
},
|
||||
"derivation_path": {
|
||||
"$id": "#/properties/derivation_path",
|
||||
"type": "string",
|
||||
"title": "Default derivation path",
|
||||
"default": "0/n",
|
||||
"examples": [
|
||||
"0/n"
|
||||
]
|
||||
},
|
||||
"installer_mode": {
|
||||
"$id": "#/properties/installer_mode",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"docker"
|
||||
],
|
||||
"title": "Install mode",
|
||||
"default": "docker",
|
||||
"examples": [
|
||||
"docker"
|
||||
]
|
||||
},
|
||||
"run_as_different_user": {
|
||||
"$id": "#/properties/run_as_different_user",
|
||||
"type": "boolean",
|
||||
"title": "Run as different user",
|
||||
"default": true,
|
||||
"examples": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"username": {
|
||||
"$id": "#/properties/username",
|
||||
"type": "string",
|
||||
"title": "Username to run under",
|
||||
"default": "cyphernode",
|
||||
"examples": [
|
||||
"cyphernode"
|
||||
]
|
||||
},
|
||||
"docker_mode": {
|
||||
"$id": "#/properties/docker_mode",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"swarm",
|
||||
"compose"
|
||||
],
|
||||
"title": "How to run the containers",
|
||||
"default": "swarm",
|
||||
"examples": [
|
||||
"compose"
|
||||
]
|
||||
},
|
||||
"bitcoin_rpcuser": {
|
||||
"$id": "#/properties/bitcoin_rpcuser",
|
||||
"type": "string",
|
||||
"title": "Bitcoin rpc user",
|
||||
"default": "bitcoin",
|
||||
"examples": [
|
||||
"bitcoin"
|
||||
]
|
||||
},
|
||||
"bitcoin_rpcpassword": {
|
||||
"$id": "#/properties/bitcoin_rpcpassword",
|
||||
"type": "string",
|
||||
"title": "Bitcoin rpc password",
|
||||
"default": "CHANGEME",
|
||||
"examples": [
|
||||
"CHANGEME"
|
||||
]
|
||||
},
|
||||
"bitcoin_uacomment": {
|
||||
"$id": "#/properties/bitcoin_uacomment",
|
||||
"type": "string",
|
||||
"title": "Bitcoin user agent comment",
|
||||
"examples": [
|
||||
"cyphernode"
|
||||
]
|
||||
},
|
||||
"bitcoin_prune": {
|
||||
"$id": "#/properties/bitcoin_prune",
|
||||
"type": "boolean",
|
||||
"title": "Bitcoin prune",
|
||||
"default": false,
|
||||
"examples": [
|
||||
"false"
|
||||
]
|
||||
},
|
||||
"bitcoin_prune_size": {
|
||||
"$id": "#/properties/bitcoin_prune_size",
|
||||
"type": "integer",
|
||||
"title": "Bitcoin prune size",
|
||||
"default": 550,
|
||||
"examples": [
|
||||
550
|
||||
]
|
||||
},
|
||||
"bitcoin_datapath": {
|
||||
"$id": "#/properties/bitcoin_datapath",
|
||||
"type": "string",
|
||||
"title": "Bitcoin datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/bitcoin"
|
||||
]
|
||||
},
|
||||
"bitcoin_datapath_custom": {
|
||||
"$id": "#/properties/bitcoin_datapath_custom",
|
||||
"type": "string",
|
||||
"title": "Bitcoin custom datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/bitcoin"
|
||||
]
|
||||
},
|
||||
"lightning_datapath": {
|
||||
"$id": "#/properties/lightning_datapath",
|
||||
"type": "string",
|
||||
"title": "Lightning datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/lightning"
|
||||
]
|
||||
},
|
||||
"lightning_datapath_custom": {
|
||||
"$id": "#/properties/lightning_datapath_custom",
|
||||
"type": "string",
|
||||
"title": "Lightning custom datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/lightning"
|
||||
]
|
||||
},
|
||||
"proxy_datapath": {
|
||||
"$id": "#/properties/proxy_datapath",
|
||||
"type": "string",
|
||||
"title": "Proxy datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/proxy"
|
||||
]
|
||||
},
|
||||
"proxy_datapath_custom": {
|
||||
"$id": "#/properties/proxy_datapath_custom",
|
||||
"type": "string",
|
||||
"title": "Proxy custom datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/proxy"
|
||||
]
|
||||
},
|
||||
"otsclient_datapath": {
|
||||
"$id": "#/properties/otsclient_datapath",
|
||||
"type": "string",
|
||||
"title": "OTS Client datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/otsclient"
|
||||
]
|
||||
},
|
||||
"otsclient_datapath_custom": {
|
||||
"$id": "#/properties/otsclient_datapath_custom",
|
||||
"type": "string",
|
||||
"title": "OTS Client custom datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/otsclient"
|
||||
]
|
||||
},
|
||||
"traefik_http_port": {
|
||||
"$id": "#/properties/traefik_port",
|
||||
"type": "integer",
|
||||
"title": "Traefik HTTP port",
|
||||
"default": 80,
|
||||
"examples": [
|
||||
80
|
||||
]
|
||||
},
|
||||
"traefik_https_port": {
|
||||
"$id": "#/properties/traefik_https_port",
|
||||
"type": "integer",
|
||||
"title": "Traefik HTTPS port",
|
||||
"default": 443,
|
||||
"examples": [
|
||||
443
|
||||
]
|
||||
},
|
||||
"traefik_datapath": {
|
||||
"$id": "#/properties/traefik_datapath",
|
||||
"type": "string",
|
||||
"title": "Traefik datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/traefik"
|
||||
]
|
||||
},
|
||||
"traefik_datapath_custom": {
|
||||
"$id": "#/properties/traefik_datapath_custom",
|
||||
"type": "string",
|
||||
"title": "Traefik custom datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/traefik"
|
||||
]
|
||||
},
|
||||
"postgres_password": {
|
||||
"$id": "#/properties/postgres_password",
|
||||
"type": "string",
|
||||
"title": "Postgres cyphernode's password",
|
||||
"default": "CHANGEME",
|
||||
"examples": [
|
||||
"CHANGEME"
|
||||
]
|
||||
},
|
||||
"postgres_datapath": {
|
||||
"$id": "#/properties/postgres_datapath",
|
||||
"type": "string",
|
||||
"title": "Postgres datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/postgres"
|
||||
]
|
||||
},
|
||||
"postgres_datapath_custom": {
|
||||
"$id": "#/properties/postgres_datapath_custom",
|
||||
"type": "string",
|
||||
"title": "Postgres custom datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/postgres"
|
||||
]
|
||||
},
|
||||
"logs_datapath": {
|
||||
"$id": "#/properties/logs_datapath",
|
||||
"type": "string",
|
||||
"title": "Logs datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/logs"
|
||||
]
|
||||
},
|
||||
"logs_datapath_custom": {
|
||||
"$id": "#/properties/logs_datapath_custom",
|
||||
"type": "string",
|
||||
"title": "Logs custom datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/logs"
|
||||
]
|
||||
},
|
||||
"tor_datapath": {
|
||||
"$id": "#/properties/tor_datapath",
|
||||
"type": "string",
|
||||
"title": "Tor datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/tor"
|
||||
]
|
||||
},
|
||||
"tor_datapath_custom": {
|
||||
"$id": "#/properties/tor_datapath_custom",
|
||||
"type": "string",
|
||||
"title": "Tor custom datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/tor"
|
||||
]
|
||||
},
|
||||
"lightning_announce": {
|
||||
"$id": "#/properties/lightning_announce",
|
||||
"type": "boolean",
|
||||
"title": "Announce lightning ip",
|
||||
"default": false,
|
||||
"examples": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"lightning_external_ip": {
|
||||
"$id": "#/properties/lightning_external_ip",
|
||||
"type": "string",
|
||||
"format": "ipv4",
|
||||
"title": "External lightning node ip",
|
||||
"examples": [
|
||||
"123.123.123.123"
|
||||
]
|
||||
},
|
||||
"bitcoin_mode": {
|
||||
"$id": "#/properties/bitcoin_mode",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"internal"
|
||||
],
|
||||
"title": "Bitcoin mode",
|
||||
"default": "internal",
|
||||
"examples": [
|
||||
"internal"
|
||||
]
|
||||
},
|
||||
"bitcoin_expose": {
|
||||
"$id": "#/properties/bitcoin_expose",
|
||||
"type": "boolean",
|
||||
"title": "Expose bitcoin node",
|
||||
"default": false,
|
||||
"examples": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"lightning_expose": {
|
||||
"$id": "#/properties/lightning_expose",
|
||||
"type": "boolean",
|
||||
"title": "Expose lightning node",
|
||||
"default": true,
|
||||
"examples": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"gatekeeper_expose": {
|
||||
"$id": "#/properties/gatekeeper_expose",
|
||||
"type": "boolean",
|
||||
"title": "Expose gatekeeper port",
|
||||
"default": false,
|
||||
"examples": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"gatekeeper_datapath": {
|
||||
"$id": "#/properties/gatekeeper_datapath",
|
||||
"type": "string",
|
||||
"title": "Gatekeeper datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/gatekeeper"
|
||||
]
|
||||
},
|
||||
"gatekeeper_datapath_custom": {
|
||||
"$id": "#/properties/gatekeeper_datapath_custom",
|
||||
"type": "string",
|
||||
"title": "Gatekeeper custom datapath",
|
||||
"examples": [
|
||||
"/tmp/cyphernode/gatekeeper"
|
||||
]
|
||||
},
|
||||
"gatekeeper_port": {
|
||||
"$id": "#/properties/gatekeeper_port",
|
||||
"type": "integer",
|
||||
"title": "Gatekeeper port",
|
||||
"default": 2009,
|
||||
"examples": [
|
||||
2009
|
||||
]
|
||||
},
|
||||
"gatekeeper_keys": {
|
||||
"$id": "#/properties/gatekeeper_keys",
|
||||
"type": "object",
|
||||
"title": "Gatekeeper keys",
|
||||
"default": {
|
||||
"configEntries": [],
|
||||
"clientInformation": []
|
||||
},
|
||||
"required": [
|
||||
"configEntries",
|
||||
"clientInformation"
|
||||
],
|
||||
"properties": {
|
||||
"configEntries": {
|
||||
"$id": "#/properties/gatekeeper_keys/configEntries",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$id": "#/properties/gatekeeper_keys/configEntries/entry",
|
||||
"type": "string",
|
||||
"pattern": "^kapi_id=\".+\";kapi_key=\".+\";kapi_groups=\".+\";.+$"
|
||||
},
|
||||
"examples": [
|
||||
[
|
||||
"kapi_id=\"000\";kapi_key=\"a27f9e73fdde6a5005879c259c9aea5e8d917eec77bbdfd73272c0af9b4c6b7a\";kapi_groups=\"stats\";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}",
|
||||
"kapi_id=\"001\";kapi_key=\"a27f9e73fdde6a5005879c273c9aea5e8d917eec77bbdfd73272c0af9b4c6b7a\";kapi_groups=\"stats,watcher\";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}",
|
||||
"kapi_id=\"002\";kapi_key=\"fe58ddbb66d7302a7087af3242a98b6326c51a257f5eab1c06bb8cc02e25890d\";kapi_groups=\"stats,watcher,spender\";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}",
|
||||
"kapi_id=\"003\";kapi_key=\"f0b8bb52f4c7007938757bcdfc73b452d6ce08cc0c660ce57c5464ae95f35417\";kapi_groups=\"stats,watcher,spender,admin\";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}"
|
||||
]
|
||||
]
|
||||
},
|
||||
"clientInformation": {
|
||||
"$id": "#/properties/gatekeeper_keys/clientInformation",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$id": "#/properties/gatekeeper_keys/clientInformation/entry",
|
||||
"type": "string",
|
||||
"pattern": "^.+=.+$"
|
||||
},
|
||||
"examples": [
|
||||
[
|
||||
"000=a27f9e73fdde6a5005879c259c9aea5e8d917eec77bbdfd73272c0af9b4c6b7a",
|
||||
"001=a27f9e73fdde6a5005879c273c9aea5e8d917eec77bbdfd73272c0af9b4c6b7a",
|
||||
"002=fe58ddbb66d7302a7087af3242a98b6326c51a257f5eab1c06bb8cc02e25890d",
|
||||
"003=f0b8bb52f4c7007938757bcdfc73b452d6ce08cc0c660ce57c5464ae95f35417"
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"gatekeeper_sslcert": {
|
||||
"$id": "#/properties/gatekeeper_sslcert",
|
||||
"type": "string",
|
||||
"title": "Gatekeeper SSL Cert"
|
||||
},
|
||||
"gatekeeper_sslkey": {
|
||||
"$id": "#/properties/gatekeeper_sslkey",
|
||||
"type": "string",
|
||||
"title": "Gatekeeper SSL Key"
|
||||
},
|
||||
"gatekeeper_cns": {
|
||||
"$id": "#/properties/gatekeeper_cns",
|
||||
"type": "string",
|
||||
"title": "Gatekeeper cns",
|
||||
"examples": [
|
||||
"myhost.mydomain.com,*.myotherdomain.com,123.123.123.123"
|
||||
]
|
||||
},
|
||||
"gatekeeper_clientkeyspassword": {
|
||||
"$id": "#/properties/gatekeeper_clientkeyspassword",
|
||||
"type": "string",
|
||||
"title": "Password for the encrypted client keys archive"
|
||||
},
|
||||
"adminhash": {
|
||||
"$id": "#/properties/adminhash",
|
||||
"type": "string",
|
||||
"title": "Bcrypted hash of admin password"
|
||||
},
|
||||
"lightning_implementation": {
|
||||
"$id": "#/properties/lightning_implementation",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"c-lightning"
|
||||
],
|
||||
"title": "The lightning implementation",
|
||||
"default": "c-lightning",
|
||||
"examples": [
|
||||
"c-lightning"
|
||||
]
|
||||
},
|
||||
"lightning_nodename": {
|
||||
"$id": "#/properties/lightning_nodename",
|
||||
"type": "string",
|
||||
"title": "The lightning node name",
|
||||
"examples": [
|
||||
"🚀 Mighty Moose 🚀"
|
||||
]
|
||||
},
|
||||
"lightning_nodecolor": {
|
||||
"$id": "#/properties/lightning_nodecolor",
|
||||
"type": "string",
|
||||
"pattern": "^[0-9A-Fa-f]{6}$",
|
||||
"title": "The lightning node color",
|
||||
"examples": [
|
||||
"ff0000",
|
||||
"00ff00",
|
||||
"00ffff"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ LIGHTNING_IMPLEMENTATION=<%= lightning_implementation %>
|
||||
PROXY_DATAPATH=<%= proxy_datapath %>
|
||||
GATEKEEPER_DATAPATH=<%= gatekeeper_datapath %>
|
||||
GATEKEEPER_PORT=<%= gatekeeper_port %>
|
||||
POSTGRES_DATAPATH=<%= postgres_datapath %>
|
||||
LOGS_DATAPATH=<%= logs_datapath %>
|
||||
TRAEFIK_DATAPATH=<%= traefik_datapath %>
|
||||
FEATURE_TOR=<%= (features.indexOf('tor') != -1)?'true':'false' %>
|
||||
|
||||
@@ -2,6 +2,36 @@ version: "3"
|
||||
|
||||
services:
|
||||
|
||||
##########################
|
||||
# POSTGRESQL #
|
||||
##########################
|
||||
|
||||
postgres:
|
||||
image: postgres:<%= postgres_version %>
|
||||
environment:
|
||||
- "POSTGRES_USER=cyphernode"
|
||||
- "POSTGRES_PASSWORD=<%= postgres_password %>"
|
||||
- "POSTGRES_DB=cyphernode"
|
||||
- "PGDATA=/var/lib/postgresql/data/pgdata"
|
||||
volumes:
|
||||
- "<%= postgres_datapath %>:/var/lib/postgresql/data"
|
||||
networks:
|
||||
- cyphernodenet
|
||||
<% if ( docker_mode === 'swarm' ) { %>
|
||||
deploy:
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.io.cyphernode == true
|
||||
restart_policy:
|
||||
condition: "any"
|
||||
delay: 1s
|
||||
update_config:
|
||||
parallelism: 1
|
||||
<% } else { %>
|
||||
restart: always
|
||||
<% } %>
|
||||
|
||||
<% if ( features.indexOf('tor') !== -1 ) { %>
|
||||
##########################
|
||||
# TOR #
|
||||
@@ -156,6 +186,7 @@ services:
|
||||
- "OTSCLIENT_CONTAINER=otsclient:6666"
|
||||
- "OTS_FILES=/proxy/otsfiles"
|
||||
- "XPUB_DERIVATION_GAP=100"
|
||||
- "PGPASSFILE=/proxy/db/pgpass"
|
||||
<% if ( devmode ) { %>
|
||||
ports:
|
||||
- "8888:8888"
|
||||
@@ -174,6 +205,8 @@ services:
|
||||
<% } %>
|
||||
networks:
|
||||
- cyphernodenet
|
||||
depends_on:
|
||||
- postgres
|
||||
<% if ( docker_mode === 'swarm' ) { %>
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
@@ -80,6 +80,19 @@ checkpycoin() {
|
||||
return 0
|
||||
}
|
||||
|
||||
checkpostgres() {
|
||||
echo -en "\r\n\e[1;36mTesting Postgres... " > /dev/console
|
||||
local rc
|
||||
|
||||
# getbatcher needs the database to return correctly...
|
||||
rc=$(curl -s -o /dev/null -w "%{http_code}" http://proxy:8888/getbatcher)
|
||||
[ "${rc}" -ne "200" ] && return 105
|
||||
|
||||
echo -e "\e[1;36mPostgres rocks!" > /dev/console
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
checkbroker() {
|
||||
echo -en "\r\n\e[1;36mTesting Broker... " > /dev/console
|
||||
local rc
|
||||
@@ -170,12 +183,12 @@ checkservice() {
|
||||
while :
|
||||
do
|
||||
outcome=0
|
||||
for container in gatekeeper proxy proxycron broker notifier pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %><%= (features.indexOf('tor') != -1)?'tor ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
|
||||
for container in gatekeeper proxy proxycron broker notifier pycoin postgres <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %><%= (features.indexOf('tor') != -1)?'tor ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
|
||||
echo -e " \e[0;32mVerifying \e[0;33m${container}\e[0;32m..." > /dev/console
|
||||
(ping -c 10 ${container} 2> /dev/null | grep "0% packet loss" > /dev/null) &
|
||||
eval ${container}=$!
|
||||
done
|
||||
for container in gatekeeper proxy proxycron broker notifier pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %><%= (features.indexOf('tor') != -1)?'tor ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
|
||||
for container in gatekeeper proxy proxycron broker notifier pycoin postgres <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %><%= (features.indexOf('tor') != -1)?'tor ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
|
||||
eval wait '$'${container} ; returncode=$? ; outcome=$((${outcome} + ${returncode}))
|
||||
eval c_${container}=${returncode}
|
||||
done
|
||||
@@ -193,12 +206,13 @@ checkservice() {
|
||||
# { "name": "proxy", "active":true },
|
||||
# { "name": "proxycron", "active":true },
|
||||
# { "name": "pycoin", "active":true },
|
||||
# { "name": "postgres", "active":true },
|
||||
# { "name": "otsclient", "active":true },
|
||||
# { "name": "tor", "active":true },
|
||||
# { "name": "bitcoin", "active":true },
|
||||
# { "name": "lightning", "active":true },
|
||||
# ]
|
||||
for container in gatekeeper proxy proxycron broker notifier pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %><%= (features.indexOf('tor') != -1)?'tor ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
|
||||
for container in gatekeeper proxy proxycron broker notifier pycoin postgres <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %><%= (features.indexOf('tor') != -1)?'tor ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
|
||||
[ -n "${result}" ] && result="${result},"
|
||||
result="${result}{\"name\":\"${container}\",\"active\":"
|
||||
eval "returncode=\$c_${container}"
|
||||
@@ -254,6 +268,7 @@ feature_status() {
|
||||
# { "name": "proxy", "active":true },
|
||||
# { "name": "proxycron", "active":true },
|
||||
# { "name": "pycoin", "active":true },
|
||||
# { "name": "postgres", "active":true },
|
||||
# { "name": "otsclient", "active":true },
|
||||
# { "name": "tor", "active":true },
|
||||
# { "name": "bitcoin", "active":true },
|
||||
@@ -262,6 +277,7 @@ feature_status() {
|
||||
# "features": [
|
||||
# { "name": "gatekeeper", "working":true },
|
||||
# { "name": "pycoin", "working":true },
|
||||
# { "name": "postgres", "working":true },
|
||||
# { "name": "otsclient", "working":true },
|
||||
# { "name": "tor", "working":true },
|
||||
# { "name": "bitcoin", "working":true },
|
||||
@@ -296,6 +312,7 @@ fi
|
||||
# "features": [
|
||||
# { "name": "gatekeeper", "working":true },
|
||||
# { "name": "pycoin", "working":true },
|
||||
# { "name": "postgres", "working":true },
|
||||
# { "name": "otsclient", "working":true },
|
||||
# { "name": "tor", "working":true },
|
||||
# { "name": "bitcoin", "working":true },
|
||||
@@ -362,6 +379,21 @@ fi
|
||||
finalreturncode=$((${returncode} | ${finalreturncode}))
|
||||
result="${result}$(feature_status ${returncode} 'Pycoin error!')}"
|
||||
|
||||
#############################
|
||||
# POSTGRES #
|
||||
#############################
|
||||
|
||||
result="${result},{\"coreFeature\":true, \"name\":\"postgres\",\"working\":"
|
||||
status=$(echo "{${containers}}" | jq ".containers[] | select(.name == \"postgres\") | .active")
|
||||
if [[ "${workingproxy}" = "true" && "${status}" = "true" ]]; then
|
||||
timeout_feature checkpostgres
|
||||
returncode=$?
|
||||
else
|
||||
returncode=1
|
||||
fi
|
||||
finalreturncode=$((${returncode} | ${finalreturncode}))
|
||||
result="${result}$(feature_status ${returncode} 'Postgres error!')}"
|
||||
|
||||
<% if (features.indexOf('otsclient') != -1) { %>
|
||||
#############################
|
||||
# OTSCLIENT #
|
||||
|
||||
1
cyphernodeconf_docker/templates/postgres/pgpass
Normal file
1
cyphernodeconf_docker/templates/postgres/pgpass
Normal file
@@ -0,0 +1 @@
|
||||
postgres:5432:cyphernode:cyphernode:<%= postgres_password %>
|
||||
23
dist/setup.sh
vendored
23
dist/setup.sh
vendored
@@ -110,7 +110,7 @@ sudo_if_required() {
|
||||
}
|
||||
|
||||
modify_permissions() {
|
||||
local directories=("$BITCOIN_DATAPATH" "$LIGHTNING_DATAPATH" "$PROXY_DATAPATH" "$GATEKEEPER_DATAPATH" "$OTSCLIENT_DATAPATH" "$LOGS_DATAPATH" "$TRAEFIK_DATAPATH" "$TOR_DATAPATH")
|
||||
local directories=("$BITCOIN_DATAPATH" "$LIGHTNING_DATAPATH" "$PROXY_DATAPATH" "$GATEKEEPER_DATAPATH" "$OTSCLIENT_DATAPATH" "$POSTGRES_DATAPATH" "$LOGS_DATAPATH" "$TRAEFIK_DATAPATH" "$TOR_DATAPATH")
|
||||
for d in "${directories[@]}"
|
||||
do
|
||||
if [[ -e $d ]]; then
|
||||
@@ -122,7 +122,7 @@ modify_permissions() {
|
||||
}
|
||||
|
||||
modify_owner() {
|
||||
local directories=("$BITCOIN_DATAPATH" "$LIGHTNING_DATAPATH" "$PROXY_DATAPATH" "$GATEKEEPER_DATAPATH" "$OTSCLIENT_DATAPATH" "$LOGS_DATAPATH" "$TRAEFIK_DATAPATH" "$TOR_DATAPATH")
|
||||
local directories=("$BITCOIN_DATAPATH" "$LIGHTNING_DATAPATH" "$PROXY_DATAPATH" "$GATEKEEPER_DATAPATH" "$OTSCLIENT_DATAPATH" "$POSTGRES_DATAPATH" "$LOGS_DATAPATH" "$TRAEFIK_DATAPATH" "$TOR_DATAPATH")
|
||||
local user=$(id -u $RUN_AS_USER):$(id -g $RUN_AS_USER)
|
||||
for d in "${directories[@]}"
|
||||
do
|
||||
@@ -193,6 +193,7 @@ configure() {
|
||||
-e PROXYCRON_VERSION=$PROXYCRON_VERSION \
|
||||
-e OTSCLIENT_VERSION=$OTSCLIENT_VERSION \
|
||||
-e PYCOIN_VERSION=$PYCOIN_VERSION \
|
||||
-e POSTGRES_VERSION=$POSTGRES_VERSION \
|
||||
-e BITCOIN_VERSION=$BITCOIN_VERSION \
|
||||
-e LIGHTNING_VERSION=$LIGHTNING_VERSION \
|
||||
-e CONF_VERSION=$CONF_VERSION \
|
||||
@@ -385,9 +386,16 @@ install_docker() {
|
||||
copy_file $cyphernodeconf_filepath/traefik/htpasswd $GATEKEEPER_DATAPATH/htpasswd 1 $SUDO_REQUIRED
|
||||
|
||||
|
||||
if [ ! -d $POSTGRES_DATAPATH ]; then
|
||||
step " [32mcreate[0m $POSTGRES_DATAPATH"
|
||||
sudo_if_required mkdir -p $POSTGRES_DATAPATH
|
||||
next
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -d $LOGS_DATAPATH ]; then
|
||||
step " [32mcreate[0m $LOGS_DATAPATH"
|
||||
sudo_if_required mkdir -p $LOGS_DATAPATH
|
||||
step " [32mcreate[0m $POSTGRES_DATAPATH"
|
||||
sudo_if_required mkdir -p $POSTGRES_DATAPATH
|
||||
next
|
||||
fi
|
||||
|
||||
@@ -461,6 +469,8 @@ install_docker() {
|
||||
|
||||
copy_file $cyphernodeconf_filepath/installer/config.sh $PROXY_DATAPATH/config.sh 1 $SUDO_REQUIRED
|
||||
copy_file $cyphernodeconf_filepath/cyphernode/info.json $PROXY_DATAPATH/info.json 1 $SUDO_REQUIRED
|
||||
copy_file $cyphernodeconf_filepath/postgres/pgpass $PROXY_DATAPATH/pgpass 1 $SUDO_REQUIRED
|
||||
sudo_if_required chmod 0600 $PROXY_DATAPATH/pgpass
|
||||
|
||||
if [[ $BITCOIN_INTERNAL == true ]]; then
|
||||
if [ ! -d $BITCOIN_DATAPATH ]; then
|
||||
@@ -652,7 +662,7 @@ install_docker() {
|
||||
|
||||
check_directory_owner() {
|
||||
# if one directory does not have access rights for $RUN_AS_USER, we echo 1, else we echo 0
|
||||
local directories=("$BITCOIN_DATAPATH" "$LIGHTNING_DATAPATH" "$PROXY_DATAPATH" "$GATEKEEPER_DATAPATH" "$LOGS_DATAPATH" "$TRAEFIK_DATAPATH" "$TOR_DATAPATH")
|
||||
local directories=("$BITCOIN_DATAPATH" "$LIGHTNING_DATAPATH" "$PROXY_DATAPATH" "$GATEKEEPER_DATAPATH" "$POSTGRES_DATAPATH" "$LOGS_DATAPATH" "$TRAEFIK_DATAPATH" "$TOR_DATAPATH")
|
||||
local status=0
|
||||
for d in "${directories[@]}"
|
||||
do
|
||||
@@ -756,7 +766,7 @@ sanity_checks_pre_install() {
|
||||
if [[ $sudo_reason == 'directories' ]]; then
|
||||
echo " [31mor check your data volumes if they have the right owner.[0m"
|
||||
echo " [31mThe owner of the following folders should be '$RUN_AS_USER':[0m"
|
||||
local directories=("$BITCOIN_DATAPATH" "$LIGHTNING_DATAPATH" "$PROXY_DATAPATH" "$GATEKEEPER_DATAPATH" "$LOGS_DATAPATH" "$TRAEFIK_DATAPATH" "$TOR_DATAPATH")
|
||||
local directories=("$BITCOIN_DATAPATH" "$LIGHTNING_DATAPATH" "$PROXY_DATAPATH" "$GATEKEEPER_DATAPATH" "$POSTGRES_DATAPATH" "$LOGS_DATAPATH" "$TRAEFIK_DATAPATH" "$TOR_DATAPATH")
|
||||
local status=0
|
||||
for d in "${directories[@]}"
|
||||
do
|
||||
@@ -859,6 +869,7 @@ BITCOIN_VERSION="v0.21.1"
|
||||
LIGHTNING_VERSION="v0.10.1"
|
||||
TRAEFIK_VERSION="v1.7.9-alpine"
|
||||
MOSQUITTO_VERSION="1.6-openssl"
|
||||
POSTGRES_VERSION="14.0-alpine"
|
||||
|
||||
SETUP_DIR=$(dirname $(realpath $0))
|
||||
|
||||
|
||||
@@ -224,8 +224,6 @@ paths:
|
||||
- "pub32"
|
||||
- "path"
|
||||
- "nstart"
|
||||
- "unconfirmedCallbackURL"
|
||||
- "confirmedCallbackURL"
|
||||
properties:
|
||||
label:
|
||||
description: "Label for that xpub. Can be used, instead for xpub, for future references in xpub-related endpoints."
|
||||
|
||||
@@ -8,7 +8,8 @@ RUN apk add --update --no-cache \
|
||||
curl \
|
||||
su-exec \
|
||||
py3-pip \
|
||||
xxd
|
||||
xxd \
|
||||
postgresql
|
||||
|
||||
WORKDIR ${HOME}
|
||||
|
||||
|
||||
164
proxy_docker/app/data/cyphernode.postgresql
Normal file
164
proxy_docker/app/data/cyphernode.postgresql
Normal file
@@ -0,0 +1,164 @@
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE watching_by_pub32 (
|
||||
id SERIAL PRIMARY KEY,
|
||||
pub32 VARCHAR UNIQUE,
|
||||
label VARCHAR UNIQUE,
|
||||
derivation_path VARCHAR,
|
||||
callback0conf VARCHAR,
|
||||
callback1conf VARCHAR,
|
||||
last_imported_n INTEGER,
|
||||
watching BOOLEAN DEFAULT FALSE,
|
||||
inserted_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE watching (
|
||||
id SERIAL PRIMARY KEY,
|
||||
address VARCHAR,
|
||||
label VARCHAR,
|
||||
watching BOOLEAN DEFAULT FALSE,
|
||||
callback0conf VARCHAR,
|
||||
calledback0conf BOOLEAN DEFAULT FALSE,
|
||||
callback1conf VARCHAR,
|
||||
calledback1conf BOOLEAN DEFAULT FALSE,
|
||||
imported BOOLEAN DEFAULT FALSE,
|
||||
watching_by_pub32_id INTEGER REFERENCES watching_by_pub32,
|
||||
pub32_index INTEGER,
|
||||
event_message VARCHAR,
|
||||
inserted_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX idx_watching_address ON watching (address);
|
||||
CREATE UNIQUE INDEX idx_watching_01 ON watching (address, COALESCE(callback0conf, ''), COALESCE(callback1conf, ''));
|
||||
CREATE INDEX idx_watching_label ON watching (label);
|
||||
CREATE INDEX idx_watching_watching ON watching (watching);
|
||||
CREATE INDEX idx_watching_imported ON watching (imported);
|
||||
CREATE INDEX idx_watching_watching_by_pub32_id ON watching (watching_by_pub32_id);
|
||||
|
||||
CREATE TABLE tx (
|
||||
id SERIAL PRIMARY KEY,
|
||||
txid VARCHAR UNIQUE,
|
||||
hash VARCHAR UNIQUE,
|
||||
confirmations INTEGER DEFAULT 0,
|
||||
timereceived INTEGER,
|
||||
fee REAL,
|
||||
size INTEGER,
|
||||
vsize INTEGER,
|
||||
is_replaceable BOOLEAN,
|
||||
blockhash VARCHAR,
|
||||
blockheight INTEGER,
|
||||
blocktime INTEGER,
|
||||
conf_target INTEGER,
|
||||
inserted_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX idx_tx_timereceived ON tx (timereceived);
|
||||
CREATE INDEX idx_tx_fee ON tx (fee);
|
||||
CREATE INDEX idx_tx_size ON tx (size);
|
||||
CREATE INDEX idx_tx_vsize ON tx (vsize);
|
||||
CREATE INDEX idx_tx_blockhash ON tx (blockhash);
|
||||
CREATE INDEX idx_tx_blockheight ON tx (blockheight);
|
||||
CREATE INDEX idx_tx_blocktime ON tx (blocktime);
|
||||
CREATE INDEX idx_tx_confirmations ON tx (confirmations);
|
||||
|
||||
CREATE TABLE watching_tx (
|
||||
watching_id INTEGER REFERENCES watching,
|
||||
tx_id INTEGER REFERENCES tx,
|
||||
vout INTEGER,
|
||||
amount REAL
|
||||
);
|
||||
CREATE UNIQUE INDEX idx_watching_tx ON watching_tx (watching_id, tx_id);
|
||||
CREATE INDEX idx_watching_tx_watching_id ON watching_tx (watching_id);
|
||||
CREATE INDEX idx_watching_tx_tx_id ON watching_tx (tx_id);
|
||||
|
||||
CREATE TABLE batcher (
|
||||
id SERIAL PRIMARY KEY,
|
||||
label VARCHAR UNIQUE,
|
||||
conf_target INTEGER,
|
||||
feerate REAL,
|
||||
inserted_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
INSERT INTO batcher (id, label, conf_target, feerate) VALUES (1, 'default', 6, NULL);
|
||||
|
||||
CREATE TABLE recipient (
|
||||
id SERIAL PRIMARY KEY,
|
||||
address VARCHAR,
|
||||
amount REAL,
|
||||
tx_id INTEGER REFERENCES tx,
|
||||
inserted_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
webhook_url VARCHAR,
|
||||
calledback BOOLEAN DEFAULT FALSE,
|
||||
calledback_ts TIMESTAMP,
|
||||
batcher_id INTEGER REFERENCES batcher,
|
||||
label VARCHAR
|
||||
);
|
||||
CREATE INDEX idx_recipient_address ON recipient (address);
|
||||
CREATE INDEX idx_recipient_label ON recipient (label);
|
||||
CREATE INDEX idx_recipient_calledback ON recipient (calledback);
|
||||
CREATE INDEX idx_recipient_webhook_url ON recipient (webhook_url);
|
||||
CREATE INDEX idx_recipient_tx_id ON recipient (tx_id);
|
||||
CREATE INDEX idx_recipient_batcher_id ON recipient (batcher_id);
|
||||
|
||||
CREATE TABLE watching_by_txid (
|
||||
id SERIAL PRIMARY KEY,
|
||||
txid VARCHAR,
|
||||
watching BOOLEAN DEFAULT FALSE,
|
||||
callback1conf VARCHAR,
|
||||
calledback1conf BOOLEAN DEFAULT FALSE,
|
||||
callbackxconf VARCHAR,
|
||||
calledbackxconf BOOLEAN DEFAULT FALSE,
|
||||
nbxconf INTEGER,
|
||||
inserted_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX idx_watching_by_txid_txid ON watching_by_txid (txid);
|
||||
CREATE UNIQUE INDEX idx_watching_by_txid_1x ON watching_by_txid (txid, callback1conf, callbackxconf);
|
||||
CREATE INDEX idx_watching_by_txid_watching ON watching_by_txid (watching);
|
||||
CREATE INDEX idx_watching_by_txid_callback1conf ON watching_by_txid (callback1conf);
|
||||
CREATE INDEX idx_watching_by_txid_calledback1conf ON watching_by_txid (calledback1conf);
|
||||
CREATE INDEX idx_watching_by_txid_callbackxconf ON watching_by_txid (callbackxconf);
|
||||
CREATE INDEX idx_watching_by_txid_calledbackxconf ON watching_by_txid (calledbackxconf);
|
||||
|
||||
CREATE TABLE stamp (
|
||||
id SERIAL PRIMARY KEY,
|
||||
hash VARCHAR UNIQUE,
|
||||
callbackUrl VARCHAR,
|
||||
requested BOOLEAN DEFAULT FALSE,
|
||||
upgraded BOOLEAN DEFAULT FALSE,
|
||||
calledback BOOLEAN DEFAULT FALSE,
|
||||
inserted_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX idx_stamp_calledback ON stamp (calledback);
|
||||
|
||||
CREATE TABLE cyphernode_props (
|
||||
id SERIAL PRIMARY KEY,
|
||||
property VARCHAR,
|
||||
value VARCHAR,
|
||||
inserted_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX idx_cp_property ON cyphernode_props (property);
|
||||
CREATE UNIQUE INDEX idx_cp_propval ON cyphernode_props (property, value);
|
||||
|
||||
INSERT INTO cyphernode_props (property, value) VALUES ('version', '0.1');
|
||||
INSERT INTO cyphernode_props (property, value) VALUES ('pay_index', '0');
|
||||
|
||||
CREATE TABLE ln_invoice (
|
||||
id SERIAL PRIMARY KEY,
|
||||
label VARCHAR UNIQUE,
|
||||
bolt11 VARCHAR UNIQUE,
|
||||
payment_hash VARCHAR,
|
||||
msatoshi INTEGER,
|
||||
status VARCHAR,
|
||||
pay_index INTEGER,
|
||||
msatoshi_received INTEGER,
|
||||
paid_at INTEGER,
|
||||
description VARCHAR,
|
||||
expires_at INTEGER,
|
||||
callback_url VARCHAR,
|
||||
calledback BOOLEAN DEFAULT FALSE,
|
||||
callback_failed BOOLEAN DEFAULT FALSE,
|
||||
inserted_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX idx_lninvoice_label ON ln_invoice (label);
|
||||
CREATE INDEX idx_lninvoice_bolt11 ON ln_invoice (bolt11);
|
||||
CREATE INDEX idx_lninvoice_calledback ON ln_invoice (calledback);
|
||||
CREATE INDEX idx_lninvoice_callback_failed ON ln_invoice (callback_failed);
|
||||
|
||||
COMMIT;
|
||||
@@ -1,27 +0,0 @@
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TABLE rawtx (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
txid TEXT UNIQUE,
|
||||
hash TEXT UNIQUE,
|
||||
confirmations INTEGER DEFAULT 0,
|
||||
timereceived INTEGER,
|
||||
fee REAL,
|
||||
size INTEGER,
|
||||
vsize INTEGER,
|
||||
is_replaceable INTEGER,
|
||||
blockhash TEXT,
|
||||
blockheight INTEGER,
|
||||
blocktime INTEGER,
|
||||
conf_target INTEGER,
|
||||
raw_tx TEXT,
|
||||
inserted_ts INTEGER DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX idx_rawtx_timereceived ON rawtx (timereceived);
|
||||
CREATE INDEX idx_rawtx_fee ON rawtx (fee);
|
||||
CREATE INDEX idx_rawtx_size ON rawtx (size);
|
||||
CREATE INDEX idx_rawtx_vsize ON rawtx (vsize);
|
||||
CREATE INDEX idx_rawtx_blockhash ON rawtx (blockhash);
|
||||
CREATE INDEX idx_rawtx_blockheight ON rawtx (blockheight);
|
||||
CREATE INDEX idx_rawtx_blocktime ON rawtx (blocktime);
|
||||
CREATE INDEX idx_rawtx_confirmations ON rawtx (confirmations);
|
||||
@@ -1,17 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Checking for rawtx database support in DB..."
|
||||
if [ ! -e ${DB_FILE}_rawtx ]; then
|
||||
# rawtx database not found
|
||||
echo "Migrating database for rawtx database support..."
|
||||
echo "Checking for new indexes in DB..."
|
||||
sqlite3 $DB_FILE ".indexes" | grep "idx_watching_watching" > /dev/null
|
||||
if [ "$?" -eq "1" ]; then
|
||||
# idx_watching_watching index not found
|
||||
echo "Migrating database with new indexes..."
|
||||
echo "Backing up current DB..."
|
||||
cp $DB_FILE $DB_FILE-sqlmigrate20210928_0.7.0-0.8.0
|
||||
echo "Altering DB..."
|
||||
cat sqlmigrate20210928_0.7.0-0.8.0.sql | sqlite3 $DB_FILE
|
||||
echo "Creating new DB..."
|
||||
cat rawtx.sql | sqlite3 ${DB_FILE}_rawtx
|
||||
echo "Inserting table in new DB..."
|
||||
sqlite3 -cmd ".timeout 25000" ${DB_FILE} "ATTACH DATABASE \"${DB_FILE}_rawtx\" AS other; INSERT INTO other.rawtx SELECT * FROM tx; DETACH other;"
|
||||
else
|
||||
echo "rawtx database support migration already done, skipping!"
|
||||
echo "New indexes migration already done, skipping!"
|
||||
fi
|
||||
|
||||
36
proxy_docker/app/data/sqlmigrate20211105_0.7.0-0.8.0.sh
Normal file
36
proxy_docker/app/data/sqlmigrate20211105_0.7.0-0.8.0.sh
Normal file
@@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Waiting for postgres to be ready..."
|
||||
(while true ; do psql -h postgres -U cyphernode -c "select 1;" ; [ "$?" -eq "0" ] && break ; sleep 10; done) &
|
||||
wait
|
||||
|
||||
echo "Checking if postgres is setup..."
|
||||
psql -h postgres -U cyphernode -c "\d" | grep "cyphernode_props" > /dev/null
|
||||
if [ "$?" -eq "1" ]; then
|
||||
# if cyphernode_props table doesn't exist, it's probably because database hasn't been setup yet
|
||||
echo "Creating postgres database..."
|
||||
psql -h postgres -f cyphernode.postgresql -U cyphernode
|
||||
|
||||
echo "Extracting and converting sqlite3 data..."
|
||||
cat sqlmigrate20211105_0.7.0-0.8.0_sqlite3-extract.sql | sqlite3 $DB_FILE
|
||||
sed -ie 's/^\(INSERT.*\);$/\1 ON CONFLICT DO NOTHING;/g' sqlmigrate20211105_0.7.0-0.8.0_sqlite3-extracted-data.sql
|
||||
|
||||
echo "...appending postgresql sequences..."
|
||||
echo "
|
||||
select setval('cyphernode_props_id_seq', (SELECT MAX(id) FROM cyphernode_props));
|
||||
select setval('ln_invoice_id_seq', (SELECT MAX(id) FROM ln_invoice));
|
||||
select setval('recipient_id_seq', (SELECT MAX(id) FROM recipient));
|
||||
select setval('stamp_id_seq', (SELECT MAX(id) FROM stamp));
|
||||
select setval('tx_id_seq', (SELECT MAX(id) FROM tx));
|
||||
select setval('watching_by_pub32_id_seq', (SELECT MAX(id) FROM watching_by_pub32));
|
||||
select setval('watching_by_txid_id_seq', (SELECT MAX(id) FROM watching_by_txid));
|
||||
select setval('watching_id_seq', (SELECT MAX(id) FROM watching));
|
||||
select setval('batcher_id_seq', (SELECT MAX(id) FROM batcher));
|
||||
commit;
|
||||
" >> sqlmigrate20211105_0.7.0-0.8.0_sqlite3-extracted-data.sql
|
||||
|
||||
echo "Importing sqlite3 data into postgresql..."
|
||||
psql -h postgres -f sqlmigrate20211105_0.7.0-0.8.0_sqlite3-extracted-data.sql -U cyphernode
|
||||
else
|
||||
echo "New indexes migration already done, skipping!"
|
||||
fi
|
||||
@@ -0,0 +1,24 @@
|
||||
.output sqlmigrate20211105_0.7.0-0.8.0_sqlite3-extracted-data.sql
|
||||
select "BEGIN;";
|
||||
.headers on
|
||||
.mode insert watching_by_pub32
|
||||
select id,pub32,label,derivation_path,callback0conf,callback1conf,last_imported_n,case when watching=1 then 'TRUE' else 'FALSE' end as watching,inserted_ts from watching_by_pub32;
|
||||
.mode insert watching
|
||||
select id,address,label,case when watching=1 then 'TRUE' else 'FALSE' end as watching,callback0conf,case when calledback0conf=1 then 'TRUE' else 'FALSE' end as calledback0conf,callback1conf,case when calledback1conf=1 then 'TRUE' else 'FALSE' end as calledback1conf,case when imported=1 then 'TRUE' else 'FALSE' end as imported,watching_by_pub32_id,pub32_index,event_message,inserted_ts from watching;
|
||||
.mode insert tx
|
||||
select id,txid,hash,confirmations,timereceived,fee,size,vsize,case when is_replaceable=1 then 'TRUE' else 'FALSE' end as is_replaceable,blockhash,blockheight,blocktime,conf_target,inserted_ts from tx;
|
||||
.mode insert watching_tx
|
||||
select * from watching_tx;
|
||||
.mode insert batcher
|
||||
select * from batcher;
|
||||
.mode insert recipient
|
||||
select id,address,amount,tx_id,inserted_ts,webhook_url,case when calledback=1 then 'TRUE' else 'FALSE' end as calledback,calledback_ts,batcher_id,label from recipient;
|
||||
.mode insert watching_by_txid
|
||||
select id,txid,case when watching=1 then 'TRUE' else 'FALSE' end as watching,callback1conf,case when calledback1conf=1 then 'TRUE' else 'FALSE' end as calledback1conf,callbackxconf,case when calledbackxconf=1 then 'TRUE' else 'FALSE' end as calledbackxconf,nbxconf,inserted_ts from watching_by_txid;
|
||||
.mode insert stamp
|
||||
select id,hash,callbackUrl,case when requested=1 then 'TRUE' else 'FALSE' end as requested,case when upgraded=1 then 'TRUE' else 'FALSE' end as upgraded,case when calledback=1 then 'TRUE' else 'FALSE' end as calledback,inserted_ts from stamp;
|
||||
.mode insert cyphernode_props
|
||||
select * from cyphernode_props;
|
||||
.mode insert ln_invoice
|
||||
select id,label,bolt11,payment_hash,msatoshi,status,pay_index,msatoshi_received,paid_at,description,expires_at,callback_url,case when calledback=1 then 'TRUE' else 'FALSE' end as calledback,case when callback_failed=1 then 'TRUE' else 'FALSE' end as callback_failed,inserted_ts from ln_invoice;
|
||||
.quit
|
||||
@@ -22,7 +22,8 @@ createbatcher() {
|
||||
|
||||
local request=${1}
|
||||
local response
|
||||
local label=$(echo "${request}" | jq ".batcherLabel")
|
||||
local returncode
|
||||
local label=$(echo "${request}" | jq -r ".batcherLabel")
|
||||
trace "[createbatcher] label=${label}"
|
||||
local conf_target=$(echo "${request}" | jq ".confTarget")
|
||||
trace "[createbatcher] conf_target=${conf_target}"
|
||||
@@ -37,13 +38,18 @@ createbatcher() {
|
||||
|
||||
local batcher_id
|
||||
|
||||
batcher_id=$(sql "INSERT OR IGNORE INTO batcher (label, conf_target, feerate) VALUES (${label}, ${conf_target}, ${feerate}); SELECT LAST_INSERT_ROWID();")
|
||||
batcher_id=$(sql "INSERT INTO batcher (label, conf_target, feerate)"\
|
||||
" VALUES ('${label}', ${conf_target}, ${feerate})"\
|
||||
" RETURNING id" \
|
||||
"SELECT id FROM batcher WHERE label='${label}'")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
if ("${batcher_id}" -eq "0"); then
|
||||
if ("${returncode}" -ne "0"); then
|
||||
trace "[createbatcher] Could not insert"
|
||||
response='{"result":null,"error":{"code":-32700,"message":"Could not create batcher, label probably already exists","data":'${request}'}}'
|
||||
else
|
||||
trace "[createbatcher] Inserted"
|
||||
trace "[createbatcher] Inserted, response=${batcher_id}"
|
||||
response='{"result":{"batcherId":'${batcher_id}'},"error":null}'
|
||||
fi
|
||||
|
||||
@@ -79,7 +85,7 @@ updatebatcher() {
|
||||
|
||||
local id=$(echo "${request}" | jq ".batcherId")
|
||||
trace "[updatebatcher] id=${id}"
|
||||
local label=$(echo "${request}" | jq ".batcherLabel")
|
||||
local label=$(echo "${request}" | jq -r ".batcherLabel")
|
||||
trace "[updatebatcher] label=${label}"
|
||||
local conf_target=$(echo "${request}" | jq ".confTarget")
|
||||
trace "[updatebatcher] conf_target=${conf_target}"
|
||||
@@ -99,12 +105,12 @@ updatebatcher() {
|
||||
# fi
|
||||
|
||||
if [ "${id}" = "null" ]; then
|
||||
whereclause="label=${label}"
|
||||
whereclause="label='${label}'"
|
||||
else
|
||||
whereclause="id = ${id}"
|
||||
fi
|
||||
|
||||
sql "UPDATE batcher set label=${label}, conf_target=${conf_target}, feerate=${feerate} WHERE ${whereclause}"
|
||||
sql "UPDATE batcher set label='${label}', conf_target=${conf_target}, feerate=${feerate} WHERE ${whereclause}"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
if [ "${returncode}" -ne 0 ]; then
|
||||
@@ -151,13 +157,13 @@ addtobatch() {
|
||||
trace "[addtobatch] address=${address}"
|
||||
local amount=$(echo "${request}" | jq ".amount")
|
||||
trace "[addtobatch] amount=${amount}"
|
||||
local label=$(echo "${request}" | jq ".outputLabel")
|
||||
local label=$(echo "${request}" | jq -r ".outputLabel")
|
||||
trace "[addtobatch] label=${label}"
|
||||
local batcher_id=$(echo "${request}" | jq ".batcherId")
|
||||
trace "[addtobatch] batcher_id=${batcher_id}"
|
||||
local batcher_label=$(echo "${request}" | jq ".batcherLabel")
|
||||
local batcher_label=$(echo "${request}" | jq -r ".batcherLabel")
|
||||
trace "[addtobatch] batcher_label=${batcher_label}"
|
||||
local webhook_url=$(echo "${request}" | jq ".webhookUrl")
|
||||
local webhook_url=$(echo "${request}" | jq -r ".webhookUrl")
|
||||
trace "[addtobatch] webhook_url=${webhook_url}"
|
||||
|
||||
# Let's lowercase bech32 addresses
|
||||
@@ -185,7 +191,7 @@ addtobatch() {
|
||||
|
||||
if [ "${batcher_id}" = "null" ]; then
|
||||
# Using batcher_label
|
||||
batcher_id=$(sql "SELECT id FROM batcher WHERE label=${batcher_label}")
|
||||
batcher_id=$(sql "SELECT id FROM batcher WHERE label='${batcher_label}'")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
fi
|
||||
@@ -195,7 +201,7 @@ addtobatch() {
|
||||
response='{"result":null,"error":{"code":-32700,"message":"batcher not found","data":'${request}'}}'
|
||||
else
|
||||
# Check if address already pending for this batcher...
|
||||
inserted_id=$(sql "SELECT id FROM recipient WHERE LOWER(address)=LOWER(\"${address}\") AND tx_id IS NULL AND batcher_id=${batcher_id}")
|
||||
inserted_id=$(sql "SELECT id FROM recipient WHERE LOWER(address)=LOWER('${address}') AND tx_id IS NULL AND batcher_id=${batcher_id}")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -211,7 +217,9 @@ addtobatch() {
|
||||
fi
|
||||
|
||||
# Insert the new destination
|
||||
inserted_id=$(sql "INSERT INTO recipient (address, amount, webhook_url, batcher_id, label) VALUES (\"${address}\", ${amount}, ${webhook_url}, ${batcher_id}, ${label}); SELECT LAST_INSERT_ROWID();")
|
||||
inserted_id=$(sql "INSERT INTO recipient (address, amount, webhook_url, batcher_id, label)"\
|
||||
" VALUES ('${address}', ${amount}, '${webhook_url}', ${batcher_id}, '${label}')"\
|
||||
" RETURNING id")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -280,7 +288,7 @@ removefrombatch() {
|
||||
if [ "${returncode}" -ne 0 ]; then
|
||||
response='{"result":null,"error":{"code":-32700,"message":"Output was not removed","data":'${request}'}}'
|
||||
else
|
||||
row=$(sql "SELECT COUNT(id), COALESCE(MIN(inserted_ts), 0), COALESCE(SUM(amount), 0.00000000) FROM recipient WHERE tx_id IS NULL AND batcher_id=${batcher_id}")
|
||||
row=$(sql "SELECT COUNT(id), COALESCE(MIN(inserted_ts), DATE '0001-01-01'), COALESCE(SUM(amount), 0.00000000) FROM recipient WHERE tx_id IS NULL AND batcher_id=${batcher_id}")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -336,7 +344,7 @@ batchspend() {
|
||||
|
||||
local batcher_id=$(echo "${request}" | jq ".batcherId")
|
||||
trace "[batchspend] batcher_id=${batcher_id}"
|
||||
local batcher_label=$(echo "${request}" | jq ".batcherLabel")
|
||||
local batcher_label=$(echo "${request}" | jq -r ".batcherLabel")
|
||||
trace "[batchspend] batcher_label=${batcher_label}"
|
||||
local conf_target=$(echo "${request}" | jq ".confTarget")
|
||||
trace "[batchspend] conf_target=${conf_target}"
|
||||
@@ -351,7 +359,7 @@ batchspend() {
|
||||
|
||||
if [ "${batcher_id}" = "null" ]; then
|
||||
# Using batcher_label
|
||||
whereclause="label=${batcher_label}"
|
||||
whereclause="label='${batcher_label}'"
|
||||
else
|
||||
whereclause="id=${batcher_id}"
|
||||
fi
|
||||
@@ -423,11 +431,11 @@ batchspend() {
|
||||
trace "[batchspend] webhook_url=${webhook_url}"
|
||||
|
||||
if [ -z "${recipientsjson}" ]; then
|
||||
whereclause="\"${recipient_id}\""
|
||||
whereclause="${recipient_id}"
|
||||
recipientsjson="\"${address}\":${amount}"
|
||||
webhooks_data="{\"outputId\":${recipient_id},\"address\":\"${address}\",\"amount\":${amount},\"webhookUrl\":\"${webhook_url}\"}"
|
||||
else
|
||||
whereclause="${whereclause},\"${recipient_id}\""
|
||||
whereclause="${whereclause},${recipient_id}"
|
||||
recipientsjson="${recipientsjson},\"${address}\":${amount}"
|
||||
webhooks_data="${webhooks_data},{\"outputId\":${recipient_id},\"address\":\"${address}\",\"amount\":${amount},\"webhookUrl\":\"${webhook_url}\"}"
|
||||
fi
|
||||
@@ -452,7 +460,7 @@ batchspend() {
|
||||
tx_raw_details=$(get_rawtransaction ${txid} | tr -d '\n')
|
||||
|
||||
# Amounts and fees are negative when spending so we absolute those fields
|
||||
local tx_hash=$(echo "${tx_raw_details}" | jq '.result.hash')
|
||||
local tx_hash=$(echo "${tx_raw_details}" | jq -r '.result.hash')
|
||||
local tx_ts_firstseen=$(echo "${tx_details}" | jq '.result.timereceived')
|
||||
local tx_amount=$(echo "${tx_details}" | jq '.result.amount | fabs' | awk '{ printf "%.8f", $0 }')
|
||||
local tx_size=$(echo "${tx_raw_details}" | jq '.result.size')
|
||||
@@ -462,25 +470,20 @@ batchspend() {
|
||||
tx_replaceable=$([ "${tx_replaceable}" = "yes" ] && echo "true" || echo "false")
|
||||
trace "[batchspend] tx_replaceable=${tx_replaceable}"
|
||||
local fees=$(echo "${tx_details}" | jq '.result.fee | fabs' | awk '{ printf "%.8f", $0 }')
|
||||
# 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}" > batchspend-rawtx-${txid}-$$.blob
|
||||
|
||||
# Get the info on the batch before setting it to done
|
||||
row=$(sql "SELECT COUNT(id), COALESCE(MIN(inserted_ts), 0), COALESCE(SUM(amount), 0.00000000) FROM recipient WHERE tx_id IS NULL AND batcher_id=${batcher_id}")
|
||||
row=$(sql "SELECT COUNT(id), COALESCE(MIN(inserted_ts), DATE '0001-01-01'), COALESCE(SUM(amount), 0.00000000) FROM recipient WHERE tx_id IS NULL AND batcher_id=${batcher_id}")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
# Let's insert the txid in our little DB -- then we'll already have it when receiving confirmation
|
||||
sql_rawtx "INSERT OR IGNORE INTO rawtx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, conf_target, raw_tx) VALUES (\"${txid}\", ${tx_hash}, 0, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${conf_target}, readfile('batchspend-rawtx-${txid}-$$.blob'))"
|
||||
trace_rc $?
|
||||
id_inserted=$(sql "INSERT OR IGNORE INTO tx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, conf_target) VALUES (\"${txid}\", ${tx_hash}, 0, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${conf_target}); SELECT LAST_INSERT_ROWID();")
|
||||
id_inserted=$(sql "INSERT INTO tx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, conf_target)"\
|
||||
" VALUES ('${txid}', '${tx_hash}', 0, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${conf_target})"\
|
||||
" RETURNING id" \
|
||||
"SELECT id FROM tx WHERE txid='${txid}'")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
if [ "${id_inserted}" -eq 0 ]; then
|
||||
id_inserted=$(sql "SELECT id FROM tx WHERE txid=\"${txid}\"")
|
||||
fi
|
||||
trace "[batchspend] id_inserted: ${id_inserted}"
|
||||
sql "UPDATE recipient SET tx_id=${id_inserted} WHERE id IN (${whereclause})"
|
||||
trace_rc $?
|
||||
@@ -495,13 +498,10 @@ batchspend() {
|
||||
trace "[batchspend] total=${total}"
|
||||
|
||||
response='{"result":{"batcherId":'${batcher_id}',"confTarget":'${conf_target}',"nbOutputs":'${count}',"oldest":"'${oldest}'","total":'${total}
|
||||
response="${response},\"status\":\"accepted\",\"txid\":\"${txid}\",\"hash\":${tx_hash},\"details\":{\"firstseen\":${tx_ts_firstseen},\"size\":${tx_size},\"vsize\":${tx_vsize},\"replaceable\":${tx_replaceable},\"fee\":${fees}},\"outputs\":[${webhooks_data}]}"
|
||||
response="${response},\"status\":\"accepted\",\"txid\":\"${txid}\",\"hash\":\"${tx_hash}\",\"details\":{\"firstseen\":${tx_ts_firstseen},\"size\":${tx_size},\"vsize\":${tx_vsize},\"replaceable\":${tx_replaceable},\"fee\":${fees}},\"outputs\":[${webhooks_data}]}"
|
||||
response="${response},\"error\":null}"
|
||||
|
||||
# Delete the temp file containing the raw tx (see above)
|
||||
rm batchspend-rawtx-${txid}-$$.blob
|
||||
|
||||
batch_webhooks "[${webhooks_data}]" '"batcherId":'${batcher_id}',"confTarget":'${conf_target}',"nbOutputs":'${count}',"oldest":"'${oldest}'","total":'${total}',"status":"accepted","txid":"'${txid}'","hash":'${tx_hash}',"details":{"firstseen":'${tx_ts_firstseen}',"size":'${tx_size}',"vsize":'${tx_vsize}',"replaceable":'${tx_replaceable}',"fee":'${fees}'}'
|
||||
batch_webhooks "[${webhooks_data}]" '"batcherId":'${batcher_id}',"confTarget":'${conf_target}',"nbOutputs":'${count}',"oldest":"'${oldest}'","total":'${total}',"status":"accepted","txid":"'${txid}'","hash":"'${tx_hash}'","details":{"firstseen":'${tx_ts_firstseen}',"size":'${tx_size}',"vsize":'${tx_vsize}',"replaceable":'${tx_replaceable}',"fee":'${fees}'}'
|
||||
|
||||
else
|
||||
local message=$(echo "${data}" | jq -e ".error.message")
|
||||
@@ -578,7 +578,7 @@ batch_check_webhooks() {
|
||||
# I know this query for each output is not very efficient, but this function should not execute often, only in case of
|
||||
# failed callbacks on batches...
|
||||
# Get the info on the batch
|
||||
row=$(sql "SELECT COUNT(id), COALESCE(MIN(inserted_ts), 0), COALESCE(SUM(amount), 0.00000000) FROM recipient r WHERE tx_id=\"${tx_id}\"")
|
||||
row=$(sql "SELECT COUNT(id), COALESCE(MIN(inserted_ts), DATE '0001-01-01'), COALESCE(SUM(amount), 0.00000000) FROM recipient r WHERE tx_id='${tx_id}'")
|
||||
|
||||
# Use the selected row above
|
||||
count=$(echo "${row}" | cut -d '|' -f1)
|
||||
@@ -654,7 +654,7 @@ batch_webhooks() {
|
||||
fi
|
||||
done
|
||||
|
||||
sql "UPDATE recipient SET calledback=1, calledback_ts=CURRENT_TIMESTAMP WHERE id IN (${successful_recipient_ids})"
|
||||
sql "UPDATE recipient SET calledback=true, calledback_ts=CURRENT_TIMESTAMP WHERE id IN (${successful_recipient_ids})"
|
||||
trace_rc $?
|
||||
}
|
||||
|
||||
@@ -671,7 +671,7 @@ listbatchers() {
|
||||
# "error":null}
|
||||
|
||||
|
||||
local batchers=$(sql "SELECT b.id, '{\"batcherId\":' || b.id || ',\"batcherLabel\":\"' || b.label || '\",\"confTarget\":' || conf_target || ',\"nbOutputs\":' || COUNT(r.id) || ',\"oldest\":\"' ||COALESCE(MIN(r.inserted_ts), 0) || '\",\"total\":' ||COALESCE(SUM(amount), 0.00000000) || '}' FROM batcher b LEFT JOIN recipient r ON r.batcher_id=b.id AND r.tx_id IS NULL GROUP BY b.id")
|
||||
local batchers=$(sql "SELECT b.id, '{\"batcherId\":' || b.id || ',\"batcherLabel\":\"' || b.label || '\",\"confTarget\":' || conf_target || ',\"nbOutputs\":' || COUNT(r.id) || ',\"oldest\":\"' ||COALESCE(MIN(r.inserted_ts), DATE '0001-01-01') || '\",\"total\":' ||COALESCE(SUM(amount), 0.00000000) || '}' FROM batcher b LEFT JOIN recipient r ON r.batcher_id=b.id AND r.tx_id IS NULL GROUP BY b.id ORDER BY b.id")
|
||||
trace "[listbatchers] batchers=${batchers}"
|
||||
|
||||
local returncode
|
||||
@@ -717,7 +717,7 @@ getbatcher() {
|
||||
|
||||
local batcher_id=$(echo "${request}" | jq ".batcherId")
|
||||
trace "[getbatcher] batcher_id=${batcher_id}"
|
||||
local batcher_label=$(echo "${request}" | jq ".batcherLabel")
|
||||
local batcher_label=$(echo "${request}" | jq -r ".batcherLabel")
|
||||
trace "[getbatcher] batcher_label=${batcher_label}"
|
||||
|
||||
if [ "${batcher_id}" = "null" ] && [ "${batcher_label}" = "null" ]; then
|
||||
@@ -728,13 +728,13 @@ getbatcher() {
|
||||
|
||||
if [ "${batcher_id}" = "null" ]; then
|
||||
# Using batcher_label
|
||||
whereclause="b.label=${batcher_label}"
|
||||
whereclause="b.label='${batcher_label}'"
|
||||
else
|
||||
# Using batcher_id
|
||||
whereclause="b.id=${batcher_id}"
|
||||
fi
|
||||
|
||||
batcher=$(sql "SELECT b.id, '{\"batcherId\":' || b.id || ',\"batcherLabel\":\"' || b.label || '\",\"confTarget\":' || conf_target || ',\"nbOutputs\":' || COUNT(r.id) || ',\"oldest\":\"' ||COALESCE(MIN(r.inserted_ts), 0) || '\",\"total\":' ||COALESCE(SUM(amount), 0.00000000) || '}' FROM batcher b LEFT JOIN recipient r ON r.batcher_id=b.id AND r.tx_id IS NULL WHERE ${whereclause} GROUP BY b.id")
|
||||
batcher=$(sql "SELECT b.id, '{\"batcherId\":' || b.id || ',\"batcherLabel\":\"' || b.label || '\",\"confTarget\":' || conf_target || ',\"nbOutputs\":' || COUNT(r.id) || ',\"oldest\":\"' ||COALESCE(MIN(r.inserted_ts), DATE '0001-01-01') || '\",\"total\":' ||COALESCE(SUM(amount), 0.00000000) || '}' FROM batcher b LEFT JOIN recipient r ON r.batcher_id=b.id AND r.tx_id IS NULL WHERE ${whereclause} GROUP BY b.id")
|
||||
trace "[getbatcher] batcher=${batcher}"
|
||||
|
||||
if [ -n "${batcher}" ]; then
|
||||
@@ -797,9 +797,9 @@ getbatchdetails() {
|
||||
|
||||
local batcher_id=$(echo "${request}" | jq ".batcherId")
|
||||
trace "[getbatchdetails] batcher_id=${batcher_id}"
|
||||
local batcher_label=$(echo "${request}" | jq ".batcherLabel")
|
||||
local batcher_label=$(echo "${request}" | jq -r ".batcherLabel")
|
||||
trace "[getbatchdetails] batcher_label=${batcher_label}"
|
||||
local txid=$(echo "${request}" | jq ".txid")
|
||||
local txid=$(echo "${request}" | jq -r ".txid")
|
||||
trace "[getbatchdetails] txid=${txid}"
|
||||
|
||||
if [ "${batcher_id}" = "null" ] && [ "${batcher_label}" = "null" ]; then
|
||||
@@ -810,7 +810,7 @@ getbatchdetails() {
|
||||
|
||||
if [ "${batcher_id}" = "null" ]; then
|
||||
# Using batcher_label
|
||||
whereclause="b.label=${batcher_label}"
|
||||
whereclause="b.label='${batcher_label}'"
|
||||
else
|
||||
# Using batcher_id
|
||||
whereclause="b.id=${batcher_id}"
|
||||
@@ -818,7 +818,7 @@ getbatchdetails() {
|
||||
|
||||
if [ "${txid}" != "null" ]; then
|
||||
# Using txid
|
||||
whereclause="${whereclause} AND t.txid=${txid}"
|
||||
whereclause="${whereclause} AND t.txid='${txid}'"
|
||||
else
|
||||
# null txid
|
||||
whereclause="${whereclause} AND t.txid IS NULL"
|
||||
@@ -826,7 +826,7 @@ getbatchdetails() {
|
||||
fi
|
||||
|
||||
# First get the batch summary
|
||||
batch=$(sql "SELECT b.id, COALESCE(t.id, NULL), '{\"batcherId\":' || b.id || ',\"batcherLabel\":\"' || b.label || '\",\"confTarget\":' || b.conf_target || ',\"nbOutputs\":' || COUNT(r.id) || ',\"oldest\":\"' ||COALESCE(MIN(r.inserted_ts), 0) || '\",\"total\":' ||COALESCE(SUM(amount), 0.00000000) FROM batcher b LEFT JOIN recipient r ON r.batcher_id=b.id ${outerclause} LEFT JOIN tx t ON t.id=r.tx_id WHERE ${whereclause} GROUP BY b.id")
|
||||
batch=$(sql "SELECT b.id, COALESCE(t.id, NULL), '{\"batcherId\":' || b.id || ',\"batcherLabel\":\"' || b.label || '\",\"confTarget\":' || b.conf_target || ',\"nbOutputs\":' || COUNT(r.id) || ',\"oldest\":\"' ||COALESCE(MIN(r.inserted_ts), DATE '0001-01-01') || '\",\"total\":' ||COALESCE(SUM(amount), 0.00000000) FROM batcher b LEFT JOIN recipient r ON r.batcher_id=b.id ${outerclause} LEFT JOIN tx t ON t.id=r.tx_id WHERE ${whereclause} GROUP BY b.id, t.id")
|
||||
trace "[getbatchdetails] batch=${batch}"
|
||||
|
||||
if [ -n "${batch}" ]; then
|
||||
@@ -839,7 +839,7 @@ getbatchdetails() {
|
||||
# Using txid
|
||||
outerclause="AND r.tx_id=${tx_id}"
|
||||
|
||||
tx=$(sql "SELECT '\"txid\":\"' || txid || '\",\"hash\":\"' || hash || '\",\"details\":{\"firstseen\":' || timereceived || ',\"size\":' || size || ',\"vsize\":' || vsize || ',\"replaceable\":' || CASE is_replaceable WHEN 1 THEN 'true' ELSE 'false' END || ',\"fee\":' || fee || '}' FROM tx WHERE id=${tx_id}")
|
||||
tx=$(sql "SELECT '\"txid\":\"' || txid || '\",\"hash\":\"' || hash || '\",\"details\":{\"firstseen\":' || timereceived || ',\"size\":' || size || ',\"vsize\":' || vsize || ',\"replaceable\":' || CASE is_replaceable WHEN true THEN 'true' ELSE 'false' END || ',\"fee\":' || fee || '}' FROM tx WHERE id=${tx_id}")
|
||||
else
|
||||
# null txid
|
||||
outerclause="AND r.tx_id IS NULL"
|
||||
|
||||
@@ -78,6 +78,14 @@ convert_pub32() {
|
||||
local checksum
|
||||
local pub32_dest
|
||||
|
||||
case "${pub32_from}" in
|
||||
${to_type}*)
|
||||
trace "[convert_pub32] Already in the right format, exiting"
|
||||
echo "${pub32_from}"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${to_type}" in
|
||||
tpub)
|
||||
versionbytes="043587cf"
|
||||
|
||||
@@ -8,8 +8,8 @@ ln_call_lightningd() {
|
||||
local response
|
||||
local returncode
|
||||
|
||||
trace "[ln_call_lightningd] ./lightning-cli $@"
|
||||
response=$(./lightning-cli $@)
|
||||
trace "[ln_call_lightningd] ./lightning-cli $(printf " \"%s\"" "$@")"
|
||||
response=$(./lightning-cli "$@")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -39,7 +39,7 @@ ln_create_invoice() {
|
||||
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}\""
|
||||
callback_url="'${callback_url}'"
|
||||
fi
|
||||
|
||||
#/proxy $ ./lightning-cli invoice 10000 "t1" "t1d" 60
|
||||
@@ -71,36 +71,33 @@ ln_create_invoice() {
|
||||
# Let's get the connect string if provided in configuration
|
||||
local connectstring=$(get_connection_string)
|
||||
|
||||
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 $?
|
||||
id=$(sql "SELECT id FROM ln_invoice WHERE bolt11=\"${bolt11}\"")
|
||||
id=$(sql "INSERT 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')"\
|
||||
" RETURNING id" \
|
||||
"SELECT id FROM ln_invoice WHERE bolt11='${bolt11}'")
|
||||
trace_rc $?
|
||||
|
||||
# {
|
||||
# "id":"",
|
||||
# "id":123,
|
||||
# "label":"",
|
||||
# "bolt11":"",
|
||||
# "connectstring":"",
|
||||
# "callbackUrl":"",
|
||||
# "payment_hash":"",
|
||||
# "msatoshi":,
|
||||
# "msatoshi":123456,
|
||||
# "status":"unpaid",
|
||||
# "description":"",
|
||||
# "expires_at":
|
||||
# "expires_at":21312312
|
||||
# }
|
||||
|
||||
data="{\"id\":\"${id}\","
|
||||
data="{\"id\":${id},"
|
||||
data="${data}\"label\":\"${label}\","
|
||||
data="${data}\"bolt11\":\"${bolt11}\","
|
||||
if [ -n "${connectstring}" ]; then
|
||||
data="${data}\"connectstring\":\"${connectstring}\","
|
||||
fi
|
||||
if [ "${callback_url}" != "null" ]; then
|
||||
data="${data}\"callbackUrl\":${callback_url},"
|
||||
data="${data}\"callbackUrl\":\"${callback_url}\","
|
||||
fi
|
||||
data="${data}\"payment_hash\":\"${payment_hash}\","
|
||||
if [ "${msatoshi}" != "null" ]; then
|
||||
|
||||
@@ -10,8 +10,17 @@ do_callbacks() {
|
||||
|
||||
trace "Entering do_callbacks()..."
|
||||
|
||||
# If called because we received a confirmation for a specific txid, let's only
|
||||
# process that txid-related callbacks...
|
||||
local txid=${1}
|
||||
local txid_where
|
||||
if [ -n "${txid}" ]; then
|
||||
trace "[do_callbacks] txid=${txid}"
|
||||
txid_where=" AND txid='${txid}'"
|
||||
fi
|
||||
|
||||
# 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, w32.label, derivation_path, event_message, hash 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, w32.label, derivation_path, event_message, hash 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 w.watching_by_pub32_id = w32.id WHERE NOT calledback0conf AND watching_id IS NOT NULL AND w.callback0conf IS NOT NULL AND w.watching${txid_where}")
|
||||
trace "[do_callbacks] callbacks0conf=${callbacks}"
|
||||
|
||||
local returncode
|
||||
@@ -25,12 +34,12 @@ do_callbacks() {
|
||||
trace_rc ${returncode}
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
address=$(echo "${row}" | cut -d '|' -f2)
|
||||
sql "UPDATE watching SET calledback0conf=1 WHERE address=\"${address}\""
|
||||
sql "UPDATE watching SET calledback0conf=true WHERE address='${address}'"
|
||||
trace_rc $?
|
||||
fi
|
||||
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, w32.label, derivation_path, event_message, hash 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, w32.label, derivation_path, event_message, hash FROM watching w JOIN watching_tx wt ON w.id = wt.watching_id JOIN tx t ON wt.tx_id = t.id LEFT JOIN watching_by_pub32 w32 ON watching_by_pub32_id = w32.id WHERE NOT calledback1conf AND confirmations>0 AND w.callback1conf IS NOT NULL AND w.watching${txid_where}")
|
||||
trace "[do_callbacks] callbacks1conf=${callbacks}"
|
||||
|
||||
for row in ${callbacks}
|
||||
@@ -39,19 +48,25 @@ do_callbacks() {
|
||||
returncode=$?
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
address=$(echo "${row}" | cut -d '|' -f2)
|
||||
sql "UPDATE watching SET calledback1conf=1, watching=0 WHERE address=\"${address}\""
|
||||
sql "UPDATE watching SET calledback1conf=true, watching=false WHERE address='${address}'"
|
||||
trace_rc $?
|
||||
fi
|
||||
done
|
||||
|
||||
callbacks=$(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 callback_failed")
|
||||
trace "[do_callbacks] ln_callbacks=${callbacks}"
|
||||
if [ -z "${txid}" ]; then
|
||||
trace "[do_callbacks] Processing LN callbacks..."
|
||||
|
||||
for row in ${callbacks}
|
||||
do
|
||||
ln_manage_callback ${row}
|
||||
trace_rc $?
|
||||
done
|
||||
callbacks=$(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 callback_failed")
|
||||
trace "[do_callbacks] ln_callbacks=${callbacks}"
|
||||
|
||||
for row in ${callbacks}
|
||||
do
|
||||
ln_manage_callback ${row}
|
||||
trace_rc $?
|
||||
done
|
||||
else
|
||||
trace "[do_callbacks] called for a specific txid, skipping LN callbacks"
|
||||
fi
|
||||
|
||||
) 200>./.callbacks.lock
|
||||
}
|
||||
@@ -70,7 +85,7 @@ ln_manage_callback() {
|
||||
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}\""
|
||||
sql "UPDATE ln_invoice SET calledback=true WHERE id=${id}"
|
||||
trace_rc $?
|
||||
return
|
||||
fi
|
||||
@@ -112,7 +127,7 @@ ln_manage_callback() {
|
||||
# "expires_at":
|
||||
# }
|
||||
|
||||
data="{\"id\":\"${id}\","
|
||||
data="{\"id\":${id},"
|
||||
data="${data}\"label\":\"${label}\","
|
||||
data="${data}\"bolt11\":\"${bolt11}\","
|
||||
data="${data}\"callback_url\":\"${callback_url}\","
|
||||
@@ -132,11 +147,11 @@ ln_manage_callback() {
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
sql "UPDATE ln_invoice SET calledback=1 WHERE id=\"${id}\""
|
||||
sql "UPDATE ln_invoice SET calledback=true WHERE id=${id}"
|
||||
trace_rc $?
|
||||
else
|
||||
trace "[ln_manage_callback] callback failed: ${callback_url}"
|
||||
sql "UPDATE ln_invoice SET callback_failed=1 WHERE id=\"${id}\""
|
||||
sql "UPDATE ln_invoice SET callback_failed=true WHERE id=${id}"
|
||||
trace_rc $?
|
||||
fi
|
||||
|
||||
@@ -212,7 +227,7 @@ build_callback() {
|
||||
vsize=$(echo "${row}" | cut -d '|' -f10)
|
||||
trace "[build_callback] vsize=${vsize}"
|
||||
is_replaceable=$(echo "${row}" | cut -d '|' -f15)
|
||||
is_replaceable=$([ "${is_replaceable}" -eq "1" ] && echo "true" || echo "false")
|
||||
is_replaceable=$([ "${is_replaceable}" = "t" ] && echo "true" || echo "false")
|
||||
trace "[build_callback] is_replaceable=${is_replaceable}"
|
||||
blockhash=$(echo "${row}" | cut -d '|' -f11)
|
||||
trace "[build_callback] blockhash=${blockhash}"
|
||||
@@ -234,7 +249,7 @@ build_callback() {
|
||||
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}\"txid\":\"${txid}\","
|
||||
data="${data}\"hash\":\"${hash}\","
|
||||
|
||||
@@ -9,8 +9,10 @@ do_callbacks_txid() {
|
||||
|
||||
trace "Entering do_callbacks_txid()..."
|
||||
|
||||
# Let's check the 1-conf (newly mined) watched txid that are included in the new block...
|
||||
|
||||
# Let's fetch all the watching txid still being watched but not called back
|
||||
local callbacks=$(sql 'SELECT id, txid, callback1conf, 1 FROM watching_by_txid WHERE watching AND callback1conf NOT NULL AND NOT calledback1conf')
|
||||
local callbacks=$(sql "SELECT id, txid, callback1conf, 1 FROM watching_by_txid WHERE watching AND callback1conf IS NOT NULL AND NOT calledback1conf")
|
||||
trace "[do_callbacks_txid] callbacks1conf=${callbacks}"
|
||||
|
||||
local returncode
|
||||
@@ -25,14 +27,16 @@ do_callbacks_txid() {
|
||||
trace_rc ${returncode}
|
||||
if [ "${returncode}" -eq "0" ]; then
|
||||
id=$(echo "${row}" | cut -d '|' -f1)
|
||||
sql "UPDATE watching_by_txid SET calledback1conf=1 WHERE id=\"${id}\""
|
||||
sql "UPDATE watching_by_txid SET calledback1conf=true WHERE id=${id}"
|
||||
trace_rc $?
|
||||
else
|
||||
trace "[do_callbacks_txid] callback returncode has error, we don't flag as calledback yet."
|
||||
fi
|
||||
done
|
||||
|
||||
local callbacks=$(sql 'SELECT id, txid, callbackxconf, nbxconf FROM watching_by_txid WHERE watching AND calledback1conf AND callbackxconf NOT NULL AND NOT calledbackxconf')
|
||||
# For the n-conf, let's only check the watched txids that are already at least 1-conf...
|
||||
|
||||
local callbacks=$(sql "SELECT id, txid, callbackxconf, nbxconf FROM watching_by_txid WHERE watching AND calledback1conf AND callbackxconf IS NOT NULL AND NOT calledbackxconf")
|
||||
trace "[do_callbacks_txid] callbacksxconf=${callbacks}"
|
||||
|
||||
for row in ${callbacks}
|
||||
@@ -42,7 +46,7 @@ do_callbacks_txid() {
|
||||
trace_rc ${returncode}
|
||||
if [ "${returncode}" -eq "0" ]; then
|
||||
id=$(echo "${row}" | cut -d '|' -f1)
|
||||
sql "UPDATE watching_by_txid SET calledbackxconf=1, watching=0 WHERE id=\"${id}\""
|
||||
sql "UPDATE watching_by_txid SET calledbackxconf=true, watching=false WHERE id=${id}"
|
||||
trace_rc $?
|
||||
else
|
||||
trace "[do_callbacks_txid] callback returncode has error, we don't flag as calledback yet."
|
||||
|
||||
@@ -64,16 +64,10 @@ compute_vin_total_amount()
|
||||
for vin_txid_vout in ${vin_txids_vout}
|
||||
do
|
||||
vin_txid=$(echo "${vin_txid_vout}" | tr -d '"' | cut -d '-' -f1)
|
||||
# Check if we already have the tx in our DB
|
||||
vin_raw_tx=$(sql_rawtx "SELECT raw_tx FROM rawtx WHERE txid=\"${vin_txid}\"")
|
||||
trace_rc $?
|
||||
if [ -z "${vin_raw_tx}" ]; then
|
||||
txid_already_inserted=false
|
||||
vin_raw_tx=$(get_rawtransaction "${vin_txid}" | tr -d '\n')
|
||||
returncode=$?
|
||||
if [ "${returncode}" -ne 0 ]; then
|
||||
return ${returncode}
|
||||
fi
|
||||
vin_raw_tx=$(get_rawtransaction "${vin_txid}" | tr -d '\n')
|
||||
returncode=$?
|
||||
if [ "${returncode}" -ne 0 ]; then
|
||||
return ${returncode}
|
||||
fi
|
||||
vout=$(echo "${vin_txid_vout}" | tr -d '"' | cut -d '-' -f2)
|
||||
trace "[compute_vin_total_amount] vout=${vout}"
|
||||
@@ -81,27 +75,23 @@ compute_vin_total_amount()
|
||||
trace "[compute_vin_total_amount] vin_vout_amount=${vin_vout_amount}"
|
||||
vin_total_amount=$(awk "BEGIN { printf(\"%.8f\", ${vin_total_amount}+${vin_vout_amount}); exit}")
|
||||
trace "[compute_vin_total_amount] vin_total_amount=${vin_total_amount}"
|
||||
vin_hash=$(echo "${vin_raw_tx}" | jq ".result.hash")
|
||||
vin_hash=$(echo "${vin_raw_tx}" | jq -r ".result.hash")
|
||||
vin_confirmations=$(echo "${vin_raw_tx}" | jq ".result.confirmations")
|
||||
vin_timereceived=$(echo "${vin_raw_tx}" | jq ".result.time")
|
||||
vin_size=$(echo "${vin_raw_tx}" | jq ".result.size")
|
||||
vin_vsize=$(echo "${vin_raw_tx}" | jq ".result.vsize")
|
||||
vin_blockhash=$(echo "${vin_raw_tx}" | jq ".result.blockhash")
|
||||
vin_blockhash=$(echo "${vin_raw_tx}" | jq -r ".result.blockhash")
|
||||
vin_blockheight=$(echo "${vin_raw_tx}" | jq ".result.blockheight")
|
||||
vin_blocktime=$(echo "${vin_raw_tx}" | jq ".result.blocktime")
|
||||
|
||||
# Let's insert the vin tx in the DB just in case it would be useful
|
||||
if ! ${txid_already_inserted}; then
|
||||
# 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 "${vin_raw_tx}" > vin-rawtx-${vin_txid}-$$.blob
|
||||
sql "INSERT OR IGNORE INTO tx (txid, hash, confirmations, timereceived, size, vsize, blockhash, blockheight, blocktime) VALUES (\"${vin_txid}\", ${vin_hash}, ${vin_confirmations}, ${vin_timereceived}, ${vin_size}, ${vin_vsize}, ${vin_blockhash}, ${vin_blockheight}, ${vin_blocktime})"
|
||||
trace_rc $?
|
||||
sql_rawtx "INSERT OR IGNORE INTO rawtx (txid, hash, confirmations, timereceived, size, vsize, blockhash, blockheight, blocktime, raw_tx) VALUES (\"${vin_txid}\", ${vin_hash}, ${vin_confirmations}, ${vin_timereceived}, ${vin_size}, ${vin_vsize}, ${vin_blockhash}, ${vin_blockheight}, ${vin_blocktime}, readfile('vin-rawtx-${vin_txid}-$$.blob'))"
|
||||
trace_rc $?
|
||||
rm vin-rawtx-${vin_txid}-$$.blob
|
||||
txid_already_inserted=true
|
||||
fi
|
||||
sql "INSERT INTO tx (txid, hash, confirmations, timereceived, size, vsize, blockhash, blockheight, blocktime)"\
|
||||
" VALUES ('${vin_txid}', '${vin_hash}', ${vin_confirmations}, ${vin_timereceived}, ${vin_size}, ${vin_vsize}, '${vin_blockhash}', ${vin_blockheight}, ${vin_blocktime})"\
|
||||
" ON CONFLICT (txid) DO"\
|
||||
" UPDATE SET blockhash='${vin_blockhash}', blockheight=${vin_blockheight}, blocktime=${vin_blocktime}, confirmations=${vin_confirmations}"\
|
||||
" RETURNING id" \
|
||||
"SELECT id FROM tx WHERE txid='${vin_txid}'"
|
||||
trace_rc $?
|
||||
done
|
||||
|
||||
echo "${vin_total_amount}"
|
||||
|
||||
@@ -44,7 +44,7 @@ confirmation() {
|
||||
# First of all, let's make sure we're working on watched addresses...
|
||||
local address
|
||||
local addresseswhere
|
||||
local addresses=$(echo "${tx_details}" | jq ".result.details[].address")
|
||||
local addresses=$(echo "${tx_details}" | jq -r ".result.details[].address")
|
||||
|
||||
local notfirst=false
|
||||
local IFS=$'\n'
|
||||
@@ -53,9 +53,9 @@ confirmation() {
|
||||
trace "[confirmation] address=${address}"
|
||||
|
||||
if ${notfirst}; then
|
||||
addresseswhere="${addresseswhere},${address}"
|
||||
addresseswhere="${addresseswhere},'${address}'"
|
||||
else
|
||||
addresseswhere="${address}"
|
||||
addresseswhere="'${address}'"
|
||||
notfirst=true
|
||||
fi
|
||||
done
|
||||
@@ -66,11 +66,11 @@ confirmation() {
|
||||
fi
|
||||
########################################################################################################
|
||||
|
||||
local tx=$(sql "SELECT id FROM tx WHERE txid=\"${txid}\"")
|
||||
local tx=$(sql "SELECT id FROM tx WHERE txid='${txid}'")
|
||||
local id_inserted
|
||||
local tx_raw_details=$(get_rawtransaction ${txid} | tr -d '\n')
|
||||
local tx_nb_conf=$(echo "${tx_details}" | jq -r '.result.confirmations // 0')
|
||||
local tx_hash=$(echo "${tx_raw_details}" | jq '.result.hash')
|
||||
local tx_hash=$(echo "${tx_raw_details}" | jq -r '.result.hash')
|
||||
|
||||
# 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
|
||||
@@ -100,45 +100,33 @@ confirmation() {
|
||||
local tx_blocktime=null
|
||||
if [ "${tx_nb_conf}" -gt "0" ]; then
|
||||
trace "[confirmation] tx_nb_conf=${tx_nb_conf}"
|
||||
tx_blockhash=$(echo "${tx_details}" | jq '.result.blockhash')
|
||||
tx_blockheight=$(get_block_info $(echo ${tx_blockhash} | tr -d '"') | jq '.result.height')
|
||||
tx_blockhash="$(echo "${tx_details}" | jq -r '.result.blockhash')"
|
||||
tx_blockheight=$(get_block_info ${tx_blockhash} | jq '.result.height')
|
||||
tx_blockhash="'${tx_blockhash}'"
|
||||
tx_blocktime=$(echo "${tx_details}" | jq '.result.blocktime')
|
||||
fi
|
||||
|
||||
sql "INSERT OR IGNORE INTO tx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, blockhash, blockheight, blocktime) VALUES (\"${txid}\", ${tx_hash}, ${tx_nb_conf}, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${tx_blockhash}, ${tx_blockheight}, ${tx_blocktime})"
|
||||
trace_rc $?
|
||||
sql_rawtx "INSERT OR IGNORE INTO rawtx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, blockhash, blockheight, blocktime, raw_tx) VALUES (\"${txid}\", ${tx_hash}, ${tx_nb_conf}, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${tx_blockhash}, ${tx_blockheight}, ${tx_blocktime}, readfile('rawtx-${txid}-$$.blob'))"
|
||||
trace_rc $?
|
||||
|
||||
id_inserted=$(sql "SELECT id FROM tx WHERE txid=\"${txid}\"")
|
||||
id_inserted=$(sql "INSERT INTO tx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, blockhash, blockheight, blocktime)"\
|
||||
" VALUES ('${txid}', '${tx_hash}', ${tx_nb_conf}, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${tx_blockhash}, ${tx_blockheight}, ${tx_blocktime})"\
|
||||
" ON CONFLICT (txid) DO"\
|
||||
" UPDATE SET blockhash=${tx_blockhash}, blockheight=${tx_blockheight}, blocktime=${tx_blocktime}, confirmations=${tx_nb_conf}"\
|
||||
" RETURNING id" \
|
||||
"SELECT id FROM tx WHERE txid='${txid}'")
|
||||
trace_rc $?
|
||||
|
||||
else
|
||||
# TX found in our DB.
|
||||
# 1-conf or executecallbacks on an unconfirmed tx or spending watched address (in this case, we probably missed conf) or spending to a watched address (in this case, spend inserted the tx in the DB)
|
||||
|
||||
local tx_blockhash=$(echo "${tx_details}" | jq '.result.blockhash')
|
||||
local tx_blockhash=$(echo "${tx_details}" | jq -r '.result.blockhash')
|
||||
trace "[confirmation] tx_blockhash=${tx_blockhash}"
|
||||
if [ "${tx_blockhash}" = "null" ]; then
|
||||
trace "[confirmation] probably being called by executecallbacks without any confirmations since the last time we checked"
|
||||
else
|
||||
local tx_blockheight=$(get_block_info $(echo "${tx_blockhash}" | tr -d '"') | jq '.result.height')
|
||||
local tx_blockheight=$(get_block_info "${tx_blockhash}" | jq '.result.height')
|
||||
local tx_blocktime=$(echo "${tx_details}" | jq '.result.blocktime')
|
||||
|
||||
sql "UPDATE tx SET
|
||||
confirmations=${tx_nb_conf},
|
||||
blockhash=${tx_blockhash},
|
||||
blockheight=${tx_blockheight},
|
||||
blocktime=${tx_blocktime}
|
||||
WHERE txid=\"${txid}\""
|
||||
trace_rc $?
|
||||
sql_rawtx "UPDATE rawtx SET
|
||||
confirmations=${tx_nb_conf},
|
||||
blockhash=${tx_blockhash},
|
||||
blockheight=${tx_blockheight},
|
||||
blocktime=${tx_blocktime},
|
||||
raw_tx=readfile('rawtx-${txid}-$$.blob')
|
||||
WHERE txid=\"${txid}\""
|
||||
sql "UPDATE tx SET confirmations=${tx_nb_conf}, blockhash='${tx_blockhash}', blockheight=${tx_blockheight}, blocktime=${tx_blocktime} WHERE txid='${txid}'"
|
||||
trace_rc $?
|
||||
fi
|
||||
id_inserted=${tx}
|
||||
@@ -171,7 +159,8 @@ confirmation() {
|
||||
# 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})"
|
||||
sql "INSERT INTO watching_tx (watching_id, tx_id, vout, amount) VALUES (${watching_id}, ${id_inserted}, ${tx_vout_n}, ${tx_vout_amount})"\
|
||||
" ON CONFLICT DO NOTHING"
|
||||
trace_rc $?
|
||||
else
|
||||
trace "[confirmation] For this tx, there's already watching_tx rows"
|
||||
@@ -211,7 +200,7 @@ confirmation() {
|
||||
# for next cron.
|
||||
if [ -z "${bypass_callbacks}" ]; then
|
||||
trace "[confirmation] Let's do the callbacks!"
|
||||
do_callbacks
|
||||
do_callbacks "${txid}"
|
||||
fi
|
||||
|
||||
echo '{"result":"confirmed"}'
|
||||
|
||||
@@ -12,8 +12,8 @@ get_txns_by_watchlabel(){
|
||||
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}
|
||||
WHERE w32.label='${1}'
|
||||
LIMIT ${2-10} OFFSET 0
|
||||
HERE
|
||||
)
|
||||
label_txns=$(sql "$query")
|
||||
@@ -38,12 +38,12 @@ get_unused_addresses_by_watchlabel(){
|
||||
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"
|
||||
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}
|
||||
LIMIT ${2-10} OFFSET 0
|
||||
HERE
|
||||
)
|
||||
label_unused_addrs=$(sql "$query")
|
||||
@@ -67,7 +67,7 @@ getactivewatches() {
|
||||
local watches
|
||||
# Let's build the string directly with sqlite instead of manipulating multiple strings afterwards, it's faster.
|
||||
# {"id":"${id}","address":"${address}","imported":"${imported}","unconfirmedCallbackURL":"${cb0conf_url}","confirmedCallbackURL":"${cb1conf_url}","watching_since":"${timestamp}"}
|
||||
watches=$(sql "SELECT '{\"id\":' || id || ',\"address\":\"' || address || '\",\"imported\":' || imported || ',\"unconfirmedCallbackURL\":\"' || COALESCE(callback0conf, '') || '\",\"confirmedCallbackURL\":\"' || COALESCE(callback1conf, '') || '\",\"label\":\"' || COALESCE(label, '') || '\",\"watching_since\":\"' || inserted_ts || '\"}' FROM watching WHERE watching AND NOT calledback1conf")
|
||||
watches=$(sql "SELECT '{\"id\":' || id || ',\"address\":\"' || address || '\",\"imported\":' || imported || ',\"unconfirmedCallbackURL\":' || CASE WHEN callback0conf IS NULL THEN 'null' ELSE ('\"' || callback0conf || '\"') END || ',\"confirmedCallbackURL\":' || CASE WHEN callback1conf IS NULL THEN 'null' ELSE ('\"' || callback1conf || '\"') END || ',\"label\":\"' || COALESCE(label, '') || '\",\"watching_since\":\"' || inserted_ts || '\"}' FROM watching WHERE watching AND NOT calledback1conf ORDER BY id")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -99,7 +99,7 @@ getactivewatchesbyxpub() {
|
||||
local xpub=${1}
|
||||
local returncode
|
||||
|
||||
getactivewatchesxpub "pub32" ${xpub}
|
||||
getactivewatchesxpub "pub32" "${xpub}"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -112,7 +112,7 @@ getactivewatchesbylabel() {
|
||||
local label=${1}
|
||||
local returncode
|
||||
|
||||
getactivewatchesxpub "label" ${label}
|
||||
getactivewatchesxpub "label" "${label}"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -130,7 +130,7 @@ getactivewatchesxpub() {
|
||||
|
||||
# Let's build the string directly with sqlite instead of manipulating multiple strings afterwards, it's faster.
|
||||
# {"id":"${id}","address":"${address}","imported":"${imported}","unconfirmedCallbackURL":"${cb0conf_url}","confirmedCallbackURL":"${cb1conf_url}","watching_since":"${timestamp}","derivation_path":"${derivation_path}","pub32_index":"${pub32_index}"}
|
||||
watches=$(sql "SELECT '{\"id\":' || w.id || ',\"address\":\"' || address || '\",\"imported\":' || imported || ',\"unconfirmedCallbackURL\":\"' || COALESCE(w.callback0conf, '') || '\",\"confirmedCallbackURL\":\"' || COALESCE(w.callback1conf, '') || '\",\"watching_since\":\"' || w.inserted_ts || '\",\"derivation_path\":\"' || derivation_path || '\",\"pub32_index\":' || pub32_index || '}' FROM watching w, watching_by_pub32 w32 WHERE watching_by_pub32_id = w32.id AND ${where} = \"${value}\" AND w.watching AND NOT calledback1conf")
|
||||
watches=$(sql "SELECT '{\"id\":' || w.id || ',\"address\":\"' || address || '\",\"imported\":' || imported || ',\"unconfirmedCallbackURL\":' || CASE WHEN w.callback0conf IS NULL THEN 'null' ELSE ('\"' || w.callback0conf || '\"') END || ',\"confirmedCallbackURL\":' || CASE WHEN w.callback1conf IS NULL THEN 'null' ELSE ('\"' || w.callback1conf || '\"') END || ',\"watching_since\":\"' || w.inserted_ts || '\",\"derivation_path\":\"' || derivation_path || '\",\"pub32_index\":' || pub32_index || '}' FROM watching w, watching_by_pub32 w32 WHERE watching_by_pub32_id = w32.id AND w32.${where} = '${value}' AND w.watching AND NOT calledback1conf ORDER BY w.id")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -162,7 +162,7 @@ getactivexpubwatches() {
|
||||
local watches
|
||||
# Let's build the string directly with sqlite instead of manipulating multiple strings afterwards, it's faster.
|
||||
# {"id":"${id}","pub32":"${pub32}","label":"${label}","derivation_path":"${derivation_path}","last_imported_n":${last_imported_n},"unconfirmedCallbackURL":"${cb0conf_url}","confirmedCallbackURL":"${cb1conf_url}","watching_since":"${timestamp}"}
|
||||
watches=$(sql "SELECT '{\"id\":' || id || ',\"pub32\":\"' || pub32 || '\",\"label\":\"' || label || '\",\"derivation_path\":\"' || derivation_path || '\",\"last_imported_n\":' || last_imported_n || ',\"unconfirmedCallbackURL\":\"' || COALESCE(callback0conf, '') || '\",\"confirmedCallbackURL\":\"' || COALESCE(callback1conf, '') || '\",\"watching_since\":\"' || inserted_ts || '\"}' FROM watching_by_pub32 WHERE watching")
|
||||
watches=$(sql "SELECT '{\"id\":' || id || ',\"pub32\":\"' || pub32 || '\",\"label\":\"' || label || '\",\"derivation_path\":\"' || derivation_path || '\",\"last_imported_n\":' || last_imported_n || ',\"unconfirmedCallbackURL\":' || CASE WHEN callback0conf IS NULL THEN 'null' ELSE ('\"' || callback0conf || '\"') END || ',\"confirmedCallbackURL\":' || CASE WHEN callback1conf IS NULL THEN 'null' ELSE ('\"' || callback1conf || '\"') END || ',\"watching_since\":\"' || inserted_ts || '\"}' FROM watching_by_pub32 WHERE watching ORDER BY id")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ importaddress_rpc() {
|
||||
if [ -z "${label}" ]; then
|
||||
label="null"
|
||||
fi
|
||||
local data='{"method":"importaddress","params":{"address":"'${address}'","label":'${label}',"rescan":false}}'
|
||||
local data='{"method":"importaddress","params":{"address":"'${address}'","label":"'${label}'","rescan":false}}'
|
||||
# local data="{\"method\":\"importaddress\",\"params\":[\"${address}\",\"\",false]}"
|
||||
local result
|
||||
result=$(send_to_watcher_node ${data})
|
||||
@@ -39,7 +39,7 @@ importmulti_rpc() {
|
||||
# {"address":"2N6Q9kBcLtNswgMSLSQ5oduhbctk7hxEJW8"},
|
||||
# {"scriptPubKey":{"address":"2N6Q9kBcLtNswgMSLSQ5oduhbctk7hxEJW8"},"timestamp":"now","watchonly":true,"label":"xpub"},
|
||||
|
||||
addresses=$(echo "${addresses}" | sed "s/\"address\"/\"scriptPubKey\":\{\"address\"/g" | sed "s/}/},\"timestamp\":\"now\",\"watchonly\":true,\"label\":${label}}/g")
|
||||
addresses=$(echo "${addresses}" | sed "s/\"address\"/\"scriptPubKey\":\{\"address\"/g" | sed "s/}/},\"timestamp\":\"now\",\"watchonly\":true,\"label\":\"${label}\"}/g")
|
||||
# trace "[importmulti_rpc] addresses=${addresses}"
|
||||
|
||||
# Now we use that in the RPC string
|
||||
|
||||
@@ -25,7 +25,7 @@ manage_not_imported() {
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
sql "UPDATE watching SET imported=1 WHERE address=\"${address}\""
|
||||
sql "UPDATE watching SET imported=true WHERE address='${address}'"
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -41,8 +41,8 @@ manage_missed_conf() {
|
||||
|
||||
trace "[Entering manage_missed_conf()]"
|
||||
|
||||
local watches=$(sql 'SELECT DISTINCT address FROM watching w LEFT JOIN watching_tx ON w.id = watching_id LEFT JOIN tx t ON t.id = tx_id WHERE watching AND imported AND (tx_id IS NULL OR t.confirmations=0) ORDER BY address')
|
||||
trace "[manage_missed_conf] watches=${watches}"
|
||||
local watches=$(sql "SELECT DISTINCT address FROM watching w LEFT JOIN watching_tx ON w.id = watching_id LEFT JOIN tx t ON t.id = tx_id WHERE watching AND imported AND (tx_id IS NULL OR t.confirmations=0) ORDER BY address")
|
||||
# trace "[manage_missed_conf] watches=${watches}"
|
||||
if [ ${#watches} -eq 0 ]; then
|
||||
trace "[manage_missed_conf] Nothing missed!"
|
||||
return 0
|
||||
@@ -55,7 +55,7 @@ manage_missed_conf() {
|
||||
data='{"method":"listreceivedbyaddress","params":[0,false,true]}'
|
||||
received=$(send_to_watcher_node "${data}")
|
||||
received_addresses=$(echo "${received}" | jq -r ".result[].address" | sort)
|
||||
trace "[manage_missed_conf] received_addresses=${received_addresses}"
|
||||
# trace "[manage_missed_conf] received_addresses=${received_addresses}"
|
||||
|
||||
# Let's extract addresses that are in the watches list as well as in the received_addresses list
|
||||
echo "${watches}" > watches-$$
|
||||
@@ -81,7 +81,7 @@ manage_missed_conf() {
|
||||
local IFS=$'\n'
|
||||
for address in ${received_watches}
|
||||
do
|
||||
watching=$(sql 'SELECT address, inserted_ts FROM watching WHERE address="'${address}'"')
|
||||
watching=$(sql "SELECT address, inserted_ts FROM watching WHERE address='${address}'")
|
||||
trace "[manage_missed_conf] watching=${watching}"
|
||||
if [ ${#watching} -eq 0 ]; then
|
||||
trace "[manage_missed_conf] Nothing missed!"
|
||||
@@ -90,7 +90,7 @@ manage_missed_conf() {
|
||||
|
||||
# Let's get confirmed received txs for the address
|
||||
# address=$(echo "${watches}" | cut -d '|' -f1)
|
||||
inserted_ts=$(date -d "$(echo "${watching}" | cut -d '|' -f2)" +"%s")
|
||||
inserted_ts=$(date -d "$(echo "${watching}" | cut -d '|' -f2)" -D '%Y-%m-%d %H:%M:%S' +"%s")
|
||||
trace "[manage_missed_conf] inserted_ts=${inserted_ts}"
|
||||
|
||||
received_address=$(echo "${received}" | jq -Mc ".result | map(select(.address==\"${address}\" and .confirmations>0))[0]")
|
||||
|
||||
@@ -25,6 +25,7 @@ newblock() {
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
# do_callbacks_txid "$(echo "${blockinfo}" | jq ".result.tx[]")"
|
||||
do_callbacks_txid
|
||||
batch_check_webhooks
|
||||
|
||||
|
||||
@@ -49,18 +49,20 @@ serve_ots_stamp() {
|
||||
returncode=$?
|
||||
fi
|
||||
else
|
||||
sql "INSERT OR IGNORE INTO stamp (hash, callbackUrl) VALUES (\"${hash}\", \"${callbackUrl}\")"
|
||||
id_inserted=$(sql "INSERT INTO stamp (hash, callbackUrl)"\
|
||||
" VALUES ('${hash}','${callbackUrl}')"\
|
||||
" RETURNING id" \
|
||||
"SELECT id FROM stamp WHERE hash='${hash}'")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
if [ "${returncode}" -eq "0" ]; then
|
||||
id_inserted=$(sql "SELECT id FROM stamp WHERE hash='${hash}'")
|
||||
trace_rc $?
|
||||
errorstring=$(request_ots_stamp "${hash}" ${id_inserted})
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
else
|
||||
trace "[serve_ots_stamp] Stamp request could not be inserted in DB"
|
||||
errorstring="Stamp request could not be inserted in DB, please retry later"
|
||||
id_inserted=null
|
||||
returncode=1
|
||||
fi
|
||||
fi
|
||||
@@ -114,7 +116,7 @@ request_ots_stamp() {
|
||||
if [ "${returncode}" -eq "0" ]; then
|
||||
# "already exists" found, let's try updating DB again
|
||||
trace "[request_ots_stamp] was already requested to the OTS server... let's update the DB, looks like it didn't work on first try"
|
||||
sql "UPDATE stamp SET requested=1 WHERE id=${id}"
|
||||
sql "UPDATE stamp SET requested=true WHERE id=${id}"
|
||||
errorstring="Duplicate stamping request, hash already exists in DB and been OTS requested"
|
||||
returncode=1
|
||||
else
|
||||
@@ -125,7 +127,7 @@ request_ots_stamp() {
|
||||
fi
|
||||
else
|
||||
trace "[request_ots_stamp] Stamping request sent successfully!"
|
||||
sql "UPDATE stamp SET requested=1 WHERE id=${id}"
|
||||
sql "UPDATE stamp SET requested=true WHERE id=${id}"
|
||||
errorstring=""
|
||||
returncode=0
|
||||
fi
|
||||
@@ -198,7 +200,7 @@ serve_ots_backoffice() {
|
||||
else
|
||||
# No failure, upgraded
|
||||
trace "[serve_ots_backoffice] just upgraded!"
|
||||
sql "UPDATE stamp SET upgraded=1 WHERE id=${id}"
|
||||
sql "UPDATE stamp SET upgraded=true WHERE id=${id}"
|
||||
trace_rc $?
|
||||
|
||||
upgraded=1
|
||||
@@ -221,13 +223,13 @@ serve_ots_backoffice() {
|
||||
# Even if curl executed ok, we need to make sure the http return code is also ok
|
||||
|
||||
if [ "${returncode}" -eq "0" ]; then
|
||||
sql "UPDATE stamp SET calledback=1 WHERE id=${id}"
|
||||
sql "UPDATE stamp SET calledback=true WHERE id=${id}"
|
||||
trace_rc $?
|
||||
fi
|
||||
else
|
||||
trace "[serve_ots_backoffice] url is empty, obviously won't try to call it!"
|
||||
|
||||
sql "UPDATE stamp SET calledback=1 WHERE id=${id}"
|
||||
sql "UPDATE stamp SET calledback=true WHERE id=${id}"
|
||||
trace_rc $?
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -76,8 +76,10 @@ main() {
|
||||
case "${cmd}" in
|
||||
helloworld)
|
||||
# GET http://192.168.111.152:8080/helloworld
|
||||
response_to_client "Hello, world!" 0
|
||||
break
|
||||
response="Hello, world!"
|
||||
returncode=0
|
||||
# response_to_client "Hello, world!" 0
|
||||
# break
|
||||
;;
|
||||
installation_info)
|
||||
# GET http://192.168.111.152:8080/info
|
||||
@@ -86,8 +88,7 @@ main() {
|
||||
else
|
||||
response='{ "error": "missing installation data" }'
|
||||
fi
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
watch)
|
||||
# POST http://192.168.111.152:8080/watch
|
||||
@@ -96,8 +97,7 @@ main() {
|
||||
# BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","confirmedCallbackURL":"192.168.111.233:1111/callback1conf","eventMessage":"eyJib3VuY2VfYWRkcmVzcyI6IjJNdkEzeHIzOHIxNXRRZWhGblBKMVhBdXJDUFR2ZTZOamNGIiwibmJfY29uZiI6MH0K","label":"myLabel"}
|
||||
|
||||
response=$(watchrequest "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
unwatch)
|
||||
# curl (GET) 192.168.111.152:8080/unwatch/2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp
|
||||
@@ -122,16 +122,15 @@ main() {
|
||||
# Let's make it work even for a GET request (equivalent to a POST with empty json object body)
|
||||
if [ "$http_method" = "POST" ]; then
|
||||
address=$(echo "${line}" | jq -r ".address")
|
||||
unconfirmedCallbackURL=$(echo "${line}" | jq ".unconfirmedCallbackURL")
|
||||
confirmedCallbackURL=$(echo "${line}" | jq ".confirmedCallbackURL")
|
||||
unconfirmedCallbackURL=$(echo "${line}" | jq -r ".unconfirmedCallbackURL")
|
||||
confirmedCallbackURL=$(echo "${line}" | jq -r ".confirmedCallbackURL")
|
||||
watchid=$(echo "${line}" | jq ".id")
|
||||
else
|
||||
address=$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)
|
||||
fi
|
||||
|
||||
response=$(unwatchrequest "${watchid}" "${address}" "${unconfirmedCallbackURL}" "${confirmedCallbackURL}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
watchxpub)
|
||||
# POST http://192.168.111.152:8080/watchxpub
|
||||
@@ -139,43 +138,37 @@ main() {
|
||||
# curl -H "Content-Type: application/json" -d '{"label":"2219","pub32":"upub5GtUcgGed1aGH4HKQ3vMYrsmLXwmHhS1AeX33ZvDgZiyvkGhNTvGd2TA5Lr4v239Fzjj4ZY48t6wTtXUy2yRgapf37QHgt6KWEZ6bgsCLpb","path":"0/1/n","nstart":55,"unconfirmedCallbackURL":"192.168.111.233:1111/callback0conf","confirmedCallbackURL":"192.168.111.233:1111/callback1conf"}' proxy:8888/watchxpub
|
||||
|
||||
response=$(watchpub32request "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
unwatchxpubbyxpub)
|
||||
# GET http://192.168.111.152:8080/unwatchxpubbyxpub/tpubD6NzVbkrYhZ4YR3QK2tyfMMvBghAvqtNaNK1LTyDWcRHLcMUm3ZN2cGm5BS3MhCRCeCkXQkTXXjiJgqxpqXK7PeUSp86DTTgkLpcjMtpKWk
|
||||
|
||||
response=$(unwatchpub32request "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
unwatchxpubbylabel)
|
||||
# GET http://192.168.111.152:8080/unwatchxpubbylabel/4421
|
||||
|
||||
response=$(unwatchpub32labelrequest "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getactivewatchesbyxpub)
|
||||
# GET http://192.168.111.152:8080/getactivewatchesbyxpub/tpubD6NzVbkrYhZ4YR3QK2tyfMMvBghAvqtNaNK1LTyDWcRHLcMUm3ZN2cGm5BS3MhCRCeCkXQkTXXjiJgqxpqXK7PeUSp86DTTgkLpcjMtpKWk
|
||||
|
||||
response=$(getactivewatchesbyxpub "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getactivewatchesbylabel)
|
||||
# GET http://192.168.111.152:8080/getactivewatchesbylabel/4421
|
||||
|
||||
response=$(getactivewatchesbylabel "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getactivexpubwatches)
|
||||
# GET http://192.168.111.152:8080/getactivexpubwatches
|
||||
|
||||
response=$(getactivexpubwatches)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
watchtxid)
|
||||
# POST http://192.168.111.152:8080/watchtxid
|
||||
@@ -183,8 +176,7 @@ main() {
|
||||
# curl -H "Content-Type: application/json" -d '{"txid":"b081ca7724386f549cf0c16f71db6affeb52ff7a0d9b606fb2e5c43faffd3387","confirmedCallbackURL":"192.168.111.233:1111/callback1conf","xconfCallbackURL":"192.168.111.233:1111/callbackXconf","nbxconf":6}' proxy:8888/watchtxid
|
||||
|
||||
response=$(watchtxidrequest "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
unwatchtxid)
|
||||
# POST http://192.168.111.152:8080/unwatchtxid
|
||||
@@ -200,87 +192,76 @@ main() {
|
||||
# - id: the id returned by watchtxid
|
||||
|
||||
local txid=$(echo "${line}" | jq -r ".txid")
|
||||
local unconfirmedCallbackURL=$(echo "${line}" | jq ".unconfirmedCallbackURL")
|
||||
local confirmedCallbackURL=$(echo "${line}" | jq ".confirmedCallbackURL")
|
||||
local unconfirmedCallbackURL=$(echo "${line}" | jq -r ".unconfirmedCallbackURL")
|
||||
local confirmedCallbackURL=$(echo "${line}" | jq -r ".confirmedCallbackURL")
|
||||
local watchid=$(echo "${line}" | jq ".id")
|
||||
|
||||
response=$(unwatchtxidrequest "${watchid}" "${txid}" "${unconfirmedCallbackURL}" "${confirmedCallbackURL}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getactivewatches)
|
||||
# curl (GET) 192.168.111.152:8080/getactivewatches
|
||||
|
||||
response=$(getactivewatches)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
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
|
||||
returncode=$?
|
||||
;;
|
||||
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
|
||||
returncode=$?
|
||||
;;
|
||||
conf)
|
||||
# curl (GET) 192.168.111.152:8080/conf/b081ca7724386f549cf0c16f71db6affeb52ff7a0d9b606fb2e5c43faffd3387
|
||||
|
||||
response=$(confirmation_request "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
newblock)
|
||||
# curl (GET) 192.168.111.152:8080/newblock/000000000000005c987120f3b6f995c95749977ef1a109c89aa74ce4bba97c1f
|
||||
|
||||
response=$(newblock "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getbestblockhash)
|
||||
# curl (GET) http://192.168.111.152:8080/getbestblockhash
|
||||
|
||||
response=$(get_best_block_hash)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getblockhash)
|
||||
# curl (GET) http://192.168.111.152:8080/getblockhash/522322
|
||||
|
||||
response=$(get_blockhash "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getblockinfo)
|
||||
# curl (GET) http://192.168.111.152:8080/getblockinfo/000000006f82a384c208ecfa04d05beea02d420f3f398ddda5c7f900de5718ea
|
||||
|
||||
response=$(get_block_info "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getblockchaininfo)
|
||||
# http://192.168.111.152:8080/getblockchaininfo
|
||||
|
||||
response=$(get_blockchain_info)
|
||||
response_to_client "${response}" ${?}
|
||||
returncode=$?
|
||||
;;
|
||||
gettransaction)
|
||||
# curl (GET) http://192.168.111.152:8080/gettransaction/af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648
|
||||
|
||||
response=$(get_rawtransaction "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getbestblockinfo)
|
||||
# curl (GET) http://192.168.111.152:8080/getbestblockinfo
|
||||
|
||||
response=$(get_best_block_info)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
executecallbacks)
|
||||
# curl (GET) http://192.168.111.152:8080/executecallbacks
|
||||
@@ -288,43 +269,37 @@ main() {
|
||||
manage_not_imported
|
||||
manage_missed_conf
|
||||
response=$(do_callbacks)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
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
|
||||
returncode=$?
|
||||
;;
|
||||
getbalance)
|
||||
# curl (GET) http://192.168.111.152:8080/getbalance
|
||||
|
||||
response=$(getbalance)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getbalances)
|
||||
# curl (GET) http://192.168.111.152:8080/getbalances
|
||||
|
||||
response=$(getbalances)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getbalancebyxpub)
|
||||
# curl (GET) http://192.168.111.152:8080/getbalancebyxpub/upub5GtUcgGed1aGH4HKQ3vMYrsmLXwmHhS1AeX33ZvDgZiyvkGhNTvGd2TA5Lr4v239Fzjj4ZY48t6wTtXUy2yRgapf37QHgt6KWEZ6bgsCLpb
|
||||
|
||||
response=$(getbalancebyxpub "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getbalancebyxpublabel)
|
||||
# curl (GET) http://192.168.111.152:8080/getbalancebyxpublabel/2219
|
||||
|
||||
response=$(getbalancebyxpublabel "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getnewaddress)
|
||||
# curl (GET) http://192.168.111.152:8080/getnewaddress
|
||||
@@ -346,8 +321,7 @@ main() {
|
||||
fi
|
||||
|
||||
response=$(getnewaddress "${address_type}" "${label}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
validateaddress)
|
||||
# GET http://192.168.111.152:8080/validateaddress/tb1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqp3mvzv
|
||||
@@ -361,8 +335,7 @@ main() {
|
||||
# BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","amount":0.00233,"eventMessage":"eyJ3aGF0ZXZlciI6MTIzfQo=","confTarget":6,"replaceable":true,"subtractfeefromamount":false}
|
||||
|
||||
response=$(spend "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
bumpfee)
|
||||
# POST http://192.168.111.152:8080/bumpfee
|
||||
@@ -370,8 +343,7 @@ main() {
|
||||
# BODY {"txid":"af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648"}
|
||||
|
||||
response=$(bumpfee "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
createbatcher)
|
||||
# POST http://192.168.111.152:8080/createbatcher
|
||||
@@ -388,8 +360,7 @@ main() {
|
||||
# NOTYET BODY {"batcherLabel":"highfees","feeRate":231.8}
|
||||
|
||||
response=$(createbatcher "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
updatebatcher)
|
||||
# POST http://192.168.111.152:8080/updatebatcher
|
||||
@@ -412,8 +383,7 @@ main() {
|
||||
# BODY {"batcherLabel":"fast","confTarget":2}
|
||||
|
||||
response=$(updatebatcher "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
addtobatch)
|
||||
# POST http://192.168.111.152:8080/addtobatch
|
||||
@@ -439,8 +409,7 @@ main() {
|
||||
# BODY {"address":"2N8DcqzfkYi8CkYzvNNS5amoq3SbAcQNXKp","amount":0.00233,"batcherId":34,"webhookUrl":"https://myCypherApp:3000/batchExecuted"}
|
||||
|
||||
response=$(addtobatch "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
removefrombatch)
|
||||
# POST http://192.168.111.152:8080/removefrombatch
|
||||
@@ -458,8 +427,7 @@ main() {
|
||||
# BODY {"outputId":72}
|
||||
|
||||
response=$(removefrombatch "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
batchspend)
|
||||
# POST http://192.168.111.152:8080/batchspend
|
||||
@@ -511,8 +479,7 @@ main() {
|
||||
# BODY {"batcherId":411,"confTarget":6}
|
||||
|
||||
response=$(batchspend "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getbatcher)
|
||||
# POST (GET) http://192.168.111.152:8080/getbatcher
|
||||
@@ -528,14 +495,13 @@ main() {
|
||||
# BODY {"batcherId":34}
|
||||
|
||||
response=$(getbatcher "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getbatchdetails)
|
||||
# POST (GET) http://192.168.111.152:8080/getbatchdetails
|
||||
#
|
||||
# args:
|
||||
# - batcherId, optional, id of the batcher, overrides batcherLabel, default batcher will be spent if not supplied
|
||||
# - batcherId, optional, id of the batcher, overrides batcherLabel, default batcher will be used if not supplied
|
||||
# - batcherLabel, optional, label of the batcher, default batcher will be used if not supplied
|
||||
# - txid, optional, if you want the details of an executed batch, supply the batch txid, will return current pending batch
|
||||
# if not supplied
|
||||
@@ -570,8 +536,7 @@ main() {
|
||||
# BODY {"batcherId":34}
|
||||
|
||||
response=$(getbatchdetails "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
listbatchers)
|
||||
# curl (GET) http://192.168.111.152:8080/listbatchers
|
||||
@@ -585,24 +550,21 @@ main() {
|
||||
# "error":null}
|
||||
|
||||
response=$(listbatchers)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
bitcoin_estimatesmartfee)
|
||||
# POST http://192.168.111.152:8080/bitcoin_estimatesmartfee
|
||||
# BODY {"confTarget":2}
|
||||
|
||||
response=$(bitcoin_estimatesmartfee "$(echo "${line}" | jq -r ".confTarget")")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
deriveindex)
|
||||
# curl GET http://192.168.111.152:8080/deriveindex/25-30
|
||||
# curl GET http://192.168.111.152:8080/deriveindex/34
|
||||
|
||||
response=$(deriveindex "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
derivepubpath)
|
||||
# POST http://192.168.111.152:8080/derivepubpath
|
||||
@@ -611,16 +573,14 @@ main() {
|
||||
# BODY {"pub32":"vpub5SLqN2bLY4WeZF3kL4VqiWF1itbf3A6oRrq9aPf16AZMVWYCuN9TxpAZwCzVgW94TNzZPNc9XAHD4As6pdnExBtCDGYRmNJrcJ4eV9hNqcv","path":"0/25-30"}
|
||||
|
||||
response=$(derivepubpath "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
deriveindex_bitcoind)
|
||||
# curl GET http://192.168.111.152:8080/deriveindex_bitcoind/25-30
|
||||
# curl GET http://192.168.111.152:8080/deriveindex_bitcoind/34
|
||||
|
||||
response=$(deriveindex_bitcoind "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
derivepubpath_bitcoind)
|
||||
# POST http://192.168.111.152:8080/derivepubpath_bitcoind
|
||||
@@ -629,45 +589,39 @@ main() {
|
||||
# BODY {"pub32":"vpub5SLqN2bLY4WeZF3kL4VqiWF1itbf3A6oRrq9aPf16AZMVWYCuN9TxpAZwCzVgW94TNzZPNc9XAHD4As6pdnExBtCDGYRmNJrcJ4eV9hNqcv","path":"0/25-30"}
|
||||
|
||||
response=$(derivepubpath_bitcoind "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
getmempoolinfo)
|
||||
# curl GET http://192.168.111.152:8080/getmempoolinfo
|
||||
|
||||
response=$(get_mempool_info)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_getinfo)
|
||||
# GET http://192.168.111.152:8080/ln_getinfo
|
||||
|
||||
response=$(ln_getinfo)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_getconnectionstring)
|
||||
# GET http://192.168.111.152:8080/ln_getconnectionstring
|
||||
|
||||
response=$(ln_get_connection_string)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_create_invoice)
|
||||
# POST http://192.168.111.152:8080/ln_create_invoice
|
||||
# BODY {"msatoshi":"10000","label":"koNCcrSvhX3dmyFhW","description":"Bylls order #10649","expiry":"900","callback_url":"http://192.168.122.159"}
|
||||
|
||||
response=$(ln_create_invoice "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_pay)
|
||||
# POST http://192.168.111.152:8080/ln_pay
|
||||
# BODY {"bolt11":"lntb1pdca82tpp5gv8mn5jqlj6xztpnt4r472zcyrwf3y2c3cvm4uzg2gqcnj90f83qdp2gf5hgcm0d9hzqnm4w3kx2apqdaexgetjyq3nwvpcxgcqp2g3d86wwdfvyxcz7kce7d3n26d2rw3wf5tzpm2m5fl2z3mm8msa3xk8nv2y32gmzlhwjved980mcmkgq83u9wafq9n4w28amnmwzujgqpmapcr3","expected_msatoshi":"10000","expected_description":"Bitcoin Outlet order #7082"}
|
||||
|
||||
response=$(ln_pay "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_listpays)
|
||||
# GET http://192.168.111.152:8080/ln_listpays
|
||||
@@ -683,8 +637,7 @@ main() {
|
||||
fi
|
||||
|
||||
response=$(ln_listpays "${bolt11}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_paystatus)
|
||||
# GET http://192.168.111.152:8080/ln_paystatus
|
||||
@@ -700,15 +653,13 @@ main() {
|
||||
fi
|
||||
|
||||
response=$(ln_paystatus "${bolt11}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_newaddr)
|
||||
# GET http://192.168.111.152:8080/ln_newaddr
|
||||
|
||||
response=$(ln_newaddr)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_connectfund)
|
||||
# POST http://192.168.111.152:8080/ln_connectfund
|
||||
@@ -716,64 +667,50 @@ main() {
|
||||
# curl -H "Content-Type: application/json" -d '{"peer":"nodeId@ip:port","msatoshi":"100000","callbackUrl":"https://callbackUrl/?channelReady=f3y2c3cvm4uzg2gq"}' proxy:8888/ln_connectfund
|
||||
|
||||
response=$(ln_connectfund "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_getinvoice)
|
||||
# GET http://192.168.111.152:8080/ln_getinvoice/label
|
||||
# GET http://192.168.111.152:8080/ln_getinvoice/koNCcrSvhX3dmyFhW
|
||||
|
||||
response=$(ln_getinvoice "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_delinvoice)
|
||||
# GET http://192.168.111.152:8080/ln_delinvoice/label
|
||||
# GET http://192.168.111.152:8080/ln_delinvoice/koNCcrSvhX3dmyFhW
|
||||
|
||||
response=$(ln_delinvoice "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_decodebolt11)
|
||||
# GET http://192.168.111.152:8080/ln_decodebolt11/bolt11
|
||||
# GET http://192.168.111.152:8080/ln_decodebolt11/lntb1pdca82tpp5gv8mn5jqlj6xztpnt4r472zcyrwf3y2c3cvm4uzg2gqcnj90f83qdp2gf5hgcm0d9hzqnm4w3kx2apqdaexgetjyq3nwvpcxgcqp2g3d86wwdfvyxcz7kce7d3n26d2rw3wf5tzpm2m5fl2z3mm8msa3xk8nv2y32gmzlhwjved980mcmkgq83u9wafq9n4w28amnmwzujgqpmapcr3
|
||||
|
||||
response=$(ln_decodebolt11 "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_listpeers)
|
||||
# GET http://192.168.111.152:8080/ln_listpeers
|
||||
|
||||
response=$(ln_listpeers)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_listfunds)
|
||||
# GET http://192.168.111.152:8080/ln_listfunds
|
||||
response=$(ln_listfunds)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
# ln_listpays)
|
||||
# # GET http://192.168.111.152:8080/ln_listpays
|
||||
# response=$(ln_listpays)
|
||||
# response_to_client "${response}" ${?}
|
||||
# break
|
||||
# ;;
|
||||
ln_getroute)
|
||||
# GET http://192.168.111.152:8080/ln_getroute/<node_id>/<msatoshi>/<riskfactor>
|
||||
response=$(ln_getroute "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f3)" "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f4)" "$(echo "${line}" | cut -d ' ' -f2 | cut -d '/' -f5)")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ln_withdraw)
|
||||
# POST http://192.168.111.152:8080/ln_withdraw
|
||||
# BODY {"destination":"segwitAddress","satoshi":"100000","feerate":0,all: false}
|
||||
response=$(ln_withdraw "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ots_stamp)
|
||||
# POST http://192.168.111.152:8080/ots_stamp
|
||||
@@ -782,15 +719,13 @@ main() {
|
||||
# curl -v -d "{\"hash\":\"a6ea81a46fec3d02d40815b8667b388351edecedc1cc9f97aab55b566db7aac8\"}" localhost:8888/ots_stamp
|
||||
|
||||
response=$(serve_ots_stamp "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ots_backoffice)
|
||||
# curl (GET) http://192.168.111.152:8080/ots_upgradeandcallback
|
||||
|
||||
response=$(serve_ots_backoffice)
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ots_getfile)
|
||||
# curl (GET) http://192.168.111.152:8080/ots_getfile/1ddfb769eb0b8876bc570e25580e6a53afcf973362ee1ee4b54a807da2e5eed7
|
||||
@@ -807,8 +742,7 @@ main() {
|
||||
# curl -v -d "{\"hash\":\"a6ea81a46fec3d02d40815b8667b388351edecedc1cc9f97aab55b566db7aac8\",\"base64otsfile\":\"$(cat a6ea81a46fec3d02d40815b8667b388351edecedc1cc9f97aab55b566db7aac8.ots | base64 | tr -d '\n')\"}" localhost:8888/ots_verify
|
||||
|
||||
response=$(serve_ots_verify "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
ots_info)
|
||||
# POST http://192.168.111.152:8080/ots_info
|
||||
@@ -821,10 +755,15 @@ main() {
|
||||
# curl -v -d "{\"hash\":\"a6ea81a46fec3d02d40815b8667b388351edecedc1cc9f97aab55b566db7aac8\",\"base64otsfile\":\"$(cat a6ea81a46fec3d02d40815b8667b388351edecedc1cc9f97aab55b566db7aac8.ots | base64 | tr -d '\n')\"}" localhost:8888/ots_info
|
||||
|
||||
response=$(serve_ots_info "${line}")
|
||||
response_to_client "${response}" ${?}
|
||||
break
|
||||
returncode=$?
|
||||
;;
|
||||
*)
|
||||
response='{"error": {"code": -32601, "message": "Method not found"}, "id": "1"}'
|
||||
returncode=1
|
||||
;;
|
||||
esac
|
||||
response=$(echo "${response}" | jq -Mc)
|
||||
response_to_client "${response}" ${returncode}
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -3,6 +3,35 @@
|
||||
. ./trace.sh
|
||||
|
||||
sql() {
|
||||
trace "Entering sql()..."
|
||||
|
||||
local select_id=${2}
|
||||
local response
|
||||
local inserted_id
|
||||
|
||||
trace "[sql] psql -qAtX -h postgres -U cyphernode -c \"${1}\""
|
||||
response=$(psql -qAtX -h postgres -U cyphernode -c "${1}")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
if [ -n "${select_id}" ]; then
|
||||
if [ "${returncode}" -eq "0" ]; then
|
||||
inserted_id=$(echo "${response}" | cut -d ' ' -f1)
|
||||
else
|
||||
trace "[sql] psql -qAtX -h postgres -U cyphernode -c \"${select_id}\""
|
||||
inserted_id=$(psql -qAtX -h postgres -U cyphernode -c "${select_id}")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
fi
|
||||
echo -n "${inserted_id}"
|
||||
else
|
||||
echo -n "${response}"
|
||||
fi
|
||||
|
||||
return ${returncode}
|
||||
}
|
||||
|
||||
sql_sqlite() {
|
||||
trace "sqlite3 -cmd \".timeout 40000\" ${DB_FILE} \"${1}\""
|
||||
sqlite3 -cmd ".timeout 40000" ${DB_FILE} "${1}"
|
||||
|
||||
@@ -14,16 +43,3 @@ sql() {
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
sql_rawtx() {
|
||||
trace "sqlite3 -cmd \".timeout 40000\" ${DB_FILE}_rawtx \"${1}\""
|
||||
sqlite3 -cmd ".timeout 40000" ${DB_FILE}_rawtx "${1}"
|
||||
|
||||
if [ "$?" -ne 0 ]; then
|
||||
# SQL didn't work, let's retry to be sure...
|
||||
trace "SQL didn't work, let's retry..."
|
||||
sqlite3 -cmd ".timeout 40000" ${DB_FILE}_rawtx "${1}"
|
||||
fi
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ createCurlConfig() {
|
||||
if [ ! -e ${DB_FILE} ]; then
|
||||
echo "DB not found, creating..."
|
||||
cat cyphernode.sql | sqlite3 $DB_FILE
|
||||
cat rawtx.sql | sqlite3 ${DB_FILE}_rawtx
|
||||
else
|
||||
echo "DB found, migrating..."
|
||||
for script in sqlmigrate*.sh; do
|
||||
@@ -42,7 +41,6 @@ else
|
||||
fi
|
||||
|
||||
chmod 0600 $DB_FILE
|
||||
chmod 0600 ${DB_FILE}_rawtx
|
||||
|
||||
createCurlConfig ${WATCHER_BTC_NODE_RPC_CFG} ${WATCHER_BTC_NODE_RPC_USER}
|
||||
createCurlConfig ${SPENDER_BTC_NODE_RPC_CFG} ${SPENDER_BTC_NODE_RPC_USER}
|
||||
|
||||
@@ -16,10 +16,10 @@ unwatchrequest() {
|
||||
# Let's lowercase bech32 addresses
|
||||
address=$(lowercase_if_bech32 "${address}")
|
||||
|
||||
trace "[unwatchrequest] Unwatch request id ${watchid} on address ${address} with url0conf ${unconfirmedCallbackURL} and url1conf ${confirmedCallbackURL}"
|
||||
trace "[unwatchrequest] Unwatch request id ${watchid} on address \"${address}\" with url0conf \"${unconfirmedCallbackURL}\" and url1conf \"${confirmedCallbackURL}\""
|
||||
|
||||
if [ "${watchid}" != "null" ]; then
|
||||
sql "UPDATE watching SET watching=0 WHERE id=${watchid}"
|
||||
sql "UPDATE watching SET watching=false WHERE id=${watchid}"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -35,11 +35,11 @@ unwatchrequest() {
|
||||
cb1_where=" AND callback1conf='${confirmedCallbackURL}'"
|
||||
fi
|
||||
|
||||
sql "UPDATE watching SET watching=0 WHERE address='${address}'${cb0_where}${cb1_where}"
|
||||
sql "UPDATE watching SET watching=false WHERE address='${address}'${cb0_where}${cb1_where}"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
data="{\"event\":\"unwatch\",\"address\":\"${address}\",\"unconfirmedCallbackURL\":${unconfirmedCallbackURL},\"confirmedCallbackURL\":${confirmedCallbackURL}}"
|
||||
data="{\"event\":\"unwatch\",\"address\":\"${address}\",\"unconfirmedCallbackURL\":\"${unconfirmedCallbackURL}\",\"confirmedCallbackURL\":\"${confirmedCallbackURL}\"}"
|
||||
fi
|
||||
|
||||
trace "[unwatchrequest] responding=${data}"
|
||||
@@ -52,20 +52,19 @@ unwatchrequest() {
|
||||
unwatchpub32request() {
|
||||
trace "Entering unwatchpub32request()..."
|
||||
|
||||
# GET http://192.168.111.152:8080/unwatchxpubbyxpub/tpubD6NzVbkrYhZ4YR3QK2tyfMMvBghAvqtNaNK1LTyDWcRHLcMUm3ZN2cGm5BS3MhCRCeCkXQkTXXjiJgqxpqXK7PeUSp86DTTgkLpcjMtpKWk
|
||||
|
||||
local request=${1}
|
||||
local pub32=$(echo "${request}" | cut -d ' ' -f2 | cut -d '/' -f3)
|
||||
local id
|
||||
local returncode
|
||||
trace "[unwatchpub32request] Unwatch pub32 ${pub32}"
|
||||
|
||||
id=$(sql "SELECT id FROM watching_by_pub32 WHERE pub32='${pub32}'")
|
||||
trace "[unwatchpub32request] id: ${id}"
|
||||
|
||||
sql "UPDATE watching_by_pub32 SET watching=0 WHERE id=${id}"
|
||||
sql "UPDATE watching w SET watching=false FROM watching_by_pub32 w32 WHERE w.watching_by_pub32_id=w32.id AND pub32='${pub32}'"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
sql "UPDATE watching SET watching=0 WHERE watching_by_pub32_id=\"${id}\""
|
||||
sql "UPDATE watching_by_pub32 SET watching=false WHERE pub32='${pub32}'"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -86,16 +85,11 @@ unwatchpub32labelrequest() {
|
||||
local returncode
|
||||
trace "[unwatchpub32labelrequest] Unwatch xpub label ${label}"
|
||||
|
||||
id=$(sql "SELECT id FROM watching_by_pub32 WHERE label='${label}'")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
trace "[unwatchpub32labelrequest] id: ${id}"
|
||||
|
||||
sql "UPDATE watching_by_pub32 SET watching=0 WHERE id=${id}"
|
||||
sql "UPDATE watching w SET watching=false FROM watching_by_pub32 w32 WHERE w.watching_by_pub32_id=w32.id AND w32.label='${label}'"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
sql "UPDATE watching SET watching=0 WHERE watching_by_pub32_id=\"${id}\""
|
||||
sql "UPDATE watching_by_pub32 SET watching=false WHERE label='${label}'"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -112,23 +106,30 @@ unwatchtxidrequest() {
|
||||
|
||||
local watchid=${1}
|
||||
local txid=${2}
|
||||
|
||||
local unconfirmedCallbackURL=${3}
|
||||
local uc_pg uc_json
|
||||
[ "${unconfirmedCallbackURL}" = "null" ] && uc_pg=" IS NULL" && uc_json="null" || uc_pg="='${unconfirmedCallbackURL}'" && uc_json="\"${unconfirmedCallbackURL}\""
|
||||
|
||||
local confirmedCallbackURL=${4}
|
||||
local c_pg c_json
|
||||
[ "${confirmedCallbackURL}" = "null" ] && c_pg=" IS NULL" && c_json="null" || c_pg="='${confirmedCallbackURL}'" && c_json="\"${confirmedCallbackURL}\""
|
||||
|
||||
local returncode
|
||||
trace "[unwatchtxidrequest] Unwatch request id ${watchid} on txid ${txid} with url0conf ${unconfirmedCallbackURL} and url1conf ${confirmedCallbackURL}"
|
||||
trace "[unwatchtxidrequest] Unwatch request id ${watchid} on txid \"${txid}\" with url0conf \"${unconfirmedCallbackURL}\" and url1conf \"${confirmedCallbackURL}\""
|
||||
|
||||
if [ "${watchid}" != "null" ]; then
|
||||
sql "UPDATE watching_by_txid SET watching=0 WHERE id=${watchid}"
|
||||
sql "UPDATE watching_by_txid SET watching=false WHERE id=${watchid}"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
data="{\"event\":\"unwatchtxid\",\"id\":${watchid}}"
|
||||
else
|
||||
sql "UPDATE watching_by_txid SET watching=0 WHERE txid='${txid}' AND callback0conf=${unconfirmedCallbackURL} AND callback1conf=${confirmedCallbackURL}"
|
||||
sql "UPDATE watching_by_txid SET watching=false WHERE txid='${txid}' AND callback0conf${uc_pg} AND callback1conf${c_pg}"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
data="{\"event\":\"unwatchtxid\",\"txid\":\"${txid}\",\"unconfirmedCallbackURL\":${unconfirmedCallbackURL},\"confirmedCallbackURL\":${confirmedCallbackURL}}"
|
||||
data="{\"event\":\"unwatchtxid\",\"txid\":\"${txid}\",\"unconfirmedCallbackURL\":${uc_json},\"confirmedCallbackURL\":${c_json}}"
|
||||
fi
|
||||
|
||||
trace "[unwatchtxidrequest] responding=${data}"
|
||||
|
||||
@@ -42,14 +42,14 @@ ln_waitanyinvoice() {
|
||||
status=$(echo "${result}" | jq -r ".status")
|
||||
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}\""
|
||||
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}\"")
|
||||
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 callback_url<>'' AND NOT calledback AND bolt11='${bolt11}'")
|
||||
|
||||
if [ -n "${row}" ]; then
|
||||
ln_manage_callback ${row}
|
||||
fi
|
||||
|
||||
sql "UPDATE cyphernode_props SET value="${pay_index}" WHERE property=\"pay_index\""
|
||||
sql "UPDATE cyphernode_props SET value='${pay_index}' WHERE property='pay_index'"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ spend() {
|
||||
tx_raw_details=$(get_rawtransaction ${txid} | tr -d '\n')
|
||||
|
||||
# Amounts and fees are negative when spending so we absolute those fields
|
||||
local tx_hash=$(echo "${tx_raw_details}" | jq '.result.hash')
|
||||
local tx_hash=$(echo "${tx_raw_details}" | jq -r '.result.hash')
|
||||
local tx_ts_firstseen=$(echo "${tx_details}" | jq '.result.timereceived')
|
||||
local tx_amount=$(echo "${tx_details}" | jq '.result.amount | fabs' | awk '{ printf "%.8f", $0 }')
|
||||
local tx_size=$(echo "${tx_raw_details}" | jq '.result.size')
|
||||
@@ -50,9 +50,6 @@ spend() {
|
||||
local tx_replaceable=$(echo "${tx_details}" | jq -r '.result."bip125-replaceable"')
|
||||
tx_replaceable=$([ ${tx_replaceable} = "yes" ] && echo "true" || echo "false")
|
||||
local fees=$(echo "${tx_details}" | jq '.result.fee | fabs' | awk '{ printf "%.8f", $0 }')
|
||||
# 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}" > spend-rawtx-${txid}-$$.blob
|
||||
|
||||
########################################################################################################
|
||||
# Let's publish the event if needed
|
||||
@@ -73,20 +70,17 @@ spend() {
|
||||
########################################################################################################
|
||||
|
||||
# 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, conf_target) VALUES (\"${txid}\", ${tx_hash}, 0, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${conf_target})"
|
||||
id_inserted=$(sql "INSERT INTO tx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, conf_target)"\
|
||||
" VALUES ('${txid}', '${tx_hash}', 0, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${conf_target})"\
|
||||
" RETURNING id" \
|
||||
"SELECT id FROM tx WHERE txid='${txid}'")
|
||||
trace_rc $?
|
||||
sql_rawtx "INSERT OR IGNORE INTO rawtx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, conf_target, raw_tx) VALUES (\"${txid}\", ${tx_hash}, 0, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${conf_target}, readfile('spend-rawtx-${txid}-$$.blob'))"
|
||||
trace_rc $?
|
||||
id_inserted=$(sql "SELECT id FROM tx WHERE txid=\"${txid}\"")
|
||||
trace_rc $?
|
||||
sql "INSERT OR IGNORE INTO recipient (address, amount, tx_id) VALUES (\"${address}\", ${amount}, ${id_inserted})"
|
||||
sql "INSERT INTO recipient (address, amount, tx_id) VALUES ('${address}', ${amount}, ${id_inserted})"\
|
||||
" ON CONFLICT DO NOTHING"
|
||||
trace_rc $?
|
||||
|
||||
data="{\"status\":\"accepted\""
|
||||
data="${data},\"txid\":\"${txid}\",\"hash\":${tx_hash},\"details\":{\"address\":\"${address}\",\"amount\":${amount},\"firstseen\":${tx_ts_firstseen},\"size\":${tx_size},\"vsize\":${tx_vsize},\"replaceable\":${tx_replaceable},\"fee\":${fees},\"subtractfeefromamount\":${subtractfeefromamount}}}"
|
||||
|
||||
# Delete the temp file containing the raw tx (see above)
|
||||
rm spend-rawtx-${txid}-$$.blob
|
||||
data="${data},\"txid\":\"${txid}\",\"hash\":\"${tx_hash}\",\"details\":{\"address\":\"${address}\",\"amount\":${amount},\"firstseen\":${tx_ts_firstseen},\"size\":${tx_size},\"vsize\":${tx_vsize},\"replaceable\":${tx_replaceable},\"fee\":${fees},\"subtractfeefromamount\":${subtractfeefromamount}}}"
|
||||
else
|
||||
local message=$(echo "${response}" | jq -e ".error.message")
|
||||
data="{\"message\":${message}}"
|
||||
@@ -222,7 +216,7 @@ getbalancebyxpublabel() {
|
||||
trace "[getbalancebyxpublabel] label=${label}"
|
||||
local xpub
|
||||
|
||||
xpub=$(sql "SELECT pub32 FROM watching_by_pub32 WHERE label=\"${label}\"")
|
||||
xpub=$(sql "SELECT pub32 FROM watching_by_pub32 WHERE label='${label}'")
|
||||
trace "[getbalancebyxpublabel] xpub=${xpub}"
|
||||
|
||||
getbalancebyxpub ${xpub} "getbalancebyxpublabel"
|
||||
|
||||
@@ -11,11 +11,72 @@ watchrequest() {
|
||||
|
||||
local returncode
|
||||
local request=${1}
|
||||
local address=$(echo "${request}" | jq -r ".address")
|
||||
local cb0conf_url=$(echo "${request}" | jq ".unconfirmedCallbackURL")
|
||||
local cb1conf_url=$(echo "${request}" | jq ".confirmedCallbackURL")
|
||||
local event_message=$(echo "${request}" | jq ".eventMessage")
|
||||
local label=$(echo "${request}" | jq ".label")
|
||||
local address address_pg
|
||||
address=$(echo "${request}" | jq -re ".address")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# address not found or null
|
||||
result='{"result":null,'\
|
||||
'"error":{'\
|
||||
'"code":-5,'\
|
||||
'"message":"address required"}}'
|
||||
trace "[watchrequest] address required"
|
||||
trace "[watchrequest] responding=${result}"
|
||||
|
||||
echo "${result}"
|
||||
|
||||
return 1
|
||||
else
|
||||
address_pg="'${address}'"
|
||||
fi
|
||||
|
||||
local cb0conf_url cb0conf_url_pg cb0conf_url_pg_where cb0conf_url_json
|
||||
cb0conf_url=$(echo "${request}" | jq -re ".unconfirmedCallbackURL")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# unconfirmedCallbackURL not found or null
|
||||
cb0conf_url_json="null"
|
||||
cb0conf_url_pg="null"
|
||||
cb0conf_url_pg_where=" IS NULL"
|
||||
else
|
||||
cb0conf_url_json="\"${cb0conf_url}\""
|
||||
cb0conf_url_pg="'${cb0conf_url}'"
|
||||
cb0conf_url_pg_where="=${cb0conf_url_pg}"
|
||||
fi
|
||||
|
||||
local cb1conf_url cb1conf_url_pg cb1conf_url_pg_where cb1conf_url_json
|
||||
cb1conf_url=$(echo "${request}" | jq -re ".confirmedCallbackURL")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# confirmedCallbackURL not found or null
|
||||
cb1conf_url_json="null"
|
||||
cb1conf_url_pg="null"
|
||||
cb1conf_url_pg_where=" IS NULL"
|
||||
else
|
||||
cb1conf_url_json="\"${cb1conf_url}\""
|
||||
cb1conf_url_pg="'${cb1conf_url}'"
|
||||
cb1conf_url_pg_where="=${cb1conf_url_pg}"
|
||||
fi
|
||||
|
||||
local event_message event_message_pg event_message_json
|
||||
event_message=$(echo "${request}" | jq -re ".eventMessage")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# eventMessage not found or null
|
||||
event_message_json="null"
|
||||
event_message_pg="null"
|
||||
else
|
||||
event_message_json="\"${event_message}\""
|
||||
event_message_pg="'${event_message}'"
|
||||
fi
|
||||
|
||||
local label label_pg label_json
|
||||
label=$(echo "${request}" | jq -re ".label")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# label not found or null
|
||||
label_json="null"
|
||||
label_pg="null"
|
||||
else
|
||||
label_json="\"${label}\""
|
||||
label_pg="'${label}'"
|
||||
fi
|
||||
|
||||
local imported
|
||||
local inserted
|
||||
local id_inserted
|
||||
@@ -24,23 +85,23 @@ watchrequest() {
|
||||
# Let's lowercase bech32 addresses
|
||||
address=$(lowercase_if_bech32 "${address}")
|
||||
|
||||
trace "[watchrequest] Watch request on address (\"${address}\"), cb 0-conf (${cb0conf_url}), cb 1-conf (${cb1conf_url}) with event_message=${event_message} and label=${label}"
|
||||
trace "[watchrequest] Watch request on address (${address}), cb 0-conf (${cb0conf_url_json}), cb 1-conf (${cb1conf_url_json}) with event_message=${event_message_json} and label=${label_json}"
|
||||
|
||||
local isvalid
|
||||
isvalid=$(validateaddress "${address}" | jq ".result.isvalid")
|
||||
if [ "${isvalid}" != "true" ]; then
|
||||
result="{
|
||||
\"result\":null,
|
||||
\"error\":{
|
||||
\"code\":-5,
|
||||
\"message\":\"Invalid address\",
|
||||
\"data\":{
|
||||
\"event\":\"watch\",
|
||||
\"address\":\"${address}\",
|
||||
\"unconfirmedCallbackURL\":${cb0conf_url},
|
||||
\"confirmedCallbackURL\":${cb1conf_url},
|
||||
\"label\":${label},
|
||||
\"eventMessage\":${event_message}}}}"
|
||||
result='{'\
|
||||
'"result":null,'\
|
||||
'"error":{'\
|
||||
'"code":-5,'\
|
||||
'"message":"Invalid address",'\
|
||||
'"data":{'\
|
||||
'"event":"watch",'\
|
||||
'"address":'"${address}"','\
|
||||
'"unconfirmedCallbackURL":'${cb0conf_url_json}','\
|
||||
'"confirmedCallbackURL":'${cb1conf_url_json}','\
|
||||
'"label":'${label_json}','\
|
||||
'"eventMessage":'${event_message_json}'}}}'
|
||||
trace "[watchrequest] Invalid address"
|
||||
trace "[watchrequest] responding=${result}"
|
||||
|
||||
@@ -53,21 +114,26 @@ watchrequest() {
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
imported=1
|
||||
imported=true
|
||||
else
|
||||
imported=0
|
||||
imported=false
|
||||
fi
|
||||
|
||||
sql "INSERT INTO watching (address, watching, callback0conf, callback1conf, imported, event_message, label) VALUES (\"${address}\", 1, ${cb0conf_url}, ${cb1conf_url}, ${imported}, ${event_message}, ${label}) ON CONFLICT(address,callback0conf,callback1conf) DO UPDATE SET watching=1, event_message=${event_message}, calledback0conf=0, calledback1conf=0, label=${label}"
|
||||
id_inserted=$(sql "INSERT INTO watching (address, watching, callback0conf, callback1conf, imported, event_message, label)"\
|
||||
" VALUES (${address_pg}, true, ${cb0conf_url_pg}, ${cb1conf_url_pg}, ${imported}, ${event_message_pg}, ${label_pg})"\
|
||||
" ON CONFLICT (address, COALESCE(callback0conf, ''), COALESCE(callback1conf, '')) DO"\
|
||||
" UPDATE SET watching=true, event_message=${event_message_pg}, calledback0conf=false, calledback1conf=false, label=${label_pg}"\
|
||||
" RETURNING id" \
|
||||
"SELECT id FROM watching WHERE address=${address_pg} AND callback0conf${cb0conf_url_pg_where} AND callback1conf${cb1conf_url_pg_where}")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
trace "[watchrequest] id_inserted=${id_inserted}"
|
||||
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
inserted=1
|
||||
id_inserted=$(sql "SELECT id FROM watching WHERE address='${address}' AND callback0conf=${cb0conf_url} AND callback1conf=${cb1conf_url}")
|
||||
inserted=true
|
||||
trace "[watchrequest] id_inserted: ${id_inserted}"
|
||||
else
|
||||
inserted=0
|
||||
inserted=false
|
||||
fi
|
||||
|
||||
local fees2blocks
|
||||
@@ -83,19 +149,19 @@ watchrequest() {
|
||||
fees144blocks=$(getestimatesmartfee 144)
|
||||
trace_rc $?
|
||||
|
||||
result="{\"id\":\"${id_inserted}\",
|
||||
\"event\":\"watch\",
|
||||
\"imported\":${imported},
|
||||
\"inserted\":${inserted},
|
||||
\"address\":\"${address}\",
|
||||
\"unconfirmedCallbackURL\":${cb0conf_url},
|
||||
\"confirmedCallbackURL\":${cb1conf_url},
|
||||
\"label\":${label},
|
||||
\"estimatesmartfee2blocks\":${fees2blocks},
|
||||
\"estimatesmartfee6blocks\":${fees6blocks},
|
||||
\"estimatesmartfee36blocks\":${fees36blocks},
|
||||
\"estimatesmartfee144blocks\":${fees144blocks},
|
||||
\"eventMessage\":${event_message}}"
|
||||
result='{"id":'${id_inserted}','\
|
||||
'"event":"watch",'\
|
||||
'"imported":'${imported}','\
|
||||
'"inserted":'${inserted}','\
|
||||
'"address":"'${address}'",'\
|
||||
'"unconfirmedCallbackURL":'${cb0conf_url_json}','\
|
||||
'"confirmedCallbackURL":'${cb1conf_url_json}','\
|
||||
'"label":'${label_json}','\
|
||||
'"estimatesmartfee2blocks":'${fees2blocks}','\
|
||||
'"estimatesmartfee6blocks":'${fees6blocks}','\
|
||||
'"estimatesmartfee36blocks":'${fees36blocks}','\
|
||||
'"estimatesmartfee144blocks":'${fees144blocks}','\
|
||||
'"eventMessage":'${event_message_json}'}'
|
||||
trace "[watchrequest] responding=${result}"
|
||||
|
||||
echo "${result}"
|
||||
@@ -106,19 +172,56 @@ watchrequest() {
|
||||
watchpub32request() {
|
||||
trace "Entering watchpub32request()..."
|
||||
|
||||
# BODY {"label":"4421","pub32":"tpubD6NzVbkrYhZ4YR3QK2tyfMMvBghAvqtNaNK1LTyDWcRHLcMUm3ZN2cGm5BS3MhCRCeCkXQkTXXjiJgqxpqXK7PeUSp86DTTgkLpcjMtpKWk","path":"0/n","nstart":0,"unconfirmedCallbackURL":"192.168.111.233:1111/callback0conf","confirmedCallbackURL":"192.168.111.233:1111/callback1conf"}
|
||||
|
||||
# Required:
|
||||
# - "label"
|
||||
# - "pub32"
|
||||
# - "path"
|
||||
# - "nstart"
|
||||
|
||||
local returncode
|
||||
local request=${1}
|
||||
local label=$(echo "${request}" | jq ".label")
|
||||
local label=$(echo "${request}" | jq -er ".label")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# label not found or null
|
||||
trace "[watchpub32request] label required"
|
||||
echo '{"error":"label required","event":"watchxpub"}'
|
||||
|
||||
return 1
|
||||
fi
|
||||
trace "[watchpub32request] label=${label}"
|
||||
local pub32=$(echo "${request}" | jq ".pub32")
|
||||
local pub32=$(echo "${request}" | jq -er ".pub32")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# pub32 not found or null
|
||||
trace "[watchpub32request] pub32 required"
|
||||
echo '{"error":"pub32 required","event":"watchxpub"}'
|
||||
|
||||
return 1
|
||||
fi
|
||||
trace "[watchpub32request] pub32=${pub32}"
|
||||
local path=$(echo "${request}" | jq ".path")
|
||||
local path=$(echo "${request}" | jq -er ".path")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# path not found or null
|
||||
trace "[watchpub32request] path required"
|
||||
echo '{"error":"path required","event":"watchxpub"}'
|
||||
|
||||
return 1
|
||||
fi
|
||||
trace "[watchpub32request] path=${path}"
|
||||
local nstart=$(echo "${request}" | jq ".nstart")
|
||||
local nstart=$(echo "${request}" | jq -er ".nstart")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# nstart not found or null
|
||||
trace "[watchpub32request] nstart required"
|
||||
echo '{"error":"nstart required","event":"watchxpub"}'
|
||||
|
||||
return 1
|
||||
fi
|
||||
trace "[watchpub32request] nstart=${nstart}"
|
||||
local cb0conf_url=$(echo "${request}" | jq ".unconfirmedCallbackURL")
|
||||
|
||||
local cb0conf_url=$(echo "${request}" | jq -r ".unconfirmedCallbackURL // empty")
|
||||
trace "[watchpub32request] cb0conf_url=${cb0conf_url}"
|
||||
local cb1conf_url=$(echo "${request}" | jq ".confirmedCallbackURL")
|
||||
local cb1conf_url=$(echo "${request}" | jq -r ".confirmedCallbackURL // empty")
|
||||
trace "[watchpub32request] cb1conf_url=${cb1conf_url}"
|
||||
|
||||
watchpub32 "${label}" "${pub32}" "${path}" "${nstart}" "${cb0conf_url}" "${cb1conf_url}"
|
||||
@@ -131,21 +234,46 @@ watchpub32request() {
|
||||
watchpub32() {
|
||||
trace "Entering watchpub32()..."
|
||||
|
||||
# Expecting args without quotes
|
||||
# label, pub32, path and nstart are required
|
||||
# When cb0conf_url and cb1conf_url are empty, means null
|
||||
|
||||
local returncode
|
||||
local label=${1}
|
||||
trace "[watchpub32] label=${label}"
|
||||
local label_pg="'${label}'"
|
||||
trace "[watchpub32] label=${label}, label_pg=${label_pg}"
|
||||
local pub32=${2}
|
||||
trace "[watchpub32] pub32=${pub32}"
|
||||
local pub32_pg="'${pub32}'"
|
||||
trace "[watchpub32] pub32=${pub32}, pub32_pg=${pub32_pg}"
|
||||
local path=${3}
|
||||
trace "[watchpub32] path=${path}"
|
||||
local path_pg="'${path}'"
|
||||
trace "[watchpub32] path=${path}, path_pg=${path_pg}"
|
||||
local nstart=${4}
|
||||
trace "[watchpub32] nstart=${nstart}"
|
||||
local last_n=$((${nstart}+${XPUB_DERIVATION_GAP}))
|
||||
trace "[watchpub32] last_n=${last_n}"
|
||||
local cb0conf_url=${5}
|
||||
trace "[watchpub32] cb0conf_url=${cb0conf_url}"
|
||||
local cb0conf_url_pg cb0conf_url_json
|
||||
if [ -z "${cb0conf_url}" ]; then
|
||||
# Empty url
|
||||
cb0conf_url_json="null"
|
||||
cb0conf_url_pg="null"
|
||||
else
|
||||
cb0conf_url_json="\"${cb0conf_url}\""
|
||||
cb0conf_url_pg="'${cb0conf_url}'"
|
||||
fi
|
||||
trace "[watchpub32] cb0conf_url=${cb0conf_url}, cb0conf_url_pg=${cb0conf_url_pg}"
|
||||
local cb1conf_url=${6}
|
||||
trace "[watchpub32] cb1conf_url=${cb1conf_url}"
|
||||
local cb1conf_url_pg cb1conf_url_json
|
||||
if [ -z "${cb1conf_url}" ]; then
|
||||
# Empty url
|
||||
cb1conf_url_json="null"
|
||||
cb1conf_url_pg="null"
|
||||
else
|
||||
cb1conf_url_json="\"${cb1conf_url}\""
|
||||
cb1conf_url_pg="'${cb1conf_url}'"
|
||||
fi
|
||||
trace "[watchpub32] cb1conf_url=${cb1conf_url}, cb1conf_url_pg=${cb1conf_url_pg}"
|
||||
|
||||
# upto_n is used when extending the watching window
|
||||
local upto_n=${7}
|
||||
@@ -156,7 +284,7 @@ watchpub32() {
|
||||
local error_msg
|
||||
local data
|
||||
|
||||
# Derive with pycoin...
|
||||
# Derive with bitcoind...
|
||||
# {"pub32":"tpubD6NzVbkrYhZ4YR3QK2tyfMMvBghAvqtNaNK1LTyDWcRHLcMUm3ZN2cGm5BS3MhCRCeCkXQkTXXjiJgqxpqXK7PeUSp86DTTgkLpcjMtpKWk","path":"0/25-30"}
|
||||
if [ -n "${upto_n}" ]; then
|
||||
# If upto_n provided, then we create from nstart to upto_n (instead of + GAP)
|
||||
@@ -165,7 +293,7 @@ watchpub32() {
|
||||
local subspath=$(echo -e $path | sed -En "s/n/${nstart}-${last_n}/p")
|
||||
trace "[watchpub32] subspath=${subspath}"
|
||||
local addresses
|
||||
addresses=$(derivepubpath "{\"pub32\":${pub32},\"path\":${subspath}}")
|
||||
addresses=$(derivepubpath '{"pub32":"'${pub32}'","path":"'${subspath}'"}')
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
# trace "[watchpub32] addresses=${addresses}"
|
||||
@@ -179,7 +307,7 @@ watchpub32() {
|
||||
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
# Importmulti in Bitcoin Core...
|
||||
result=$(importmulti_rpc "${WATCHER_BTC_NODE_XPUB_WALLET}" ${pub32} "${addresses}")
|
||||
result=$(importmulti_rpc "${WATCHER_BTC_NODE_XPUB_WALLET}" "${pub32}" "${addresses}")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
trace "[watchpub32] result=${result}"
|
||||
@@ -187,29 +315,31 @@ watchpub32() {
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
if [ -n "${upto_n}" ]; then
|
||||
# Update existing row, we are extending the watching window
|
||||
sql "UPDATE watching_by_pub32 set last_imported_n=${upto_n} WHERE pub32=${pub32}"
|
||||
id_inserted=$(sql "UPDATE watching_by_pub32 set last_imported_n=${upto_n} WHERE pub32=${pub32_pg} RETURNING id")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
else
|
||||
# Insert in our DB...
|
||||
sql "INSERT INTO watching_by_pub32 (pub32, label, derivation_path, watching, callback0conf, callback1conf, last_imported_n) VALUES (${pub32}, ${label}, ${path}, 1, ${cb0conf_url}, ${cb1conf_url}, ${last_n})"
|
||||
id_inserted=$(sql "INSERT INTO watching_by_pub32 (pub32, label, derivation_path, watching, callback0conf, callback1conf, last_imported_n)"\
|
||||
" VALUES (${pub32_pg}, ${label_pg}, ${path_pg}, true, ${cb0conf_url_pg}, ${cb1conf_url_pg}, ${last_n})"\
|
||||
" ON CONFLICT (pub32) DO"\
|
||||
" UPDATE SET watching=true, label=${label_pg}, callback0conf=${cb0conf_url_pg}, callback1conf=${cb1conf_url_pg}, derivation_path=${path_pg}, last_imported_n=${last_n}"\
|
||||
" RETURNING id" \
|
||||
"SELECT id FROM watching_by_pub32 WHERE pub32=${pub32_pg}")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
if [ "${returncode}" -ne "0" ]; then
|
||||
trace "[watchpub32] xpub or label already being watched, updating with new values based on supplied xpub..."
|
||||
sql "UPDATE watching_by_pub32 SET watching=1, label=${label}, callback0conf=${cb0conf_url}, callback1conf=${cb1conf_url} WHERE pub32=${pub32}"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
id_inserted=$(sql "SELECT id FROM watching_by_pub32 WHERE pub32=${pub32}")
|
||||
trace "[watchpub32] id_inserted: ${id_inserted}"
|
||||
|
||||
addresses=$(echo ${addresses} | jq ".addresses[].address")
|
||||
insert_watches "${addresses}" "${cb0conf_url}" "${cb1conf_url}" "${id_inserted}" "${nstart}"
|
||||
addresses=$(echo ${addresses} | jq -r ".addresses[].address")
|
||||
insert_watches "${addresses}" "${label}" "${cb0conf_url}" "${cb1conf_url}" "${id_inserted}" "${nstart}"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
if [ "${returncode}" -ne 0 ]; then
|
||||
error_msg="Can't insert xpub watches in DB"
|
||||
fi
|
||||
else
|
||||
error_msg="Can't insert xpub watcher in DB"
|
||||
fi
|
||||
@@ -224,25 +354,25 @@ watchpub32() {
|
||||
fi
|
||||
|
||||
if [ -z "${error_msg}" ]; then
|
||||
data="{\"id\":${id_inserted},
|
||||
\"event\":\"watchxpub\",
|
||||
\"pub32\":${pub32},
|
||||
\"label\":${label},
|
||||
\"path\":${path},
|
||||
\"nstart\":${nstart},
|
||||
\"unconfirmedCallbackURL\":${cb0conf_url},
|
||||
\"confirmedCallbackURL\":${cb1conf_url}}"
|
||||
data='{"id":'${id_inserted}','\
|
||||
'"event":"watchxpub",'\
|
||||
'"pub32":"'${pub32}'",'\
|
||||
'"label":"'${label}'",'\
|
||||
'"path":"'${path}'",'\
|
||||
'"nstart":'${nstart}','\
|
||||
'"unconfirmedCallbackURL":'${cb0conf_url_json}','\
|
||||
'"confirmedCallbackURL":'${cb1conf_url_json}'}'
|
||||
|
||||
returncode=0
|
||||
else
|
||||
data="{\"error\":\"${error_msg}\",
|
||||
\"event\":\"watchxpub\",
|
||||
\"pub32\":${pub32},
|
||||
\"label\":${label},
|
||||
\"path\":${path},
|
||||
\"nstart\":${nstart},
|
||||
\"unconfirmedCallbackURL\":${cb0conf_url},
|
||||
\"confirmedCallbackURL\":${cb1conf_url}}"
|
||||
data='{"error":"'${error_msg}'",'\
|
||||
'"event":"watchxpub",'\
|
||||
'"pub32":"'${pub32}'",'
|
||||
'"label":"'${label}'",'\
|
||||
'"path":"'${path}'",'\
|
||||
'"nstart":${nstart},'\
|
||||
'"unconfirmedCallbackURL":'${cb0conf_url_json}','\
|
||||
'"confirmedCallbackURL":'${cb1conf_url_json}'}'
|
||||
|
||||
returncode=1
|
||||
fi
|
||||
@@ -256,29 +386,54 @@ watchpub32() {
|
||||
insert_watches() {
|
||||
trace "Entering insert_watches()..."
|
||||
|
||||
# Expecting args without quotes
|
||||
# When callback0conf and callback1conf are empty, means null
|
||||
|
||||
local addresses=${1}
|
||||
local callback0conf=${2}
|
||||
local callback1conf=${3}
|
||||
local xpub_id=${4}
|
||||
local nstart=${5}
|
||||
local inserted_values=""
|
||||
local label=${2}
|
||||
local label_pg
|
||||
if [ -z "${label}" ]; then
|
||||
# Empty url
|
||||
label_pg="null"
|
||||
else
|
||||
label_pg="'${label}'"
|
||||
fi
|
||||
local callback0conf=${3}
|
||||
local callback0conf_pg
|
||||
if [ -z "${callback0conf}" ]; then
|
||||
# Empty url
|
||||
callback0conf_pg="null"
|
||||
else
|
||||
callback0conf_pg="'${callback0conf}'"
|
||||
fi
|
||||
local callback1conf=${4}
|
||||
local callback1conf_pg
|
||||
if [ -z "${callback1conf}" ]; then
|
||||
# Empty url
|
||||
callback1conf_pg="null"
|
||||
else
|
||||
callback1conf_pg="'${callback1conf}'"
|
||||
fi
|
||||
local xpub_id=${5}
|
||||
local nstart=${6}
|
||||
local inserted_values
|
||||
|
||||
local IFS=$'\n'
|
||||
for address in ${addresses}
|
||||
do
|
||||
# (address, watching, callback0conf, callback1conf, imported, watching_by_pub32_id)
|
||||
# (address, label, watching, callback0conf, callback1conf, imported, watching_by_pub32_id)
|
||||
if [ -n "${inserted_values}" ]; then
|
||||
inserted_values="${inserted_values},"
|
||||
fi
|
||||
inserted_values="${inserted_values}(${address}, 1, ${callback0conf}, ${callback1conf}, 1"
|
||||
if [ -n "${xpub_id}" ]; then
|
||||
inserted_values="${inserted_values}, ${xpub_id}, ${nstart}"
|
||||
nstart=$((${nstart} + 1))
|
||||
fi
|
||||
inserted_values="${inserted_values})"
|
||||
inserted_values="${inserted_values}('${address}', ${label_pg}, true, ${callback0conf_pg}, ${callback1conf_pg}, true, ${xpub_id}, ${nstart})"
|
||||
|
||||
nstart=$((${nstart} + 1))
|
||||
done
|
||||
|
||||
sql "INSERT INTO watching (address, watching, callback0conf, callback1conf, imported, watching_by_pub32_id, pub32_index) VALUES ${inserted_values} ON CONFLICT(address,callback0conf,callback1conf) DO UPDATE SET watching=1, event_message=${event_message}, calledback0conf=0, calledback1conf=0"
|
||||
sql "INSERT INTO watching (address, label, watching, callback0conf, callback1conf, imported, watching_by_pub32_id, pub32_index)"\
|
||||
" VALUES ${inserted_values}"\
|
||||
" ON CONFLICT (address, COALESCE(callback0conf, ''), COALESCE(callback1conf, '')) DO"\
|
||||
" UPDATE SET watching=true, calledback0conf=false, calledback1conf=false, label=${label_pg}"
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -288,6 +443,8 @@ insert_watches() {
|
||||
extend_watchers() {
|
||||
trace "Entering extend_watchers()..."
|
||||
|
||||
# Expecting args without quotes
|
||||
|
||||
local watching_by_pub32_id=${1}
|
||||
trace "[extend_watchers] watching_by_pub32_id=${watching_by_pub32_id}"
|
||||
local pub32_index=${2}
|
||||
@@ -297,7 +454,8 @@ extend_watchers() {
|
||||
|
||||
local last_imported_n
|
||||
local row
|
||||
row=$(sql "SELECT COALESCE('\"'||pub32||'\"', 'null'), COALESCE('\"'||label||'\"', 'null'), COALESCE('\"'||derivation_path||'\"', 'null'), COALESCE('\"'||callback0conf||'\"', 'null'), COALESCE('\"'||callback1conf||'\"', 'null'), last_imported_n FROM watching_by_pub32 WHERE id=${watching_by_pub32_id} AND watching")
|
||||
# row=$(sql "SELECT COALESCE('\"'||pub32||'\"', 'null'), COALESCE('\"'||label||'\"', 'null'), COALESCE('\"'||derivation_path||'\"', 'null'), COALESCE('\"'||callback0conf||'\"', 'null'), COALESCE('\"'||callback1conf||'\"', 'null'), last_imported_n FROM watching_by_pub32 WHERE id=${watching_by_pub32_id} AND watching")
|
||||
row=$(sql "SELECT pub32, label, derivation_path, callback0conf, callback1conf, last_imported_n FROM watching_by_pub32 WHERE id=${watching_by_pub32_id} AND watching")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
@@ -335,52 +493,88 @@ watchtxidrequest() {
|
||||
trace "Entering watchtxidrequest()..."
|
||||
|
||||
local returncode
|
||||
local result
|
||||
local request=${1}
|
||||
trace "[watchtxidrequest] request=${request}"
|
||||
local txid=$(echo "${request}" | jq ".txid")
|
||||
trace "[watchtxidrequest] txid=${txid}"
|
||||
local cb1conf_url=$(echo "${request}" | jq ".confirmedCallbackURL")
|
||||
trace "[watchtxidrequest] cb1conf_url=${cb1conf_url}"
|
||||
local cbxconf_url=$(echo "${request}" | jq ".xconfCallbackURL")
|
||||
trace "[watchtxidrequest] cbxconf_url=${cbxconf_url}"
|
||||
local txid txid_pg txid_pg_where
|
||||
txid=$(echo "${request}" | jq -re ".txid")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# txid not found or null
|
||||
result='{"result":null,'\
|
||||
'"error":{'\
|
||||
'"code":-5,'\
|
||||
'"message":"txid required"}}'
|
||||
trace "[watchrequest] txid required"
|
||||
trace "[watchrequest] responding=${result}"
|
||||
|
||||
echo "${result}"
|
||||
|
||||
return 1
|
||||
else
|
||||
txid_pg="'${address}'"
|
||||
fi
|
||||
trace "[watchtxidrequest] txid=${txid}, txid_pg=${txid_pg}"
|
||||
|
||||
local cb1conf_url cb1conf_url_pg cb1conf_url_pg_where cb1conf_url_json
|
||||
cb1conf_url=$(echo "${request}" | jq -re ".confirmedCallbackURL")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# cb1conf_url not found or null
|
||||
cb1conf_url_json="null"
|
||||
cb1conf_url_pg="null"
|
||||
cb1conf_url_pg_where=" IS NULL"
|
||||
else
|
||||
cb1conf_url_json="\"${cb1conf_url}\""
|
||||
cb1conf_url_pg="'${cb1conf_url}'"
|
||||
cb1conf_url_pg_where="=${cb1conf_url_pg}"
|
||||
fi
|
||||
trace "[watchtxidrequest] cb1conf_url=${cb1conf_url}, cb1conf_url_pg=${cb1conf_url_pg}, cb1conf_url_pg_where=${cb1conf_url_pg_where}, cb1conf_url_json=${cb1conf_url_json}"
|
||||
|
||||
local cbxconf_url cbxconf_url_pg cbxconf_url_pg_where
|
||||
cbxconf_url=$(echo "${request}" | jq -e ".xconfCallbackURL")
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# cbxconf_url not found or null
|
||||
cbxconf_url_json="null"
|
||||
cbxconf_url_pg="null"
|
||||
cbxconf_url_pg_where=" IS NULL"
|
||||
else
|
||||
cbxconf_url_json="\"${cbxconf_url}\""
|
||||
cbxconf_url_pg="'${cbxconf_url}'"
|
||||
cbxconf_url_pg_where="=${cbxconf_url_pg}"
|
||||
fi
|
||||
trace "[watchtxidrequest] cbxconf_url=${cbxconf_url}, cbxconf_url_pg=${cbxconf_url_pg}, cbxconf_url_pg_where=${cbxconf_url_pg_where}, cbxconf_url_json=${cbxconf_url_json}"
|
||||
|
||||
local nbxconf=$(echo "${request}" | jq ".nbxconf")
|
||||
trace "[watchtxidrequest] nbxconf=${nbxconf}"
|
||||
local cb1cond
|
||||
local cbxcond
|
||||
local inserted
|
||||
local id_inserted
|
||||
local result
|
||||
trace "[watchtxidrequest] Watch request on txid (${txid}), cb 1-conf (${cb1conf_url}) and cb x-conf (${cbxconf_url}) on ${nbxconf} confirmations."
|
||||
|
||||
sql "INSERT INTO watching_by_txid (txid, watching, callback1conf, callbackxconf, nbxconf) VALUES (${txid}, 1, ${cb1conf_url}, ${cbxconf_url}, ${nbxconf}) ON CONFLICT(txid, callback1conf, callbackxconf) DO UPDATE SET watching=1, nbxconf=${nbxconf}, calledback1conf=0, calledbackxconf=0"
|
||||
id_inserted=$(sql "INSERT INTO watching_by_txid (txid, watching, callback1conf, callbackxconf, nbxconf)"\
|
||||
" VALUES (${txid_pg}, true, ${cb1conf_url_pg}, ${cbxconf_url_pg}, ${nbxconf})"\
|
||||
" ON CONFLICT (txid, COALESCE(callback1conf, ''), COALESCE(callbackxconf, '')) DO"\
|
||||
" UPDATE SET watching=true, nbxconf=${nbxconf}, calledback1conf=false, calledbackxconf=false"\
|
||||
" RETURNING id" \
|
||||
"SELECT id FROM watching_by_txid WHERE txid=${txid_pg} AND callback1conf${cb1conf_url_pg_where} AND callbackxconf${cbxconf_url_pg_where}")
|
||||
returncode=$?
|
||||
trace_rc ${returncode}
|
||||
|
||||
if [ "${returncode}" -eq 0 ]; then
|
||||
inserted=1
|
||||
if [ "${cb1conf_url}" = "null" ]; then
|
||||
cb1cond=" IS NULL"
|
||||
else
|
||||
cb1cond="=${cb1conf_url}"
|
||||
fi
|
||||
if [ "${cbxconf_url}" = "null" ]; then
|
||||
cbxcond=" IS NULL"
|
||||
else
|
||||
cbxcond="=${cbxconf_url}"
|
||||
fi
|
||||
id_inserted=$(sql "SELECT id FROM watching_by_txid WHERE txid=${txid} AND callback1conf${cb1cond} AND callbackxconf${cbxcond}")
|
||||
inserted=true
|
||||
trace "[watchtxidrequest] id_inserted: ${id_inserted}"
|
||||
else
|
||||
inserted=0
|
||||
inserted=false
|
||||
id_inserted=null
|
||||
fi
|
||||
|
||||
local data="{\"id\":${id_inserted},
|
||||
\"event\":\"watchtxid\",
|
||||
\"inserted\":${inserted},
|
||||
\"txid\":${txid},
|
||||
\"confirmedCallbackURL\":${cb1conf_url},
|
||||
\"xconfCallbackURL\":${cbxconf_url},
|
||||
\"nbxconf\":${nbxconf}}"
|
||||
local data='{"id":'${id_inserted}','\
|
||||
'"event":"watchtxid",'\
|
||||
'"inserted":'${inserted}','\
|
||||
'"txid":"'${txid}'",'\
|
||||
'"confirmedCallbackURL":'${cb1conf_url_json}','\
|
||||
'"xconfCallbackURL":'${cbxconf_url_json}','\
|
||||
'"nbxconf":'${nbxconf}'}'
|
||||
trace "[watchtxidrequest] responding=${data}"
|
||||
|
||||
echo "${data}"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This needs to be run in regtest
|
||||
|
||||
# This will mine n blocks. If n is not supplied, will mine 1 block.
|
||||
|
||||
# Mine
|
||||
mine() {
|
||||
local nbblocks=${1:-1}
|
||||
|
||||
15
proxy_docker/app/tests/startcallbackserver.sh
Executable file
15
proxy_docker/app/tests/startcallbackserver.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
date
|
||||
|
||||
callbackservername=${1:-"tests-manage-missed"}
|
||||
callbackserverport=${2:-"1111"}
|
||||
callbackserverport2=${3:-"1112"}
|
||||
callbackserverport3=${4:-"1113"}
|
||||
callbackserverport4=${5:-"1114"}
|
||||
|
||||
docker run --rm -d --network cyphernodeappsnet --name ${callbackservername} alpine sh -c "nc -vlkp${callbackserverport} -e sh -c 'echo -en \"HTTP/1.1 200 OK\\\\r\\\\n\\\\r\\\\n\" ; date >&2 ; timeout 1 tee /dev/tty | cat ; echo 1>&2'"
|
||||
docker exec -d ${callbackservername} sh -c "nc -vlkp${callbackserverport2} -e sh -c 'echo -en \"HTTP/1.1 200 OK\\\\r\\\\n\\\\r\\\\n\" ; date >&2 ; timeout 1 tee /dev/tty | cat ; echo 1>&2'"
|
||||
docker exec -d ${callbackservername} sh -c "nc -vlkp${callbackserverport3} -e sh -c 'echo -en \"HTTP/1.1 200 OK\\\\r\\\\n\\\\r\\\\n\" ; date >&2 ; timeout 1 tee /dev/tty | cat ; echo 1>&2'"
|
||||
docker exec -d ${callbackservername} sh -c "nc -vlkp${callbackserverport4} -e sh -c 'echo -en \"HTTP/1.1 200 OK\\\\r\\\\n\\\\r\\\\n\" ; date >&2 ; timeout 1 tee /dev/tty | cat ; echo 1>&2'"
|
||||
|
||||
@@ -2,6 +2,26 @@
|
||||
|
||||
# docker exec -it $(docker ps -q -f "name=proxy\.") ./tests/test-batching.sh
|
||||
|
||||
# This needs to be run in regtest
|
||||
|
||||
# This will test:
|
||||
#
|
||||
# - listbatchers
|
||||
# - getbatcher
|
||||
# - getbatchdetails
|
||||
# - getnewaddress
|
||||
# - addtobatch
|
||||
# - batchspend
|
||||
# - removefrombatch
|
||||
# - createbatcher
|
||||
#
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Notes:
|
||||
# curl localhost:8888/listbatchers | jq
|
||||
# curl -d '{}' localhost:8888/getbatcher | jq
|
||||
# curl -d '{}' localhost:8888/getbatchdetails | jq
|
||||
@@ -316,6 +336,10 @@ testbatching() {
|
||||
# List batchers
|
||||
# Remove from batch
|
||||
# List batchers
|
||||
|
||||
echo
|
||||
echo "Tests successful!"
|
||||
|
||||
}
|
||||
|
||||
wait_for_callbacks() {
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
# docker run -it --rm -it --name test-derive --network=cyphernodenet -v "$PWD/test-derive.sh:/test-derive.sh" alpine /test-derive.sh
|
||||
|
||||
# This will test:
|
||||
#
|
||||
# - deriveindex
|
||||
# - derivepubpath
|
||||
# - deriveindex_bitcoind
|
||||
# - derivepubpath_bitcoind
|
||||
#
|
||||
# ...and it will compare performance between Pycoin et Bitcoin Core's address derivations...
|
||||
#
|
||||
|
||||
test_derive() {
|
||||
local address
|
||||
local address1
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
. ./colors.sh
|
||||
. ./mine.sh
|
||||
|
||||
# This needs to be run in regtest
|
||||
|
||||
# This will test the missed watched transactions mechanisms by broadcasting
|
||||
# transactions on watched addresses while the proxy is shut down...
|
||||
#
|
||||
# - getnewaddress
|
||||
# - watch
|
||||
# - executecallbacks
|
||||
#
|
||||
|
||||
trace() {
|
||||
if [ "${1}" -le "${TRACING}" ]; then
|
||||
echo "$(date -u +%FT%TZ) ${2}" 1>&2
|
||||
@@ -46,10 +56,11 @@ test_manage_missed_0_conf() {
|
||||
trace 3 "[test_manage_missed_0_conf] response=${response}"
|
||||
|
||||
trace 3 "[test_manage_missed_0_conf] Shutting down the proxy..."
|
||||
docker stop $(docker ps -q -f "name=proxy")
|
||||
docker stop $(docker ps -q -f "name=proxy\.")
|
||||
|
||||
trace 3 "[test_manage_missed_0_conf] Sending coins to watched address while proxy is down..."
|
||||
docker exec -it $(docker ps -q -f "name=cyphernode_bitcoin") bitcoin-cli -rpcwallet=spending01.dat sendtoaddress ${address} 0.0001
|
||||
# txid1=$(exec_in_test_container curl -d '{"address":"'${address}'","amount":0.0001}' proxy:8888/spend | jq -r ".txid")
|
||||
|
||||
trace 3 "[test_manage_missed_0_conf] Sleeping for 10 seconds to let the proxy restart..."
|
||||
sleep 10
|
||||
@@ -87,12 +98,13 @@ test_manage_missed_1_conf() {
|
||||
|
||||
trace 3 "[test_manage_missed_1_conf] Sending coins to watched address while proxy is up..."
|
||||
docker exec -it $(docker ps -q -f "name=cyphernode_bitcoin") bitcoin-cli -rpcwallet=spending01.dat sendtoaddress ${address} 0.0001
|
||||
# txid1=$(exec_in_test_container curl -d '{"address":"'${address}'","amount":0.0001}' proxy:8888/spend | jq -r ".txid")
|
||||
|
||||
trace 3 "[test_manage_missed_1_conf] Sleeping for 10 seconds to let the 0-conf callbacks to happen..."
|
||||
sleep 10
|
||||
|
||||
trace 3 "[test_manage_missed_1_conf] Shutting down the proxy..."
|
||||
docker stop $(docker ps -q -f "name=proxy")
|
||||
docker stop $(docker ps -q -f "name=proxy\.")
|
||||
|
||||
trace 3 "[test_manage_missed_1_conf] Mine a new block..."
|
||||
mine
|
||||
@@ -116,6 +128,7 @@ wait_for_callbacks() {
|
||||
|
||||
TRACING=3
|
||||
|
||||
stop_test_container
|
||||
start_test_container
|
||||
wait_for_callbacks
|
||||
|
||||
|
||||
445
proxy_docker/app/tests/test-watchpub32.sh
Executable file
445
proxy_docker/app/tests/test-watchpub32.sh
Executable file
@@ -0,0 +1,445 @@
|
||||
#!/bin/sh
|
||||
|
||||
. ./colors.sh
|
||||
. ./mine.sh
|
||||
|
||||
# This needs to be run in regtest
|
||||
|
||||
# This will test:
|
||||
#
|
||||
# - watchxpub
|
||||
# - get_unused_addresses_by_watchlabel
|
||||
# - derivepubpath_bitcoind
|
||||
# - getactivexpubwatches
|
||||
# - getactivewatchesbyxpub
|
||||
# - getactivewatchesbylabel
|
||||
# - spend
|
||||
# - get_txns_by_watchlabel
|
||||
# - unwatchxpubbyxpub
|
||||
# - unwatchxpubbylabel
|
||||
#
|
||||
|
||||
trace() {
|
||||
if [ "${1}" -le "${TRACING}" ]; then
|
||||
echo "$(date -u +%FT%TZ) ${2}" 1>&2
|
||||
fi
|
||||
}
|
||||
|
||||
start_test_container() {
|
||||
docker run -d --rm -it --name tests-watch-pub32 --network=cyphernodenet alpine
|
||||
}
|
||||
|
||||
stop_test_container() {
|
||||
trace 1 "\n\n[test_watch_pub32] ${BCyan}Stopping existing containers if they are running...${Color_Off}\n"
|
||||
|
||||
docker stop tests-watch-pub32
|
||||
docker stop tests-watch-pub32-cb
|
||||
}
|
||||
|
||||
exec_in_test_container() {
|
||||
docker exec -it tests-watch-pub32 "$@"
|
||||
}
|
||||
|
||||
test_watch_pub32() {
|
||||
# Watch an xpub
|
||||
# 1. Call watchxpub with xpub1 label1 with url1 as callback
|
||||
# 2. Call watchxpub with xpub2 label2 with url2 as callback
|
||||
|
||||
# 3. Call get_unused_addresses_by_watchlabel with label1 /10, take last as address1, save index1
|
||||
# 4. Call get_unused_addresses_by_watchlabel with label2 /10, take last as address2, save index2
|
||||
|
||||
# 5. Call derivepubpath_bitcoind with xpub1 path 0/index1, compare with address1
|
||||
# 6. Call derivepubpath_bitcoind with xpub2 path 0/index2, compare with address2
|
||||
|
||||
# 7. Call getactivexpubwatches
|
||||
# 8. Call getactivewatchesbyxpub with xpub1, compare index1'th address with address1
|
||||
# 9. Call getactivewatchesbyxpub with xpub2, compare index2'th address with address2
|
||||
# 10. Call getactivewatchesbylabel with label1, compare index1'th address with address1
|
||||
# 11. Call getactivewatchesbylabel with label2, compare index2'th address with address2
|
||||
|
||||
# 12. Send coins to address1, wait for callback
|
||||
# 13. Send coins to address2, wait for callback
|
||||
|
||||
# 14. Call get_txns_by_watchlabel for label1, search sent tx
|
||||
# 15. Call get_txns_by_watchlabel for label2, search sent tx
|
||||
|
||||
# 16. Call get_unused_addresses_by_watchlabel with label1 /10, check address1 is NOT there
|
||||
# 17. Call get_unused_addresses_by_watchlabel with label2 /10, check address2 is NOT there
|
||||
|
||||
# 18. Call getactivexpubwatches
|
||||
# 19. Call getactivewatchesbyxpub with xpub1, last n should be 10 more (index1 + 100)
|
||||
# 20. Call getactivewatchesbyxpub with xpub2, last n should be 10 more (index2 + 100)
|
||||
|
||||
# 21. Call unwatchxpubbyxpub with xpub1
|
||||
# 22. Call unwatchxpubbylabel with label2
|
||||
|
||||
# 23. Call getactivewatchesbyxpub with xpub1, should be empty
|
||||
# 24. Call getactivewatchesbyxpub with xpub2, should be empty
|
||||
|
||||
local xpub1="upub5GtUcgGed1aGH4HKQ3vMYrsmLXwmHhS1AeX33ZvDgZiyvkGhNTvGd2TA5Lr4v239Fzjj4ZY48t6wTtXUy2yRgapf37QHgt6KWEZ6bgsCLpb"
|
||||
local xpub2="tpubD6NzVbkrYhZ4YR3QK2tyfMMvBghAvqtNaNK1LTyDWcRHLcMUm3ZN2cGm5BS3MhCRCeCkXQkTXXjiJgqxpqXK7PeUSp86DTTgkLpcjMtpKWk"
|
||||
local label1="label$RANDOM"
|
||||
local label2="label$RANDOM"
|
||||
local path1="0/n"
|
||||
local path2="0/n"
|
||||
local path_a1
|
||||
local path_a2
|
||||
local callbackurl0conf1="http://${callbackservername}:1111/callbackurl0conf1"
|
||||
local callbackurl1conf1="http://${callbackservername}:1112/callbackurl1conf1"
|
||||
local callbackurl0conf2="http://${callbackservername}:1113/callbackurl0conf2"
|
||||
local callbackurl1conf2="http://${callbackservername}:1114/callbackurl1conf2"
|
||||
local address
|
||||
local address1
|
||||
local address2
|
||||
local last_imported_n1
|
||||
local last_imported_n2
|
||||
local last_imported_n1_x
|
||||
local last_imported_n2_x
|
||||
local index
|
||||
local index1
|
||||
local index2
|
||||
local txid
|
||||
local txid1
|
||||
local txid2
|
||||
local data
|
||||
local response
|
||||
|
||||
trace 1 "\n\n[test_watch_pub32] ${BCyan}Let's test \"watch by xpub\" features!...${Color_Off}\n"
|
||||
|
||||
# 1. Call watchxpub with xpub1 label1 with url1 as callback
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}1. watchxpub 1...${Color_Off}\n"
|
||||
data='{"label":"'${label1}'","pub32":"'${xpub1}'","path":"'${path1}'","nstart":0,"unconfirmedCallbackURL":"'${callbackurl0conf1}'","confirmedCallbackURL":"'${callbackurl1conf1}'"}'
|
||||
trace 3 "[test_watch_pub32] data=${data}"
|
||||
response=$(exec_in_test_container curl -d "${data}" proxy:8888/watchxpub)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
data=$(echo "${response}" | jq -re ".label")
|
||||
if [ "${label1}" != "${data}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 1. watchxpub 1 failed! ${Color_Off}\n"
|
||||
return 10
|
||||
fi
|
||||
|
||||
# 2. Call watchxpub with xpub2 label2 with url2 as callback
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}2. watchxpub 2...${Color_Off}\n"
|
||||
data='{"label":"'${label2}'","pub32":"'${xpub2}'","path":"'${path2}'","nstart":0,"unconfirmedCallbackURL":"'${callbackurl0conf2}'","confirmedCallbackURL":"'${callbackurl1conf2}'"}'
|
||||
trace 3 "[test_watch_pub32] data=${data}"
|
||||
response=$(exec_in_test_container curl -d "${data}" proxy:8888/watchxpub)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
data=$(echo "${response}" | jq -re ".label")
|
||||
if [ "${label2}" != "${data}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 2. watchxpub 2 failed! ${Color_Off}\n"
|
||||
return 20
|
||||
fi
|
||||
|
||||
|
||||
# 3. Call get_unused_addresses_by_watchlabel with label1 /10, take last as address1, save index1
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}3. Call get_unused_addresses_by_watchlabel with label1 /10...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/get_unused_addresses_by_watchlabel/${label1}/10)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
address1=$(echo "${response}" | jq -r ".label_unused_addresses[9] | .address")
|
||||
trace 3 "[test_watch_pub32] address1=${address1}"
|
||||
index1=$(echo "${response}" | jq -r ".label_unused_addresses[9] | .address_pub32_index")
|
||||
trace 3 "[test_watch_pub32] index1=${index1}"
|
||||
if [ "${address1}" = "null" ] || [ "${index1}" = "null" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 3. Call get_unused_addresses_by_watchlabel with label1 /10! ${Color_Off}\n"
|
||||
return 87
|
||||
fi
|
||||
|
||||
# 4. Call get_unused_addresses_by_watchlabel with label2 /10, take last as address2, save index2
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}4. Call get_unused_addresses_by_watchlabel with label2 /10...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/get_unused_addresses_by_watchlabel/${label2}/10)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
address2=$(echo "${response}" | jq -r ".label_unused_addresses[9] | .address")
|
||||
trace 3 "[test_watch_pub32] address2=${address2}"
|
||||
index2=$(echo "${response}" | jq -r ".label_unused_addresses[9] | .address_pub32_index")
|
||||
trace 3 "[test_watch_pub32] index2=${index2}"
|
||||
if [ "${address2}" = "null" ] || [ "${index2}" = "null" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 4. Call get_unused_addresses_by_watchlabel with label2 /10! ${Color_Off}\n"
|
||||
return 87
|
||||
fi
|
||||
|
||||
|
||||
# 5. Call derivepubpath_bitcoind with xpub1 path 0/index1, compare with address1
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}5. Call derivepubpath_bitcoind with xpub1 path 0/index1...${Color_Off}\n"
|
||||
path_a1=$(echo "${path1}" | sed -En "s/n/${index1}/p")
|
||||
data='{"pub32":"'${xpub1}'","path":"'${path_a1}'"}'
|
||||
trace 3 "[test_watch_pub32] data=${data}"
|
||||
response=$(exec_in_test_container curl -d "${data}" proxy:8888/derivepubpath_bitcoind)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
address=$(echo "${response}" | jq -r ".[0]")
|
||||
trace 3 "[test_watch_pub32] address=${address}"
|
||||
if [ "${address}" != "${address1}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 5. Call derivepubpath_bitcoind with xpub1 path 0/index1! ${Color_Off}\n"
|
||||
return 30
|
||||
fi
|
||||
|
||||
# 6. Call derivepubpath_bitcoind with xpub2 path 0/index2, compare with address2
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}6. Call derivepubpath_bitcoind with xpub2 path 0/index2...${Color_Off}\n"
|
||||
path_a2=$(echo "${path2}" | sed -En "s/n/${index2}/p")
|
||||
data='{"pub32":"'${xpub2}'","path":"'${path_a2}'"}'
|
||||
trace 3 "[test_watch_pub32] data=${data}"
|
||||
response=$(exec_in_test_container curl -d "${data}" proxy:8888/derivepubpath_bitcoind)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
address=$(echo "${response}" | jq -r ".[0]")
|
||||
trace 3 "[test_watch_pub32] address=${address}"
|
||||
if [ "${address}" != "${address2}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 6. Call derivepubpath_bitcoind with xpub2 path 0/index2! ${Color_Off}\n"
|
||||
return 30
|
||||
fi
|
||||
|
||||
|
||||
# 7. Call getactivexpubwatches
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}7. getactivexpubwatches...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/getactivexpubwatches)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
last_imported_n1=$(echo "${response}" | jq -r ".watches | map(select(.pub32 == \"${xpub1}\"))[0] | .last_imported_n")
|
||||
trace 3 "[test_watch_pub32] last_imported_n1=${last_imported_n1}"
|
||||
last_imported_n2=$(echo "${response}" | jq -r ".watches | map(select(.pub32 == \"${xpub2}\"))[0] | .last_imported_n")
|
||||
trace 3 "[test_watch_pub32] last_imported_n2=${last_imported_n2}"
|
||||
if [ "${last_imported_n1}" -ne "100" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 7. \"${last_imported_n1}\" -ne \"100\"! ${Color_Off}\n"
|
||||
return 50
|
||||
fi
|
||||
if [ "${last_imported_n2}" -ne "100" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 7. \"${last_imported_n2}\" -ne \"100\"! ${Color_Off}\n"
|
||||
return 55
|
||||
fi
|
||||
|
||||
# 8. Call getactivewatchesbyxpub with xpub1, compare index1'th address with address1
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}8. Call getactivewatchesbyxpub with xpub1...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/getactivewatchesbyxpub/${xpub1})
|
||||
# trace 3 "[test_watch_pub32] response=${response}"
|
||||
address=$(echo "${response}" | jq -r ".watches | map(select(.pub32_index == ${index1}))[0] | .address")
|
||||
trace 3 "[test_watch_pub32] ${index1}th address=${address}"
|
||||
if [ "${address}" != "${address1}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 8. Call getactivewatchesbyxpub with xpub1: \"${address}\" != \"${address1}\"! ${Color_Off}\n"
|
||||
return 60
|
||||
fi
|
||||
# Check if last_imported_n1 exists in watched list
|
||||
index=$(echo "${response}" | jq -r "[.watches[].pub32_index] | index(${last_imported_n1})")
|
||||
trace 3 "[test_watch_pub32] index=${index}"
|
||||
if [ "${index}" != "100" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 8. Call getactivewatchesbyxpub with xpub1: \"${index}\" != \"100\"! ${Color_Off}\n"
|
||||
return 65
|
||||
fi
|
||||
|
||||
# 9. Call getactivewatchesbyxpub with xpub2, compare index2'th address with address2
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}9. Call getactivewatchesbyxpub with xpub2...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/getactivewatchesbyxpub/${xpub2})
|
||||
# trace 3 "[test_watch_pub32] response=${response}"
|
||||
address=$(echo "${response}" | jq -r ".watches | map(select(.pub32_index == ${index2}))[0] | .address")
|
||||
trace 3 "[test_watch_pub32] ${index2}th address=${address}"
|
||||
if [ "${address}" != "${address2}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 9. Call getactivewatchesbyxpub with xpub2: \"${address}\" != \"${address2}\"! ${Color_Off}\n"
|
||||
return 60
|
||||
fi
|
||||
# Check if last_imported_n1 exists in watched list
|
||||
index=$(echo "${response}" | jq -r "[.watches[].pub32_index] | index(${last_imported_n2})")
|
||||
trace 3 "[test_watch_pub32] index=${index}"
|
||||
if [ "${index}" != "100" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 9. Call getactivewatchesbyxpub with xpub2: \"${index}\" != \"100\"! ${Color_Off}\n"
|
||||
return 65
|
||||
fi
|
||||
|
||||
# 10. Call getactivewatchesbylabel with label1, compare index1'th address with address1
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}10. Call getactivewatchesbylabel with label1...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/getactivewatchesbylabel/${label1})
|
||||
# trace 3 "[test_watch_pub32] response=${response}"
|
||||
address=$(echo "${response}" | jq -r ".watches | map(select(.pub32_index == ${index1}))[0] | .address")
|
||||
trace 3 "[test_watch_pub32] ${index1}th address=${address}"
|
||||
if [ "${address}" != "${address1}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 10. Call getactivewatchesbylabel with label1: \"${address}\" != \"${address1}\"! ${Color_Off}\n"
|
||||
return 80
|
||||
fi
|
||||
|
||||
# 11. Call getactivewatchesbylabel with label2, compare index2'th address with address2
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}11. Call getactivewatchesbylabel with label2...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/getactivewatchesbylabel/${label2})
|
||||
# trace 3 "[test_watch_pub32] response=${response}"
|
||||
address=$(echo "${response}" | jq -r ".watches | map(select(.pub32_index == ${index2}))[0] | .address")
|
||||
trace 3 "[test_watch_pub32] ${index2}th address=${address}"
|
||||
if [ "${address}" != "${address2}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 11. Call getactivewatchesbylabel with label2: \"${address}\" != \"${address2}\"! ${Color_Off}\n"
|
||||
return 80
|
||||
fi
|
||||
|
||||
|
||||
# 12. Send coins to address1, wait for callback
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}12. Send coins to address1...${Color_Off}\n"
|
||||
start_callback_server 1111
|
||||
# Let's use the bitcoin node directly to better simulate an external spend
|
||||
txid1=$(docker exec -it $(docker ps -q -f "name=cyphernode_bitcoin") bitcoin-cli -rpcwallet=spending01.dat sendtoaddress ${address1} 0.0001 | tr -d "\r\n")
|
||||
# txid1=$(exec_in_test_container curl -d '{"address":"'${address1}'","amount":0.001}' proxy:8888/spend | jq -r ".txid")
|
||||
trace 3 "[test_watch_pub32] txid1=${txid1}"
|
||||
trace 3 "[test_watch_pub32] Waiting for 0-conf callback on address1..."
|
||||
wait
|
||||
|
||||
# 13. Send coins to address2, wait for callback
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}13. Send coins to address2...${Color_Off}\n"
|
||||
start_callback_server 1113
|
||||
# Let's use the bitcoin node directly to better simulate an external spend
|
||||
txid2=$(docker exec -it $(docker ps -q -f "name=cyphernode_bitcoin") bitcoin-cli -rpcwallet=spending01.dat sendtoaddress ${address2} 0.0001 | tr -d "\r\n")
|
||||
# txid2=$(exec_in_test_container curl -d '{"address":"'${address2}'","amount":0.001}' proxy:8888/spend | jq -r ".txid")
|
||||
trace 3 "[test_watch_pub32] txid2=${txid2}"
|
||||
trace 3 "[test_watch_pub32] Waiting for 0-conf callback on address2..."
|
||||
wait
|
||||
|
||||
|
||||
# 14. Call get_txns_by_watchlabel for label1, search sent tx
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}14. Call get_txns_by_watchlabel for label1...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/get_txns_by_watchlabel/${label1}/1000)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
txid=$(echo "${response}" | jq -r ".label_txns | map(select(.txid == \"${txid1}\"))[0] | .txid")
|
||||
trace 3 "[test_watch_pub32] txid searched=${txid}"
|
||||
if [ "${txid}" != "${txid1}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 14. Call get_txns_by_watchlabel for label1: \"${txid}\" != \"${txid1}\"! ${Color_Off}\n"
|
||||
return 88
|
||||
fi
|
||||
|
||||
# 15. Call get_txns_by_watchlabel for label2, search sent tx
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}15. Call get_txns_by_watchlabel for label2...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/get_txns_by_watchlabel/${label2}/1000)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
txid=$(echo "${response}" | jq -r ".label_txns | map(select(.txid == \"${txid2}\"))[0] | .txid")
|
||||
trace 3 "[test_watch_pub32] txid searched=${txid}"
|
||||
if [ "${txid}" != "${txid2}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 15. Call get_txns_by_watchlabel for label2: \"${txid}\" != \"${txid2}\"! ${Color_Off}\n"
|
||||
return 88
|
||||
fi
|
||||
|
||||
|
||||
# 16. Call get_unused_addresses_by_watchlabel with label1 /10, check address1 is NOT there
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}16. Call get_unused_addresses_by_watchlabel with label1 /10...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/get_unused_addresses_by_watchlabel/${label1}/10)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
address=$(echo "${response}" | jq -r ".label_unused_addresses | map(select(.address == \"${address1}\"))[0] | .address")
|
||||
trace 3 "[test_watch_pub32] ${index1}th address searched=${address}"
|
||||
if [ "${address}" = "${address1}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 16. Call get_unused_addresses_by_watchlabel with label1 /10: \"${address}\" = \"${address1}\"! ${Color_Off}\n"
|
||||
return 87
|
||||
fi
|
||||
|
||||
# 17. Call get_unused_addresses_by_watchlabel with label2 /10, check address2 is NOT there
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}17. Call get_unused_addresses_by_watchlabel with label2 /10...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/get_unused_addresses_by_watchlabel/${label2}/10)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
address=$(echo "${response}" | jq -r ".label_unused_addresses | map(select(.address == \"${address2}\"))[0] | .address")
|
||||
trace 3 "[test_watch_pub32] ${index2}th address searched=${address}"
|
||||
if [ "${address}" = "${address2}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 17. Call get_unused_addresses_by_watchlabel with label2 /10: \"${address}\" = \"${address2}\"! ${Color_Off}\n"
|
||||
return 87
|
||||
fi
|
||||
|
||||
|
||||
# 18. Call getactivexpubwatches
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}18. getactivexpubwatches...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/getactivexpubwatches)
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
last_imported_n1_x=$(echo "${response}" | jq -r ".watches | map(select(.pub32 == \"${xpub1}\"))[0] | .last_imported_n")
|
||||
trace 3 "[test_watch_pub32] last_imported_n1_x=${last_imported_n1_x}"
|
||||
last_imported_n2_x=$(echo "${response}" | jq -r ".watches | map(select(.pub32 == \"${xpub2}\"))[0] | .last_imported_n")
|
||||
trace 3 "[test_watch_pub32] last_imported_n2_x=${last_imported_n2_x}"
|
||||
if [ "${last_imported_n1_x}" -ne "$((100+${index1}))" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 18. Call getactivexpubwatches: \"${last_imported_n1_x}\" -ne \"$((100+${index1}))\"! ${Color_Off}\n"
|
||||
return 90
|
||||
fi
|
||||
if [ "${last_imported_n2_x}" -ne "$((100+${index2}))" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 18. Call getactivexpubwatches \"${last_imported_n2_x}\" -ne \"$((100+${index2}))\"! ${Color_Off}\n"
|
||||
return 95
|
||||
fi
|
||||
|
||||
# 19. Call getactivewatchesbyxpub with xpub1, last n should be 10 more (index1 + 100)
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}19. Call getactivewatchesbyxpub with xpub1...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/getactivewatchesbyxpub/${xpub1})
|
||||
# trace 3 "[test_watch_pub32] response=${response}"
|
||||
index=$(echo "${response}" | jq -r "[.watches[].pub32_index] | index(${last_imported_n1_x})")
|
||||
trace 3 "[test_watch_pub32] index=${index}"
|
||||
if [ "${index}" != "${last_imported_n1_x}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 19. Call getactivewatchesbyxpub with xpub1: \"${index}\" != \"${last_imported_n1_x}\"! ${Color_Off}\n"
|
||||
return 100
|
||||
fi
|
||||
|
||||
# 20. Call getactivewatchesbyxpub with xpub2, last n should be 10 more (index2 + 100)
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}20. Call getactivewatchesbyxpub with xpub2...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/getactivewatchesbyxpub/${xpub2})
|
||||
# trace 3 "[test_watch_pub32] response=${response}"
|
||||
index=$(echo "${response}" | jq -r "[.watches[].pub32_index] | index(${last_imported_n2_x})")
|
||||
trace 3 "[test_watch_pub32] index=${index}"
|
||||
if [ "${index}" != "${last_imported_n2_x}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 20. Call getactivewatchesbyxpub with xpub2: \"${index}\" != \"${last_imported_n2_x}\"! ${Color_Off}\n"
|
||||
return 100
|
||||
fi
|
||||
|
||||
|
||||
# 21. Call unwatchxpubbyxpub with xpub1
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}21. unwatchxpubbyxpub with xpub1...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/unwatchxpubbyxpub/${xpub1})
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
data=$(echo "${response}" | jq -re ".pub32")
|
||||
if [ "${xpub1}" != "${data}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 21. Call unwatchxpubbyxpub with xpub1! ${Color_Off}\n"
|
||||
return 120
|
||||
fi
|
||||
|
||||
# 22. Call unwatchxpubbylabel with label2
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}22. unwatchxpubbylabel with label2...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/unwatchxpubbylabel/${label2})
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
data=$(echo "${response}" | jq -re ".label")
|
||||
if [ "${label2}" != "${data}" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 22. Call unwatchxpubbylabel with label2 failed! ${Color_Off}\n"
|
||||
return 130
|
||||
fi
|
||||
|
||||
|
||||
# 23. Call getactivewatchesbyxpub with xpub1, should be empty
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}23. getactivewatchesbyxpub with xpub1...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/getactivewatchesbyxpub/${xpub1})
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
data=$(echo "${response}" | jq ".watches | length")
|
||||
if [ "${data}" -ne "0" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 23. getactivewatchesbyxpub xpub1 still watching! ${Color_Off}\n"
|
||||
return 140
|
||||
fi
|
||||
|
||||
# 24. Call getactivewatchesbyxpub with xpub2, should be empty
|
||||
trace 2 "\n\n[test_watch_pub32] ${BCyan}24. getactivewatchesbyxpub with xpub2...${Color_Off}\n"
|
||||
response=$(exec_in_test_container curl proxy:8888/getactivewatchesbyxpub/${xpub2})
|
||||
trace 3 "[test_watch_pub32] response=${response}"
|
||||
data=$(echo "${response}" | jq ".watches | length")
|
||||
if [ "${data}" -ne "0" ]; then
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_Red}${BBlack} 24. getactivewatchesbyxpub xpub2 still watching! ${Color_Off}\n"
|
||||
return 150
|
||||
fi
|
||||
|
||||
trace 1 "\n\n[test_watch_pub32] ${On_IGreen}${BBlack} ALL GOOD! Yayyyy! ${Color_Off}\n"
|
||||
|
||||
}
|
||||
|
||||
start_callback_server() {
|
||||
trace 1 "\n\n[start_callback_server] ${BCyan}Let's start a callback server!...${Color_Off}\n"
|
||||
|
||||
port=${1:-${callbackserverport}}
|
||||
docker run --rm -t --name tests-watch-pub32-cb --network=cyphernodenet alpine sh -c "nc -vlp${port} -e sh -c 'echo -en \"HTTP/1.1 200 OK\\\\r\\\\n\\\\r\\\\n\" ; echo -en \"\\033[40m\\033[0;37m\" >&2 ; date >&2 ; timeout 1 tee /dev/tty | cat ; echo -e \"\033[0m\" >&2'" &
|
||||
|
||||
# docker run --rm -it --name tests-watch-pub32-cb --network=cyphernodenet alpine sh -c "nc -vlkp1111 -e sh -c 'echo -en \"HTTP/1.1 200 OK\\\\r\\\\n\\\\r\\\\n\" ; echo -en \"\\033[40m\\033[0;37m\" >&2 ; date >&2 ; timeout 1 tee /dev/tty | cat ; echo -e \"\033[0m\" >&2'"
|
||||
}
|
||||
|
||||
TRACING=3
|
||||
|
||||
stop_test_container
|
||||
start_test_container
|
||||
|
||||
callbackserverport="1111"
|
||||
callbackservername="tests-watch-pub32-cb"
|
||||
|
||||
trace 1 "\n\n[test_watch_pub32] ${BCyan}Installing needed packages...${Color_Off}\n"
|
||||
exec_in_test_container apk add curl
|
||||
|
||||
test_watch_pub32
|
||||
|
||||
trace 1 "\n\n[test_watch_pub32] ${BCyan}Tearing down...${Color_Off}\n"
|
||||
wait
|
||||
|
||||
stop_test_container
|
||||
|
||||
trace 1 "\n\n[test_watch_pub32] ${BCyan}See ya!${Color_Off}\n"
|
||||
@@ -2,8 +2,28 @@
|
||||
|
||||
# . /mine.sh
|
||||
|
||||
# This should be run in regtest
|
||||
|
||||
# docker run -it --rm -it --name cn-tests --network=cyphernodenet -v "$PWD/mine.sh:/mine.sh" -v "$PWD/tests.sh:/tests.sh" -v "$PWD/tests-cb.sh:/tests-cb.sh" alpine /tests.sh
|
||||
|
||||
# This will test:
|
||||
#
|
||||
# - getbestblockhash
|
||||
# - getbestblockinfo
|
||||
# - getblockinfo
|
||||
# - getnewaddress
|
||||
# - getbalance
|
||||
# - watch and callbacks
|
||||
# - getactivewatches
|
||||
# - unwatch
|
||||
# - deriveindex
|
||||
# - derivepubpath
|
||||
# - spend
|
||||
# - gettransaction
|
||||
# - ln_getinfo
|
||||
# - ln_newaddr
|
||||
#
|
||||
#
|
||||
|
||||
tests()
|
||||
{
|
||||
@@ -108,12 +128,12 @@ tests()
|
||||
fi
|
||||
local imported=$(echo "${response}" | jq ".imported" | tr -d '\"')
|
||||
echo "imported=${imported}"
|
||||
if [ "${imported}" != "1" ]; then
|
||||
if [ "${imported}" != "true" ]; then
|
||||
exit 30
|
||||
fi
|
||||
local inserted=$(echo "${response}" | jq ".inserted" | tr -d '\"')
|
||||
echo "inserted=${inserted}"
|
||||
if [ "${inserted}" != "1" ]; then
|
||||
if [ "${inserted}" != "true" ]; then
|
||||
exit 40
|
||||
fi
|
||||
local unconfirmedCallbackURL=$(echo "${response}" | jq ".unconfirmedCallbackURL" | tr -d '\"')
|
||||
|
||||
Reference in New Issue
Block a user