Parse & display liquidity ads on node page
This commit is contained in:
		
							parent
							
								
									010e9f2bb1
								
							
						
					
					
						commit
						c2ab0bc715
					
				
							
								
								
									
										31
									
								
								frontend/src/app/lightning/node/liquidity-ad.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								frontend/src/app/lightning/node/liquidity-ad.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
export interface ILiquidityAd {
 | 
			
		||||
  funding_weight: number;
 | 
			
		||||
  lease_fee_basis: number; // lease fee rate in parts-per-thousandth
 | 
			
		||||
  lease_fee_base_sat: number; // fixed lease fee in sats
 | 
			
		||||
  channel_fee_max_rate: number; // max routing fee rate in parts-per-thousandth
 | 
			
		||||
  channel_fee_max_base: number; // max routing base fee in milli-sats
 | 
			
		||||
  compact_lease?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function parseLiquidityAdHex(compact_lease: string): ILiquidityAd | false {
 | 
			
		||||
  if (!compact_lease || compact_lease.length < 20 || compact_lease.length > 28) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  try {
 | 
			
		||||
    const liquidityAd: ILiquidityAd = {
 | 
			
		||||
      funding_weight: parseInt(compact_lease.slice(0, 4), 16),
 | 
			
		||||
      lease_fee_basis: parseInt(compact_lease.slice(4, 8), 16),
 | 
			
		||||
      channel_fee_max_rate: parseInt(compact_lease.slice(8, 12), 16),
 | 
			
		||||
      lease_fee_base_sat: parseInt(compact_lease.slice(12, 20), 16),
 | 
			
		||||
      channel_fee_max_base: compact_lease.length > 20 ? parseInt(compact_lease.slice(20), 16) : 0,
 | 
			
		||||
    }
 | 
			
		||||
    if (Object.values(liquidityAd).reduce((valid: boolean, value: number): boolean => (valid && !isNaN(value) && value >= 0), true)) {
 | 
			
		||||
      liquidityAd.compact_lease = compact_lease;
 | 
			
		||||
      return liquidityAd;
 | 
			
		||||
    } else {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -127,19 +127,84 @@
 | 
			
		||||
 | 
			
		||||
  <div *ngIf="hasDetails" [hidden]="!showDetails" id="details" class="details mt-3">
 | 
			
		||||
    <div class="box">
 | 
			
		||||
      <h5 class="mb-3" i18n="node.tlv.records">TLV extension records</h5>
 | 
			
		||||
      <div class="row">
 | 
			
		||||
        <div class="col">
 | 
			
		||||
          <table class="table table-borderless table-striped">
 | 
			
		||||
            <tbody>
 | 
			
		||||
              <tr *ngFor="let recordItem of node.custom_records | keyvalue">
 | 
			
		||||
                <td class="tlv-type">{{ recordItem.key }}</td>
 | 
			
		||||
                <td class="tlv-payload">{{ recordItem.value }}</td>
 | 
			
		||||
              </tr>
 | 
			
		||||
            </tbody>
 | 
			
		||||
          </table>
 | 
			
		||||
      <ng-template [ngIf]="liquidityAd">
 | 
			
		||||
        <div class="detail-section">
 | 
			
		||||
          <h5 class="mb-3" i18n="node.liquidity-ad">Liquidity ad</h5>
 | 
			
		||||
          <div class="row">
 | 
			
		||||
            <div class="col-md">
 | 
			
		||||
              <table class="table table-borderless table-striped">
 | 
			
		||||
                <tbody>
 | 
			
		||||
                  <tr>
 | 
			
		||||
                    <td class="label" i18n="liquidity-ad.lease-fee-rate|Liquidity ad lease fee rate">Lease fee rate</td>
 | 
			
		||||
                    <td>
 | 
			
		||||
                      <span class="d-inline-block">
 | 
			
		||||
                        {{ liquidityAd.lease_fee_basis !== null ? ((liquidityAd.lease_fee_basis * 1000) | amountShortener : 2 : undefined : true) : '-' }} <span class="symbol">ppm {{ liquidityAd.lease_fee_basis !== null ? '(' + (liquidityAd.lease_fee_basis / 10 | amountShortener : 2 : undefined : true) + '%)' : '' }}</span>
 | 
			
		||||
                      </span>
 | 
			
		||||
                    </td>
 | 
			
		||||
                  </tr>
 | 
			
		||||
                  <tr>
 | 
			
		||||
                    <td class="label" i18n="liquidity-ad.lease-base-fee">Lease base fee</td>
 | 
			
		||||
                    <td>
 | 
			
		||||
                      <app-sats [valueOverride]="liquidityAd.lease_fee_base_sat === null ? '- ' : undefined" [satoshis]="liquidityAd.lease_fee_base_sat"></app-sats>
 | 
			
		||||
                    </td>
 | 
			
		||||
                  </tr>
 | 
			
		||||
                  <tr>
 | 
			
		||||
                    <td class="label" i18n="liquidity-ad.funding-weight">Funding weight</td>
 | 
			
		||||
                    <td [innerHTML]="'‎' + (liquidityAd.funding_weight | wuBytes: 2)"></td>
 | 
			
		||||
                  </tr>
 | 
			
		||||
                </tbody>
 | 
			
		||||
              </table>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="col-md">
 | 
			
		||||
              <table class="table table-borderless table-striped">
 | 
			
		||||
                <tbody>
 | 
			
		||||
                  <tr>
 | 
			
		||||
                    <td class="label" i18n="liquidity-ad.channel-fee-rate|Liquidity ad channel fee rate">Channel fee rate</td>
 | 
			
		||||
                    <td>
 | 
			
		||||
                      <span class="d-inline-block">
 | 
			
		||||
                        {{ liquidityAd.channel_fee_max_rate !== null ? ((liquidityAd.channel_fee_max_rate * 1000) | amountShortener : 2 : undefined : true) : '-' }} <span class="symbol">ppm {{ liquidityAd.channel_fee_max_rate !== null ? '(' + (liquidityAd.channel_fee_max_rate / 10 | amountShortener : 2 : undefined : true) + '%)' : '' }}</span>
 | 
			
		||||
                      </span>
 | 
			
		||||
                    </td>
 | 
			
		||||
                  </tr>
 | 
			
		||||
                  <tr>
 | 
			
		||||
                    <td class="label" i18n="liquidity-ad.channel-base-fee">Channel base fee</td>
 | 
			
		||||
                    <td>
 | 
			
		||||
                      <span *ngIf="liquidityAd.channel_fee_max_base !== null">
 | 
			
		||||
                        {{ liquidityAd.channel_fee_max_base | amountShortener : 0 }}
 | 
			
		||||
                        <span class="symbol" i18n="shared.m-sats">mSats</span>
 | 
			
		||||
                      </span>
 | 
			
		||||
                      <span *ngIf="liquidityAd.channel_fee_max_base === null">
 | 
			
		||||
                        -
 | 
			
		||||
                      </span>
 | 
			
		||||
                    </td>
 | 
			
		||||
                  </tr>
 | 
			
		||||
                  <tr>
 | 
			
		||||
                    <td class="label" i18n="liquidity-ad.compact-lease">Compact lease</td>
 | 
			
		||||
                    <td class="compact-lease">{{ liquidityAd.compact_lease }}</td>
 | 
			
		||||
                  </tr>
 | 
			
		||||
                </tbody>
 | 
			
		||||
              </table>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      </ng-template>
 | 
			
		||||
      <ng-template [ngIf]="tlvRecords?.length">
 | 
			
		||||
        <div class="detail-section">
 | 
			
		||||
          <h5 class="mb-3" i18n="node.tlv.records">TLV extension records</h5>
 | 
			
		||||
          <div class="row">
 | 
			
		||||
            <div class="col">
 | 
			
		||||
              <table class="table table-borderless table-striped">
 | 
			
		||||
                <tbody>
 | 
			
		||||
                  <tr *ngFor="let recordItem of tlvRecords">
 | 
			
		||||
                    <td class="tlv-type">{{ recordItem.type }}</td>
 | 
			
		||||
                    <td class="tlv-payload">{{ recordItem.payload }}</td>
 | 
			
		||||
                  </tr>
 | 
			
		||||
                </tbody>
 | 
			
		||||
              </table>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </ng-template>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -73,17 +73,31 @@ app-fiat {
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.details tbody {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
.details {
 | 
			
		||||
 | 
			
		||||
  .detail-section {
 | 
			
		||||
    margin-bottom: 1.5rem;
 | 
			
		||||
    &:last-child {
 | 
			
		||||
      margin-bottom: 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .tlv-type {
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    color: #ffffff66;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .tlv-payload {
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    word-break: break-all;
 | 
			
		||||
    white-space: normal;
 | 
			
		||||
    font-family: "Courier New", Courier, monospace;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .compact-lease {
 | 
			
		||||
    word-break: break-all;
 | 
			
		||||
    white-space: normal;
 | 
			
		||||
    font-family: "Courier New", Courier, monospace;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,12 @@ import { catchError, map, switchMap, tap } from 'rxjs/operators';
 | 
			
		||||
import { SeoService } from '../../services/seo.service';
 | 
			
		||||
import { LightningApiService } from '../lightning-api.service';
 | 
			
		||||
import { GeolocationData } from '../../shared/components/geolocation/geolocation.component';
 | 
			
		||||
import { ILiquidityAd, parseLiquidityAdHex } from './liquidity-ad';
 | 
			
		||||
 | 
			
		||||
interface CustomRecord {
 | 
			
		||||
  type: string;
 | 
			
		||||
  payload: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-node',
 | 
			
		||||
@ -26,6 +32,8 @@ export class NodeComponent implements OnInit {
 | 
			
		||||
  torSocketCount = 0;
 | 
			
		||||
  hasDetails = false;
 | 
			
		||||
  showDetails = false;
 | 
			
		||||
  liquidityAd: ILiquidityAd;
 | 
			
		||||
  tlvRecords: CustomRecord[];
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private lightningApiService: LightningApiService,
 | 
			
		||||
@ -38,6 +46,8 @@ export class NodeComponent implements OnInit {
 | 
			
		||||
      .pipe(
 | 
			
		||||
        switchMap((params: ParamMap) => {
 | 
			
		||||
          this.publicKey = params.get('public_key');
 | 
			
		||||
          this.tlvRecords = [];
 | 
			
		||||
          this.liquidityAd = null;
 | 
			
		||||
          return this.lightningApiService.getNode$(params.get('public_key'));
 | 
			
		||||
        }),
 | 
			
		||||
        map((node) => {
 | 
			
		||||
@ -83,6 +93,23 @@ export class NodeComponent implements OnInit {
 | 
			
		||||
        }),
 | 
			
		||||
        tap((node) => {
 | 
			
		||||
          this.hasDetails = Object.keys(node.custom_records).length > 0;
 | 
			
		||||
          for (const [type, payload] of Object.entries(node.custom_records)) {
 | 
			
		||||
            if (typeof payload !== 'string') {
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let parsed = false;
 | 
			
		||||
            if (type === '1') {
 | 
			
		||||
              const ad = parseLiquidityAdHex(payload);
 | 
			
		||||
              if (ad) {
 | 
			
		||||
                parsed = true;
 | 
			
		||||
                this.liquidityAd = ad;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            if (!parsed) {
 | 
			
		||||
              this.tlvRecords.push({ type, payload });
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }),
 | 
			
		||||
        catchError(err => {
 | 
			
		||||
          this.error = err;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user