Merge branch 'master' into nymkappa/bugfix/remove-1mb-node-capacity
This commit is contained in:
		
						commit
						a14565e288
					
				| @ -5,7 +5,7 @@ class NodesApi { | |||||||
|   public async $getNode(public_key: string): Promise<any> { |   public async $getNode(public_key: string): Promise<any> { | ||||||
|     try { |     try { | ||||||
|       const query = ` |       const query = ` | ||||||
|         SELECT nodes.*, geo_names_as.names as as_organization, geo_names_city.names as city, |         SELECT nodes.*, geo_names_iso.names as iso_code, geo_names_as.names as as_organization, geo_names_city.names as city, | ||||||
|         geo_names_country.names as country, geo_names_subdivision.names as subdivision, |         geo_names_country.names as country, geo_names_subdivision.names as subdivision, | ||||||
|           (SELECT Count(*) |           (SELECT Count(*) | ||||||
|           FROM channels |           FROM channels | ||||||
| @ -24,6 +24,7 @@ class NodesApi { | |||||||
|         LEFT JOIN geo_names geo_names_city on geo_names_city.id = city_id |         LEFT JOIN geo_names geo_names_city on geo_names_city.id = city_id | ||||||
|         LEFT JOIN geo_names geo_names_subdivision on geo_names_subdivision.id = subdivision_id |         LEFT JOIN geo_names geo_names_subdivision on geo_names_subdivision.id = subdivision_id | ||||||
|         LEFT JOIN geo_names geo_names_country on geo_names_country.id = country_id |         LEFT JOIN geo_names geo_names_country on geo_names_country.id = country_id | ||||||
|  |         LEFT JOIN geo_names geo_names_iso ON geo_names_iso.id = nodes.country_id AND geo_names_iso.type = 'country_iso_code' | ||||||
|         WHERE public_key = ? |         WHERE public_key = ? | ||||||
|       `;
 |       `;
 | ||||||
|       const [rows]: any = await DB.query(query, [public_key, public_key, public_key, public_key, public_key, public_key, public_key, public_key, public_key]); |       const [rows]: any = await DB.query(query, [public_key, public_key, public_key, public_key, public_key, public_key, public_key, public_key, public_key]); | ||||||
|  | |||||||
| @ -5,9 +5,9 @@ const P2SH_P2WSH_COST  = 35 * 4; // the WU cost for the non-witness part of P2SH | |||||||
| 
 | 
 | ||||||
| export function calcSegwitFeeGains(tx: Transaction) { | export function calcSegwitFeeGains(tx: Transaction) { | ||||||
|   // calculated in weight units
 |   // calculated in weight units
 | ||||||
|   let realizedBech32Gains = 0; |   let realizedSegwitGains = 0; | ||||||
|   let potentialBech32Gains = 0; |   let potentialSegwitGains = 0; | ||||||
|   let potentialP2shGains = 0; |   let potentialP2shSegwitGains = 0; | ||||||
|   let potentialTaprootGains = 0; |   let potentialTaprootGains = 0; | ||||||
|   let realizedTaprootGains = 0; |   let realizedTaprootGains = 0; | ||||||
| 
 | 
 | ||||||
| @ -24,31 +24,33 @@ export function calcSegwitFeeGains(tx: Transaction) { | |||||||
|     const isP2tr         = vin.prevout.scriptpubkey_type === 'v1_p2tr'; |     const isP2tr         = vin.prevout.scriptpubkey_type === 'v1_p2tr'; | ||||||
| 
 | 
 | ||||||
|     const op = vin.scriptsig ? vin.scriptsig_asm.split(' ')[0] : null; |     const op = vin.scriptsig ? vin.scriptsig_asm.split(' ')[0] : null; | ||||||
|     const isP2sh2Wpkh = isP2sh && !!vin.witness && op === 'OP_PUSHBYTES_22'; |     const isP2shP2Wpkh = isP2sh && !!vin.witness && op === 'OP_PUSHBYTES_22'; | ||||||
|     const isP2sh2Wsh  = isP2sh && !!vin.witness && op === 'OP_PUSHBYTES_34'; |     const isP2shP2Wsh  = isP2sh && !!vin.witness && op === 'OP_PUSHBYTES_34'; | ||||||
| 
 | 
 | ||||||
|     switch (true) { |     switch (true) { | ||||||
|       // Native Segwit - P2WPKH/P2WSH (Bech32)
 |       // Native Segwit - P2WPKH/P2WSH/P2TR
 | ||||||
|       case isP2wpkh: |       case isP2wpkh: | ||||||
|       case isP2wsh: |       case isP2wsh: | ||||||
|       case isP2tr: |       case isP2tr: | ||||||
|         // maximal gains: the scriptSig is moved entirely to the witness part
 |         // maximal gains: the scriptSig is moved entirely to the witness part
 | ||||||
|         realizedBech32Gains += witnessSize(vin) * 3; |         // if taproot is used savings are 42 WU higher because it produces smaller signatures and doesn't require a pubkey in the witness
 | ||||||
|  |         // this number is explained above `realizedTaprootGains += 42;`
 | ||||||
|  |         realizedSegwitGains += (witnessSize(vin) + (isP2tr ? 42 : 0)) * 3; | ||||||
|         // XXX P2WSH output creation is more expensive, should we take this into consideration?
 |         // XXX P2WSH output creation is more expensive, should we take this into consideration?
 | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|       // Backward compatible Segwit - P2SH-P2WPKH
 |       // Backward compatible Segwit - P2SH-P2WPKH
 | ||||||
|       case isP2sh2Wpkh: |       case isP2shP2Wpkh: | ||||||
|         // the scriptSig is moved to the witness, but we have extra 21 extra non-witness bytes (48 WU)
 |         // the scriptSig is moved to the witness, but we have extra 21 extra non-witness bytes (84 WU)
 | ||||||
|         realizedBech32Gains += witnessSize(vin) * 3 - P2SH_P2WPKH_COST; |         realizedSegwitGains += witnessSize(vin) * 3 - P2SH_P2WPKH_COST; | ||||||
|         potentialBech32Gains += P2SH_P2WPKH_COST; |         potentialSegwitGains += P2SH_P2WPKH_COST; | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|       // Backward compatible Segwit - P2SH-P2WSH
 |       // Backward compatible Segwit - P2SH-P2WSH
 | ||||||
|       case isP2sh2Wsh: |       case isP2shP2Wsh: | ||||||
|         // the scriptSig is moved to the witness, but we have extra 35 extra non-witness bytes
 |         // the scriptSig is moved to the witness, but we have extra 35 extra non-witness bytes (140 WU)
 | ||||||
|         realizedBech32Gains += witnessSize(vin) * 3 - P2SH_P2WSH_COST; |         realizedSegwitGains += witnessSize(vin) * 3 - P2SH_P2WSH_COST; | ||||||
|         potentialBech32Gains += P2SH_P2WSH_COST; |         potentialSegwitGains += P2SH_P2WSH_COST; | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|       // Non-segwit P2PKH/P2SH/P2PK/bare multisig
 |       // Non-segwit P2PKH/P2SH/P2PK/bare multisig
 | ||||||
| @ -56,9 +58,13 @@ export function calcSegwitFeeGains(tx: Transaction) { | |||||||
|       case isP2sh: |       case isP2sh: | ||||||
|       case isP2pk: |       case isP2pk: | ||||||
|       case isBareMultisig: { |       case isBareMultisig: { | ||||||
|         const fullGains = scriptSigSize(vin) * 3; |         let fullGains = scriptSigSize(vin) * 3; | ||||||
|         potentialBech32Gains += fullGains; |         if (isBareMultisig) { | ||||||
|         potentialP2shGains += fullGains - (isP2pkh ? P2SH_P2WPKH_COST : P2SH_P2WSH_COST); |           // a _bare_ multisig has the keys in the output script, but P2SH and P2WSH require them to be in the scriptSig/scriptWitness
 | ||||||
|  |           fullGains -= vin.prevout.scriptpubkey.length / 2; | ||||||
|  |         } | ||||||
|  |         potentialSegwitGains += fullGains; | ||||||
|  |         potentialP2shSegwitGains += fullGains - (isP2pkh ? P2SH_P2WPKH_COST : P2SH_P2WSH_COST); | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @ -79,11 +85,11 @@ export function calcSegwitFeeGains(tx: Transaction) { | |||||||
|         // TODO maybe add some complex scripts that are specified somewhere, so that size is known, such as lightning scripts
 |         // TODO maybe add some complex scripts that are specified somewhere, so that size is known, such as lightning scripts
 | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       const script = isP2sh2Wsh || isP2wsh ? vin.inner_witnessscript_asm : vin.inner_redeemscript_asm; |       const script = isP2shP2Wsh || isP2wsh ? vin.inner_witnessscript_asm : vin.inner_redeemscript_asm; | ||||||
|       let replacementSize: number; |       let replacementSize: number; | ||||||
|       if ( |       if ( | ||||||
|         // single sig
 |         // single sig
 | ||||||
|         isP2pk || isP2pkh || isP2wpkh || isP2sh2Wpkh || |         isP2pk || isP2pkh || isP2wpkh || isP2shP2Wpkh || | ||||||
|         // multisig
 |         // multisig
 | ||||||
|         isBareMultisig || parseMultisigScript(script) |         isBareMultisig || parseMultisigScript(script) | ||||||
|       ) { |       ) { | ||||||
| @ -105,11 +111,11 @@ export function calcSegwitFeeGains(tx: Transaction) { | |||||||
| 
 | 
 | ||||||
|   // returned as percentage of the total tx weight
 |   // returned as percentage of the total tx weight
 | ||||||
|   return { |   return { | ||||||
|     realizedBech32Gains: realizedBech32Gains / (tx.weight + realizedBech32Gains), // percent of the pre-segwit tx size
 |     realizedSegwitGains: realizedSegwitGains / (tx.weight + realizedSegwitGains), // percent of the pre-segwit tx size
 | ||||||
|     potentialBech32Gains: potentialBech32Gains / tx.weight, |     potentialSegwitGains: potentialSegwitGains / tx.weight, | ||||||
|     potentialP2shGains: potentialP2shGains / tx.weight, |     potentialP2shSegwitGains: potentialP2shSegwitGains / tx.weight, | ||||||
|     potentialTaprootGains: potentialTaprootGains / tx.weight, |     potentialTaprootGains: potentialTaprootGains / tx.weight, | ||||||
|     realizedTaprootGains: realizedTaprootGains / tx.weight |     realizedTaprootGains: realizedTaprootGains / (tx.weight + realizedTaprootGains) | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -188,12 +194,12 @@ export function moveDec(num: number, n: number) { | |||||||
|   return neg + (int || '0') + (frac.length ? '.' + frac : ''); |   return neg + (int || '0') + (frac.length ? '.' + frac : ''); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function zeros(n) { | function zeros(n: number) { | ||||||
|   return new Array(n + 1).join('0'); |   return new Array(n + 1).join('0'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Formats a number for display. Treats the number as a string to avoid rounding errors.
 | // Formats a number for display. Treats the number as a string to avoid rounding errors.
 | ||||||
| export const formatNumber = (s, precision = null) => { | export const formatNumber = (s: number | string, precision: number | null = null) => { | ||||||
|   let [ whole, dec ] = s.toString().split('.'); |   let [ whole, dec ] = s.toString().split('.'); | ||||||
| 
 | 
 | ||||||
|   // divide numbers into groups of three separated with a thin space (U+202F, "NARROW NO-BREAK SPACE"),
 |   // divide numbers into groups of three separated with a thin space (U+202F, "NARROW NO-BREAK SPACE"),
 | ||||||
| @ -219,27 +225,27 @@ const witnessSize = (vin: Vin) => vin.witness ? vin.witness.reduce((S, w) => S + | |||||||
| const scriptSigSize = (vin: Vin) => vin.scriptsig ? vin.scriptsig.length / 2 : 0; | const scriptSigSize = (vin: Vin) => vin.scriptsig ? vin.scriptsig.length / 2 : 0; | ||||||
| 
 | 
 | ||||||
| // Power of ten wrapper
 | // Power of ten wrapper
 | ||||||
| export function selectPowerOfTen(val: number) { | export function selectPowerOfTen(val: number): { divider: number, unit: string } { | ||||||
|   const powerOfTen = { |   const powerOfTen = { | ||||||
|     exa: Math.pow(10, 18), |     exa: Math.pow(10, 18), | ||||||
|     peta: Math.pow(10, 15), |     peta: Math.pow(10, 15), | ||||||
|     terra: Math.pow(10, 12), |     tera: Math.pow(10, 12), | ||||||
|     giga: Math.pow(10, 9), |     giga: Math.pow(10, 9), | ||||||
|     mega: Math.pow(10, 6), |     mega: Math.pow(10, 6), | ||||||
|     kilo: Math.pow(10, 3), |     kilo: Math.pow(10, 3), | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let selectedPowerOfTen; |   let selectedPowerOfTen: { divider: number, unit: string }; | ||||||
|   if (val < powerOfTen.kilo) { |   if (val < powerOfTen.kilo) { | ||||||
|     selectedPowerOfTen = { divider: 1, unit: '' }; // no scaling
 |     selectedPowerOfTen = { divider: 1, unit: '' }; // no scaling
 | ||||||
|   } else if (val < powerOfTen.mega) { |   } else if (val < powerOfTen.mega) { | ||||||
|     selectedPowerOfTen = { divider: powerOfTen.kilo, unit: 'k' }; |     selectedPowerOfTen = { divider: powerOfTen.kilo, unit: 'k' }; | ||||||
|   } else if (val < powerOfTen.giga) { |   } else if (val < powerOfTen.giga) { | ||||||
|     selectedPowerOfTen = { divider: powerOfTen.mega, unit: 'M' }; |     selectedPowerOfTen = { divider: powerOfTen.mega, unit: 'M' }; | ||||||
|   } else if (val < powerOfTen.terra) { |   } else if (val < powerOfTen.tera) { | ||||||
|     selectedPowerOfTen = { divider: powerOfTen.giga, unit: 'G' }; |     selectedPowerOfTen = { divider: powerOfTen.giga, unit: 'G' }; | ||||||
|   } else if (val < powerOfTen.peta) { |   } else if (val < powerOfTen.peta) { | ||||||
|     selectedPowerOfTen = { divider: powerOfTen.terra, unit: 'T' }; |     selectedPowerOfTen = { divider: powerOfTen.tera, unit: 'T' }; | ||||||
|   } else if (val < powerOfTen.exa) { |   } else if (val < powerOfTen.exa) { | ||||||
|     selectedPowerOfTen = { divider: powerOfTen.peta, unit: 'P' }; |     selectedPowerOfTen = { divider: powerOfTen.peta, unit: 'P' }; | ||||||
|   } else { |   } else { | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| <span *ngIf="segwitGains.realizedBech32Gains && !segwitGains.potentialBech32Gains; else segwitTwo" class="badge badge-success mr-1" i18n-ngbTooltip="ngbTooltip about segwit gains" ngbTooltip="This transaction saved {{ segwitGains.realizedBech32Gains * 100 | number:  '1.0-0' }}% on fees by using native SegWit-Bech32" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span> | <span *ngIf="segwitGains.realizedSegwitGains && !segwitGains.potentialSegwitGains; else segwitTwo" class="badge badge-success mr-1" i18n-ngbTooltip="ngbTooltip about segwit gains" ngbTooltip="This transaction saved {{ segwitGains.realizedSegwitGains * 100 | number:  '1.0-0' }}% on fees by using native SegWit" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span> | ||||||
| <ng-template #segwitTwo> | <ng-template #segwitTwo> | ||||||
|   <span *ngIf="segwitGains.realizedBech32Gains && segwitGains.potentialBech32Gains; else potentialP2shGains" class="badge badge-warning mr-1" i18n-ngbTooltip="ngbTooltip about double segwit gains" ngbTooltip="This transaction saved {{ segwitGains.realizedBech32Gains * 100 | number:  '1.0-0' }}% on fees by using SegWit and could save {{ segwitGains.potentialBech32Gains * 100 | number : '1.0-0' }}% more by fully upgrading to native SegWit-Bech32" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span> |   <span *ngIf="segwitGains.realizedSegwitGains && segwitGains.potentialSegwitGains; else potentialP2shSegwitGains" class="badge badge-warning mr-1" i18n-ngbTooltip="ngbTooltip about double segwit gains" ngbTooltip="This transaction saved {{ segwitGains.realizedSegwitGains * 100 | number:  '1.0-0' }}% on fees by using SegWit and could save {{ segwitGains.potentialSegwitGains * 100 | number : '1.0-0' }}% more by fully upgrading to native SegWit" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span> | ||||||
|   <ng-template #potentialP2shGains> |   <ng-template #potentialP2shSegwitGains> | ||||||
|     <span *ngIf="segwitGains.potentialP2shGains" class="badge badge-danger mr-1" i18n-ngbTooltip="ngbTooltip about missed out gains" ngbTooltip="This transaction could save {{ segwitGains.potentialBech32Gains * 100 | number : '1.0-0' }}% on fees by upgrading to native SegWit-Bech32 or {{ segwitGains.potentialP2shGains * 100 | number:  '1.0-0' }}% by upgrading to SegWit-P2SH" placement="bottom"><del i18n="tx-features.tag.segwit|SegWit">SegWit</del></span> |     <span *ngIf="segwitGains.potentialP2shSegwitGains" class="badge badge-danger mr-1" i18n-ngbTooltip="ngbTooltip about missed out gains" ngbTooltip="This transaction could save {{ segwitGains.potentialSegwitGains * 100 | number : '1.0-0' }}% on fees by upgrading to native SegWit or {{ segwitGains.potentialP2shSegwitGains * 100 | number:  '1.0-0' }}% by upgrading to SegWit-P2SH" placement="bottom"><del i18n="tx-features.tag.segwit|SegWit">SegWit</del></span> | ||||||
|   </ng-template> |   </ng-template> | ||||||
| </ng-template> | </ng-template> | ||||||
| 
 | 
 | ||||||
| <span *ngIf="segwitGains.realizedTaprootGains && !segwitGains.potentialTaprootGains; else notFullyTaproot" class="badge badge-success mr-1" i18n-ngbTooltip="Tooltip about privacy and fees saved with taproot" ngbTooltip="This transaction uses Taproot and the user's thereby increased privacy and saved at least {{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}% on fees" placement="bottom" i18n="tx-features.tag.taproot|Taproot">Taproot</span> | <span *ngIf="segwitGains.realizedTaprootGains && !segwitGains.potentialTaprootGains; else notFullyTaproot" class="badge badge-success mr-1" i18n-ngbTooltip="Tooltip about privacy and fees saved with taproot" ngbTooltip="This transaction uses Taproot and thereby increased the user's privacy and saved at least {{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}% on fees" placement="bottom" i18n="tx-features.tag.taproot|Taproot">Taproot</span> | ||||||
| <ng-template #notFullyTaproot> | <ng-template #notFullyTaproot> | ||||||
|   <span *ngIf="segwitGains.realizedTaprootGains && segwitGains.potentialTaprootGains; else noTaproot" class="badge badge-warning mr-1" i18n-ngbTooltip="Tooltip about privacy and more fees that could be saved with more taproot" ngbTooltip="This transaction uses Taproot and thereby increased the user's privacy and already saved at least {{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}% on fees, but could save an additional {{ segwitGains.potentialTaprootGains * 100 | number: '1.0-0' }}% by fully using Taproot" placement="bottom" i18n="tx-features.tag.taproot|Taproot">Taproot</span> |   <span *ngIf="segwitGains.realizedTaprootGains && segwitGains.potentialTaprootGains; else noTaproot" class="badge badge-warning mr-1" i18n-ngbTooltip="Tooltip about privacy and more fees that could be saved with more taproot" ngbTooltip="This transaction uses Taproot and thereby increased the user's privacy and already saved at least {{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}% on fees, but could save an additional {{ segwitGains.potentialTaprootGains * 100 | number: '1.0-0' }}% by fully using Taproot" placement="bottom" i18n="tx-features.tag.taproot|Taproot">Taproot</span> | ||||||
|   <ng-template #noTaproot> |   <ng-template #noTaproot> | ||||||
|  | |||||||
| @ -12,9 +12,9 @@ export class TxFeaturesComponent implements OnChanges { | |||||||
|   @Input() tx: Transaction; |   @Input() tx: Transaction; | ||||||
| 
 | 
 | ||||||
|   segwitGains = { |   segwitGains = { | ||||||
|     realizedBech32Gains: 0, |     realizedSegwitGains: 0, | ||||||
|     potentialBech32Gains: 0, |     potentialSegwitGains: 0, | ||||||
|     potentialP2shGains: 0, |     potentialP2shSegwitGains: 0, | ||||||
|     potentialTaprootGains: 0, |     potentialTaprootGains: 0, | ||||||
|     realizedTaprootGains: 0 |     realizedTaprootGains: 0 | ||||||
|   }; |   }; | ||||||
|  | |||||||
| @ -43,11 +43,23 @@ | |||||||
|             </tr> |             </tr> | ||||||
|             <tr *ngIf="node.country && node.city && node.subdivision"> |             <tr *ngIf="node.country && node.city && node.subdivision"> | ||||||
|               <td i18n="location">Location</td> |               <td i18n="location">Location</td> | ||||||
|               <td>{{ node.city.en }}, {{ node.subdivision.en }}<br>{{ node.country.en }}</td> |               <td> | ||||||
|  |                 <span>{{ node.city.en }}, {{ node.subdivision.en }}</span> | ||||||
|  |                 <br> | ||||||
|  |                 <a class="d-flex align-items-center" [routerLink]="['/lightning/nodes/country' | relativeUrl, node.iso_code]"> | ||||||
|  |                   <span class="link">{{ node.country.en }}</span> | ||||||
|  |                     | ||||||
|  |                   <span class="flag">{{ node.flag }}</span> | ||||||
|  |                 </a> | ||||||
|  |               </td> | ||||||
|             </tr> |             </tr> | ||||||
|             <tr *ngIf="node.country && !node.city"> |             <tr *ngIf="node.country && !node.city"> | ||||||
|               <td i18n="location">Location</td> |               <td i18n="location">Location</td> | ||||||
|               <td>{{ node.country.en }}</td> |               <td> | ||||||
|  |                 <a [routerLink]="['/lightning/nodes/country' | relativeUrl, node.iso_code]"> | ||||||
|  |                   {{ node.country.en }} {{ node.flag }} | ||||||
|  |                 </a> | ||||||
|  |               </td> | ||||||
|             </tr> |             </tr> | ||||||
|           </tbody> |           </tbody> | ||||||
|         </table> |         </table> | ||||||
| @ -77,7 +89,9 @@ | |||||||
|             <tr *ngIf="node.country"> |             <tr *ngIf="node.country"> | ||||||
|               <td i18n="isp">ISP</td> |               <td i18n="isp">ISP</td> | ||||||
|               <td> |               <td> | ||||||
|  |                 <a [routerLink]="['/lightning/nodes/isp' | relativeUrl, node.as_number]"> | ||||||
|                   {{ node.as_organization }} [ASN {{node.as_number}}] |                   {{ node.as_organization }} [ASN {{node.as_number}}] | ||||||
|  |                 </a>                 | ||||||
|               </td> |               </td> | ||||||
|             </tr> |             </tr> | ||||||
|           </tbody> |           </tbody> | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ import { ActivatedRoute, ParamMap } from '@angular/router'; | |||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { catchError, map, switchMap } from 'rxjs/operators'; | import { catchError, map, switchMap } from 'rxjs/operators'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from 'src/app/services/seo.service'; | ||||||
|  | import { getFlagEmoji } from 'src/app/shared/graphs.utils'; | ||||||
| import { LightningApiService } from '../lightning-api.service'; | import { LightningApiService } from '../lightning-api.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
| @ -51,6 +52,7 @@ export class NodeComponent implements OnInit { | |||||||
|             } else if (socket.indexOf('onion') > -1) { |             } else if (socket.indexOf('onion') > -1) { | ||||||
|               label = 'Tor'; |               label = 'Tor'; | ||||||
|             } |             } | ||||||
|  |             node.flag = getFlagEmoji(node.iso_code); | ||||||
|             socketsObject.push({ |             socketsObject.push({ | ||||||
|               label: label, |               label: label, | ||||||
|               socket: node.public_key + '@' + socket, |               socket: node.public_key + '@' + socket, | ||||||
|  | |||||||
| @ -92,6 +92,9 @@ export function detectWebGL() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function getFlagEmoji(countryCode) { | export function getFlagEmoji(countryCode) { | ||||||
|  |   if (!countryCode) { | ||||||
|  |     return ''; | ||||||
|  |   } | ||||||
|   const codePoints = countryCode |   const codePoints = countryCode | ||||||
|     .toUpperCase() |     .toUpperCase() | ||||||
|     .split('') |     .split('') | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user