parent
							
								
									1a756c5fa9
								
							
						
					
					
						commit
						40dc476460
					
				@ -70,7 +70,7 @@ class ChannelsRoutes {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async $getChannelsByTransactionIds(req: Request, res: Response) {
 | 
					  private async $getChannelsByTransactionIds(req: Request, res: Response): Promise<void> {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      if (!Array.isArray(req.query.txId)) {
 | 
					      if (!Array.isArray(req.query.txId)) {
 | 
				
			||||||
        res.status(400).send('Not an array');
 | 
					        res.status(400).send('Not an array');
 | 
				
			||||||
@ -83,27 +83,26 @@ class ChannelsRoutes {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      const channels = await channelsApi.$getChannelsByTransactionId(txIds);
 | 
					      const channels = await channelsApi.$getChannelsByTransactionId(txIds);
 | 
				
			||||||
      const inputs: any[] = [];
 | 
					      const result: any[] = [];
 | 
				
			||||||
      const outputs: any[] = [];
 | 
					 | 
				
			||||||
      for (const txid of txIds) {
 | 
					      for (const txid of txIds) {
 | 
				
			||||||
        const foundChannelInputs = channels.find((channel) => channel.closing_transaction_id === txid);
 | 
					        const inputs: any = {};
 | 
				
			||||||
        if (foundChannelInputs) {
 | 
					        const outputs: any = {};
 | 
				
			||||||
          inputs.push(foundChannelInputs);
 | 
					        // Assuming that we only have one lightning close input in each transaction. This may not be true in the future
 | 
				
			||||||
        } else {
 | 
					        const foundChannelsFromInput = channels.find((channel) => channel.closing_transaction_id === txid);
 | 
				
			||||||
          inputs.push(null);
 | 
					        if (foundChannelsFromInput) {
 | 
				
			||||||
 | 
					          inputs[0] = foundChannelsFromInput;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const foundChannelOutputs = channels.find((channel) => channel.transaction_id === txid);
 | 
					        const foundChannelsFromOutputs = channels.filter((channel) => channel.transaction_id === txid);
 | 
				
			||||||
        if (foundChannelOutputs) {
 | 
					        for (const output of foundChannelsFromOutputs) {
 | 
				
			||||||
          outputs.push(foundChannelOutputs);
 | 
					          outputs[output.transaction_vout] = output;
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          outputs.push(null);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        result.push({
 | 
				
			||||||
 | 
					          inputs,
 | 
				
			||||||
 | 
					          outputs,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      res.json({
 | 
					      res.json(result);
 | 
				
			||||||
        inputs: inputs,
 | 
					 | 
				
			||||||
        outputs: outputs,
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
      res.status(500).send(e instanceof Error ? e.message : e);
 | 
					      res.status(500).send(e instanceof Error ? e.message : e);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@
 | 
				
			|||||||
      <div class="col">
 | 
					      <div class="col">
 | 
				
			||||||
        <table class="table table-borderless smaller-text table-sm table-tx-vin">
 | 
					        <table class="table table-borderless smaller-text table-sm table-tx-vin">
 | 
				
			||||||
          <tbody>
 | 
					          <tbody>
 | 
				
			||||||
            <ng-template ngFor let-vin [ngForOf]="tx['@vinLimit'] ? ((tx.vin.length > rowLimit) ? tx.vin.slice(0, rowLimit - 2) : tx.vin.slice(0, rowLimit)) : tx.vin" [ngForTrackBy]="trackByIndexFn">
 | 
					            <ng-template ngFor let-vin let-vindex="index" [ngForOf]="tx['@vinLimit'] ? ((tx.vin.length > rowLimit) ? tx.vin.slice(0, rowLimit - 2) : tx.vin.slice(0, rowLimit)) : tx.vin" [ngForTrackBy]="trackByIndexFn">
 | 
				
			||||||
              <tr [ngClass]="{
 | 
					              <tr [ngClass]="{
 | 
				
			||||||
                'assetBox': assetsMinimal && vin.prevout && assetsMinimal[vin.prevout.asset] && !vin.is_coinbase && vin.prevout.scriptpubkey_address && tx._unblinded,
 | 
					                'assetBox': assetsMinimal && vin.prevout && assetsMinimal[vin.prevout.asset] && !vin.is_coinbase && vin.prevout.scriptpubkey_address && tx._unblinded,
 | 
				
			||||||
                'highlight': vin.prevout?.scriptpubkey_address === this.address && this.address !== ''
 | 
					                'highlight': vin.prevout?.scriptpubkey_address === this.address && this.address !== ''
 | 
				
			||||||
@ -77,7 +77,7 @@
 | 
				
			|||||||
                          {{ vin.prevout.scriptpubkey_type?.toUpperCase() }}
 | 
					                          {{ vin.prevout.scriptpubkey_type?.toUpperCase() }}
 | 
				
			||||||
                        </ng-template>
 | 
					                        </ng-template>
 | 
				
			||||||
                        <div>
 | 
					                        <div>
 | 
				
			||||||
                          <app-address-labels [vin]="vin" [channel]="channels && channels.inputs[i] || null"></app-address-labels>
 | 
					                          <app-address-labels [vin]="vin" [channel]="tx._channels && tx._channels.inputs[vin.vout] || null"></app-address-labels>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                      </ng-template>
 | 
					                      </ng-template>
 | 
				
			||||||
                    </ng-container>
 | 
					                    </ng-container>
 | 
				
			||||||
@ -172,7 +172,7 @@
 | 
				
			|||||||
                    </span>
 | 
					                    </span>
 | 
				
			||||||
                  </a>
 | 
					                  </a>
 | 
				
			||||||
                  <div>
 | 
					                  <div>
 | 
				
			||||||
                    <app-address-labels [vout]="vout" [channel]="channels && channels.outputs[i] && channels.outputs[i].transaction_vout === vindex ? channels.outputs[i] : null"></app-address-labels>
 | 
					                    <app-address-labels [vout]="vout" [channel]="tx._channels && tx._channels.outputs[vindex] ? tx._channels.outputs[vindex] : null"></app-address-labels>
 | 
				
			||||||
                  </div>
 | 
					                  </div>
 | 
				
			||||||
                  <ng-template #scriptpubkey_type>
 | 
					                  <ng-template #scriptpubkey_type>
 | 
				
			||||||
                    <ng-template [ngIf]="vout.pegout" [ngIfElse]="defaultscriptpubkey_type">
 | 
					                    <ng-template [ngIf]="vout.pegout" [ngIfElse]="defaultscriptpubkey_type">
 | 
				
			||||||
@ -212,15 +212,15 @@
 | 
				
			|||||||
                  </ng-template>
 | 
					                  </ng-template>
 | 
				
			||||||
                </td>
 | 
					                </td>
 | 
				
			||||||
                <td class="arrow-td">
 | 
					                <td class="arrow-td">
 | 
				
			||||||
                  <span *ngIf="!outspends[i] || vout.scriptpubkey_type === 'op_return' || vout.scriptpubkey_type === 'fee' ; else outspend" class="grey">
 | 
					                  <span *ngIf="!tx._outspends || vout.scriptpubkey_type === 'op_return' || vout.scriptpubkey_type === 'fee' ; else outspend" class="grey">
 | 
				
			||||||
                    <fa-icon [icon]="['fas', 'arrow-alt-circle-right']" [fixedWidth]="true"></fa-icon>
 | 
					                    <fa-icon [icon]="['fas', 'arrow-alt-circle-right']" [fixedWidth]="true"></fa-icon>
 | 
				
			||||||
                  </span>
 | 
					                  </span>
 | 
				
			||||||
                  <ng-template #outspend>
 | 
					                  <ng-template #outspend>
 | 
				
			||||||
                    <span *ngIf="!outspends[i][vindex] || !outspends[i][vindex].spent; else spent" class="green">
 | 
					                    <span *ngIf="!tx._outspends[vindex] || !tx._outspends[vindex].spent; else spent" class="green">
 | 
				
			||||||
                      <fa-icon [icon]="['fas', 'arrow-alt-circle-right']" [fixedWidth]="true"></fa-icon>
 | 
					                      <fa-icon [icon]="['fas', 'arrow-alt-circle-right']" [fixedWidth]="true"></fa-icon>
 | 
				
			||||||
                    </span>
 | 
					                    </span>
 | 
				
			||||||
                    <ng-template #spent>
 | 
					                    <ng-template #spent>
 | 
				
			||||||
                      <a *ngIf="outspends[i][vindex].txid else outputNoTxId" [routerLink]="['/tx/' | relativeUrl, outspends[i][vindex].txid]" class="red">
 | 
					                      <a *ngIf="tx._outspends[vindex].txid else outputNoTxId" [routerLink]="['/tx/' | relativeUrl, tx._outspends[vindex].txid]" class="red">
 | 
				
			||||||
                        <fa-icon [icon]="['fas', 'arrow-alt-circle-right']" [fixedWidth]="true"></fa-icon>
 | 
					                        <fa-icon [icon]="['fas', 'arrow-alt-circle-right']" [fixedWidth]="true"></fa-icon>
 | 
				
			||||||
                      </a>
 | 
					                      </a>
 | 
				
			||||||
                      <ng-template #outputNoTxId>
 | 
					                      <ng-template #outputNoTxId>
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,6 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
  @Input() outputIndex: number;
 | 
					  @Input() outputIndex: number;
 | 
				
			||||||
  @Input() address: string = '';
 | 
					  @Input() address: string = '';
 | 
				
			||||||
  @Input() rowLimit = 12;
 | 
					  @Input() rowLimit = 12;
 | 
				
			||||||
  @Input() channels: { inputs: any[], outputs: any[] };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Output() loadMore = new EventEmitter();
 | 
					  @Output() loadMore = new EventEmitter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,8 +35,8 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
  refreshOutspends$: ReplaySubject<string[]> = new ReplaySubject();
 | 
					  refreshOutspends$: ReplaySubject<string[]> = new ReplaySubject();
 | 
				
			||||||
  refreshChannels$: ReplaySubject<string[]> = new ReplaySubject();
 | 
					  refreshChannels$: ReplaySubject<string[]> = new ReplaySubject();
 | 
				
			||||||
  showDetails$ = new BehaviorSubject<boolean>(false);
 | 
					  showDetails$ = new BehaviorSubject<boolean>(false);
 | 
				
			||||||
  outspends: Outspend[][] = [];
 | 
					 | 
				
			||||||
  assetsMinimal: any;
 | 
					  assetsMinimal: any;
 | 
				
			||||||
 | 
					  transactionsLength: number = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
    public stateService: StateService,
 | 
					    public stateService: StateService,
 | 
				
			||||||
@ -47,7 +46,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
    private ref: ChangeDetectorRef,
 | 
					    private ref: ChangeDetectorRef,
 | 
				
			||||||
  ) { }
 | 
					  ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ngOnInit() {
 | 
					  ngOnInit(): void {
 | 
				
			||||||
    this.latestBlock$ = this.stateService.blocks$.pipe(map(([block]) => block));
 | 
					    this.latestBlock$ = this.stateService.blocks$.pipe(map(([block]) => block));
 | 
				
			||||||
    this.stateService.networkChanged$.subscribe((network) => this.network = network);
 | 
					    this.stateService.networkChanged$.subscribe((network) => this.network = network);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -62,14 +61,17 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
        .pipe(
 | 
					        .pipe(
 | 
				
			||||||
          switchMap((txIds) => this.apiService.getOutspendsBatched$(txIds)),
 | 
					          switchMap((txIds) => this.apiService.getOutspendsBatched$(txIds)),
 | 
				
			||||||
          tap((outspends: Outspend[][]) => {
 | 
					          tap((outspends: Outspend[][]) => {
 | 
				
			||||||
            this.outspends = this.outspends.concat(outspends);
 | 
					            const transactions = this.transactions.filter((tx) => !tx._outspends);
 | 
				
			||||||
 | 
					            outspends.forEach((outspend, i) => {
 | 
				
			||||||
 | 
					              transactions[i]._outspends = outspend;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
          }),
 | 
					          }),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      this.stateService.utxoSpent$
 | 
					      this.stateService.utxoSpent$
 | 
				
			||||||
        .pipe(
 | 
					        .pipe(
 | 
				
			||||||
          tap((utxoSpent) => {
 | 
					          tap((utxoSpent) => {
 | 
				
			||||||
            for (const i in utxoSpent) {
 | 
					            for (const i in utxoSpent) {
 | 
				
			||||||
              this.outspends[0][i] = {
 | 
					              this.transactions[0]._outspends[i] = {
 | 
				
			||||||
                spent: true,
 | 
					                spent: true,
 | 
				
			||||||
                txid: utxoSpent[i].txid,
 | 
					                txid: utxoSpent[i].txid,
 | 
				
			||||||
                vin: utxoSpent[i].vin,
 | 
					                vin: utxoSpent[i].vin,
 | 
				
			||||||
@ -81,21 +83,23 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
          .pipe(
 | 
					          .pipe(
 | 
				
			||||||
            filter(() => this.stateService.env.LIGHTNING),
 | 
					            filter(() => this.stateService.env.LIGHTNING),
 | 
				
			||||||
            switchMap((txIds) => this.apiService.getChannelByTxIds$(txIds)),
 | 
					            switchMap((txIds) => this.apiService.getChannelByTxIds$(txIds)),
 | 
				
			||||||
            map((channels) => {
 | 
					            tap((channels) => {
 | 
				
			||||||
              this.channels = channels;
 | 
					              const transactions = this.transactions.filter((tx) => !tx._channels);
 | 
				
			||||||
 | 
					              channels.forEach((channel, i) => {
 | 
				
			||||||
 | 
					                transactions[i]._channels = channel;
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
            }),
 | 
					            }),
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
        ,
 | 
					        ,
 | 
				
			||||||
    ).subscribe(() => this.ref.markForCheck());
 | 
					    ).subscribe(() => this.ref.markForCheck());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ngOnChanges() {
 | 
					  ngOnChanges(): void {
 | 
				
			||||||
    if (!this.transactions || !this.transactions.length) {
 | 
					    if (!this.transactions || !this.transactions.length) {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (this.paginated) {
 | 
					
 | 
				
			||||||
      this.outspends = [];
 | 
					    this.transactionsLength = this.transactions.length;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (this.outputIndex) {
 | 
					    if (this.outputIndex) {
 | 
				
			||||||
      setTimeout(() => {
 | 
					      setTimeout(() => {
 | 
				
			||||||
        const assetBoxElements = document.getElementsByClassName('assetBox');
 | 
					        const assetBoxElements = document.getElementsByClassName('assetBox');
 | 
				
			||||||
@ -126,14 +130,19 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
        tx['addressValue'] = addressIn - addressOut;
 | 
					        tx['addressValue'] = addressIn - addressOut;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    const txIds = this.transactions.map((tx) => tx.txid);
 | 
					    const txIds = this.transactions.filter((tx) => !tx._outspends).map((tx) => tx.txid);
 | 
				
			||||||
 | 
					    if (txIds.length) {
 | 
				
			||||||
      this.refreshOutspends$.next(txIds);
 | 
					      this.refreshOutspends$.next(txIds);
 | 
				
			||||||
    if (!this.channels) {
 | 
					    }
 | 
				
			||||||
 | 
					    if (this.stateService.env.LIGHTNING) {
 | 
				
			||||||
 | 
					      const txIds = this.transactions.filter((tx) => !tx._channels).map((tx) => tx.txid);
 | 
				
			||||||
 | 
					      if (txIds.length) {
 | 
				
			||||||
        this.refreshChannels$.next(txIds);
 | 
					        this.refreshChannels$.next(txIds);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  onScroll() {
 | 
					  onScroll(): void {
 | 
				
			||||||
    const scrollHeight = document.body.scrollHeight;
 | 
					    const scrollHeight = document.body.scrollHeight;
 | 
				
			||||||
    const scrollTop = document.documentElement.scrollTop;
 | 
					    const scrollTop = document.documentElement.scrollTop;
 | 
				
			||||||
    if (scrollHeight > 0){
 | 
					    if (scrollHeight > 0){
 | 
				
			||||||
@ -148,11 +157,11 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
    return tx.vout.some((v: any) => v.value === undefined);
 | 
					    return tx.vout.some((v: any) => v.value === undefined);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getTotalTxOutput(tx: Transaction) {
 | 
					  getTotalTxOutput(tx: Transaction): number {
 | 
				
			||||||
    return tx.vout.map((v: Vout) => v.value || 0).reduce((a: number, b: number) => a + b);
 | 
					    return tx.vout.map((v: Vout) => v.value || 0).reduce((a: number, b: number) => a + b);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  switchCurrency() {
 | 
					  switchCurrency(): void {
 | 
				
			||||||
    if (this.network === 'liquid' || this.network === 'liquidtestnet') {
 | 
					    if (this.network === 'liquid' || this.network === 'liquidtestnet') {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -164,7 +173,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
    return tx.txid + tx.status.confirmed;
 | 
					    return tx.txid + tx.status.confirmed;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  trackByIndexFn(index: number) {
 | 
					  trackByIndexFn(index: number): number {
 | 
				
			||||||
    return index;
 | 
					    return index;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -177,7 +186,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
    return Math.pow(base, exponent);
 | 
					    return Math.pow(base, exponent);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  toggleDetails() {
 | 
					  toggleDetails(): void {
 | 
				
			||||||
    if (this.showDetails$.value === true) {
 | 
					    if (this.showDetails$.value === true) {
 | 
				
			||||||
      this.showDetails$.next(false);
 | 
					      this.showDetails$.next(false);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -185,7 +194,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  loadMoreInputs(tx: Transaction) {
 | 
					  loadMoreInputs(tx: Transaction): void {
 | 
				
			||||||
    tx['@vinLimit'] = false;
 | 
					    tx['@vinLimit'] = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.electrsApiService.getTransaction$(tx.txid)
 | 
					    this.electrsApiService.getTransaction$(tx.txid)
 | 
				
			||||||
@ -196,7 +205,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ngOnDestroy() {
 | 
					  ngOnDestroy(): void {
 | 
				
			||||||
    this.outspendsSubscription.unsubscribe();
 | 
					    this.outspendsSubscription.unsubscribe();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					import { IChannel } from './node-api.interface';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface Transaction {
 | 
					export interface Transaction {
 | 
				
			||||||
  txid: string;
 | 
					  txid: string;
 | 
				
			||||||
  version: number;
 | 
					  version: number;
 | 
				
			||||||
@ -19,6 +21,13 @@ export interface Transaction {
 | 
				
			|||||||
  deleteAfter?: number;
 | 
					  deleteAfter?: number;
 | 
				
			||||||
  _unblinded?: any;
 | 
					  _unblinded?: any;
 | 
				
			||||||
  _deduced?: boolean;
 | 
					  _deduced?: boolean;
 | 
				
			||||||
 | 
					  _outspends?: Outspend[];
 | 
				
			||||||
 | 
					  _channels?: TransactionChannels;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface TransactionChannels {
 | 
				
			||||||
 | 
					  inputs: { [vin: number]: IChannel };
 | 
				
			||||||
 | 
					  outputs: { [vout: number]: IChannel };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface Ancestor {
 | 
					interface Ancestor {
 | 
				
			||||||
 | 
				
			|||||||
@ -189,3 +189,35 @@ export interface IOldestNodes {
 | 
				
			|||||||
  city?: any,
 | 
					  city?: any,
 | 
				
			||||||
  country?: any,
 | 
					  country?: any,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IChannel {
 | 
				
			||||||
 | 
					  id: number;
 | 
				
			||||||
 | 
					  short_id: string;
 | 
				
			||||||
 | 
					  capacity: number;
 | 
				
			||||||
 | 
					  transaction_id: string;
 | 
				
			||||||
 | 
					  transaction_vout: number;
 | 
				
			||||||
 | 
					  closing_transaction_id: string;
 | 
				
			||||||
 | 
					  closing_reason: string;
 | 
				
			||||||
 | 
					  updated_at: string;
 | 
				
			||||||
 | 
					  created: string;
 | 
				
			||||||
 | 
					  status: number;
 | 
				
			||||||
 | 
					  node_left: Node,
 | 
				
			||||||
 | 
					  node_right: Node,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface INode {
 | 
				
			||||||
 | 
					  alias: string;
 | 
				
			||||||
 | 
					  public_key: string;
 | 
				
			||||||
 | 
					  channels: number;
 | 
				
			||||||
 | 
					  capacity: number;
 | 
				
			||||||
 | 
					  base_fee_mtokens: number;
 | 
				
			||||||
 | 
					  cltv_delta: number;
 | 
				
			||||||
 | 
					  fee_rate: number;
 | 
				
			||||||
 | 
					  is_disabled: boolean;
 | 
				
			||||||
 | 
					  max_htlc_mtokens: number;
 | 
				
			||||||
 | 
					  min_htlc_mtokens: number;
 | 
				
			||||||
 | 
					  updated_at: string;
 | 
				
			||||||
 | 
					  longitude: number;
 | 
				
			||||||
 | 
					  latitude: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -65,13 +65,13 @@
 | 
				
			|||||||
    <ng-container *ngIf="transactions$ | async as transactions">
 | 
					    <ng-container *ngIf="transactions$ | async as transactions">
 | 
				
			||||||
      <ng-template [ngIf]="transactions[0]">
 | 
					      <ng-template [ngIf]="transactions[0]">
 | 
				
			||||||
        <h3>Opening transaction</h3>
 | 
					        <h3>Opening transaction</h3>
 | 
				
			||||||
        <app-transactions-list [transactions]="[transactions[0]]" [showConfirmations]="true" [rowLimit]="5" [channels]="{ inputs: [], outputs: [channel] }"></app-transactions-list>
 | 
					        <app-transactions-list [transactions]="[transactions[0]]" [showConfirmations]="true" [rowLimit]="5"></app-transactions-list>
 | 
				
			||||||
      </ng-template>
 | 
					      </ng-template>
 | 
				
			||||||
      <ng-template [ngIf]="transactions[1]">
 | 
					      <ng-template [ngIf]="transactions[1]">
 | 
				
			||||||
        <div class="closing-header">
 | 
					        <div class="closing-header">
 | 
				
			||||||
          <h3 style="margin: 0;">Closing transaction</h3>  <app-closing-type [type]="channel.closing_reason"></app-closing-type>
 | 
					          <h3 style="margin: 0;">Closing transaction</h3>  <app-closing-type [type]="channel.closing_reason"></app-closing-type>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <app-transactions-list [transactions]="[transactions[1]]" [showConfirmations]="true" [rowLimit]="5" [channels]="{ inputs: [channel], outputs: [] }"></app-transactions-list>
 | 
					        <app-transactions-list [transactions]="[transactions[1]]" [showConfirmations]="true" [rowLimit]="5"></app-transactions-list>
 | 
				
			||||||
      </ng-template>
 | 
					      </ng-template>
 | 
				
			||||||
    </ng-container>
 | 
					    </ng-container>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
 | 
				
			|||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
 | 
					import { ActivatedRoute, ParamMap } from '@angular/router';
 | 
				
			||||||
import { forkJoin, Observable, of, share, zip } from 'rxjs';
 | 
					import { forkJoin, Observable, of, share, zip } from 'rxjs';
 | 
				
			||||||
import { catchError, map, shareReplay, switchMap, tap } from 'rxjs/operators';
 | 
					import { catchError, map, shareReplay, switchMap, tap } from 'rxjs/operators';
 | 
				
			||||||
 | 
					import { IChannel } from 'src/app/interfaces/node-api.interface';
 | 
				
			||||||
import { ApiService } from 'src/app/services/api.service';
 | 
					import { ApiService } from 'src/app/services/api.service';
 | 
				
			||||||
import { ElectrsApiService } from 'src/app/services/electrs-api.service';
 | 
					import { ElectrsApiService } from 'src/app/services/electrs-api.service';
 | 
				
			||||||
import { SeoService } from 'src/app/services/seo.service';
 | 
					import { SeoService } from 'src/app/services/seo.service';
 | 
				
			||||||
@ -62,10 +63,15 @@ export class ChannelComponent implements OnInit {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.transactions$ = this.channel$.pipe(
 | 
					    this.transactions$ = this.channel$.pipe(
 | 
				
			||||||
      switchMap((data) => {
 | 
					      switchMap((channel: IChannel) => {
 | 
				
			||||||
        return zip([
 | 
					        return zip([
 | 
				
			||||||
          data.transaction_id ? this.electrsApiService.getTransaction$(data.transaction_id) : of(null),
 | 
					          channel.transaction_id ? this.electrsApiService.getTransaction$(channel.transaction_id) : of(null),
 | 
				
			||||||
          data.closing_transaction_id ? this.electrsApiService.getTransaction$(data.closing_transaction_id) : of(null),
 | 
					          channel.closing_transaction_id ? this.electrsApiService.getTransaction$(channel.closing_transaction_id).pipe(
 | 
				
			||||||
 | 
					            map((tx) => {
 | 
				
			||||||
 | 
					              tx._channels = { inputs: {0: channel}, outputs: {}};
 | 
				
			||||||
 | 
					              return tx;
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					          ) : of(null),
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
      }),
 | 
					      }),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
				
			|||||||
@ -242,12 +242,12 @@ export class ApiService {
 | 
				
			|||||||
    return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + `/api/v1/enterprise/info/` + name);
 | 
					    return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + `/api/v1/enterprise/info/` + name);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getChannelByTxIds$(txIds: string[]): Observable<{ inputs: any[], outputs: any[] }> {
 | 
					  getChannelByTxIds$(txIds: string[]): Observable<any[]> {
 | 
				
			||||||
    let params = new HttpParams();
 | 
					    let params = new HttpParams();
 | 
				
			||||||
    txIds.forEach((txId: string) => {
 | 
					    txIds.forEach((txId: string) => {
 | 
				
			||||||
      params = params.append('txId[]', txId);
 | 
					      params = params.append('txId[]', txId);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    return this.httpClient.get<{ inputs: any[], outputs: any[] }>(this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/channels/txids/', { params });
 | 
					    return this.httpClient.get<any[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/channels/txids/', { params });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  lightningSearch$(searchText: string): Observable<any[]> {
 | 
					  lightningSearch$(searchText: string): Observable<any[]> {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user