@@ -153,6 +153,7 @@ function setupSingleMutationObserver() {
153
153
setupVisualCues ( processedElements ) ;
154
154
disableSwapTriggers ( processedElements ) ;
155
155
enableSellAndSwapModals ( processedElements ) ;
156
+ obfuscateAddresses ( processedElements ) ;
156
157
} ;
157
158
158
159
// Create one mutation observer for all DOM modifications
@@ -1117,6 +1118,17 @@ const demoCSS = `
1117
1118
display: none;
1118
1119
}
1119
1120
1121
+ /* Demo address tooltip styling */
1122
+ .tooltip.demo-tooltip {
1123
+ width: max-content;
1124
+ background: var(--nimiq-orange-bg);
1125
+ margin-left: -7rem;
1126
+ }
1127
+
1128
+ .tooltip.demo-tooltip::after {
1129
+ background: #fc750c; /* Match the red theme for the demo warning */
1130
+ }
1131
+
1120
1132
.demo-highlight-badge {
1121
1133
position: absolute;
1122
1134
width: 34px;
@@ -1843,3 +1855,78 @@ export class DemoHubApi extends HubApi {
1843
1855
} ) ;
1844
1856
}
1845
1857
}
1858
+
1859
+ /**
1860
+ * Obfuscates addresses in the UI by:
1861
+ * - Showing only first 3 chunks of addresses (rest are XXXX) for NIM addresses
1862
+ * - Showing only the first few characters for BTC and polygon addresses
1863
+ * - Changing the copy tooltip message
1864
+ * - Changing the copy functionality to provide a demo disclaimer
1865
+ */
1866
+ function obfuscateAddresses ( processedElements : WeakSet < HTMLElement > ) {
1867
+ // Adds the common clipboard click handler to an element.
1868
+ function addDemoClickHandler ( el : HTMLElement ) {
1869
+ el . addEventListener ( 'click' , ( e : MouseEvent ) => {
1870
+ e . preventDefault ( ) ;
1871
+ e . stopPropagation ( ) ;
1872
+ el . classList . add ( 'copied' ) ;
1873
+ setTimeout ( ( ) => el . classList . remove ( 'copied' ) , 1500 ) ;
1874
+ navigator . clipboard . writeText ( 'This is a demo address - not for actual use' ) ;
1875
+ } , true ) ;
1876
+ }
1877
+
1878
+ // Updates the tooltip for an element.
1879
+ function updateTooltip ( el : HTMLElement ) {
1880
+ const tooltip = el . querySelector ( '.tooltip' ) as HTMLElement ;
1881
+ if ( tooltip && ! processedElements . has ( tooltip ) ) {
1882
+ processedElements . add ( tooltip ) ;
1883
+ tooltip . textContent = 'Demo address' ;
1884
+ tooltip . classList . add ( 'demo-tooltip' ) ;
1885
+ addDemoClickHandler ( tooltip ) ;
1886
+ }
1887
+ }
1888
+
1889
+ // Processes an element: marks it as processed, applies any extra changes, updates tooltip, and adds a click handler.
1890
+ function processElement ( el : HTMLElement , extraProcess : ( ( el : HTMLElement ) => void ) | null = null ) {
1891
+ if ( processedElements . has ( el ) ) return ;
1892
+ processedElements . add ( el ) ;
1893
+ if ( extraProcess ) extraProcess ( el ) ;
1894
+ updateTooltip ( el ) ;
1895
+ addDemoClickHandler ( el ) ;
1896
+ }
1897
+
1898
+ // Process NIM address displays: obfuscate address chunks beyond the first three.
1899
+ const nimAddressElements = document . querySelectorAll ( '.copyable.address-display' ) as NodeListOf < HTMLElement > ;
1900
+ nimAddressElements . forEach ( el =>
1901
+ processElement ( el , ( element ) => {
1902
+ const chunks = element . querySelectorAll ( '.chunk' ) ;
1903
+ for ( let i = 3 ; i < chunks . length ; i ++ ) {
1904
+ const chunk = chunks [ i ] ;
1905
+ const space = chunk . querySelector ( '.space' ) ;
1906
+ chunk . textContent = 'XXXX' ;
1907
+ if ( space ) chunk . appendChild ( space ) ;
1908
+ }
1909
+ } )
1910
+ ) ;
1911
+
1912
+ // Process short address displays: change the last chunk of the short address.
1913
+ const shortAddressElements = document . querySelectorAll ( '.tooltip.interactive-short-address.is-copyable' ) as NodeListOf < HTMLElement > ;
1914
+ shortAddressElements . forEach ( el =>
1915
+ processElement ( el , ( element ) => {
1916
+ const lastChunk = element . querySelector ( '.short-address .address:last-child' ) ;
1917
+ if ( lastChunk ) {
1918
+ lastChunk . textContent = 'xxxx' ;
1919
+ }
1920
+ } )
1921
+ ) ;
1922
+
1923
+ // Process tooltip boxes inside short address displays.
1924
+ const tooltipBoxElements = document . querySelectorAll ( '.tooltip.interactive-short-address.is-copyable .tooltip-box' ) as NodeListOf < HTMLElement > ;
1925
+ tooltipBoxElements . forEach ( el => {
1926
+ if ( processedElements . has ( el ) ) return ;
1927
+ processedElements . add ( el ) ;
1928
+ el . textContent = 'Demo address' ;
1929
+ el . classList . add ( 'demo-tooltip' ) ;
1930
+ addDemoClickHandler ( el ) ;
1931
+ } ) ;
1932
+ }
0 commit comments