Channel status
This commit is contained in:
		
							parent
							
								
									795bb6a7a6
								
							
						
					
					
						commit
						65c731e1ad
					
				@ -2,7 +2,9 @@
 | 
				
			|||||||
  <div class="mb-2">
 | 
					  <div class="mb-2">
 | 
				
			||||||
    <h1 i18n="shared.address" class="mb-0">Channel <a [routerLink]="['/lightning/channel' | relativeUrl, channel.id]">{{ channel.id }}</a> <app-clipboard [text]="channel.id"></app-clipboard></h1>
 | 
					    <h1 i18n="shared.address" class="mb-0">Channel <a [routerLink]="['/lightning/channel' | relativeUrl, channel.id]">{{ channel.id }}</a> <app-clipboard [text]="channel.id"></app-clipboard></h1>
 | 
				
			||||||
    <div class="badges">
 | 
					    <div class="badges">
 | 
				
			||||||
      <span class="badge rounded-pill badge-success">Open</span>
 | 
					      <span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
 | 
				
			||||||
 | 
					      <span class="badge rounded-pill badge-success" *ngIf="channel.status === 1">Active</span>
 | 
				
			||||||
 | 
					      <span class="badge rounded-pill badge-danger" *ngIf="channel.status === 2">Closed</span>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -46,98 +48,95 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <br>
 | 
					    <br>
 | 
				
			||||||
    <h2>Peers</h2>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="box">
 | 
					    <div class="row row-cols-1 row-cols-md-2">
 | 
				
			||||||
 | 
					      <div class="col">
 | 
				
			||||||
      <div class="row">
 | 
					        <div class="mb-2">
 | 
				
			||||||
        <div class="col-md">
 | 
					          <h2 class="mb-0">{{ channel.alias_left }}</h2>
 | 
				
			||||||
          <table class="table table-borderless table-striped">
 | 
					          <a [routerLink]="['/lightning/node' | relativeUrl, channel.node1_public_key]" >
 | 
				
			||||||
            <tbody>
 | 
					            {{ channel.node1_public_key | shortenString : 18 }}
 | 
				
			||||||
              <tr>
 | 
					          </a>
 | 
				
			||||||
                <td i18n="address.total-sent">Node</td>
 | 
					          <app-clipboard [text]="channel.node1_public_key"></app-clipboard>
 | 
				
			||||||
                <td>
 | 
					 | 
				
			||||||
                  {{ channel.alias_left }}
 | 
					 | 
				
			||||||
                  <br>
 | 
					 | 
				
			||||||
                  <a [routerLink]="['/lightning/node' | relativeUrl, channel.node1_public_key]" >
 | 
					 | 
				
			||||||
                    {{ channel.node1_public_key | shortenString : 18 }}
 | 
					 | 
				
			||||||
                  </a>
 | 
					 | 
				
			||||||
                  <app-clipboard [text]="channel.node1_public_key"></app-clipboard>
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
              </tr>
 | 
					 | 
				
			||||||
              <tr>
 | 
					 | 
				
			||||||
                <td i18n="address.total-sent">Fee rate</td>
 | 
					 | 
				
			||||||
                <td>
 | 
					 | 
				
			||||||
                  {{ channel.node1_fee_rate / 10000 | number }}%
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
              </tr>
 | 
					 | 
				
			||||||
              <tr>
 | 
					 | 
				
			||||||
                <td i18n="address.total-sent">Base fee</td>
 | 
					 | 
				
			||||||
                <td>
 | 
					 | 
				
			||||||
                  <app-sats [satoshis]="channel.node1_base_fee_mtokens / 1000"></app-sats>
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
              </tr>
 | 
					 | 
				
			||||||
              <tr>
 | 
					 | 
				
			||||||
                <td i18n="address.total-sent">Min HTLC</td>
 | 
					 | 
				
			||||||
                <td>
 | 
					 | 
				
			||||||
                  <app-sats [satoshis]="channel.node1_min_htlc_mtokens / 1000"></app-sats>
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
              </tr>
 | 
					 | 
				
			||||||
              <tr>
 | 
					 | 
				
			||||||
                <td i18n="address.total-sent">Max HTLC</td>
 | 
					 | 
				
			||||||
                <td>
 | 
					 | 
				
			||||||
                  <app-sats [satoshis]="channel.node1_max_htlc_mtokens / 1000"></app-sats>
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
              </tr>
 | 
					 | 
				
			||||||
            </tbody>
 | 
					 | 
				
			||||||
          </table>
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="w-100 d-block d-md-none"></div>
 | 
					        <div class="box">
 | 
				
			||||||
        <div class="col-md">
 | 
					
 | 
				
			||||||
          <table class="table table-borderless table-striped">
 | 
					          <div class="row">
 | 
				
			||||||
            <tbody>
 | 
					            <div class="col-md">
 | 
				
			||||||
              <tr>
 | 
					              <table class="table table-borderless table-striped">
 | 
				
			||||||
                <td i18n="address.total-sent">Node</td>
 | 
					                <tbody>
 | 
				
			||||||
                <td>
 | 
					                  <tr>
 | 
				
			||||||
                  {{ channel.alias_right }}
 | 
					                    <td i18n="address.total-sent">Fee rate</td>
 | 
				
			||||||
                  <br>
 | 
					                    <td>
 | 
				
			||||||
                  <a [routerLink]="['/lightning/node' | relativeUrl, channel.node2_public_key]" >
 | 
					                      {{ channel.node1_fee_rate / 10000 | number }}%
 | 
				
			||||||
                    {{ channel.node2_public_key | shortenString : 18 }}
 | 
					                    </td>
 | 
				
			||||||
                  </a>
 | 
					                  </tr>
 | 
				
			||||||
                  <app-clipboard [text]="channel.node1_public_key"></app-clipboard>
 | 
					                  <tr>
 | 
				
			||||||
                </td>
 | 
					                    <td i18n="address.total-sent">Base fee</td>
 | 
				
			||||||
              </tr>
 | 
					                    <td>
 | 
				
			||||||
              <tr>
 | 
					                      <app-sats [satoshis]="channel.node1_base_fee_mtokens / 1000"></app-sats>
 | 
				
			||||||
                <td i18n="address.total-sent">Fee rate</td>
 | 
					                    </td>
 | 
				
			||||||
                <td>
 | 
					                  </tr>
 | 
				
			||||||
                  {{ channel.node2_fee_rate / 10000 | number }}%
 | 
					                  <tr>
 | 
				
			||||||
                </td>
 | 
					                    <td i18n="address.total-sent">Min HTLC</td>
 | 
				
			||||||
              </tr>
 | 
					                    <td>
 | 
				
			||||||
              <tr>
 | 
					                      <app-sats [satoshis]="channel.node1_min_htlc_mtokens / 1000"></app-sats>
 | 
				
			||||||
                <td i18n="address.total-sent">Base fee</td>
 | 
					                    </td>
 | 
				
			||||||
                <td>
 | 
					                  </tr>
 | 
				
			||||||
                  <app-sats [satoshis]="channel.node2_base_fee_mtokens / 1000"></app-sats>
 | 
					                  <tr>
 | 
				
			||||||
                </td>
 | 
					                    <td i18n="address.total-sent">Max HTLC</td>
 | 
				
			||||||
              </tr>
 | 
					                    <td>
 | 
				
			||||||
              <tr>
 | 
					                      <app-sats [satoshis]="channel.node1_max_htlc_mtokens / 1000"></app-sats>
 | 
				
			||||||
                <td i18n="address.total-sent">Min HTLC</td>
 | 
					                    </td>
 | 
				
			||||||
                <td>
 | 
					                  </tr>
 | 
				
			||||||
                  <app-sats [satoshis]="channel.node2_min_htlc_mtokens / 1000"></app-sats>
 | 
					                </tbody>
 | 
				
			||||||
                </td>
 | 
					              </table>
 | 
				
			||||||
              </tr>
 | 
					            </div>
 | 
				
			||||||
              <tr>
 | 
					          </div>
 | 
				
			||||||
                <td i18n="address.total-sent">Max HTLC</td>
 | 
					 | 
				
			||||||
                <td>
 | 
					 | 
				
			||||||
                  <app-sats [satoshis]="channel.node2_max_htlc_mtokens / 1000"></app-sats>
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
              </tr>
 | 
					 | 
				
			||||||
            </tbody>
 | 
					 | 
				
			||||||
          </table>
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="col">
 | 
				
			||||||
 | 
					        <div class="mb-2">
 | 
				
			||||||
 | 
					          <h2 class="mb-0">{{ channel.alias_right }}</h2>
 | 
				
			||||||
 | 
					          <a [routerLink]="['/lightning/node' | relativeUrl, channel.node2_public_key]" >
 | 
				
			||||||
 | 
					            {{ channel.node2_public_key | shortenString : 18 }}
 | 
				
			||||||
 | 
					          </a>
 | 
				
			||||||
 | 
					          <app-clipboard [text]="channel.node1_public_key"></app-clipboard>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="box">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div class="col-md">
 | 
				
			||||||
 | 
					            <table class="table table-borderless table-striped">
 | 
				
			||||||
 | 
					              <tbody>
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                  <td i18n="address.total-sent">Fee rate</td>
 | 
				
			||||||
 | 
					                  <td>
 | 
				
			||||||
 | 
					                    {{ channel.node2_fee_rate / 10000 | number }}%
 | 
				
			||||||
 | 
					                  </td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                  <td i18n="address.total-sent">Base fee</td>
 | 
				
			||||||
 | 
					                  <td>
 | 
				
			||||||
 | 
					                    <app-sats [satoshis]="channel.node2_base_fee_mtokens / 1000"></app-sats>
 | 
				
			||||||
 | 
					                  </td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                  <td i18n="address.total-sent">Min HTLC</td>
 | 
				
			||||||
 | 
					                  <td>
 | 
				
			||||||
 | 
					                    <app-sats [satoshis]="channel.node2_min_htlc_mtokens / 1000"></app-sats>
 | 
				
			||||||
 | 
					                  </td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                  <td i18n="address.total-sent">Max HTLC</td>
 | 
				
			||||||
 | 
					                  <td>
 | 
				
			||||||
 | 
					                    <app-sats [satoshis]="channel.node2_max_htlc_mtokens / 1000"></app-sats>
 | 
				
			||||||
 | 
					                  </td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					              </tbody>
 | 
				
			||||||
 | 
					            </table>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,3 @@
 | 
				
			|||||||
.badges {
 | 
					.badges {
 | 
				
			||||||
  font-size: 18px;
 | 
					  font-size: 20px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -3,6 +3,7 @@
 | 
				
			|||||||
  <table class="table table-borderless">
 | 
					  <table class="table table-borderless">
 | 
				
			||||||
    <thead>
 | 
					    <thead>
 | 
				
			||||||
      <th class="alias text-left" i18n="nodes.alias">Node Alias</th>
 | 
					      <th class="alias text-left" i18n="nodes.alias">Node Alias</th>
 | 
				
			||||||
 | 
					      <th class="alias text-left" i18n="nodes.alias">Status</th>
 | 
				
			||||||
      <th class="channels text-right" i18n="channels.rate">Fee Rate</th>
 | 
					      <th class="channels text-right" i18n="channels.rate">Fee Rate</th>
 | 
				
			||||||
      <th class="capacity text-right" i18n="channels.id">Channel ID</th>
 | 
					      <th class="capacity text-right" i18n="channels.id">Channel ID</th>
 | 
				
			||||||
      <th class="capacity text-right" i18n="nodes.capacity">Capacity</th>
 | 
					      <th class="capacity text-right" i18n="nodes.capacity">Capacity</th>
 | 
				
			||||||
@ -14,6 +15,11 @@
 | 
				
			|||||||
          <td class="alias text-left">
 | 
					          <td class="alias text-left">
 | 
				
			||||||
            <a [routerLink]="['/lightning/node' | relativeUrl, channel.node1_public_key]">{{ channel.alias_left }}</a>
 | 
					            <a [routerLink]="['/lightning/node' | relativeUrl, channel.node1_public_key]">{{ channel.alias_left }}</a>
 | 
				
			||||||
          </td>
 | 
					          </td>
 | 
				
			||||||
 | 
					          <td>
 | 
				
			||||||
 | 
					            <span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
 | 
				
			||||||
 | 
					            <span class="badge rounded-pill badge-success" *ngIf="channel.status === 1">Active</span>
 | 
				
			||||||
 | 
					            <span class="badge rounded-pill badge-danger" *ngIf="channel.status === 2">Closed</span>
 | 
				
			||||||
 | 
					          </td>
 | 
				
			||||||
          <td class="capacity text-right">
 | 
					          <td class="capacity text-right">
 | 
				
			||||||
           {{ channel.node1_fee_rate / 10000 | number }}%
 | 
					           {{ channel.node1_fee_rate / 10000 | number }}%
 | 
				
			||||||
          </td>
 | 
					          </td>
 | 
				
			||||||
@ -22,6 +28,11 @@
 | 
				
			|||||||
          <td class="alias text-left" *ngIf="channel.node1_public_key === publicKey">
 | 
					          <td class="alias text-left" *ngIf="channel.node1_public_key === publicKey">
 | 
				
			||||||
            <a [routerLink]="['/lightning/node' | relativeUrl, channel.node2_public_key]">{{ channel.alias_right }}</a>
 | 
					            <a [routerLink]="['/lightning/node' | relativeUrl, channel.node2_public_key]">{{ channel.alias_right }}</a>
 | 
				
			||||||
          </td>
 | 
					          </td>
 | 
				
			||||||
 | 
					          <td>
 | 
				
			||||||
 | 
					            <span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
 | 
				
			||||||
 | 
					            <span class="badge rounded-pill badge-success" *ngIf="channel.status === 1">Active</span>
 | 
				
			||||||
 | 
					            <span class="badge rounded-pill badge-danger" *ngIf="channel.status === 2">Closed</span>
 | 
				
			||||||
 | 
					          </td>
 | 
				
			||||||
          <td class="capacity text-right">
 | 
					          <td class="capacity text-right">
 | 
				
			||||||
            {{ channel.node2_fee_rate / 10000 | number }}%
 | 
					            {{ channel.node2_fee_rate / 10000 | number }}%
 | 
				
			||||||
           </td>
 | 
					           </td>
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,12 @@
 | 
				
			|||||||
    "TSL_CERT_PATH": "",
 | 
					    "TSL_CERT_PATH": "",
 | 
				
			||||||
    "MACAROON_PATH": ""
 | 
					    "MACAROON_PATH": ""
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  "CORE_RPC": {
 | 
				
			||||||
 | 
					    "HOST": "127.0.0.1",
 | 
				
			||||||
 | 
					    "PORT": 8332,
 | 
				
			||||||
 | 
					    "USERNAME": "mempool",
 | 
				
			||||||
 | 
					    "PASSWORD": "mempool"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  "DATABASE": {
 | 
					  "DATABASE": {
 | 
				
			||||||
    "HOST": "127.0.0.1",
 | 
					    "HOST": "127.0.0.1",
 | 
				
			||||||
    "PORT": 3306,
 | 
					    "PORT": 3306,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								lightning-backend/src/api/bitcoin/bitcoin-client.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								lightning-backend/src/api/bitcoin/bitcoin-client.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import config from '../../config';
 | 
				
			||||||
 | 
					const bitcoin = require('./rpc-api/index');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const nodeRpcCredentials: any = {
 | 
				
			||||||
 | 
					  host: config.CORE_RPC.HOST,
 | 
				
			||||||
 | 
					  port: config.CORE_RPC.PORT,
 | 
				
			||||||
 | 
					  user: config.CORE_RPC.USERNAME,
 | 
				
			||||||
 | 
					  pass: config.CORE_RPC.PASSWORD,
 | 
				
			||||||
 | 
					  timeout: 60000,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default new bitcoin.Client(nodeRpcCredentials);
 | 
				
			||||||
							
								
								
									
										92
									
								
								lightning-backend/src/api/bitcoin/rpc-api/commands.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								lightning-backend/src/api/bitcoin/rpc-api/commands.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  addMultiSigAddress: 'addmultisigaddress',
 | 
				
			||||||
 | 
					  addNode: 'addnode', // bitcoind v0.8.0+
 | 
				
			||||||
 | 
					  backupWallet: 'backupwallet',
 | 
				
			||||||
 | 
					  createMultiSig: 'createmultisig',
 | 
				
			||||||
 | 
					  createRawTransaction: 'createrawtransaction', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  decodeRawTransaction: 'decoderawtransaction', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  decodeScript: 'decodescript',
 | 
				
			||||||
 | 
					  dumpPrivKey: 'dumpprivkey',
 | 
				
			||||||
 | 
					  dumpWallet: 'dumpwallet', // bitcoind v0.9.0+
 | 
				
			||||||
 | 
					  encryptWallet: 'encryptwallet',
 | 
				
			||||||
 | 
					  estimateFee: 'estimatefee', // bitcoind v0.10.0x
 | 
				
			||||||
 | 
					  estimatePriority: 'estimatepriority', // bitcoind v0.10.0+
 | 
				
			||||||
 | 
					  generate: 'generate', // bitcoind v0.11.0+
 | 
				
			||||||
 | 
					  getAccount: 'getaccount',
 | 
				
			||||||
 | 
					  getAccountAddress: 'getaccountaddress',
 | 
				
			||||||
 | 
					  getAddedNodeInfo: 'getaddednodeinfo', // bitcoind v0.8.0+
 | 
				
			||||||
 | 
					  getAddressesByAccount: 'getaddressesbyaccount',
 | 
				
			||||||
 | 
					  getBalance: 'getbalance',
 | 
				
			||||||
 | 
					  getBestBlockHash: 'getbestblockhash', // bitcoind v0.9.0+
 | 
				
			||||||
 | 
					  getBlock: 'getblock',
 | 
				
			||||||
 | 
					  getBlockStats: 'getblockstats',
 | 
				
			||||||
 | 
					  getBlockFilter: 'getblockfilter',
 | 
				
			||||||
 | 
					  getBlockchainInfo: 'getblockchaininfo', // bitcoind v0.9.2+
 | 
				
			||||||
 | 
					  getBlockCount: 'getblockcount',
 | 
				
			||||||
 | 
					  getBlockHash: 'getblockhash',
 | 
				
			||||||
 | 
					  getBlockHeader: 'getblockheader',
 | 
				
			||||||
 | 
					  getBlockTemplate: 'getblocktemplate', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  getChainTips: 'getchaintips', // bitcoind v0.10.0+
 | 
				
			||||||
 | 
					  getChainTxStats: 'getchaintxstats',
 | 
				
			||||||
 | 
					  getConnectionCount: 'getconnectioncount',
 | 
				
			||||||
 | 
					  getDifficulty: 'getdifficulty',
 | 
				
			||||||
 | 
					  getGenerate: 'getgenerate',
 | 
				
			||||||
 | 
					  getInfo: 'getinfo',
 | 
				
			||||||
 | 
					  getMempoolAncestors: 'getmempoolancestors',
 | 
				
			||||||
 | 
					  getMempoolDescendants: 'getmempooldescendants',
 | 
				
			||||||
 | 
					  getMempoolEntry: 'getmempoolentry',
 | 
				
			||||||
 | 
					  getMempoolInfo: 'getmempoolinfo', // bitcoind v0.10+
 | 
				
			||||||
 | 
					  getMiningInfo: 'getmininginfo',
 | 
				
			||||||
 | 
					  getNetTotals: 'getnettotals',
 | 
				
			||||||
 | 
					  getNetworkInfo: 'getnetworkinfo', // bitcoind v0.9.2+
 | 
				
			||||||
 | 
					  getNetworkHashPs: 'getnetworkhashps', // bitcoind v0.9.0+
 | 
				
			||||||
 | 
					  getNewAddress: 'getnewaddress',
 | 
				
			||||||
 | 
					  getPeerInfo: 'getpeerinfo', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  getRawChangeAddress: 'getrawchangeaddress', // bitcoin v0.9+
 | 
				
			||||||
 | 
					  getRawMemPool: 'getrawmempool', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  getRawTransaction: 'getrawtransaction', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  getReceivedByAccount: 'getreceivedbyaccount',
 | 
				
			||||||
 | 
					  getReceivedByAddress: 'getreceivedbyaddress',
 | 
				
			||||||
 | 
					  getTransaction: 'gettransaction',
 | 
				
			||||||
 | 
					  getTxOut: 'gettxout', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  getTxOutProof: 'gettxoutproof', // bitcoind v0.11.0+
 | 
				
			||||||
 | 
					  getTxOutSetInfo: 'gettxoutsetinfo', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  getUnconfirmedBalance: 'getunconfirmedbalance', // bitcoind v0.9.0+
 | 
				
			||||||
 | 
					  getWalletInfo: 'getwalletinfo', // bitcoind v0.9.2+
 | 
				
			||||||
 | 
					  help: 'help',
 | 
				
			||||||
 | 
					  importAddress: 'importaddress', // bitcoind v0.10.0+
 | 
				
			||||||
 | 
					  importPrivKey: 'importprivkey',
 | 
				
			||||||
 | 
					  importWallet: 'importwallet', // bitcoind v0.9.0+
 | 
				
			||||||
 | 
					  keypoolRefill: 'keypoolrefill',
 | 
				
			||||||
 | 
					  keyPoolRefill: 'keypoolrefill',
 | 
				
			||||||
 | 
					  listAccounts: 'listaccounts',
 | 
				
			||||||
 | 
					  listAddressGroupings: 'listaddressgroupings', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  listLockUnspent: 'listlockunspent', // bitcoind v0.8.0+
 | 
				
			||||||
 | 
					  listReceivedByAccount: 'listreceivedbyaccount',
 | 
				
			||||||
 | 
					  listReceivedByAddress: 'listreceivedbyaddress',
 | 
				
			||||||
 | 
					  listSinceBlock: 'listsinceblock',
 | 
				
			||||||
 | 
					  listTransactions: 'listtransactions',
 | 
				
			||||||
 | 
					  listUnspent: 'listunspent', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  lockUnspent: 'lockunspent', // bitcoind v0.8.0+
 | 
				
			||||||
 | 
					  move: 'move',
 | 
				
			||||||
 | 
					  ping: 'ping', // bitcoind v0.9.0+
 | 
				
			||||||
 | 
					  prioritiseTransaction: 'prioritisetransaction', // bitcoind v0.10.0+
 | 
				
			||||||
 | 
					  sendFrom: 'sendfrom',
 | 
				
			||||||
 | 
					  sendMany: 'sendmany',
 | 
				
			||||||
 | 
					  sendRawTransaction: 'sendrawtransaction', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  sendToAddress: 'sendtoaddress',
 | 
				
			||||||
 | 
					  setAccount: 'setaccount',
 | 
				
			||||||
 | 
					  setGenerate: 'setgenerate',
 | 
				
			||||||
 | 
					  setTxFee: 'settxfee',
 | 
				
			||||||
 | 
					  signMessage: 'signmessage',
 | 
				
			||||||
 | 
					  signRawTransaction: 'signrawtransaction', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  stop: 'stop',
 | 
				
			||||||
 | 
					  submitBlock: 'submitblock', // bitcoind v0.7.0+
 | 
				
			||||||
 | 
					  validateAddress: 'validateaddress',
 | 
				
			||||||
 | 
					  verifyChain: 'verifychain', // bitcoind v0.9.0+
 | 
				
			||||||
 | 
					  verifyMessage: 'verifymessage',
 | 
				
			||||||
 | 
					  verifyTxOutProof: 'verifytxoutproof', // bitcoind v0.11.0+
 | 
				
			||||||
 | 
					  walletLock: 'walletlock',
 | 
				
			||||||
 | 
					  walletPassphrase: 'walletpassphrase',
 | 
				
			||||||
 | 
					  walletPassphraseChange: 'walletpassphrasechange'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										61
									
								
								lightning-backend/src/api/bitcoin/rpc-api/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								lightning-backend/src/api/bitcoin/rpc-api/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					var commands = require('./commands')
 | 
				
			||||||
 | 
					var rpc = require('./jsonrpc')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					// JsonRPC
 | 
				
			||||||
 | 
					// ===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					function Client (opts) {
 | 
				
			||||||
 | 
					  // @ts-ignore
 | 
				
			||||||
 | 
					  this.rpc = new rpc.JsonRPC(opts)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					// cmd
 | 
				
			||||||
 | 
					// ===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					Client.prototype.cmd = function () {
 | 
				
			||||||
 | 
					  var args = [].slice.call(arguments)
 | 
				
			||||||
 | 
					  var cmd = args.shift()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  callRpc(cmd, args, this.rpc)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					// callRpc
 | 
				
			||||||
 | 
					// ===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					function callRpc (cmd, args, rpc) {
 | 
				
			||||||
 | 
					  var fn = args[args.length - 1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // If the last argument is a callback, pop it from the args list
 | 
				
			||||||
 | 
					  if (typeof fn === 'function') {
 | 
				
			||||||
 | 
					    args.pop()
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    fn = function () {}
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return rpc.call(cmd, args, function () {
 | 
				
			||||||
 | 
					    var args = [].slice.call(arguments)
 | 
				
			||||||
 | 
					      // @ts-ignore
 | 
				
			||||||
 | 
					    args.unshift(null)
 | 
				
			||||||
 | 
					      // @ts-ignore
 | 
				
			||||||
 | 
					    fn.apply(this, args)
 | 
				
			||||||
 | 
					  }, function (err) {
 | 
				
			||||||
 | 
					    fn(err)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					// Initialize wrappers
 | 
				
			||||||
 | 
					// ===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					(function () {
 | 
				
			||||||
 | 
					  for (var protoFn in commands) {
 | 
				
			||||||
 | 
					    (function (protoFn) {
 | 
				
			||||||
 | 
					      Client.prototype[protoFn] = function () {
 | 
				
			||||||
 | 
					        var args = [].slice.call(arguments)
 | 
				
			||||||
 | 
					        return callRpc(commands[protoFn], args, this.rpc)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })(protoFn)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					})()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Export!
 | 
				
			||||||
 | 
					module.exports.Client = Client;
 | 
				
			||||||
							
								
								
									
										162
									
								
								lightning-backend/src/api/bitcoin/rpc-api/jsonrpc.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								lightning-backend/src/api/bitcoin/rpc-api/jsonrpc.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,162 @@
 | 
				
			|||||||
 | 
					var http = require('http')
 | 
				
			||||||
 | 
					var https = require('https')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var JsonRPC = function (opts) {
 | 
				
			||||||
 | 
					  // @ts-ignore
 | 
				
			||||||
 | 
					  this.opts = opts || {}
 | 
				
			||||||
 | 
					  // @ts-ignore
 | 
				
			||||||
 | 
					  this.http = this.opts.ssl ? https : http
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					JsonRPC.prototype.call = function (method, params) {
 | 
				
			||||||
 | 
					  return new Promise((resolve, reject) => {
 | 
				
			||||||
 | 
					    var time = Date.now()
 | 
				
			||||||
 | 
					    var requestJSON
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (Array.isArray(method)) {
 | 
				
			||||||
 | 
					      // multiple rpc batch call
 | 
				
			||||||
 | 
					      requestJSON = []
 | 
				
			||||||
 | 
					      method.forEach(function (batchCall, i) {
 | 
				
			||||||
 | 
					        requestJSON.push({
 | 
				
			||||||
 | 
					          id: time + '-' + i,
 | 
				
			||||||
 | 
					          method: batchCall.method,
 | 
				
			||||||
 | 
					          params: batchCall.params
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      // single rpc call
 | 
				
			||||||
 | 
					      requestJSON = {
 | 
				
			||||||
 | 
					        id: time,
 | 
				
			||||||
 | 
					        method: method,
 | 
				
			||||||
 | 
					        params: params
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // First we encode the request into JSON
 | 
				
			||||||
 | 
					    requestJSON = JSON.stringify(requestJSON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // prepare request options
 | 
				
			||||||
 | 
					    var requestOptions = {
 | 
				
			||||||
 | 
					      host: this.opts.host || 'localhost',
 | 
				
			||||||
 | 
					      port: this.opts.port || 8332,
 | 
				
			||||||
 | 
					      method: 'POST',
 | 
				
			||||||
 | 
					      path: '/',
 | 
				
			||||||
 | 
					      headers: {
 | 
				
			||||||
 | 
					        'Host': this.opts.host || 'localhost',
 | 
				
			||||||
 | 
					        'Content-Length': requestJSON.length
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      agent: false,
 | 
				
			||||||
 | 
					      rejectUnauthorized: this.opts.ssl && this.opts.sslStrict !== false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (this.opts.ssl && this.opts.sslCa) {
 | 
				
			||||||
 | 
					    // @ts-ignore 
 | 
				
			||||||
 | 
					      requestOptions.ca = this.opts.sslCa
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // use HTTP auth if user and password set
 | 
				
			||||||
 | 
					    if (this.opts.user && this.opts.pass) {
 | 
				
			||||||
 | 
					      // @ts-ignore
 | 
				
			||||||
 | 
					      requestOptions.auth = this.opts.user + ':' + this.opts.pass
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Now we'll make a request to the server
 | 
				
			||||||
 | 
					    var cbCalled = false
 | 
				
			||||||
 | 
					    var request = this.http.request(requestOptions)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // start request timeout timer
 | 
				
			||||||
 | 
					    var reqTimeout = setTimeout(function () {
 | 
				
			||||||
 | 
					      if (cbCalled) return
 | 
				
			||||||
 | 
					      cbCalled = true
 | 
				
			||||||
 | 
					      request.abort()
 | 
				
			||||||
 | 
					      var err = new Error('ETIMEDOUT')
 | 
				
			||||||
 | 
					      // @ts-ignore
 | 
				
			||||||
 | 
					      err.code = 'ETIMEDOUT'
 | 
				
			||||||
 | 
					      reject(err)
 | 
				
			||||||
 | 
					    }, this.opts.timeout || 30000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set additional timeout on socket in case of remote freeze after sending headers
 | 
				
			||||||
 | 
					    request.setTimeout(this.opts.timeout || 30000, function () {
 | 
				
			||||||
 | 
					      if (cbCalled) return
 | 
				
			||||||
 | 
					      cbCalled = true
 | 
				
			||||||
 | 
					      request.abort()
 | 
				
			||||||
 | 
					      var err = new Error('ESOCKETTIMEDOUT')
 | 
				
			||||||
 | 
					      // @ts-ignore
 | 
				
			||||||
 | 
					      err.code = 'ESOCKETTIMEDOUT'
 | 
				
			||||||
 | 
					      reject(err)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    request.on('error', function (err) {
 | 
				
			||||||
 | 
					      if (cbCalled) return
 | 
				
			||||||
 | 
					      cbCalled = true
 | 
				
			||||||
 | 
					      clearTimeout(reqTimeout)
 | 
				
			||||||
 | 
					      reject(err)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    request.on('response', function (response) {
 | 
				
			||||||
 | 
					      clearTimeout(reqTimeout)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // We need to buffer the response chunks in a nonblocking way.
 | 
				
			||||||
 | 
					      var buffer = ''
 | 
				
			||||||
 | 
					      response.on('data', function (chunk) {
 | 
				
			||||||
 | 
					        buffer = buffer + chunk
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      // When all the responses are finished, we decode the JSON and
 | 
				
			||||||
 | 
					      // depending on whether it's got a result or an error, we call
 | 
				
			||||||
 | 
					      // emitSuccess or emitError on the promise.
 | 
				
			||||||
 | 
					      response.on('end', function () {
 | 
				
			||||||
 | 
					        var err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (cbCalled) return
 | 
				
			||||||
 | 
					        cbCalled = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					          var decoded = JSON.parse(buffer)
 | 
				
			||||||
 | 
					        } catch (e) {
 | 
				
			||||||
 | 
					          if (response.statusCode !== 200) {
 | 
				
			||||||
 | 
					            err = new Error('Invalid params, response status code: ' + response.statusCode)
 | 
				
			||||||
 | 
					            err.code = -32602
 | 
				
			||||||
 | 
					            reject(err)
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            err = new Error('Problem parsing JSON response from server')
 | 
				
			||||||
 | 
					            err.code = -32603
 | 
				
			||||||
 | 
					            reject(err)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          return
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!Array.isArray(decoded)) {
 | 
				
			||||||
 | 
					          decoded = [decoded]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // iterate over each response, normally there will be just one
 | 
				
			||||||
 | 
					        // unless a batch rpc call response is being processed
 | 
				
			||||||
 | 
					        decoded.forEach(function (decodedResponse, i) {
 | 
				
			||||||
 | 
					          if (decodedResponse.hasOwnProperty('error') && decodedResponse.error != null) {
 | 
				
			||||||
 | 
					            if (reject) {
 | 
				
			||||||
 | 
					              err = new Error(decodedResponse.error.message || '')
 | 
				
			||||||
 | 
					              if (decodedResponse.error.code) {
 | 
				
			||||||
 | 
					                err.code = decodedResponse.error.code
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              reject(err)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          } else if (decodedResponse.hasOwnProperty('result')) {
 | 
				
			||||||
 | 
					            // @ts-ignore
 | 
				
			||||||
 | 
					            resolve(decodedResponse.result, response.headers)
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            if (reject) {
 | 
				
			||||||
 | 
					              err = new Error(decodedResponse.error.message || '')
 | 
				
			||||||
 | 
					              if (decodedResponse.error.code) {
 | 
				
			||||||
 | 
					                err.code = decodedResponse.error.code
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              reject(err)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    request.end(requestJSON);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports.JsonRPC = JsonRPC
 | 
				
			||||||
@ -2,6 +2,28 @@ import logger from '../../logger';
 | 
				
			|||||||
import DB from '../../database';
 | 
					import DB from '../../database';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChannelsApi {
 | 
					class ChannelsApi {
 | 
				
			||||||
 | 
					  public async $getAllChannels(): Promise<any[]> {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const query = `SELECT * FROM channels`;
 | 
				
			||||||
 | 
					      const [rows]: any = await DB.query(query);
 | 
				
			||||||
 | 
					      return rows;
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      logger.err('$getChannel error: ' + (e instanceof Error ? e.message : e));
 | 
				
			||||||
 | 
					      throw e;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public async $getChannelsByStatus(status: number): Promise<any[]> {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const query = `SELECT * FROM channels WHERE status = ?`;
 | 
				
			||||||
 | 
					      const [rows]: any = await DB.query(query, [status]);
 | 
				
			||||||
 | 
					      return rows;
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      logger.err('$getChannel error: ' + (e instanceof Error ? e.message : e));
 | 
				
			||||||
 | 
					      throw e;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public async $getChannel(shortId: string): Promise<any> {
 | 
					  public async $getChannel(shortId: string): Promise<any> {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const query = `SELECT n1.alias AS alias_left, n2.alias AS alias_right, channels.* FROM channels LEFT JOIN nodes AS n1 ON n1.public_key = channels.node1_public_key LEFT JOIN nodes AS n2 ON n2.public_key = channels.node2_public_key WHERE channels.id = ?`;
 | 
					      const query = `SELECT n1.alias AS alias_left, n2.alias AS alias_right, channels.* FROM channels LEFT JOIN nodes AS n1 ON n1.public_key = channels.node1_public_key LEFT JOIN nodes AS n2 ON n2.public_key = channels.node2_public_key WHERE channels.id = ?`;
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,12 @@ interface IConfig {
 | 
				
			|||||||
    TSL_CERT_PATH: string;
 | 
					    TSL_CERT_PATH: string;
 | 
				
			||||||
    MACAROON_PATH: string;
 | 
					    MACAROON_PATH: string;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					  CORE_RPC: {
 | 
				
			||||||
 | 
					    HOST: string;
 | 
				
			||||||
 | 
					    PORT: number;
 | 
				
			||||||
 | 
					    USERNAME: string;
 | 
				
			||||||
 | 
					    PASSWORD: string;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
  DATABASE: {
 | 
					  DATABASE: {
 | 
				
			||||||
    HOST: string,
 | 
					    HOST: string,
 | 
				
			||||||
    SOCKET: string,
 | 
					    SOCKET: string,
 | 
				
			||||||
@ -48,6 +54,12 @@ const defaults: IConfig = {
 | 
				
			|||||||
    'TSL_CERT_PATH': '',
 | 
					    'TSL_CERT_PATH': '',
 | 
				
			||||||
    'MACAROON_PATH': '',
 | 
					    'MACAROON_PATH': '',
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  'CORE_RPC': {
 | 
				
			||||||
 | 
					    'HOST': '127.0.0.1',
 | 
				
			||||||
 | 
					    'PORT': 8332,
 | 
				
			||||||
 | 
					    'USERNAME': 'mempool',
 | 
				
			||||||
 | 
					    'PASSWORD': 'mempool'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  'DATABASE': {
 | 
					  'DATABASE': {
 | 
				
			||||||
    'HOST': '127.0.0.1',
 | 
					    'HOST': '127.0.0.1',
 | 
				
			||||||
    'SOCKET': '',
 | 
					    'SOCKET': '',
 | 
				
			||||||
@ -62,6 +74,7 @@ class Config implements IConfig {
 | 
				
			|||||||
  MEMPOOL: IConfig['MEMPOOL'];
 | 
					  MEMPOOL: IConfig['MEMPOOL'];
 | 
				
			||||||
  SYSLOG: IConfig['SYSLOG'];
 | 
					  SYSLOG: IConfig['SYSLOG'];
 | 
				
			||||||
  LN_NODE_AUTH: IConfig['LN_NODE_AUTH'];
 | 
					  LN_NODE_AUTH: IConfig['LN_NODE_AUTH'];
 | 
				
			||||||
 | 
					  CORE_RPC: IConfig['CORE_RPC'];
 | 
				
			||||||
  DATABASE: IConfig['DATABASE'];
 | 
					  DATABASE: IConfig['DATABASE'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor() {
 | 
					  constructor() {
 | 
				
			||||||
@ -69,6 +82,7 @@ class Config implements IConfig {
 | 
				
			|||||||
    this.MEMPOOL = configs.MEMPOOL;
 | 
					    this.MEMPOOL = configs.MEMPOOL;
 | 
				
			||||||
    this.SYSLOG = configs.SYSLOG;
 | 
					    this.SYSLOG = configs.SYSLOG;
 | 
				
			||||||
    this.LN_NODE_AUTH = configs.LN_NODE_AUTH;
 | 
					    this.LN_NODE_AUTH = configs.LN_NODE_AUTH;
 | 
				
			||||||
 | 
					    this.CORE_RPC = configs.CORE_RPC;
 | 
				
			||||||
    this.DATABASE = configs.DATABASE;
 | 
					    this.DATABASE = configs.DATABASE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,8 @@ import DB from '../database';
 | 
				
			|||||||
import logger from '../logger';
 | 
					import logger from '../logger';
 | 
				
			||||||
import lightningApi from '../api/lightning/lightning-api-factory';
 | 
					import lightningApi from '../api/lightning/lightning-api-factory';
 | 
				
			||||||
import { ILightningApi } from '../api/lightning/lightning-api.interface';
 | 
					import { ILightningApi } from '../api/lightning/lightning-api.interface';
 | 
				
			||||||
 | 
					import channelsApi from '../api/nodes/channels.api';
 | 
				
			||||||
 | 
					import bitcoinClient from '../api/bitcoin/bitcoin-client';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NodeSyncService {
 | 
					class NodeSyncService {
 | 
				
			||||||
  constructor() {}
 | 
					  constructor() {}
 | 
				
			||||||
@ -25,15 +27,35 @@ class NodeSyncService {
 | 
				
			|||||||
        await this.$saveNode(node);
 | 
					        await this.$saveNode(node);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      await this.$setChannelsInactive();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (const channel of networkGraph.channels) {
 | 
					      for (const channel of networkGraph.channels) {
 | 
				
			||||||
        await this.$saveChannel(channel);
 | 
					        await this.$saveChannel(channel);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      await this.$scanForClosedChannels();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      logger.err('$updateNodes() error: ' + (e instanceof Error ? e.message : e));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private async $scanForClosedChannels() {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const channels = await channelsApi.$getChannelsByStatus(0);
 | 
				
			||||||
 | 
					      for (const channel of channels) {
 | 
				
			||||||
 | 
					        const outspends = await bitcoinClient.getTxOut(channel.transaction_id, channel.transaction_vout);
 | 
				
			||||||
 | 
					        if (outspends === null) {
 | 
				
			||||||
 | 
					          logger.debug('Marking channel: ' + channel.id + ' as closed.');
 | 
				
			||||||
 | 
					          await DB.query(`UPDATE channels SET status = 2 WHERE id = ?`, [channel.id]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
      logger.err('$updateNodes() error: ' + (e instanceof Error ? e.message : e));
 | 
					      logger.err('$updateNodes() error: ' + (e instanceof Error ? e.message : e));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async $saveChannel(channel: ILightningApi.Channel) {
 | 
					  private async $saveChannel(channel: ILightningApi.Channel): Promise<void> {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const d = new Date(Date.parse(channel.updated_at));
 | 
					      const d = new Date(Date.parse(channel.updated_at));
 | 
				
			||||||
      const query = `INSERT INTO channels
 | 
					      const query = `INSERT INTO channels
 | 
				
			||||||
@ -43,6 +65,7 @@ class NodeSyncService {
 | 
				
			|||||||
          transaction_id,
 | 
					          transaction_id,
 | 
				
			||||||
          transaction_vout,
 | 
					          transaction_vout,
 | 
				
			||||||
          updated_at,
 | 
					          updated_at,
 | 
				
			||||||
 | 
					          status,
 | 
				
			||||||
          node1_public_key,
 | 
					          node1_public_key,
 | 
				
			||||||
          node1_base_fee_mtokens,
 | 
					          node1_base_fee_mtokens,
 | 
				
			||||||
          node1_cltv_delta,
 | 
					          node1_cltv_delta,
 | 
				
			||||||
@ -60,10 +83,11 @@ class NodeSyncService {
 | 
				
			|||||||
          node2_min_htlc_mtokens,
 | 
					          node2_min_htlc_mtokens,
 | 
				
			||||||
          node2_updated_at
 | 
					          node2_updated_at
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
 | 
					        VALUES (?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
 | 
				
			||||||
        ON DUPLICATE KEY UPDATE
 | 
					        ON DUPLICATE KEY UPDATE
 | 
				
			||||||
          capacity = ?,
 | 
					          capacity = ?,
 | 
				
			||||||
          updated_at = ?,
 | 
					          updated_at = ?,
 | 
				
			||||||
 | 
					          status = 1,
 | 
				
			||||||
          node1_public_key = ?,
 | 
					          node1_public_key = ?,
 | 
				
			||||||
          node1_base_fee_mtokens = ?,
 | 
					          node1_base_fee_mtokens = ?,
 | 
				
			||||||
          node1_cltv_delta = ?,
 | 
					          node1_cltv_delta = ?,
 | 
				
			||||||
@ -128,7 +152,15 @@ class NodeSyncService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async $saveNode(node: ILightningApi.Node) {
 | 
					  private async $setChannelsInactive(): Promise<void> {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      await DB.query(`UPDATE channels SET status = 0 WHERE status = 1`);
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      logger.err('$setChannelsInactive() error: ' + (e instanceof Error ? e.message : e));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private async $saveNode(node: ILightningApi.Node): Promise<void> {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const updatedAt = this.utcDateToMysql(node.updated_at);
 | 
					      const updatedAt = this.utcDateToMysql(node.updated_at);
 | 
				
			||||||
      const query = `INSERT INTO nodes(
 | 
					      const query = `INSERT INTO nodes(
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user