mirror of
https://github.com/alexbosworth/balanceofsatoshis.git
synced 2026-08-13 12:33:37 +02:00
fix remove peer, add circular rebalance reports
This commit is contained in:
parent
ee862f0c0e
commit
a27bf1a8ae
12 changed files with 637 additions and 223 deletions
|
|
@ -1,5 +1,10 @@
|
|||
# Versions
|
||||
|
||||
## Version 5.21.1
|
||||
|
||||
- `remove-peer`: Fix specifying peer public key
|
||||
- `report`: Highlight circular rebalances
|
||||
|
||||
## Version 5.21.0
|
||||
|
||||
- `chain-receive`: add `--in` argument to specify desired inbound peer
|
||||
|
|
@ -17,7 +22,7 @@ Improve compatibility with older node versions
|
|||
- `peers`: add `--idle-days` to show only peers that have been idle for n days
|
||||
- `peers`: add `--last-received` to show the last final hop payments from peer
|
||||
- `peers`: add `--omit` to omit peers from the list
|
||||
- `send`: add method to unilaterally send to a destionation accepting such sends
|
||||
- `send`: add method to unilaterally send to a destination accepting such sends
|
||||
- `telegram`: show messages received with received payments
|
||||
|
||||
## Version 5.18.0
|
||||
|
|
|
|||
|
|
@ -40,9 +40,6 @@ Or ask about commands on [Telegram](https://t.me/balanceofsatoshis)
|
|||
# See an accounting formatted list of various types of transactions
|
||||
bos accounting "category"
|
||||
|
||||
# Set autopilot on or off. With heuristic externalscore, set guided autopilot
|
||||
bos autopilot "on"
|
||||
|
||||
# See total balance, including pending funds, excluding future commit fees
|
||||
bos balance
|
||||
# 1337
|
||||
|
|
@ -77,9 +74,6 @@ bos find "query"
|
|||
# Output a summarized version of peers forwarded towards
|
||||
bos forwards
|
||||
|
||||
# Send a gift of some tokens to a directly connected peer
|
||||
bos gift "pubkey" "amount"
|
||||
|
||||
# See help about a command
|
||||
bos help "command"
|
||||
|
||||
|
|
@ -119,9 +113,6 @@ bos probe "payment_request/public_key"
|
|||
# Rebalance funds between peers
|
||||
bos rebalance
|
||||
|
||||
# Attempt to reconnect to disconnected peers
|
||||
bos reconnect
|
||||
|
||||
# Remove all channels with a peer
|
||||
bos remove-peer
|
||||
|
||||
|
|
|
|||
18
bos
18
bos
|
|
@ -64,10 +64,13 @@ const {version} = require('./package');
|
|||
const {exit} = process;
|
||||
const flatten = arr => [].concat(...arr);
|
||||
const {FLOAT} = prog;
|
||||
const hexMatch = /^[0-9a-f]+$/i;
|
||||
const {INT} = prog;
|
||||
const {isArray} = Array;
|
||||
const {keys} = Object;
|
||||
const months = [...Array(12).keys()].map(n => ++n);
|
||||
const {REPEATABLE} = prog;
|
||||
const yearMatch = /^\d{4}$/;
|
||||
|
||||
prog
|
||||
.version(version)
|
||||
|
|
@ -78,10 +81,10 @@ prog
|
|||
.help(`Categories: ${keys(accountingCategories).join(', ')}`)
|
||||
.help(`Rate providers: ${rateProviders.join(', ')}`)
|
||||
.option('--csv', 'Output a CSV')
|
||||
.option('--month <month>', 'Show only records for specific month')
|
||||
.option('--month <month>', 'Show only records for specific month', months)
|
||||
.option('--node <node_name>', 'Get details from named node')
|
||||
.option('--rate-provider <rate_provider>', 'Rate provider', rateProviders)
|
||||
.option('--year <year>', 'Show only records for specified year')
|
||||
.option('--year <year>', 'Show only records for specified year', yearMatch)
|
||||
.action((args, options, logger) => {
|
||||
const table = !!options.csv ? null : 'rows';
|
||||
|
||||
|
|
@ -106,6 +109,7 @@ prog
|
|||
|
||||
// Direct autopilot to mirror one or more nodes on the network
|
||||
.command('autopilot', 'Enable autopilot')
|
||||
.visible(false)
|
||||
.argument('<status>', 'Status of autopilot', ['off', 'on'])
|
||||
.help('Autopilot status is either on or off')
|
||||
.help('Mirroring and urls require lnd --autopilot.heuristic=externalscore:1')
|
||||
|
|
@ -179,6 +183,7 @@ prog
|
|||
// Deposit coins
|
||||
.command('chain-deposit', 'Deposit coins in the on-chain wallet')
|
||||
.argument('[amount]', 'Amount to receive', INT)
|
||||
.option('--no-color', 'Mute all colors')
|
||||
.option('--node <node_name>', 'Node to deposit coins to')
|
||||
.action((args, options, logger) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
|
@ -197,7 +202,7 @@ prog
|
|||
// Create on-chain submarine swap
|
||||
.command('chain-receive', 'Receive funds on-chain via submarine swap')
|
||||
.argument('[amount]', 'Amount to receive', INT, 1e6)
|
||||
.option('--api-key <api_key>', 'Pre-paid API key to use')
|
||||
.option('--api-key <api_key>', 'Pre-paid API key to use', hexMatch)
|
||||
.option('--in <peer>', 'Request receiving through a specific peer')
|
||||
.option('--max-fee <max_fee>', 'Max fee in tokens to pay', INT, 4000)
|
||||
.option('--no-auth', 'Avoid using authenticated service')
|
||||
|
|
@ -424,6 +429,7 @@ prog
|
|||
|
||||
// Start a REST gateway
|
||||
.command('gateway', 'Start REST request gateway')
|
||||
.visible(false)
|
||||
.option('--node <node_name>', 'Node for gateway')
|
||||
.option('--port <port>', 'Port for gateway', INT, 4805)
|
||||
.action((args, options, logger) => {
|
||||
|
|
@ -441,6 +447,7 @@ prog
|
|||
|
||||
// Give a peer some tokens
|
||||
.command('gift', 'Give a direct peer some free funds off-chain')
|
||||
.visible(false)
|
||||
.help('Send some funds to a connected peer')
|
||||
.argument('<target>', 'Peer to give funds to')
|
||||
.argument('<amount>', 'Tokens to give', INT)
|
||||
|
|
@ -499,7 +506,7 @@ prog
|
|||
.option('--confs <confs>', 'Confs to consider reorg safe', INT, 1)
|
||||
.option('--dryrun', 'Only show cost estimate for increase')
|
||||
.option('--fast', 'Request swap server avoid batching delay')
|
||||
.option('--max-fee <max_fee>', 'Maximum estimated fee tokens', INT, 3000)
|
||||
.option('--max-fee <max_fee>', 'Maximum estimated fee tokens', INT, 4000)
|
||||
.option('--max-hours <max_hours>', 'Maximum hours to wait', INT, 24)
|
||||
.option('--no-auth', 'Avoid using authenticated service')
|
||||
.option('--no-color', 'Mute all colors')
|
||||
|
|
@ -824,6 +831,7 @@ prog
|
|||
|
||||
// Attempt reconnecting to disconnected channel partners
|
||||
.command('reconnect', 'Reconnect to disconnected channel parterners')
|
||||
.visible(false)
|
||||
.option('--no-color', 'Mute all colors')
|
||||
.option('--node <node_name>', 'Node to attempt reconnects on')
|
||||
.action((args, options, logger) => {
|
||||
|
|
@ -875,7 +883,7 @@ prog
|
|||
lnd: (await authenticatedLnd({logger, node: options.node})).lnd,
|
||||
omit: flatten([options.omit].filter(n => !!n)),
|
||||
outbound_liquidity_below: options.outboundBelow,
|
||||
public_key: args.public_key,
|
||||
public_key: args.publicKey,
|
||||
},
|
||||
returnObject({logger, reject, resolve}));
|
||||
} catch (err) {
|
||||
|
|
|
|||
262
package-lock.json
generated
262
package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "balanceofsatoshis",
|
||||
"version": "5.21.0",
|
||||
"version": "5.21.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
@ -49,12 +49,12 @@
|
|||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz",
|
||||
"integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==",
|
||||
"version": "7.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.6.tgz",
|
||||
"integrity": "sha512-4bpOR5ZBz+wWcMeVtcf7FbjcFzCp+817z2/gHNncIRcM9MmKzUhtWCYAq27RAfUrAFwb+OCG1s9WEaVxfi6cjg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.8.3",
|
||||
"@babel/types": "^7.8.6",
|
||||
"jsesc": "^2.5.1",
|
||||
"lodash": "^4.17.13",
|
||||
"source-map": "^0.5.0"
|
||||
|
|
@ -140,9 +140,9 @@
|
|||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
|
||||
"integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
|
||||
"version": "7.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.6.tgz",
|
||||
"integrity": "sha512-trGNYSfwq5s0SgM1BMEB8hX3NDmO7EP2wsDGDexiaKMB92BaRpS+qZfpkMqUBhcsOTBwNy9B/jieo4ad/t/z2g==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/runtime": {
|
||||
|
|
@ -155,28 +155,28 @@
|
|||
}
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
|
||||
"integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
|
||||
"version": "7.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
|
||||
"integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.8.3",
|
||||
"@babel/parser": "^7.8.3",
|
||||
"@babel/types": "^7.8.3"
|
||||
"@babel/parser": "^7.8.6",
|
||||
"@babel/types": "^7.8.6"
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
|
||||
"integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
|
||||
"version": "7.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.6.tgz",
|
||||
"integrity": "sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.8.3",
|
||||
"@babel/generator": "^7.8.4",
|
||||
"@babel/generator": "^7.8.6",
|
||||
"@babel/helper-function-name": "^7.8.3",
|
||||
"@babel/helper-split-export-declaration": "^7.8.3",
|
||||
"@babel/parser": "^7.8.4",
|
||||
"@babel/types": "^7.8.3",
|
||||
"@babel/parser": "^7.8.6",
|
||||
"@babel/types": "^7.8.6",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0",
|
||||
"lodash": "^4.17.13"
|
||||
|
|
@ -200,9 +200,9 @@
|
|||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
|
||||
"integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
|
||||
"version": "7.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.6.tgz",
|
||||
"integrity": "sha512-wqz7pgWMIrht3gquyEFPVXeXCti72Rm8ep9b5tQKz9Yg9LzJA3HxosF1SB3Kc81KD1A3XBkkVYtJvCKS2Z/QrA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
|
|
@ -338,9 +338,9 @@
|
|||
}
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz",
|
||||
"integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
|
||||
"integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
|
|
@ -562,9 +562,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"base-x": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.7.tgz",
|
||||
"integrity": "sha512-zAKJGuQPihXW22fkrfOclUUZXM2g92z5GzlSMHxhO6r6Qj+Nm0ccaGNBzDZojzwOMkpjAv4J0fOv1U4go+a4iw==",
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz",
|
||||
"integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==",
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
|
|
@ -868,6 +868,11 @@
|
|||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
||||
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -1928,18 +1933,18 @@
|
|||
"dev": true
|
||||
},
|
||||
"flow-parser": {
|
||||
"version": "0.118.0",
|
||||
"resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.118.0.tgz",
|
||||
"integrity": "sha512-PM3aKA5K3e5kK2hJPsSVdQD4/SVZUQni9qfB0+JHBCjqoAS5mSe3SlhLR9TlH3WDQccL0H2b6zpP8LjOzx9Wtg==",
|
||||
"version": "0.119.1",
|
||||
"resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.119.1.tgz",
|
||||
"integrity": "sha512-yFd4z6ZBXq//TJo/gtSzGKhz6wEVeI2m+6JB25JzXuRAOhM5Ze4xFkc3FSIStbYjrAx4H1IUiUTI/yy30oKp8A==",
|
||||
"dev": true
|
||||
},
|
||||
"flow-remove-types": {
|
||||
"version": "2.118.0",
|
||||
"resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.118.0.tgz",
|
||||
"integrity": "sha512-HrrN9WFCB0Ausk5EvCqQC3RQqgjOsDny+ByxBRYXBqgJrt1Ropxj4JTXBeHcPoeBuN/l8l2Uh0ve7L9NwWXslg==",
|
||||
"version": "2.119.1",
|
||||
"resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.119.1.tgz",
|
||||
"integrity": "sha512-PjPcdfyizk8/+IQL8pKInPkneRVzkJSV7Eqgl/8oHIWtEdQMkqrioxwSc1H38zIRzyALpgSdvcDvFHY28FUqLQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"flow-parser": "^0.118.0",
|
||||
"flow-parser": "^0.119.1",
|
||||
"pirates": "^3.0.2",
|
||||
"vlq": "^0.2.1"
|
||||
}
|
||||
|
|
@ -2671,9 +2676,9 @@
|
|||
}
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz",
|
||||
"integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==",
|
||||
"version": "2.8.8",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
|
||||
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
|
||||
"dev": true
|
||||
},
|
||||
"html-escaper": {
|
||||
|
|
@ -2775,11 +2780,11 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"ansi-escapes": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz",
|
||||
"integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==",
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz",
|
||||
"integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==",
|
||||
"requires": {
|
||||
"type-fest": "^0.8.1"
|
||||
"type-fest": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
|
|
@ -2824,9 +2829,9 @@
|
|||
}
|
||||
},
|
||||
"figures": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz",
|
||||
"integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
|
||||
"integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.5"
|
||||
}
|
||||
|
|
@ -2916,15 +2921,35 @@
|
|||
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
|
||||
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
|
||||
},
|
||||
"invoices": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/invoices/-/invoices-1.0.0.tgz",
|
||||
"integrity": "sha512-blukVcU2sw3Vs6La0E4JHY/YNCpq3UyQXm2HR2WUtgMI0XzaZBOohVteja3FMXTO5BYFkV+OAs+1QQ5bybr5lA==",
|
||||
"requires": {
|
||||
"bech32": "1.1.3",
|
||||
"bitcoinjs-lib": "5.1.7",
|
||||
"bn.js": "5.1.1",
|
||||
"bolt07": "1.4.4",
|
||||
"bolt09": "0.0.1",
|
||||
"secp256k1": "4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bn.js": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz",
|
||||
"integrity": "sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ip-regex": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
|
||||
"integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk="
|
||||
},
|
||||
"ipaddr.js": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
|
||||
"integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
||||
},
|
||||
"is-arrayish": {
|
||||
"version": "0.2.1",
|
||||
|
|
@ -3378,15 +3403,15 @@
|
|||
}
|
||||
},
|
||||
"ln-accounting": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ln-accounting/-/ln-accounting-4.0.0.tgz",
|
||||
"integrity": "sha512-B155Yqjtajfap+64Rv9HFgu7LrTr7EHt0MUnrCbVz5j5FqKxDYCz/D+1SOFmoDp7X52HG+Pl10Dg0ARQmhCAMA==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ln-accounting/-/ln-accounting-4.1.0.tgz",
|
||||
"integrity": "sha512-Dft5HXkMpSxJ3NxxStZSkQ4v+m3Hj2+7v0HxFtQdzn8MQfK4PKCzmna3IOiijoCqPv4nRB3dHEn0wD849iSp/A==",
|
||||
"requires": {
|
||||
"async": "3.1.1",
|
||||
"asyncjs-util": "1.1.3",
|
||||
"goldengate": "5.1.2",
|
||||
"goldengate": "5.2.0",
|
||||
"json2csv": "4.5.4",
|
||||
"ln-service": "47.14.6"
|
||||
"ln-service": "47.14.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"bn.js": {
|
||||
|
|
@ -3394,31 +3419,10 @@
|
|||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz",
|
||||
"integrity": "sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA=="
|
||||
},
|
||||
"goldengate": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/goldengate/-/goldengate-5.1.2.tgz",
|
||||
"integrity": "sha512-p44S/h18nNYYuCQDouav18fO/xVzfABa38SwKlQNvELSeF2CuRkLMIR+dzfDO9jrtEZvM2FLxft/MQmkCwiipw==",
|
||||
"requires": {
|
||||
"@grpc/proto-loader": "0.5.3",
|
||||
"@mitmaro/http-authorization-header": "1.0.0",
|
||||
"async": "3.1.1",
|
||||
"asyncjs-util": "1.1.3",
|
||||
"bip65": "1.0.3",
|
||||
"bitcoin-ops": "1.4.1",
|
||||
"bitcoinjs-lib": "5.1.7",
|
||||
"bn.js": "5.1.1",
|
||||
"cbor": "5.0.1",
|
||||
"grpc": "1.24.2",
|
||||
"ln-service": "47.14.6",
|
||||
"macaroon": "3.0.4",
|
||||
"pushdata-bitcoin": "1.0.1",
|
||||
"varuint-bitcoin": "1.1.2"
|
||||
}
|
||||
},
|
||||
"ln-service": {
|
||||
"version": "47.14.6",
|
||||
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-47.14.6.tgz",
|
||||
"integrity": "sha512-RGxorO9sSPnevMk04uxsGNiFQEgneis1gbVbD2dqay/NQERpKoP2HT1gdc8PS/x7VYyVN72GQhnX44zLkJz7mg==",
|
||||
"version": "47.14.7",
|
||||
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-47.14.7.tgz",
|
||||
"integrity": "sha512-Vji4ptmIE9ESwtlwCZJxtbeRjRkiecB0cXUaWDK6T9de0e6AC3A6fMZpbG9UU34MRF5sLzAzqRckCF3rNoIqnQ==",
|
||||
"requires": {
|
||||
"@alexbosworth/request": "2.88.3",
|
||||
"@datastructures-js/priority-queue": "1.0.2",
|
||||
|
|
@ -3452,14 +3456,14 @@
|
|||
}
|
||||
},
|
||||
"ln-service": {
|
||||
"version": "47.14.7",
|
||||
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-47.14.7.tgz",
|
||||
"integrity": "sha512-Vji4ptmIE9ESwtlwCZJxtbeRjRkiecB0cXUaWDK6T9de0e6AC3A6fMZpbG9UU34MRF5sLzAzqRckCF3rNoIqnQ==",
|
||||
"version": "47.15.0",
|
||||
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-47.15.0.tgz",
|
||||
"integrity": "sha512-VI7v/TwUUysB3595IXOFKJ/9w7rD1YWc5HrIXVdFml5YfStMTIp9XW0Obl8x5Jp73ySpNuft3Ls3GT0q7F7daw==",
|
||||
"requires": {
|
||||
"@alexbosworth/request": "2.88.3",
|
||||
"@datastructures-js/priority-queue": "1.0.2",
|
||||
"@grpc/proto-loader": "0.5.3",
|
||||
"async": "3.1.1",
|
||||
"async": "3.2.0",
|
||||
"asyncjs-util": "1.1.3",
|
||||
"basicauth-middleware": "3.1.0",
|
||||
"bech32": "1.1.3",
|
||||
|
|
@ -3474,8 +3478,7 @@
|
|||
"express": "4.17.1",
|
||||
"grpc": "1.24.2",
|
||||
"is-base64": "1.0.0",
|
||||
"is-hex": "1.1.3",
|
||||
"lightning": "1.2.2",
|
||||
"lightning": "1.2.3",
|
||||
"lodash": "4.17.15",
|
||||
"macaroon": "3.0.4",
|
||||
"morgan": "1.9.1",
|
||||
|
|
@ -3485,10 +3488,41 @@
|
|||
"ws": "7.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
|
||||
"integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
|
||||
},
|
||||
"bn.js": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz",
|
||||
"integrity": "sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA=="
|
||||
},
|
||||
"lightning": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/lightning/-/lightning-1.2.3.tgz",
|
||||
"integrity": "sha512-wu2KDfB7+0Cd1pMGJhmTd3vbDRRUVlDP6II4rb7E4s8bQTZF6Vz3lYv53q5oUrmCBpIBwhG6qaHo3CnxwNZjpQ==",
|
||||
"requires": {
|
||||
"@grpc/proto-loader": "0.5.3",
|
||||
"async": "3.1.1",
|
||||
"asyncjs-util": "1.1.3",
|
||||
"bn.js": "5.1.1",
|
||||
"body-parser": "1.19.0",
|
||||
"bolt07": "1.4.4",
|
||||
"bolt09": "0.0.1",
|
||||
"cbor": "5.0.1",
|
||||
"express": "4.17.1",
|
||||
"grpc": "1.24.2",
|
||||
"invoices": "1.0.0",
|
||||
"is-base64": "1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.1.1.tgz",
|
||||
"integrity": "sha512-X5Dj8hK1pJNC2Wzo2Rcp9FBVdJMGRR/S7V+lH46s8GVFhtbo5O4Le5GECCF/8PISVdkUA6mMPvgz7qTTD1rf1g=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -3626,9 +3660,9 @@
|
|||
}
|
||||
},
|
||||
"make-error": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
|
||||
"integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"dev": true
|
||||
},
|
||||
"md5.js": {
|
||||
|
|
@ -4330,12 +4364,12 @@
|
|||
}
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
|
||||
"integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
|
||||
"integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
|
||||
"requires": {
|
||||
"forwarded": "~0.1.2",
|
||||
"ipaddr.js": "1.9.0"
|
||||
"ipaddr.js": "1.9.1"
|
||||
}
|
||||
},
|
||||
"pseudomap": {
|
||||
|
|
@ -4417,9 +4451,9 @@
|
|||
}
|
||||
},
|
||||
"react": {
|
||||
"version": "16.12.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz",
|
||||
"integrity": "sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA==",
|
||||
"version": "16.13.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.13.0.tgz",
|
||||
"integrity": "sha512-TSavZz2iSLkq5/oiE7gnFzmURKZMltmi193rm5HEoUDAXpzT9Kzw6oNZnGoai/4+fUnm7FqS5dwgUL34TujcWQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
|
|
@ -4428,9 +4462,9 @@
|
|||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.12.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
|
||||
"integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==",
|
||||
"version": "16.13.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.0.tgz",
|
||||
"integrity": "sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==",
|
||||
"dev": true
|
||||
},
|
||||
"read": {
|
||||
|
|
@ -4643,9 +4677,9 @@
|
|||
}
|
||||
},
|
||||
"run-async": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
|
||||
"integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz",
|
||||
"integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==",
|
||||
"requires": {
|
||||
"is-promise": "^2.1.0"
|
||||
}
|
||||
|
|
@ -6267,9 +6301,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "13.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.1.tgz",
|
||||
"integrity": "sha512-Zq8gcQGmn4txQEJeiXo/KiLpon8TzAl0kmKH4zdWctPj05nWwp1ClMdAVEloqrQKfaC48PNLdgN/aVaLqUrluA=="
|
||||
"version": "13.7.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.7.tgz",
|
||||
"integrity": "sha512-Uo4chgKbnPNlxQwoFmYIwctkQVkMMmsAoGGU4JKwLuvBefF0pCq4FybNSnfkfRCpC7ZW7kttcC/TrRtAJsvGtg=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
|
|
@ -6396,9 +6430,9 @@
|
|||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
|
||||
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
|
||||
"integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
|
|
@ -6419,9 +6453,9 @@
|
|||
"integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw=="
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
||||
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz",
|
||||
"integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ=="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.18",
|
||||
|
|
@ -6451,9 +6485,9 @@
|
|||
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g=="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.7.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz",
|
||||
"integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==",
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz",
|
||||
"integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==",
|
||||
"dev": true
|
||||
},
|
||||
"unicode-length": {
|
||||
|
|
@ -6775,9 +6809,9 @@
|
|||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"write-file-atomic": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz",
|
||||
"integrity": "sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
|
||||
"integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
|
||||
"requires": {
|
||||
"imurmurhash": "^0.1.4",
|
||||
"is-typedarray": "^1.0.0",
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@
|
|||
"goldengate": "5.2.0",
|
||||
"ini": "1.3.5",
|
||||
"inquirer": "7.0.4",
|
||||
"ln-accounting": "4.0.0",
|
||||
"ln-service": "47.14.7",
|
||||
"ln-accounting": "4.1.0",
|
||||
"ln-service": "47.15.0",
|
||||
"moment": "2.24.0",
|
||||
"qrcode-terminal": "0.12.0",
|
||||
"sanitize-filename": "1.6.3",
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
"url": "https://github.com/alexbosworth/balanceofsatoshis.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tap test/arrays/*.js test/balances/*.js test/chain/*.js test/encryption/*.js test/fiat/*.js test/lnd/*.js test/network/*.js test/nodes/*.js test/responses/*.js test/routing/*.js test/swaps/*.js test/telegram/*.js"
|
||||
"test": "tap test/arrays/*.js test/balances/*.js test/chain/*.js test/encryption/*.js test/fiat/*.js test/lnd/*.js test/network/*.js test/nodes/*.js test/responses/*.js test/routing/*.js test/swaps/*.js test/telegram/*.js test/wallets/*.js"
|
||||
},
|
||||
"version": "5.21.0"
|
||||
"version": "5.21.1"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ const defaultMaxFee = 1337;
|
|||
const defaultMaxFeeRate = 250;
|
||||
const flatten = arr => [].concat(...arr);
|
||||
const highInbound = 4500000;
|
||||
const {isArray} = Array;
|
||||
const {max} = Math;
|
||||
const maxPaymentSize = 4294967;
|
||||
const maxRebalanceTokens = 4294967;
|
||||
|
|
@ -68,6 +69,10 @@ module.exports = (args, cbk) => {
|
|||
return cbk([400, 'ExpectedLoggerToRebalance'])
|
||||
}
|
||||
|
||||
if (isArray(args.in_through)) {
|
||||
return cbk([400, 'MultipleInPeersIsNotSupported']);
|
||||
}
|
||||
|
||||
if (!!args.in_through && args.in_through === args.out_through) {
|
||||
return cbk([400, 'ExpectedInPeerNotEqualToOutPeer']);
|
||||
}
|
||||
|
|
@ -84,6 +89,10 @@ module.exports = (args, cbk) => {
|
|||
return cbk([400, 'ExpectedNonZeroMaxFeeRateForRebalance']);
|
||||
}
|
||||
|
||||
if (isArray(args.out_through)) {
|
||||
return cbk([400, 'MultipleOutPeersIsNotSupported']);
|
||||
}
|
||||
|
||||
if (!!args.out_through && args.in_through === args.out_through) {
|
||||
return cbk([400, 'ExpectedOutPeerNotEqualToInPeer']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ module.exports = (args, cbk) => {
|
|||
}
|
||||
|
||||
if (!!args.max_fee && getQuote.fee > args.max_fee) {
|
||||
return cbk([400, 'FeeForSwapExceedsMaximumFeeLimit']);
|
||||
return cbk([400, 'FeeForSwapExceedsMaximumFeeLimit', getQuote]);
|
||||
}
|
||||
|
||||
if (getQuote.cltv_delta < minCltvDelta) {
|
||||
|
|
|
|||
125
test/wallets/test_channels_as_report_activity.js
Normal file
125
test/wallets/test_channels_as_report_activity.js
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
const {test} = require('tap');
|
||||
|
||||
const method = require('./../../wallets/channels_as_report_activity');
|
||||
|
||||
const tests = [
|
||||
{
|
||||
args: {
|
||||
backups: [],
|
||||
chain: {
|
||||
currency: 'currency',
|
||||
height: 1,
|
||||
network: 'ltcmainnet',
|
||||
},
|
||||
channels: [],
|
||||
days: 1,
|
||||
nodes: [],
|
||||
},
|
||||
description: 'No channels generates no activity',
|
||||
expected: {},
|
||||
},
|
||||
{
|
||||
args: {
|
||||
backups: [
|
||||
{backup: '02', transaction_id: '01', transaction_vout: 1},
|
||||
{backup: '01', transaction_id: '00', transaction_vout: 2},
|
||||
{backup: '00', transaction_id: '00', transaction_vout: 1},
|
||||
],
|
||||
chain: {
|
||||
currency: 'currency',
|
||||
height: 1,
|
||||
network: 'network',
|
||||
},
|
||||
channels: [{
|
||||
id: '1x1x1',
|
||||
local_balance: 1,
|
||||
partner_public_key: 'a',
|
||||
remote_balance: 1,
|
||||
transaction_id: '00',
|
||||
transaction_vout: 1,
|
||||
}],
|
||||
days: 1,
|
||||
nodes: [{alias: 'alias', public_key: 'a'}],
|
||||
now: () => 1,
|
||||
},
|
||||
description: 'A channel open returns liquidity',
|
||||
expected: {
|
||||
activity: {
|
||||
date: '1970-01-01T00:00:00.001Z',
|
||||
elements: [
|
||||
{
|
||||
subtitle: 'a few seconds ago',
|
||||
title: 'alias',
|
||||
},
|
||||
{
|
||||
action: 'Opened channel',
|
||||
},
|
||||
{
|
||||
details: 'Liquidity now 0.00000001 currency inbound, 0.00000001 currency outbound',
|
||||
},
|
||||
{
|
||||
details: 'Backup: 00:1 00',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
args: {
|
||||
backups: [
|
||||
{backup: '02', transaction_id: '01', transaction_vout: 1},
|
||||
{backup: '01', transaction_id: '00', transaction_vout: 2},
|
||||
{backup: '00', transaction_id: '00', transaction_vout: 1},
|
||||
],
|
||||
chain: {
|
||||
currency: 'currency',
|
||||
height: 1,
|
||||
network: 'network',
|
||||
},
|
||||
channels: [{
|
||||
id: '1x1x1',
|
||||
local_balance: 1,
|
||||
partner_public_key: 'a',
|
||||
remote_balance: 1,
|
||||
transaction_id: '00',
|
||||
transaction_vout: 1,
|
||||
}],
|
||||
days: 1,
|
||||
nodes: [{public_key: 'b'}],
|
||||
now: () => 1,
|
||||
},
|
||||
description: 'A channel open with no known node',
|
||||
expected: {
|
||||
activity: {
|
||||
date: '1970-01-01T00:00:00.001Z',
|
||||
elements: [
|
||||
{
|
||||
subtitle: 'a few seconds ago',
|
||||
title: 'a',
|
||||
},
|
||||
{
|
||||
action: 'Opened channel',
|
||||
},
|
||||
{
|
||||
details: 'Liquidity now 0.00000001 currency inbound, 0.00000001 currency outbound',
|
||||
},
|
||||
{
|
||||
details: 'Backup: 00:1 00',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
tests.forEach(({args, description, error, expected}) => {
|
||||
return test(description, async ({deepIs, end, rejects}) => {
|
||||
const {activity} = method(args);
|
||||
|
||||
const [element] = activity;
|
||||
|
||||
deepIs(element, expected.activity, 'Got expected activity');
|
||||
|
||||
return end();
|
||||
});
|
||||
});
|
||||
75
test/wallets/test_report_overview.js
Normal file
75
test/wallets/test_report_overview.js
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
const {test} = require('tap');
|
||||
|
||||
const method = require('./../../wallets/report_overview');
|
||||
|
||||
const report = [
|
||||
{
|
||||
subtitle: 'current status',
|
||||
title: 'Node',
|
||||
},
|
||||
{
|
||||
details: 'public_key',
|
||||
},
|
||||
{
|
||||
details: 'alias',
|
||||
},
|
||||
{
|
||||
details: '0.00000001 CURRENCY ($0.00)',
|
||||
},
|
||||
{
|
||||
details: '1 CURRENCY~$1.00',
|
||||
},
|
||||
{},
|
||||
{
|
||||
subtitle: '50 years ago',
|
||||
title: 'Last Block:',
|
||||
},
|
||||
{
|
||||
subtitle: '100%',
|
||||
title: 'Funds on Lightning',
|
||||
},
|
||||
{
|
||||
subtitle: '1 per vbyte',
|
||||
title: 'Confirmation Fee:',
|
||||
},
|
||||
];
|
||||
|
||||
const tests = [
|
||||
{
|
||||
args: {
|
||||
alias: 'alias',
|
||||
balance: 1,
|
||||
chain_fee: 1,
|
||||
channel_balance: 1,
|
||||
currency: 'CURRENCY',
|
||||
latest_block_at: new Date(1).toISOString(),
|
||||
public_key: 'public_key',
|
||||
rate: 100,
|
||||
},
|
||||
description: 'An overview is generated',
|
||||
expected: {report},
|
||||
},
|
||||
{
|
||||
args: {
|
||||
alias: 'alias',
|
||||
balance: 1,
|
||||
channel_balance: 1,
|
||||
currency: 'CURRENCY',
|
||||
latest_block_at: new Date(1).toISOString(),
|
||||
public_key: 'public_key',
|
||||
rate: 100,
|
||||
},
|
||||
description: 'An overview is generated when no chainfee is specified',
|
||||
expected: {report: report.filter(n => n.title !== 'Confirmation Fee:')},
|
||||
},
|
||||
];
|
||||
|
||||
tests.forEach(({args, description, error, expected}) => {
|
||||
return test(description, async ({deepIs, end, rejects}) => {
|
||||
const {report} = method(args);
|
||||
|
||||
deepIs(report, expected.report, 'Got expected report');
|
||||
|
||||
return end();
|
||||
});
|
||||
});
|
||||
105
wallets/channels_as_report_activity.js
Normal file
105
wallets/channels_as_report_activity.js
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
const {decodeChanId} = require('bolt07');
|
||||
const moment = require('moment');
|
||||
|
||||
const action = 'Opened channel';
|
||||
const minutesPerBlock = network => network === 'ltcmainnet' ? 10 / 4 : 10;
|
||||
const minutesPerDay = 24 * 60;
|
||||
const msPerMinute = 1000 * 60;
|
||||
const sumOf = arr => arr.reduce((sum, n) => n + sum, 0);
|
||||
const tokensAsBigToken = tokens => (tokens / 1e8).toFixed(8);
|
||||
|
||||
/** Channels as report elements
|
||||
|
||||
{
|
||||
backups: [{
|
||||
transaction_id: <Channel Transaction Id Hex String>
|
||||
transaction_vout: <Channel Transaction Vout Number>
|
||||
}]
|
||||
chain: {
|
||||
currency: <Currency Code String>
|
||||
height: <Current Block Height Number>
|
||||
network: <Network Name String>
|
||||
}
|
||||
channels: [{
|
||||
id: <Standard Format Channel Id String>
|
||||
local_balance: <Local Balance Tokens Number>
|
||||
partner_public_key: <Partner Public Key Hex String>
|
||||
remote_balance: <Remote Balance Tokens Number>
|
||||
transaction_id: <Channel Transaction Id Hex String>
|
||||
transaction_vout: <Channel Transaction Output Index Number>
|
||||
}]
|
||||
days: <Days Number>
|
||||
nodes: [{
|
||||
alias: <Alias String>
|
||||
public_key: <Public Key Hex String>
|
||||
}]
|
||||
now: <Current Time Function>
|
||||
}
|
||||
|
||||
@returns
|
||||
{
|
||||
activity: [{
|
||||
date: <Activity Date String>
|
||||
elements: [<Report Element String>]
|
||||
}]
|
||||
}
|
||||
*/
|
||||
module.exports = ({backups, chain, channels, days, nodes, now}) => {
|
||||
const activity = [];
|
||||
const blocks = minutesPerDay / minutesPerBlock(chain.network) * days;
|
||||
const msPerBlock = msPerMinute * minutesPerBlock(chain.network);
|
||||
|
||||
channels
|
||||
.filter(({id}) => {
|
||||
return chain.height - decodeChanId({channel: id}).block_height < blocks;
|
||||
})
|
||||
.forEach(channel => {
|
||||
const chanId = channel.id;
|
||||
const elements = [];
|
||||
const pubKey = channel.partner_public_key;
|
||||
const utxo = `${channel.transaction_id}:${channel.transaction_vout}`;
|
||||
|
||||
const chanBlockHeight = decodeChanId({channel: chanId}).block_height;
|
||||
const node = nodes.find(n => n.public_key === pubKey) || {};
|
||||
|
||||
const blocksSinceOpen = chain.height - chanBlockHeight;
|
||||
const title = node.alias || channel.partner_public_key;
|
||||
|
||||
const date = moment(now() - blocksSinceOpen * msPerBlock);
|
||||
|
||||
const {backup} = backups.find(chan => {
|
||||
if (chan.transaction_id !== channel.transaction_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return chan.transaction_vout === channel.transaction_vout;
|
||||
});
|
||||
|
||||
const peerChannels = channels.filter(chan => {
|
||||
return chan.partner_public_key === channel.partner_public_key
|
||||
});
|
||||
|
||||
const localBalances = peerChannels.map(n => n.local_balance);
|
||||
const remoteBalances = peerChannels.map(n => n.remote_balance);
|
||||
|
||||
const inbound = tokensAsBigToken(sumOf(remoteBalances));
|
||||
const outbound = tokensAsBigToken(sumOf(localBalances));
|
||||
|
||||
const inboundLiquid = `${inbound} ${chain.currency} inbound`;
|
||||
const outboundLiquid = `${outbound} ${chain.currency} outbound`;
|
||||
|
||||
elements.push({title, subtitle: date.from(moment(now()))});
|
||||
|
||||
elements.push({action});
|
||||
|
||||
elements.push({
|
||||
details: `Liquidity now ${inboundLiquid}, ${outboundLiquid}`,
|
||||
});
|
||||
|
||||
elements.push({details: `Backup: ${utxo} ${backup}`});
|
||||
|
||||
return activity.push({elements, date: date.toISOString()});
|
||||
});
|
||||
|
||||
return {activity};
|
||||
};
|
||||
|
|
@ -17,10 +17,13 @@ const request = require('@alexbosworth/request');
|
|||
const {returnResult} = require('asyncjs-util');
|
||||
|
||||
const {authenticatedLnd} = require('./../lnd');
|
||||
const channelsAsReportActivity = require('./channels_as_report_activity');
|
||||
const {currencyForNetwork} = require('./../network');
|
||||
const {getBalance} = require('./../balances');
|
||||
const {getCoindeskCurrentPrice} = require('./../fiat');
|
||||
const {getForwards} = require('./../network');
|
||||
const {getNetwork} = require('./../network');
|
||||
const reportOverview = require('./report_overview');
|
||||
|
||||
const afterMs = 1000 * 60 * 60 * 24;
|
||||
const centsPerDollar = 100;
|
||||
|
|
@ -122,6 +125,11 @@ module.exports = ({node, style}, cbk) => {
|
|||
return getInvoices({lnd: getLnd.lnd}, cbk);
|
||||
}],
|
||||
|
||||
// Get network
|
||||
getNetwork: ['getLnd', ({getLnd}, cbk) => {
|
||||
return getNetwork({lnd: getLnd.lnd}, cbk);
|
||||
}],
|
||||
|
||||
// Get payments
|
||||
getPayments: ['getLnd', ({getLnd}, cbk) => {
|
||||
return getPayments({lnd: getLnd.lnd}, cbk);
|
||||
|
|
@ -145,6 +153,7 @@ module.exports = ({node, style}, cbk) => {
|
|||
'getGraph',
|
||||
'getInfo',
|
||||
'getInvoices',
|
||||
'getNetwork',
|
||||
'getPayments',
|
||||
'getRate',
|
||||
({
|
||||
|
|
@ -159,111 +168,51 @@ module.exports = ({node, style}, cbk) => {
|
|||
getGraph,
|
||||
getInfo,
|
||||
getInvoices,
|
||||
getNetwork,
|
||||
getPayments,
|
||||
getRate,
|
||||
}, cbk) =>
|
||||
{
|
||||
const activity = [];
|
||||
const balance = formatAsBigUnit(getBalance.balance);
|
||||
const channelBalance = getBalance.channel_balance;
|
||||
const currentHeight = getInfo.current_block_height;
|
||||
const {nodes} = getGraph;
|
||||
const rate = getRate.cents;
|
||||
const totalBalance = getBalance.balance;
|
||||
|
||||
const fiatBalance = (balance * rate / centsPerDollar).toFixed(2);
|
||||
const findNode = pk => nodes.find(n => n.public_key === pk) || {};
|
||||
const lightningFunds = (channelBalance / totalBalance * 100).toFixed();
|
||||
|
||||
const report = [
|
||||
{subtitle: 'current status', title: 'Node'},
|
||||
{details: getInfo.public_key},
|
||||
{details: getInfo.alias},
|
||||
{details: `${balance} ${currency} ($${fiatBalance})`},
|
||||
{details: `1 ${currency}~$${(rate / 100).toFixed(2)}`},
|
||||
{},
|
||||
{
|
||||
is_hidden: !getAutopilot.is_enabled,
|
||||
subtitle: 'Enabled',
|
||||
title: 'Autopilot:',
|
||||
const {report} = reportOverview({
|
||||
currency,
|
||||
alias: getInfo.alias,
|
||||
balance: getBalance.balance,
|
||||
chain_fee: !getChainFee ? undefined : getChainFee.tokens_per_vbyte,
|
||||
channel_balance: getBalance.channel_balance,
|
||||
latest_block_at: getInfo.latest_block_at,
|
||||
public_key: getInfo.public_key,
|
||||
rate: getRate.cents,
|
||||
});
|
||||
|
||||
const channelsActivity = channelsAsReportActivity({
|
||||
now,
|
||||
backups: getBackups.channels,
|
||||
chain: {
|
||||
currency,
|
||||
height: getInfo.current_block_height,
|
||||
network: getNetwork.network,
|
||||
},
|
||||
{
|
||||
subtitle: moment(getInfo.latest_block_at).fromNow(),
|
||||
title: 'Last Block:',
|
||||
},
|
||||
{
|
||||
subtitle: `${lightningFunds}%`,
|
||||
title: 'Funds on Lightning',
|
||||
},
|
||||
];
|
||||
channels: getChannels.channels.slice().reverse(),
|
||||
days: 1,
|
||||
nodes: getGraph.nodes,
|
||||
});
|
||||
|
||||
if (!!getChainFee) {
|
||||
report.push({
|
||||
subtitle: `${getChainFee.tokens_per_vbyte} sat/vbyte`,
|
||||
title: 'Confirmation Fee:',
|
||||
});
|
||||
}
|
||||
|
||||
getChannels.channels.slice().reverse()
|
||||
.filter(({id}) => {
|
||||
const chanHeight = decodeChanId({channel: id}).block_height;
|
||||
|
||||
return getInfo.current_block_height - chanHeight < 144;
|
||||
})
|
||||
.forEach(channel => {
|
||||
const chanId = channel.id;
|
||||
const elements = [];
|
||||
const pubKey = channel.partner_public_key;
|
||||
|
||||
const {backup} = getBackups.channels.find(chan => {
|
||||
if (chan.transaction_id !== channel.transaction_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return chan.transaction_vout === channel.transaction_vout;
|
||||
});
|
||||
|
||||
const channels = getChannels.channels.filter(chan => {
|
||||
return chan.partner_public_key === channel.partner_public_key
|
||||
});
|
||||
|
||||
const chanBlockHeight = decodeChanId({channel: chanId}).block_height;
|
||||
|
||||
const blocksSinceOpen = currentHeight - chanBlockHeight;
|
||||
|
||||
const date = moment(now() - blocksSinceOpen * msPerBlock);
|
||||
const node = getGraph.nodes.find(n => n.public_key === pubKey) || {};
|
||||
|
||||
elements.push({
|
||||
subtitle: date.fromNow(),
|
||||
title: node.alias || channel.partner_public_key,
|
||||
});
|
||||
|
||||
elements.push({action: 'Opened channel'});
|
||||
|
||||
const localBalances = channels.map(n => n.local_balance);
|
||||
const remoteBalances = channels.map(n => n.remote_balance);
|
||||
|
||||
const inbound = (sumOf(remoteBalances) / 1e8).toFixed(8);
|
||||
const outbound = (sumOf(localBalances) / 1e8).toFixed(8);
|
||||
|
||||
const inboundLiquid = `${inbound} ${currency} inbound`;
|
||||
const outboundLiquid = `${outbound} ${currency} outbound`;
|
||||
|
||||
elements.push({
|
||||
details: `Liquidity now ${inboundLiquid}, ${outboundLiquid}`,
|
||||
});
|
||||
|
||||
const utxo = `${channel.transaction_id}:${channel.transaction_vout}`;
|
||||
|
||||
elements.push({details: `Backup: ${utxo} ${backup}`});
|
||||
|
||||
return activity.push({elements, date: date.toISOString()});
|
||||
});
|
||||
channelsActivity.activity.forEach(n => activity.push(n));
|
||||
|
||||
getInvoices.invoices.slice().reverse()
|
||||
.filter(invoice => !!invoice.confirmed_at)
|
||||
.filter(invoice => now() - Date.parse(invoice.confirmed_at) < afterMs)
|
||||
.filter(invoice => {
|
||||
const isToSelf = getPayments.payments.find(n => n.id === invoice.id);
|
||||
|
||||
return !isToSelf;
|
||||
})
|
||||
.forEach(invoice => {
|
||||
const elements = [];
|
||||
const received = invoice.received;
|
||||
|
|
@ -278,6 +227,7 @@ module.exports = ({node, style}, cbk) => {
|
|||
});
|
||||
|
||||
elements.push({
|
||||
is_hidden: !invoice.description,
|
||||
details: `"${invoice.description}"`,
|
||||
});
|
||||
|
||||
|
|
@ -290,6 +240,41 @@ module.exports = ({node, style}, cbk) => {
|
|||
|
||||
getPayments.payments.slice().reverse()
|
||||
.filter(payment => now() - Date.parse(payment.created_at) < afterMs)
|
||||
.filter(payment => payment.destination === getInfo.public_key)
|
||||
.forEach(payment => {
|
||||
const elements = [];
|
||||
const {fee} = payment;
|
||||
const {tokens} = payment;
|
||||
|
||||
const amount = `${formatAsBigUnit(tokens)} ${currency}`;
|
||||
|
||||
const [outHop] = payment.hops;
|
||||
|
||||
const outNode = getGraph.nodes.find(n => n.public_key === outHop);
|
||||
|
||||
const outbound = (outNode || {}).alias || (outNode || {}).public_key;
|
||||
|
||||
elements.push({
|
||||
subtitle: moment(payment.created_at).fromNow(),
|
||||
title: getInfo.alias || getInfo.public_key,
|
||||
});
|
||||
|
||||
elements.push({action: 'Rebalance'});
|
||||
|
||||
elements.push({
|
||||
details: `Increased inbound liquidity on ${outbound} by ${amount}`,
|
||||
});
|
||||
|
||||
elements.push({
|
||||
details: `Fee: ${formatAsBigUnit(fee)} ${currency}`,
|
||||
});
|
||||
|
||||
return activity.push({elements, date: payment.created_at});
|
||||
});
|
||||
|
||||
getPayments.payments.slice().reverse()
|
||||
.filter(payment => now() - Date.parse(payment.created_at) < afterMs)
|
||||
.filter(payment => payment.destination !== getInfo.public_key)
|
||||
.forEach(payment => {
|
||||
const elements = [];
|
||||
const node = findNode(payment.destination);
|
||||
|
|
@ -312,6 +297,12 @@ module.exports = ({node, style}, cbk) => {
|
|||
details: `Sent: ${formatAsBigUnit(payment.tokens)} ${currency}`,
|
||||
});
|
||||
|
||||
if (!!payment.fee) {
|
||||
elements.push({
|
||||
details: `Fee: ${formatAsBigUnit(payment.fee)} ${currency}`,
|
||||
});
|
||||
}
|
||||
|
||||
return activity.push({elements, date: payment.created_at});
|
||||
});
|
||||
|
||||
|
|
|
|||
71
wallets/report_overview.js
Normal file
71
wallets/report_overview.js
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
const moment = require('moment');
|
||||
|
||||
const dollarFormat = cents => (cents / 100).toFixed(2);
|
||||
const formatAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
|
||||
const percentFormat = n => (n * 100).toFixed();
|
||||
|
||||
/** Derive report overview
|
||||
|
||||
{
|
||||
alias: <Alias String>
|
||||
balance: <Tokens Balance>
|
||||
[chain_fee]: <Chain Fee Tokens Per VByte Number>
|
||||
channel_balance: <Channel Balance Number>
|
||||
currency: <Currency String>
|
||||
latest_block_at: <Last Block At ISO 8601 Date String>
|
||||
public_key: <Public Key Hex String>
|
||||
rate: <Fiat Rate Number>
|
||||
}
|
||||
|
||||
@returns
|
||||
{
|
||||
report: [{
|
||||
[details]: <Details String>
|
||||
[is_hidden]: <Line Is Hidden Bool>
|
||||
[subtitle]: <Subtitle String>
|
||||
[title]: <Title String>
|
||||
}]
|
||||
}
|
||||
*/
|
||||
module.exports = args => {
|
||||
const balance = formatAsBigUnit(args.balance);
|
||||
|
||||
const fiatBalance = dollarFormat(balance * args.rate);
|
||||
|
||||
const report = [
|
||||
{
|
||||
subtitle: 'current status',
|
||||
title: 'Node',
|
||||
},
|
||||
{
|
||||
details: args.public_key,
|
||||
},
|
||||
{
|
||||
details: args.alias,
|
||||
},
|
||||
{
|
||||
details: `${balance} ${args.currency} ($${fiatBalance})`,
|
||||
},
|
||||
{
|
||||
details: `1 ${args.currency}~$${dollarFormat(args.rate)}`,
|
||||
},
|
||||
{},
|
||||
{
|
||||
subtitle: moment(args.latest_block_at).fromNow(),
|
||||
title: 'Last Block:',
|
||||
},
|
||||
{
|
||||
subtitle: `${percentFormat(args.channel_balance / args.balance)}%`,
|
||||
title: 'Funds on Lightning',
|
||||
},
|
||||
];
|
||||
|
||||
if (!!args.chain_fee) {
|
||||
report.push({
|
||||
subtitle: `${args.chain_fee} per vbyte`,
|
||||
title: 'Confirmation Fee:',
|
||||
});
|
||||
}
|
||||
|
||||
return {report};
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue