Umbrel support (#141)
* Don't require BTC core connection * Docker: Don't clone, but use local repo * Add GitHub workflows * Allow to overwrite hostname * chore: update dependencies * Get tor URL from env
This commit is contained in:
		
							parent
							
								
									76b289b652
								
							
						
					
					
						commit
						f0493d595f
					
				@ -3,7 +3,7 @@
 | 
			
		||||
  "plugins": [
 | 
			
		||||
      "prettier"
 | 
			
		||||
  ],
 | 
			
		||||
  "extends": ["prettier"],
 | 
			
		||||
  "extends": ["plugin:prettier/recommended"],
 | 
			
		||||
  "rules": {
 | 
			
		||||
    "prettier/prettier": [
 | 
			
		||||
      "warn",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										54
									
								
								.github/workflows/push.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								.github/workflows/push.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
name: Build on push
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
    push:
 | 
			
		||||
        branches:
 | 
			
		||||
            - master
 | 
			
		||||
 | 
			
		||||
env:
 | 
			
		||||
  DOCKER_CLI_EXPERIMENTAL: enabled
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    name: Build image
 | 
			
		||||
    runs-on: ubuntu-20.04
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        platform:
 | 
			
		||||
          - linux/amd64
 | 
			
		||||
          - linux/arm64
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout project
 | 
			
		||||
        uses: actions/checkout@v2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      - name: Set env variables
 | 
			
		||||
        run: echo "BRANCH=$(echo ${GITHUB_REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Login to Docker Hub
 | 
			
		||||
        uses: docker/login-action@v1
 | 
			
		||||
        with:
 | 
			
		||||
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
 | 
			
		||||
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
 | 
			
		||||
 | 
			
		||||
      - name: Set up QEMU
 | 
			
		||||
        uses: docker/setup-qemu-action@v1
 | 
			
		||||
        id: qemu
 | 
			
		||||
 | 
			
		||||
      - name: Setup Docker buildx action
 | 
			
		||||
        uses: docker/setup-buildx-action@v1
 | 
			
		||||
        id: buildx
 | 
			
		||||
 | 
			
		||||
      - name: Show available Docker buildx platforms
 | 
			
		||||
        run: echo ${{ steps.buildx.outputs.platforms }}
 | 
			
		||||
 | 
			
		||||
     
 | 
			
		||||
      - name: Run Docker buildx
 | 
			
		||||
        run: |
 | 
			
		||||
                docker buildx build \
 | 
			
		||||
                --cache-from "type=local,src=/tmp/.buildx-cache" \
 | 
			
		||||
                --cache-to "type=local,dest=/tmp/.buildx-cache" \
 | 
			
		||||
                --platform ${{matrix.platform}} \
 | 
			
		||||
                --tag ${{ secrets.DOCKER_CONTAINER_USERNAME }}/lndhub:$BRANCH \
 | 
			
		||||
                --output "type=registry" ./
 | 
			
		||||
							
								
								
									
										62
									
								
								.github/workflows/tag.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								.github/workflows/tag.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
name: Build on push
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
        push:
 | 
			
		||||
                tags:
 | 
			
		||||
                  - v[0-9]+.[0-9]+.[0-9]+
 | 
			
		||||
                  - v[0-9]+.[0-9]+.[0-9]+-*
 | 
			
		||||
 | 
			
		||||
env:
 | 
			
		||||
  DOCKER_CLI_EXPERIMENTAL: enabled
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    name: Build image
 | 
			
		||||
    runs-on: ubuntu-20.04
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        platform:
 | 
			
		||||
          - linux/amd64
 | 
			
		||||
          - linux/arm64
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout project
 | 
			
		||||
        uses: actions/checkout@v2
 | 
			
		||||
 | 
			
		||||
      - name: Set env variables
 | 
			
		||||
        run: echo "TAG=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
 | 
			
		||||
                
 | 
			
		||||
      - name: Login to Docker Hub
 | 
			
		||||
        uses: docker/login-action@v1
 | 
			
		||||
        with:
 | 
			
		||||
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
 | 
			
		||||
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
 | 
			
		||||
 | 
			
		||||
      - name: Set up QEMU
 | 
			
		||||
        uses: docker/setup-qemu-action@v1
 | 
			
		||||
        id: qemu
 | 
			
		||||
 | 
			
		||||
      - name: Setup Docker buildx action
 | 
			
		||||
        uses: docker/setup-buildx-action@v1
 | 
			
		||||
        id: buildx
 | 
			
		||||
 | 
			
		||||
      - name: Show available Docker buildx platforms
 | 
			
		||||
        run: echo ${{ steps.buildx.outputs.platforms }}
 | 
			
		||||
 | 
			
		||||
     
 | 
			
		||||
      - name: Run Docker buildx
 | 
			
		||||
        run: |
 | 
			
		||||
                docker buildx build \
 | 
			
		||||
                --cache-from "type=local,src=/tmp/.buildx-cache" \
 | 
			
		||||
                --cache-to "type=local,dest=/tmp/.buildx-cache" \
 | 
			
		||||
                --platform ${{matrix.platform}} \
 | 
			
		||||
                --tag ${{ secrets.DOCKER_CONTAINER_USERNAME }}/lndhub:$TAG \
 | 
			
		||||
                --output "type=registry" ./
 | 
			
		||||
      - name: Run Docker buildx
 | 
			
		||||
        run: |
 | 
			
		||||
                docker buildx build \
 | 
			
		||||
                --cache-from "type=local,src=/tmp/.buildx-cache" \
 | 
			
		||||
                --cache-to "type=local,dest=/tmp/.buildx-cache" \
 | 
			
		||||
                --platform ${{matrix.platform}} \
 | 
			
		||||
                --tag ${{ secrets.DOCKER_CONTAINER_USERNAME }}/lndhub:latest \
 | 
			
		||||
                --output "type=registry" ./
 | 
			
		||||
							
								
								
									
										23
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								Dockerfile
									
									
									
									
									
								
							@ -6,19 +6,26 @@ RUN adduser --disabled-password \
 | 
			
		||||
            --gecos "" \
 | 
			
		||||
            "lndhub"
 | 
			
		||||
 | 
			
		||||
FROM node:buster-slim AS builder
 | 
			
		||||
FROM node:12-buster-slim AS builder
 | 
			
		||||
 | 
			
		||||
# These packages are required for building LNDHub
 | 
			
		||||
RUN apt-get update && apt-get -y install git python3
 | 
			
		||||
 | 
			
		||||
# TODO: Switch to official images once my PR is merged
 | 
			
		||||
RUN git clone https://github.com/AaronDewes/LndHub.git -b update-dependencies /lndhub
 | 
			
		||||
RUN apt-get update && apt-get -y install python3
 | 
			
		||||
 | 
			
		||||
WORKDIR /lndhub
 | 
			
		||||
 | 
			
		||||
# Copy 'package-lock.json' and 'package.json'
 | 
			
		||||
COPY package.json package-lock.json ./
 | 
			
		||||
 | 
			
		||||
# Install dependencies
 | 
			
		||||
RUN npm i
 | 
			
		||||
 | 
			
		||||
FROM node:buster-slim
 | 
			
		||||
# Copy project files and folders to the current working directory
 | 
			
		||||
COPY . .
 | 
			
		||||
 | 
			
		||||
# Delete git data as it's not needed inside the container
 | 
			
		||||
RUN rm -rf .git
 | 
			
		||||
 | 
			
		||||
FROM node:12-buster-slim
 | 
			
		||||
 | 
			
		||||
# Create a specific user so LNDHub doesn't run as root
 | 
			
		||||
COPY  --from=perms /etc/group /etc/passwd /etc/shadow  /etc/
 | 
			
		||||
@ -26,12 +33,8 @@ COPY  --from=perms /etc/group /etc/passwd /etc/shadow  /etc/
 | 
			
		||||
# Copy LNDHub with installed modules from builder
 | 
			
		||||
COPY  --from=builder /lndhub /lndhub
 | 
			
		||||
 | 
			
		||||
# Delete git data as it's not needed inside the container
 | 
			
		||||
RUN rm -rf .git
 | 
			
		||||
 | 
			
		||||
# Create logs folder and ensure permissions are set correctly
 | 
			
		||||
RUN mkdir /lndhub/logs && chown -R lndhub:lndhub /lndhub
 | 
			
		||||
 | 
			
		||||
USER lndhub
 | 
			
		||||
 | 
			
		||||
ENV PORT=3000
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								bitcoin.js
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								bitcoin.js
									
									
									
									
									
								
							@ -2,6 +2,10 @@
 | 
			
		||||
const config = require('./config');
 | 
			
		||||
let jayson = require('jayson/promise');
 | 
			
		||||
let url = require('url');
 | 
			
		||||
let rpc = url.parse(config.bitcoind.rpc);
 | 
			
		||||
rpc.timeout = 15000;
 | 
			
		||||
module.exports = jayson.client.http(rpc);
 | 
			
		||||
if (config.bitcoind) {
 | 
			
		||||
  let rpc = url.parse(config.bitcoind.rpc);
 | 
			
		||||
  rpc.timeout = 15000;
 | 
			
		||||
  module.exports = jayson.client.http(rpc);
 | 
			
		||||
} else {
 | 
			
		||||
  module.exports = {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										79
									
								
								btc-decoder.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								btc-decoder.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
			
		||||
const bitcoin = require('bitcoinjs-lib');
 | 
			
		||||
const classify = require('bitcoinjs-lib/src/classify');
 | 
			
		||||
 | 
			
		||||
const decodeFormat = (tx) => ({
 | 
			
		||||
  txid: tx.getId(),
 | 
			
		||||
  version: tx.version,
 | 
			
		||||
  locktime: tx.locktime,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const decodeInput = function (tx) {
 | 
			
		||||
  const result = [];
 | 
			
		||||
  tx.ins.forEach(function (input, n) {
 | 
			
		||||
    result.push({
 | 
			
		||||
      txid: input.hash.reverse().toString('hex'),
 | 
			
		||||
      n: input.index,
 | 
			
		||||
      script: bitcoin.script.toASM(input.script),
 | 
			
		||||
      sequence: input.sequence,
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
  return result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const decodeOutput = function (tx, network) {
 | 
			
		||||
  const format = function (out, n, network) {
 | 
			
		||||
    const vout = {
 | 
			
		||||
      satoshi: out.value,
 | 
			
		||||
      value: (1e-8 * out.value).toFixed(8),
 | 
			
		||||
      n: n,
 | 
			
		||||
      scriptPubKey: {
 | 
			
		||||
        asm: bitcoin.script.toASM(out.script),
 | 
			
		||||
        hex: out.script.toString('hex'),
 | 
			
		||||
        type: classify.output(out.script),
 | 
			
		||||
        addresses: [],
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
    switch (vout.scriptPubKey.type) {
 | 
			
		||||
      case 'pubkeyhash':
 | 
			
		||||
      case 'scripthash':
 | 
			
		||||
        vout.scriptPubKey.addresses.push(bitcoin.address.fromOutputScript(out.script, network));
 | 
			
		||||
        break;
 | 
			
		||||
      case 'witnesspubkeyhash':
 | 
			
		||||
      case 'witnessscripthash':
 | 
			
		||||
        const data = bitcoin.script.decompile(out.script)[1];
 | 
			
		||||
        vout.scriptPubKey.addresses.push(bitcoin.address.toBech32(data, 0, network.bech32));
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return vout;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const result = [];
 | 
			
		||||
  tx.outs.forEach(function (out, n) {
 | 
			
		||||
    result.push(format(out, n, network));
 | 
			
		||||
  });
 | 
			
		||||
  return result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class TxDecoder {
 | 
			
		||||
  constructor(rawTx, network = bitcoin.networks.bitcoin) {
 | 
			
		||||
    this.tx = bitcoin.Transaction.fromHex(rawTx);
 | 
			
		||||
    this.format = decodeFormat(this.tx);
 | 
			
		||||
    this.inputs = decodeInput(this.tx);
 | 
			
		||||
    this.outputs = decodeOutput(this.tx, network);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  decode() {
 | 
			
		||||
    const result = {};
 | 
			
		||||
    const self = this;
 | 
			
		||||
    Object.keys(self.format).forEach(function (key) {
 | 
			
		||||
      result[key] = self.format[key];
 | 
			
		||||
    });
 | 
			
		||||
    result.outputs = self.outputs;
 | 
			
		||||
    result.inputs = self.inputs;
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.decodeRawHex = (rawTx, network = bitcoin.networks.bitcoin) => {
 | 
			
		||||
  return new TxDecoder(rawTx, network).decode();
 | 
			
		||||
};
 | 
			
		||||
@ -3,6 +3,8 @@ import { Lock } from './Lock';
 | 
			
		||||
var crypto = require('crypto');
 | 
			
		||||
var lightningPayReq = require('bolt11');
 | 
			
		||||
import { BigNumber } from 'bignumber.js';
 | 
			
		||||
import { decodeRawHex } from '../btc-decoder';
 | 
			
		||||
const config = require('../config');
 | 
			
		||||
 | 
			
		||||
// static cache:
 | 
			
		||||
let _invoice_ispaid_cache = {};
 | 
			
		||||
@ -114,11 +116,11 @@ export class User {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let self = this;
 | 
			
		||||
    return new Promise(function(resolve, reject) {
 | 
			
		||||
      self._lightning.newAddress({ type: 0 }, async function(err, response) {
 | 
			
		||||
    return new Promise(function (resolve, reject) {
 | 
			
		||||
      self._lightning.newAddress({ type: 0 }, async function (err, response) {
 | 
			
		||||
        if (err) return reject('LND failure when trying to generate new address');
 | 
			
		||||
        await self.addAddress(response.address);
 | 
			
		||||
        self._bitcoindrpc.request('importaddress', [response.address, response.address, false]);
 | 
			
		||||
        if (config.bitcoind) self._bitcoindrpc.request('importaddress', [response.address, response.address, false]);
 | 
			
		||||
        resolve();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
@ -126,7 +128,7 @@ export class User {
 | 
			
		||||
 | 
			
		||||
  async watchAddress(address) {
 | 
			
		||||
    if (!address) return;
 | 
			
		||||
    return this._bitcoindrpc.request('importaddress', [address, address, false]);
 | 
			
		||||
    if (config.bitcoind) return this._bitcoindrpc.request('importaddress', [address, address, false]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
@ -304,7 +306,10 @@ export class User {
 | 
			
		||||
        _invoice_ispaid_cache[invoice.payment_hash] = paymentHashPaidAmountSat;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      invoice.amt = (paymentHashPaidAmountSat && parseInt(paymentHashPaidAmountSat) > decoded.satoshis) ? parseInt(paymentHashPaidAmountSat) : decoded.satoshis;
 | 
			
		||||
      invoice.amt =
 | 
			
		||||
        paymentHashPaidAmountSat && parseInt(paymentHashPaidAmountSat) > decoded.satoshis
 | 
			
		||||
          ? parseInt(paymentHashPaidAmountSat)
 | 
			
		||||
          : decoded.satoshis;
 | 
			
		||||
      invoice.expire_time = 3600 * 24;
 | 
			
		||||
      // ^^^default; will keep for now. if we want to un-hardcode it - it should be among tags (`expire_time`)
 | 
			
		||||
      invoice.timestamp = decoded.timestamp;
 | 
			
		||||
@ -326,12 +331,7 @@ export class User {
 | 
			
		||||
   * @returns {Promise<Array>}
 | 
			
		||||
   */
 | 
			
		||||
  async getTxs() {
 | 
			
		||||
    let addr = await this.getAddress();
 | 
			
		||||
    if (!addr) {
 | 
			
		||||
      await this.generateAddress();
 | 
			
		||||
      addr = await this.getAddress();
 | 
			
		||||
    }
 | 
			
		||||
    if (!addr) throw new Error('cannot get transactions: no onchain address assigned to user');
 | 
			
		||||
    const addr = await this.getOrGenerateAddress();
 | 
			
		||||
    let txs = await this._listtransactions();
 | 
			
		||||
    txs = txs.result;
 | 
			
		||||
    let result = [];
 | 
			
		||||
@ -402,17 +402,22 @@ export class User {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      let txs = await this._bitcoindrpc.request('listtransactions', ['*', 100500, 0, true]);
 | 
			
		||||
      // now, compacting response a bit
 | 
			
		||||
      let ret = { result: [] };
 | 
			
		||||
      for (const tx of txs.result) {
 | 
			
		||||
        ret.result.push({
 | 
			
		||||
          category: tx.category,
 | 
			
		||||
          amount: tx.amount,
 | 
			
		||||
          confirmations: tx.confirmations,
 | 
			
		||||
          address: tx.address,
 | 
			
		||||
          time: tx.time,
 | 
			
		||||
        });
 | 
			
		||||
      if (config.bitcoind) {
 | 
			
		||||
        let txs = await this._bitcoindrpc.request('listtransactions', ['*', 100500, 0, true]);
 | 
			
		||||
        // now, compacting response a bit
 | 
			
		||||
        for (const tx of txs.result) {
 | 
			
		||||
          ret.result.push({
 | 
			
		||||
            category: tx.category,
 | 
			
		||||
            amount: tx.amount,
 | 
			
		||||
            confirmations: tx.confirmations,
 | 
			
		||||
            address: tx.address,
 | 
			
		||||
            time: tx.time,
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        let txs = await this._getChainTransactions();
 | 
			
		||||
        ret.result.push(...txs);
 | 
			
		||||
      }
 | 
			
		||||
      _listtransactions_cache = JSON.stringify(ret);
 | 
			
		||||
      _listtransactions_cache_expiry_ts = +new Date() + 5 * 60 * 1000; // 5 min
 | 
			
		||||
@ -426,18 +431,42 @@ export class User {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async _getChainTransactions() {
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
      this._lightning.getTransactions({}, (err, data) => {
 | 
			
		||||
        if (err) return reject(err);
 | 
			
		||||
        const { transactions } = data;
 | 
			
		||||
        const outTxns = [];
 | 
			
		||||
        // on lightning incoming transactions have no labels
 | 
			
		||||
        // for now filter out known labels to reduce transactions
 | 
			
		||||
        transactions
 | 
			
		||||
          .filter((tx) => tx.label !== 'external' && !tx.label.includes('openchannel'))
 | 
			
		||||
          .map((tx) => {
 | 
			
		||||
            const decodedTx = decodeRawHex(tx.raw_tx_hex);
 | 
			
		||||
            decodedTx.outputs.forEach((vout) =>
 | 
			
		||||
              outTxns.push({
 | 
			
		||||
                // mark all as received, since external is filtered out
 | 
			
		||||
                category: 'receive',
 | 
			
		||||
                confirmations: tx.num_confirmations,
 | 
			
		||||
                amount: Number(vout.value),
 | 
			
		||||
                address: vout.scriptPubKey.addresses[0],
 | 
			
		||||
                time: tx.time_stamp,
 | 
			
		||||
              }),
 | 
			
		||||
            );
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
        resolve(outTxns);
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returning onchain txs for user's address that are less than 3 confs
 | 
			
		||||
   *
 | 
			
		||||
   * @returns {Promise<Array>}
 | 
			
		||||
   */
 | 
			
		||||
  async getPendingTxs() {
 | 
			
		||||
    let addr = await this.getAddress();
 | 
			
		||||
    if (!addr) {
 | 
			
		||||
      await this.generateAddress();
 | 
			
		||||
      addr = await this.getAddress();
 | 
			
		||||
    }
 | 
			
		||||
    if (!addr) throw new Error('cannot get transactions: no onchain address assigned to user');
 | 
			
		||||
    const addr = await this.getOrGenerateAddress();
 | 
			
		||||
    let txs = await this._listtransactions();
 | 
			
		||||
    txs = txs.result;
 | 
			
		||||
    let result = [];
 | 
			
		||||
@ -556,6 +585,16 @@ export class User {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async getOrGenerateAddress() {
 | 
			
		||||
    let addr = await this.getAddress();
 | 
			
		||||
    if (!addr) {
 | 
			
		||||
      await this.generateAddress();
 | 
			
		||||
      addr = await this.getAddress();
 | 
			
		||||
    }
 | 
			
		||||
    if (!addr) throw new Error('cannot get transactions: no onchain address assigned to user');
 | 
			
		||||
    return addr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _hash(string) {
 | 
			
		||||
    return crypto.createHash('sha256').update(string).digest().toString('hex');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ const config = require('../config');
 | 
			
		||||
let express = require('express');
 | 
			
		||||
let router = express.Router();
 | 
			
		||||
let logger = require('../utils/logger');
 | 
			
		||||
const MIN_BTC_BLOCK = 670000;
 | 
			
		||||
console.log('using config', JSON.stringify(config));
 | 
			
		||||
 | 
			
		||||
var Redis = require('ioredis');
 | 
			
		||||
@ -19,17 +20,19 @@ let lightning = require('../lightning');
 | 
			
		||||
let identity_pubkey = false;
 | 
			
		||||
// ###################### SMOKE TESTS ########################
 | 
			
		||||
 | 
			
		||||
bitcoinclient.request('getblockchaininfo', false, function (err, info) {
 | 
			
		||||
  if (info && info.result && info.result.blocks) {
 | 
			
		||||
    if (info.result.chain === 'mainnet' && info.result.blocks < 550000) {
 | 
			
		||||
      console.error('bitcoind is not caught up');
 | 
			
		||||
      process.exit(1);
 | 
			
		||||
if (config.bitcoind) {
 | 
			
		||||
  bitcoinclient.request('getblockchaininfo', false, function (err, info) {
 | 
			
		||||
    if (info && info.result && info.result.blocks) {
 | 
			
		||||
      if (info.result.chain === 'mainnet' && info.result.blocks < MIN_BTC_BLOCK && !config.forceStart) {
 | 
			
		||||
        console.error('bitcoind is not caught up');
 | 
			
		||||
        process.exit(1);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      console.error('bitcoind failure:', err, info);
 | 
			
		||||
      process.exit(2);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    console.error('bitcoind failure:', err, info);
 | 
			
		||||
    process.exit(2);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
lightning.getInfo({}, function (err, info) {
 | 
			
		||||
  if (err) {
 | 
			
		||||
@ -39,7 +42,7 @@ lightning.getInfo({}, function (err, info) {
 | 
			
		||||
  }
 | 
			
		||||
  if (info) {
 | 
			
		||||
    console.info(info);
 | 
			
		||||
    if (!info.synced_to_chain) {
 | 
			
		||||
    if (!info.synced_to_chain && !config.forceStart) {
 | 
			
		||||
      console.error('lnd not synced');
 | 
			
		||||
      // process.exit(4);
 | 
			
		||||
    }
 | 
			
		||||
@ -70,7 +73,10 @@ const subscribeInvoicesCallCallback = async function (response) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    let invoice = new Invo(redis, bitcoinclient, lightning);
 | 
			
		||||
    await invoice._setIsPaymentHashPaidInDatabase(LightningInvoiceSettledNotification.hash, LightningInvoiceSettledNotification.amt_paid_sat || 1);
 | 
			
		||||
    await invoice._setIsPaymentHashPaidInDatabase(
 | 
			
		||||
      LightningInvoiceSettledNotification.hash,
 | 
			
		||||
      LightningInvoiceSettledNotification.amt_paid_sat || 1,
 | 
			
		||||
    );
 | 
			
		||||
    const user = new User(redis, bitcoinclient, lightning);
 | 
			
		||||
    user._userid = await user.getUseridByPaymentHash(LightningInvoiceSettledNotification.hash);
 | 
			
		||||
    await user.clearBalanceCache();
 | 
			
		||||
@ -469,7 +475,7 @@ router.get('/checkrouteinvoice', async function (req, res) {
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.get('/queryroutes/:source/:dest/:amt', async function(req, res) {
 | 
			
		||||
router.get('/queryroutes/:source/:dest/:amt', async function (req, res) {
 | 
			
		||||
  logger.log('/queryroutes', [req.id]);
 | 
			
		||||
 | 
			
		||||
  let request = {
 | 
			
		||||
@ -477,7 +483,7 @@ router.get('/queryroutes/:source/:dest/:amt', async function(req, res) {
 | 
			
		||||
    amt: req.params.amt,
 | 
			
		||||
    source_pub_key: req.params.source,
 | 
			
		||||
  };
 | 
			
		||||
  lightning.queryRoutes(request, function(err, response) {
 | 
			
		||||
  lightning.queryRoutes(request, function (err, response) {
 | 
			
		||||
    console.log(JSON.stringify(response, null, 2));
 | 
			
		||||
    res.send(response);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,10 @@
 | 
			
		||||
let express = require('express');
 | 
			
		||||
let router = express.Router();
 | 
			
		||||
let fs = require('fs');
 | 
			
		||||
let mustache = require('mustache');
 | 
			
		||||
let lightning = require('../lightning');
 | 
			
		||||
let logger = require('../utils/logger');
 | 
			
		||||
var qr = require('qr-image');
 | 
			
		||||
const express = require('express');
 | 
			
		||||
const router = express.Router();
 | 
			
		||||
const fs = require('fs');
 | 
			
		||||
const mustache = require('mustache');
 | 
			
		||||
const lightning = require('../lightning');
 | 
			
		||||
const logger = require('../utils/logger');
 | 
			
		||||
const qr = require('qr-image');
 | 
			
		||||
 | 
			
		||||
let lightningGetInfo = {};
 | 
			
		||||
let lightningListChannels = {};
 | 
			
		||||
@ -92,7 +92,11 @@ router.get('/', function (req, res) {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.get('/qr', function (req, res) {
 | 
			
		||||
  const url = "bluewallet:setlndhuburl?url=" + encodeURIComponent(req.protocol + '://' + req.headers.host);
 | 
			
		||||
  let host = req.headers.host;
 | 
			
		||||
  if (process.env.TOR_URL) {
 | 
			
		||||
    host = process.env.TOR_URL;
 | 
			
		||||
  }
 | 
			
		||||
  const url = 'bluewallet:setlndhuburl?url=' + encodeURIComponent(req.protocol + '://' + host);
 | 
			
		||||
  var code = qr.image(url, { type: 'png' });
 | 
			
		||||
  res.setHeader('Content-type', 'image/png');
 | 
			
		||||
  code.pipe(res);
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ const loaderOptions = {
 | 
			
		||||
  longs: String,
 | 
			
		||||
  enums: String,
 | 
			
		||||
  defaults: true,
 | 
			
		||||
  oneofs: true
 | 
			
		||||
  oneofs: true,
 | 
			
		||||
};
 | 
			
		||||
const packageDefinition = protoLoader.loadSync('rpc.proto', loaderOptions);
 | 
			
		||||
var lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8904
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8904
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										29
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								package.json
									
									
									
									
									
								
							@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "LndHub",
 | 
			
		||||
  "name": "lndhub",
 | 
			
		||||
  "version": "1.2.2",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
@ -12,24 +12,25 @@
 | 
			
		||||
  "author": "Igor Korsakov <overtorment@gmail.com>",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@babel/cli": "^7.12.10",
 | 
			
		||||
    "@babel/core": "^7.12.10",
 | 
			
		||||
    "@babel/eslint-parser": "^7.12.1",
 | 
			
		||||
    "@babel/node": "^7.12.10",
 | 
			
		||||
    "@babel/preset-env": "^7.12.11",
 | 
			
		||||
    "@babel/register": "^7.12.10",
 | 
			
		||||
    "@grpc/grpc-js": "^1.2.2",
 | 
			
		||||
    "@babel/cli": "^7.13.0",
 | 
			
		||||
    "@babel/core": "^7.13.1",
 | 
			
		||||
    "@babel/eslint-parser": "^7.13.4",
 | 
			
		||||
    "@babel/node": "^7.13.0",
 | 
			
		||||
    "@babel/preset-env": "^7.13.5",
 | 
			
		||||
    "@babel/register": "^7.13.0",
 | 
			
		||||
    "@grpc/grpc-js": "^1.2.8",
 | 
			
		||||
    "@grpc/proto-loader": "^0.5.6",
 | 
			
		||||
    "bignumber.js": "^9.0.1",
 | 
			
		||||
    "bitcoinjs-lib": "^5.2.0",
 | 
			
		||||
    "bolt11": "^1.2.7",
 | 
			
		||||
    "core-js": "^3.8.1",
 | 
			
		||||
    "eslint": "^7.19.0",
 | 
			
		||||
    "eslint-config-prettier": "^7.1.0",
 | 
			
		||||
    "eslint-plugin-prettier": "^3.3.0",
 | 
			
		||||
    "core-js": "^3.9.0",
 | 
			
		||||
    "eslint": "^7.20.0",
 | 
			
		||||
    "eslint-config-prettier": "^8.0.0",
 | 
			
		||||
    "eslint-plugin-prettier": "^3.3.1",
 | 
			
		||||
    "express": "^4.17.1",
 | 
			
		||||
    "express-rate-limit": "^5.2.3",
 | 
			
		||||
    "express-rate-limit": "^5.2.6",
 | 
			
		||||
    "frisbee": "^3.1.4",
 | 
			
		||||
    "ioredis": "^4.19.4",
 | 
			
		||||
    "ioredis": "^4.22.0",
 | 
			
		||||
    "jayson": "^3.4.4",
 | 
			
		||||
    "morgan": "^1.10.0",
 | 
			
		||||
    "mustache": "^4.1.0",
 | 
			
		||||
 | 
			
		||||
@ -13,45 +13,45 @@ const important_channels = {
 | 
			
		||||
    name: 'coingate.com',
 | 
			
		||||
    uri: '0242a4ae0c5bef18048fbecf995094b74bfb0f7391418d71ed394784373f41e4f3@3.124.63.44:9735',
 | 
			
		||||
  },
 | 
			
		||||
//  '0254ff808f53b2f8c45e74b70430f336c6c76ba2f4af289f48d6086ae6e60462d3': {
 | 
			
		||||
//    name: 'bitrefill thor',
 | 
			
		||||
//    uri: '0254ff808f53b2f8c45e74b70430f336c6c76ba2f4af289f48d6086ae6e60462d3@52.30.63.2:9735',
 | 
			
		||||
//    wumbo: 1,
 | 
			
		||||
//  },
 | 
			
		||||
  //  '0254ff808f53b2f8c45e74b70430f336c6c76ba2f4af289f48d6086ae6e60462d3': {
 | 
			
		||||
  //    name: 'bitrefill thor',
 | 
			
		||||
  //    uri: '0254ff808f53b2f8c45e74b70430f336c6c76ba2f4af289f48d6086ae6e60462d3@52.30.63.2:9735',
 | 
			
		||||
  //    wumbo: 1,
 | 
			
		||||
  //  },
 | 
			
		||||
  '030c3f19d742ca294a55c00376b3b355c3c90d61c6b6b39554dbc7ac19b141c14f': {
 | 
			
		||||
    name: 'bitrefill 2',
 | 
			
		||||
    uri: '030c3f19d742ca294a55c00376b3b355c3c90d61c6b6b39554dbc7ac19b141c14f@52.50.244.44:9735',
 | 
			
		||||
    wumbo: 1,
 | 
			
		||||
  },
 | 
			
		||||
//  '025f1456582e70c4c06b61d5c8ed3ce229e6d0db538be337a2dc6d163b0ebc05a5': {
 | 
			
		||||
//    name: 'paywithmoon.com',
 | 
			
		||||
//    uri: '025f1456582e70c4c06b61d5c8ed3ce229e6d0db538be337a2dc6d163b0ebc05a5@52.86.210.65:9735',
 | 
			
		||||
//  },
 | 
			
		||||
//  '0279c22ed7a068d10dc1a38ae66d2d6461e269226c60258c021b1ddcdfe4b00bc4': {
 | 
			
		||||
//    name: 'ln1.satoshilabs.com',
 | 
			
		||||
//    uri: '0279c22ed7a068d10dc1a38ae66d2d6461e269226c60258c021b1ddcdfe4b00bc4@157.230.28.160:9735',
 | 
			
		||||
//  },
 | 
			
		||||
//   '02004c625d622245606a1ea2c1c69cfb4516b703b47945a3647713c05fe4aaeb1c': {
 | 
			
		||||
//     name: 'LivingRoomOfSatoshi',
 | 
			
		||||
//     uri: '02004c625d622245606a1ea2c1c69cfb4516b703b47945a3647713c05fe4aaeb1c@172.81.178.151:9735',
 | 
			
		||||
//   },
 | 
			
		||||
  //  '025f1456582e70c4c06b61d5c8ed3ce229e6d0db538be337a2dc6d163b0ebc05a5': {
 | 
			
		||||
  //    name: 'paywithmoon.com',
 | 
			
		||||
  //    uri: '025f1456582e70c4c06b61d5c8ed3ce229e6d0db538be337a2dc6d163b0ebc05a5@52.86.210.65:9735',
 | 
			
		||||
  //  },
 | 
			
		||||
  //  '0279c22ed7a068d10dc1a38ae66d2d6461e269226c60258c021b1ddcdfe4b00bc4': {
 | 
			
		||||
  //    name: 'ln1.satoshilabs.com',
 | 
			
		||||
  //    uri: '0279c22ed7a068d10dc1a38ae66d2d6461e269226c60258c021b1ddcdfe4b00bc4@157.230.28.160:9735',
 | 
			
		||||
  //  },
 | 
			
		||||
  //   '02004c625d622245606a1ea2c1c69cfb4516b703b47945a3647713c05fe4aaeb1c': {
 | 
			
		||||
  //     name: 'LivingRoomOfSatoshi',
 | 
			
		||||
  //     uri: '02004c625d622245606a1ea2c1c69cfb4516b703b47945a3647713c05fe4aaeb1c@172.81.178.151:9735',
 | 
			
		||||
  //   },
 | 
			
		||||
  '02816caed43171d3c9854e3b0ab2cf0c42be086ff1bd4005acc2a5f7db70d83774': {
 | 
			
		||||
    name: 'ln.pizza aka fold',
 | 
			
		||||
    uri: '02816caed43171d3c9854e3b0ab2cf0c42be086ff1bd4005acc2a5f7db70d83774@35.238.153.25:9735',
 | 
			
		||||
    wumbo: 1,
 | 
			
		||||
  },
 | 
			
		||||
//  '0331f80652fb840239df8dc99205792bba2e559a05469915804c08420230e23c7c': {
 | 
			
		||||
//    name: 'LightningPowerUsers.com',
 | 
			
		||||
//    uri: '0331f80652fb840239df8dc99205792bba2e559a05469915804c08420230e23c7c@34.200.181.109:9735',
 | 
			
		||||
//  },
 | 
			
		||||
//  '033d8656219478701227199cbd6f670335c8d408a92ae88b962c49d4dc0e83e025': {
 | 
			
		||||
//    name: 'bfx-lnd0',
 | 
			
		||||
//    uri: '033d8656219478701227199cbd6f670335c8d408a92ae88b962c49d4dc0e83e025@34.65.85.39:9735',
 | 
			
		||||
//  },
 | 
			
		||||
//  '037f990e61acee8a7697966afd29dd88f3b1f8a7b14d625c4f8742bd952003a590': {
 | 
			
		||||
//    name: 'fixedfloat.com',
 | 
			
		||||
//    uri: '037f990e61acee8a7697966afd29dd88f3b1f8a7b14d625c4f8742bd952003a590@185.5.53.91:9735',
 | 
			
		||||
//  },
 | 
			
		||||
  //  '0331f80652fb840239df8dc99205792bba2e559a05469915804c08420230e23c7c': {
 | 
			
		||||
  //    name: 'LightningPowerUsers.com',
 | 
			
		||||
  //    uri: '0331f80652fb840239df8dc99205792bba2e559a05469915804c08420230e23c7c@34.200.181.109:9735',
 | 
			
		||||
  //  },
 | 
			
		||||
  //  '033d8656219478701227199cbd6f670335c8d408a92ae88b962c49d4dc0e83e025': {
 | 
			
		||||
  //    name: 'bfx-lnd0',
 | 
			
		||||
  //    uri: '033d8656219478701227199cbd6f670335c8d408a92ae88b962c49d4dc0e83e025@34.65.85.39:9735',
 | 
			
		||||
  //  },
 | 
			
		||||
  //  '037f990e61acee8a7697966afd29dd88f3b1f8a7b14d625c4f8742bd952003a590': {
 | 
			
		||||
  //    name: 'fixedfloat.com',
 | 
			
		||||
  //    uri: '037f990e61acee8a7697966afd29dd88f3b1f8a7b14d625c4f8742bd952003a590@185.5.53.91:9735',
 | 
			
		||||
  //  },
 | 
			
		||||
  '03c2abfa93eacec04721c019644584424aab2ba4dff3ac9bdab4e9c97007491dda': {
 | 
			
		||||
    name: 'tippin.me',
 | 
			
		||||
    uri: '03c2abfa93eacec04721c019644584424aab2ba4dff3ac9bdab4e9c97007491dda@157.245.68.47:9735',
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user