1var connectWalletButton = document.querySelector('#btn-connect'); 2var bragButton = document.querySelector('#btn-brag'); 3var contentPostBrag = document.querySelector('#content-post-brag'); 4var contentPostBragGas = document.querySelector('#content-post-brag-gas'); 5var contentMain = document.querySelector('#content-main'); 6var contentFooter = document.querySelector('#content-footer'); 7var bragText = document.querySelector('#textarea-field'); 8var bragLikeButton; 9var bragReplyText; 10var bragReplyButton; 11var bragDetailButton; 12var account; 13var config; 14 15const cfg_payForLike = false; 16 17if (typeof window.ethereum !== 'undefined') { 18 console.log("Web3 detected!"); 19 20 connectWalletButton.addEventListener('click', () => { 21 window.ethereum.enable(); 22 getAccount(); 23 }); 24 25 async function getAccount() { 26 const accounts = await window.ethereum.request({ method: 'eth_accounts' }); 27 account = accounts[0]; 28 let accountDialog = document.getElementById("dialog-account"); 29 30 if (account == undefined) { 31 connectWalletButton.innerHTML = "Connect"; 32 connectWalletButton.classList.remove('btn-success'); 33 connectWalletButton.classList.add('btn-outline-primary'); 34 bragButton.innerHTML = "not connected"; 35 bragButton.classList.remove('is-primary'); 36 bragButton.classList.add('is-disabled'); 37 bragReplyButton = document.querySelectorAll("#btn-brag-reply"); 38 bragReplyButton.forEach(element => { 39 element.innerHTML = "not connected"; 40 element.classList.remove('is-primary'); 41 element.classList.add('is-disabled'); 42 }); 43 } 44 else { 45 /*function showLackingBratModal() { 46 document.getElementById('dialog-lacking-brat').showModal(); 47 }*/ 48 connectWalletButton.innerHTML = account.slice(0,5)+"..."+account.slice(38); 49 connectWalletButton.classList.remove('btn-outline-primary'); 50 connectWalletButton.classList.add('btn-success'); 51 52 window.getBratBalance(account).then(balance => { 53 if (balance < 1) { 54 bragButton.innerHTML = "not enough $BRAT"; 55 bragButton.classList.remove('is-primary'); 56 bragButton.classList.add('is-disabled'); 57 //bragButton.addEventListener("click",showLackingBratModal()); 58 bragReplyButton = document.querySelectorAll("#btn-brag-reply"); 59 bragReplyButton.forEach(element => { 60 element.innerHTML = "not enough $BRAT"; 61 element.classList.remove('is-primary'); 62 element.classList.add('is-disabled'); 63 //element.addEventListener("click",showLackingBratModal()); 64 }); 65 } 66 else { 67 bragButton.innerHTML = "braggg"; 68 bragButton.classList.remove('is-disabled'); 69 bragButton.classList.add('is-primary'); 70 //bragButton.removeEventListener("click",showLackingBratModal()); 71 bragReplyButton = document.querySelectorAll("#btn-brag-reply"); 72 bragReplyButton.forEach(element => { 73 element.innerHTML = "Braggg Reply"; 74 element.classList.remove('is-disabled'); 75 element.classList.add('is-primary'); 76 //bragButton.removeEventListener("click",showLackingBratModal()); 77 }); 78 } 79 window.getBragAddrIds(account).then(bragIds => { 80 let rank = judgeRank(balance); 81 accountDialog.children[0].children[0].innerHTML = 'Hi '+ account.slice(0,5)+"..."+account.slice(38) +'!'; 82 accountDialog.children[0].children[1].innerHTML = 83 '<span>Balance: '+balance+' BRAT</span><br><span>RANK: <span class="nes-text '+rank['class']+'">'+rank['title']+'</span>'+ 84 '</span><br><span>Brags: '+bragIds.length+'</span>'; 85 }); 86 }); 87 88 bragButton.addEventListener('click', () => { 89 window.postBrag(bragText.value,0).then(txId => { 90 window.waitForTx(txId).then(result => { 91 console.log(result); 92 }); 93 }); 94 }); 95 96 forceChain(); 97 } 98 } 99 100 async function forceChain() { 101 fetch('./js/config.json') 102 .then((response) => response.json()) 103 .then(async function(config) { 104 var params = { 105 chainId: config.networks[config.activeNetwork].chainId, 106 chainName: config.networks[config.activeNetwork].chainName, 107 nativeCurrency: config.networks[config.activeNetwork].nativeCurrency, 108 rpcUrls: config.networks[config.activeNetwork].rpcUrls, 109 blockExplorerUrls: config.networks[config.activeNetwork].blockExplorerUrls, 110 }; 111 112 113 let result = await window.ethereum.request({ 114 method: 'wallet_addEthereumChain', 115 params: [params], 116 }); 117 return result; 118 }); 119 } 120 121 document.addEventListener("DOMContentLoaded", function(){ 122 getAccount(); 123 124 }); 125 126 ethereum.on('accountsChanged', (accounts) => { 127 getAccount(); 128 }); 129 130 ethereum.on('chainChanged', (chainId) => { 131 forceChain(); 132 getAccount(); 133 console.log("ChainId: "+chainId); 134 }); 135 136 bragText.addEventListener('change', () => { 137 contentPostBragGas.innerHTML = "calculating" 138 window.calcGas(bragText.value).then(gasValue => { 139 contentPostBragGas.innerHTML = "Cost: \~"+gasValue/1e9*20+" ETH ("+gasValue+")"; // auto load gas Price?? 140 }); 141 }); 142} 143 144/****************************************/ 145/************* LOAD BRAGS ***************/ 146/****************************************/ 147 148function renderBrag(result,isReply=false,replyLevel=0,charLimit=false) { 149 var safeText = result['text'].replace(/[\u00A0-\u9999<>\&]/g, function(i) { 150 return '&#'+i.charCodeAt(0)+';'; 151 }); 152 safeText = safeText.replace(/\n/g, "<br>"); 153 if (charLimit != false) { 154 safeText = (safeText.length > charLimit) ? safeText.substring(0, charLimit)+' <span class="nes-text is-primary">show more...</span>' : safeText; 155 } 156 var isLiked = (result['liked'] == true) ? " is-liked" : ""; 157 var isReply = (isReply == true) ? " reply"+replyLevel : ""; 158 var timestamp = timeDifference(result['timestamp']); 159 160 var rank = judgeRank(result['bratbalance']); 161 162 brag = 163 '<div class="nes-container with-title'+isReply+'" data-bragid="'+result['id']+'">\n'+ 164 '<span class="title">\n<a href="#u/'+result['owner']+'">'+ 165 result['owner'].slice(0,9)+"..."+result['owner'].slice(38)+ 166 '</a> '+timestamp+':</span>\n'+ 167 '<p class="text" onclick="window.location=\'#b/'+result['id']+'\'">'+safeText+'</p>\n'+ 168 '<span hidden>'+result['replies']+'</span>\n'+ 169 '<i class="nes-icon is-small thumbs-up'+isLiked+'"></i>\n'+ 170 '<span>'+result['likes']+'</span>\n'+ 171 '<a class="nes-badge"><span class="'+rank['class']+'">'+rank['title']+'</span></a>'+ 172 '<button class="nes-btn brags details">\n<span>></span>\n</button>\n'+ 173 '</div>\n'+ 174 '<div class="nes-container brag-details" data-detailid="'+result['id']+'" hidden>\n'+ 175 '<p class="text">Brag ID: <span>'+result['id']+'</span></br>\n'+ 176 'Tx ID: <span>...</span></br>\n'+ 177 'Date: <span>
177'+new Date(result['timestamp'] * 1000).toLocaleString()+'</span></br>\n'+ 178 '</p></div>'; 179 180 return brag; 181} 182 183function seasonBragButtons() { 184 bragLikeButton = document.querySelectorAll(".thumbs-up"); 185 bragLikeButton.forEach(element => { 186 if (!element.classList.contains("is-liked")) { 187 element.addEventListener("click", function(e) { 188 189 let bragId = e.target.parentNode.dataset.bragid; 190 191 if (cfg_payForLike) { 192 document.getElementById('dialog-like-step1').showModal(); 193 window.approveBrat("1").then(txId => { 194 window.waitForTx(txId).then(result => { 195 if (result) { 196 document.getElementById('dialog-like-step1').close(); 197 document.getElementById('dialog-like-step2').showModal(); 198 window.postLike(bragId).then(txId => { 199 window.waitForTx(txId).then(result => { 200 if (result) { 201 document.getElementById('dialog-like-step2').close(); 202 document.getElementById('dialog-like-success').showModal(); 203 } 204 else console.log(result); 205 }); 206 }); 207 } 208 else console.log("failed"); 209 }); 210 }); 211 } 212 else { 213 window.postLike(bragId).then(txId => { 214 console.log("number1: "+txId) 215 window.waitForTx(txId).then(result => { 216 console.log("number2: "+txId) 217 if (result) { 218 document.getElementById('dialog-like-success').showModal(); 219 } 220 else console.log(result); 221 }); 222 }); 223 } 224 }); 225 } 226 else { 227 // we don't do unlikes 228 } 229 }); 230 231 bragDetailButton = document.querySelectorAll(".details"); 232 bragDetailButton.forEach(element => { 233 element.addEventListener("click", function(e) { 234 var bragId = e.target.parentNode.dataset.bragid; 235 var detailDiv = document.querySelector('[data-detailid="'+bragId+'"]'); 236 if (detailDiv.hidden) { 237 detailDiv.hidden = false; 238 window.getBragTx(bragId).then(txId => { 239 if (txId == 0) { 240 detailDiv.querySelector("span:nth-child(3)").innerHTML = "n/a" 241 } 242 else { 243 detailDiv.querySelector("span:nth-child(3)").innerHTML = '<a href="https://etherscan.io/tx/'+txId+'" target="_blank">'+txId+'</a>'; 244 } 245 }); 246 } 247 else { 248 detailDiv.hidden = true; 249 } 250 }); 251 }); 252 return 253} 254 255function timeDifference(timestamp) { 256 257 var msPerMinute = 60 * 1000; 258 var msPerHour = msPerMinute * 60; 259 var msPerDay = msPerHour * 24; 260 var msPerMonth = msPerDay * 30; 261 var msPerYear = msPerDay * 365; 262 263 var elapsed = Date.now() - timestamp*1000; 264 var result; 265 266 if (elapsed < msPerMinute) { 267 result = Math.round(elapsed/1000); 268 if (result == 1) return result + ' second ago'; 269 else return result + ' seconds ago'; 270 } 271 else if (elapsed < msPerHour) { 272 result = Math.round(elapsed/msPerMinute); 273 if (result == 1) return result + ' minute ago'; 274 else return result + ' minutes ago'; 275 } 276 else if (elapsed < msPerDay ) { 277 result = Math.round(elapsed/msPerHour); 278 if (result == 1) return result + ' hour ago'; 279 else return result + ' hours ago'; 280 } 281 else if (elapsed < msPerMonth) { 282 result = Math.round(elapsed/msPerDay); 283 if (result == 1) return result + ' day ago'; 284 else return result + ' days ago'; 285 } 286 else if (elapsed < msPerYear) { 287 result = Math.round(elapsed/msPerMonth); 288 if (result == 1) return result + ' month ago'; 289 else return result + ' months ago'; 290 } 291 else { 292 result = Math.round(elapsed/msPerYear); 293 if (result == 1) return result + ' year ago'; 294 else return result + ' years ago'; 295 } 296} 297 298/*function judgeRank (balance) { 299 var rank = new Array(); 300 var factor = 1000; 301 if (balance < 1*factor) { rank['title'] = "Shrimp"; rank['class'] = "is-dark"; } 302 else if (balance >= 1*factor && balance < 5*factor) { rank['title'] = "Guppy"; rank['class'] = "is-dark"; } 303 else if (balance >= 5*factor && balance < 10*factor) { rank['title'] = "Flounder"; rank['class'] = "is-primary"; } 304 else if (balance >= 10*factor && balance < 20*factor) { rank['title'] = "Mackerel"; rank['class'] = "is-primary"; } 305 else if (balance >= 20*factor && balance < 50*factor) { rank['title'] = "Barracuda"; rank['class'] = "is-success"; } 306 else if (balance >= 50*factor && balance < 200*factor) { rank['title'] = "Dolphin"; rank['class'] = "is-success"; } 307 else if (balance >= 200*factor && balance < 1000*factor) { rank['title'] = "Shark"; rank['class'] = "is-warning"; } 308 else if (balance >= 1000*factor && balance < 10000*factor) { rank['title'] = "Giant Squid"; rank['class'] = "is-warning"; } 309 else if (balance >= 10000*factor) { rank['title'] = "Whale"; rank['class'] = "is-error"; } 310 return rank 311}*/ 312 313function judgeRank (balance) { 314 var rank = new Array(); 315 var factor = 1000; 316 if (balance < 1*factor) { rank['title'] = "Micro Peewee"; rank['class'] = "is-dark"; } 317 else if (balance >= 1*factor && balance < 5*factor) { rank['title'] = "Timid Twig"; rank['class'] = "is-dark"; } 318 else if (balance >= 5*factor && balance < 10*factor) { rank['title'] = "Petite Pepper"; rank['class'] = "is-primary"; } 319 else if (balance >= 10*factor && balance < 20*factor) { rank['title'] = "Modest Meat"; rank['class'] = "is-primary"; } 320 else if (balance >= 20*factor && balance < 50*factor) { rank['title'] = "Confid Cucumb"; rank['class'] = "is-success"; } 321 else if (balance >= 50*factor && balance < 200*factor) { rank['title'] = "Big Boy Wurst"; rank['class'] = "is-success"; } 322 else if (balance >= 200*factor && balance < 1000*factor) { rank['title'] = "Major Shlong"; rank['class'] = "is-warning"; } 323 else if (balance >= 1000*factor && balance < 10000*factor) { rank['title'] = "Giant Gherkin"; rank['class'] = "is-warning"; } 324 else if (balance >= 10000*factor) { rank['title'] = "Titanic T-Bone"; rank['class'] = "is-error"; } 325 return rank 326} 327 328window.getRecentBrags = async function(limit,offset=0) { 329 const start = Date.now(); 330 var brag_section = document.querySelector('#brags'); 331 var loading_text = document.querySelector('#loading-text'); 332 333 window.getCurrentBragId().then(currentId => { // 12 334 currentId = currentId-1-offset; 335 if (limit > currentId) limit = currentId+1; 336 337 // fetch recent brags from Blockchain 338 var brags = new Array(); 339 for (let i=currentId; i>(currentId-limit); i--) { 340 brags[i] = window.fetchBragData(i,account); 341 } 342 console.log(`Execution time: ${Date.now() - start} ms`) 343 brags.reverse(); 344 345 Promise.all(brags) 346 .then((results) => { 347 if (offset == 0) { 348 brag_section.innerHTML = '<h2 id="about" class="recent-brags"><a href="">#</a>Recent Brags</h2>'; 349 } 350 else { 351 document.querySelector('.show-more').remove(); 352 } 353 354 for (let result of results) { 355 if (result !== undefined) { 356 brag_section.innerHTML += renderBrag(result,false,0,280); 357 } 358 } 359 360 if (currentId >= 0) { 361 brag_section.innerHTML += '<div class="nes-text is-primary show-more">\n'+ 362 '<span>show more brags</span>\n</div>\n'; 363 var showMoreButton = document.querySelector('.show-more'); 364 showMoreButton.addEventListener('click', () => { 365 document.querySelector('.show-more > span').classList.add("dot-typing"); 366 window.getRecentBrags(limit,offset+limit); 367 }); 368 } 369 else { 370 brag_section.innerHTML += '<div class="nes-text" style="text-align:center;">\n'+ 371 '<span>no more brags to show</span>\n</div>\n'; 372 } 373 374 seasonBragButtons(); 375 const end = Date.now(); 376 console.log(`Execution time: ${end - start} ms`); 377 }); 378 }); 379} 380 381window.getBragsByAddress = async function(address,limit,offset=0) { 382 const start = Date.now(); 383 let brag_section = document.querySelector('#brags'); 384 let loading = document.querySelector('.loading'); 385 386 let brags = new Array(); 387 388 window.getBragAddrIds(address).then(bragIds => { // 12 389 bragIds.sort(function(a, b){return b - a}); 390 391 maxBrags = limit+offset>bragIds.length ? bragIds.length : limit+offset; 392 393 let i = offset; // 394 for (; i < maxBrags; i++) { // 5 5-10 395 brags[i] = window.fetchBragData(bragIds[i],account); 396 } 397 398 Promise.all(brags) 399 .then((results) => { 400 if (offset == 0) { 401 brag_section.innerHTML = '<h2 id="about" class="recent-brags"><a href="">#</a>
401Brags by '+address+'</h2>'; 402 } 403 else { 404 document.querySelector('.show-more').remove(); 405 } 406 407 for (const result of results) { 408 if (result !== undefined) { 409 brag_section.innerHTML += renderBrag(result); 410 } 411 } 412 413 if (i == maxBrags) { 414 brag_section.innerHTML += '<div class="nes-text is-primary show-more">\n'+ 415 '<span>show more brags</span>\n</div>\n'; 416 var showMoreButton = document.querySelector('.show-more'); 417 showMoreButton.addEventListener('click', () => { 418 document.querySelector('.show-more > span').classList.add("dot-typing"); 419 window.getBragsByAddress(address,limit,offset+limit); 420 }); 421 } 422 else { 423 brag_section.innerHTML += '<div class="nes-text" style="text-align:center;">\n'+ 424 '<span>no more brags to show</span>\n</div>\n'; 425 } 426 427 seasonBragButtons(); 428 const end = Date.now(); 429 console.log(`Execution time: ${end - start} ms`); 430 }); 431 }); 432} 433 434window.getBragReplies = async function(originalBragId,limit,offset=0) { 435 const start = Date.now(); 436 let brag_section = document.querySelector('#brags'); 437 let loading = document.querySelector('.loading'); 438 439 let brags = new Array(); 440 441 window.getBragReplyIds(originalBragId).then(bragIds => { 442 bragIds.sort(function(a, b){return b - a}); 443 console.log(bragIds); 444 445 maxBrags = limit+offset>bragIds.length ? bragIds.length : limit+offset; 446 447 let i = offset; // 448 for (; i < maxBrags; i++) { // 5 5-10 449 brags[i] = window.fetchBragData(bragIds[i],account); 450 } 451 452 Promise.all(brags) 453 .then((results) => { 454 if (offset == 0) { 455 } 456 else { 457 document.querySelector('.show-more').remove(); 458 } 459 460 for (const result of results) { 461 if (result !== undefined) { 462 brag_section.innerHTML += renderBrag(result,true); 463 } 464 } 465 console.log(i); 466 if (i == maxBrags) { 467 brag_section.innerHTML += '<div class="nes-text is-primary show-more">\n'+ 468 '<span>show more brags</span>\n</div>\n'; 469 var showMoreButton = document.querySelector('.show-more'); 470 showMoreButton.addEventListener('click', () => { 471 document.querySelector('.show-more > span').classList.add("dot-typing"); 472 window.getBragReplies(originalBragId,limit,offset+limit); 473 }); 474 } 475 else { 476 brag_section.innerHTML += '<div class="nes-text" style="text-align:center;">\n'+ 477 '<span>no more brags to show</span>\n</div>\n'; 478 } 479 480 seasonBragButtons(); 481 const end = Date.now(); 482 console.log(`Execution time: ${end - start} ms`); 483 }); 484 }); 485} 486 487/****************************************/ 488/*************** PROFILE ****************/ 489/****************************************/ 490 491 492 493/****************************************/ 494/**************** PAGES *****************/ 495/****************************************/ 496 497function getPage() { 498 fireText(); 499 var pathname = new String(window.location.hash); 500 501 fetch('./js/config.json') 502 .then((response) => response.json()) 503 .then(async function(data) { 504 config = data; 505 }); 506 507 if (pathname == "") { 508 document.addEventListener("DOMContentLoaded", function(){ 509 contentPostBrag.hidden = false; 510 window.getRecentBrags(5); 511 }); 512 } 513 else if (pathname.substring(0,3) == "#u/") { 514 515 const regex = new RegExp('^0x[a-fA-F0-9]{40}$'); 516 if (regex.test(pathname.substring(3,45))) { 517 contentPostBrag.hidden = true; 518 let address = pathname.substring(3,45); 519 window.getBragsByAddress(address,5); 520 } 521 else { 522 // 404 523 } 524 } 525 else if (pathname.substring(0,3) == "#b/") { 526 527 const regex = new RegExp("^[0-9]\\d*$"); 528 const i = pathname.replace('#b/',''); 529 if (regex.test(i)) { 530 contentPostBrag.hidden = true; 531 var brag_section = document.querySelector('#brags'); 532 brag_section.innerHTML = '<div class="loading">\n<img src="img/mana.gif">\n<p id="loading-text">loading...</p>\n</div>'; 533 534 window.fetchBragData(i).then(result => { 535 brag_section.innerHTML = renderBrag(result); 536 //window.getBragReplies(i,5); 537 }); 538 } 539 else { 540 // 404 541 } 542 } 543 else if (pathname.substring(0,10) == "#whitelist") { 544 fetch("templates/whitelist.html").then(response => { 545 contentPostBrag.hidden = true; 546 response.text().then(html => { 547 contentMain.innerHTML = html; 548 }); 549 }); 550 } 551 else if (pathname.substring(0,5) == "#brat") { 552 fetch("templates/brat.html").then(response => { 553 contentPostBrag.hidden = true; 554 response.text().then(html => { 555 556 window.getSaleRoundDetails().then(result => { 557 contentMain.innerHTML = html; 558 let roundBlock = document.querySelector('[data-round="'+result['currentRound']+'"]'); 559 560 let progress = roundBlock.children[1].children[1]; 561 progress.value = (result['roundTotalAmount']-result['roundAmountLeft'])*100/result['roundTotalAmount']; 562 563 let amountSold = roundBlock.children[1].children[2]; 564 amountSold.innerHTML = result['roundTotalAmount']-result['roundAmountLeft']; 565 566 let amountTotal = roundBlock.children[1].children[3]; 567 amountTotal.innerHTML = result['roundTotalAmount']; 568 569 let maxUserAmount = roundBlock.children[3].children[1]; 570 maxUserAmount.innerHTML = result['maxUserAmount']; 571 572 var buyButton = document.querySelector('#btn-buy'); 573 buyButton.addEventListener('click', () => { 574 window.saleBuy("0").then(txId => { 575 window.waitForTx(txId).then(result => { 576 console.log(result); 577 }); 578 }); 579 }); 580 581 }); 582 }); 583 }); 584 } 585 else if (pathname.substring(0,4) == "#api") { 586 fetch("templates/api.html").then(response => { 587 contentPostBrag.hidden = true; 588 response.text().then(html => { 589 contentMain.innerHTML = html; 590 }); 591 }); 592 } 593 //console.log(window.location.hash); 594} 595 596getPage(); 597window.addEventListener('hashchange', function () { 598 getPage(); 599}); 600 601function fireText() { 602 console.log( 603 " /$$ "+ '\n' + 604 "| $$ "+ '\n' + 605 "| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ "+ '\n' + 606 "| $$__ $$ /$$__ $$|____ $$ /$$__ $$ /$$__ $$ /$$__ $$ /$$__ $$"+ '\n' + 607 "| $$ \\ $$| $$ \\__/ /$$$$$$$| $$ \\ $$| $$ \\ $$| $$$$$$$$| $$ \\__/"+ '\n' + 608 "| $$ | $$| $$ /$$__ $$| $$ | $$| $$ | $$| $$_____/| $$ "+ '\n' + 609 "| $$$$$$$/| $$ | $$$$$$$| $$$$$$$| $$$$$$$| $$$$$$$| $$ "+ '\n' + 610 "|_______/ |__/ \\_______/ \\____ $$ \\____ $$ \\_______/|__/ "+ '\n' + 611 " /$$ \\ $$ /$$ \\ $$ "+ '\n' + 612 " | $$$$$$/| $$$$$$/ "+ '\n' + 613 " \\______/ \\______/ "); 614} 615
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.