From 279741517ee19661838e9382d542c1236b02ce85 Mon Sep 17 00:00:00 2001 From: rodribp Date: Wed, 12 Aug 2026 00:42:43 -0600 Subject: [PATCH] feat: coldcard warning on transaction page --- .../transactions-list.component.html | 6 ++++ .../transactions-list.component.scss | 16 +++++++++ .../transactions-list.component.ts | 35 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/frontend/src/app/components/transactions-list/transactions-list.component.html b/frontend/src/app/components/transactions-list/transactions-list.component.html index 41633a0a7..542e740b7 100644 --- a/frontend/src/app/components/transactions-list/transactions-list.component.html +++ b/frontend/src/app/components/transactions-list/transactions-list.component.html @@ -21,6 +21,12 @@ Warning! This transaction involves deceptively similar addresses. It may be an address poisoning attack. } + @if (showColdcardWarning) { + + }
diff --git a/frontend/src/app/components/transactions-list/transactions-list.component.scss b/frontend/src/app/components/transactions-list/transactions-list.component.scss index 81b097c47..004adc994 100644 --- a/frontend/src/app/components/transactions-list/transactions-list.component.scss +++ b/frontend/src/app/components/transactions-list/transactions-list.component.scss @@ -416,6 +416,22 @@ h2 { } } +.coldcard-warning { + display: flex; + align-items: center; + position: relative; + background-color: #b71c1c; + border-color: #b71c1c; + a { + color: #fff; + } +} + +.btn-close:hover, +.btn-close:focus { + opacity: 1; +} + @keyframes acceleratePulse { 0% { background-color: #653b9c; box-shadow: #ad7de57f 0px 0px 12px -2px; } 50% { background-color: #8457bb; box-shadow: #ad7de5 0px 0px 18px -2px;} diff --git a/frontend/src/app/components/transactions-list/transactions-list.component.ts b/frontend/src/app/components/transactions-list/transactions-list.component.ts index 45659a5b6..a83b8dc18 100644 --- a/frontend/src/app/components/transactions-list/transactions-list.component.ts +++ b/frontend/src/app/components/transactions-list/transactions-list.component.ts @@ -72,6 +72,7 @@ export class TransactionsListComponent implements OnInit, OnChanges, OnDestroy { showTaprootControlBlock: { [vinIndex: number]: boolean } = {}; showOrdData: { [key: string]: { show: boolean; inscriptions?: Inscription[]; runestone?: Runestone, runeInfo?: { [id: string]: { etching: Etching; txid: string; } }; } } = {}; similarityMatches: Map> = new Map(); + showColdcardWarning: boolean = false; selectedSig: { txIndex: number, vindex: number, sig: SigInfo } | null = null; sigHighlights: { vin: boolean[], vout: boolean[] } = { vin: [], vout: [] }; @@ -186,6 +187,7 @@ export class TransactionsListComponent implements OnInit, OnChanges, OnDestroy { }); this.updateAddressSimilarities(); + this.updateShowColdcardWarning(); } refreshPrice(): void { @@ -476,6 +478,33 @@ export class TransactionsListComponent implements OnInit, OnChanges, OnDestroy { } } + updateShowColdcardWarning(): void { + const showCCWarningPref = this.storageService.getValue('showTxColdcardWarning'); + // there's only one tx, it's the tx page, it's unconfirmed, it contains inputs that are p2sh, v0_p2wsh or p2sh-p2wsh, is multisig and network is mainnet + if (showCCWarningPref && showCCWarningPref === 'false') { + return; + } + + if (!this.transactionPage || this.txPreview) { + return; + } + + if (this.transactions.length > 1 || this.transactions[0].status.confirmed) { + return; + } + + const vinPossibleCC: Vin[] = this.transactions[0].vin.filter((input: Vin) => { + const addressTypeInfo = new AddressTypeInfo(this.network || 'mainnet', input.prevout.scriptpubkey_address, input.prevout?.scriptpubkey_type as AddressType, [input]); + return ['p2sh', 'v0_p2wsh', 'p2sh-p2wsh'].includes(addressTypeInfo.type) && !!addressTypeInfo.isMultisig && addressTypeInfo.network === 'mainnet'; + }); + + if (vinPossibleCC.length === 0) { + return; + } + + this.showColdcardWarning = true; + } + // assume any address with 12 or more contiguous repeated substrings is fake fakeScriptHashRegex = new RegExp(/(.+?)\1{11,}/); isFakeScripthash(vout: Vout): boolean { @@ -713,6 +742,12 @@ export class TransactionsListComponent implements OnInit, OnChanges, OnDestroy { } } + dismissWarning(): void { + this.storageService.setValue('showTxColdcardWarning', 'false'); + this.showColdcardWarning = false; + this.ref.markForCheck(); + } + ngOnDestroy(): void { this.outspendsSubscription.unsubscribe(); this.currencyChangeSubscription?.unsubscribe();