$(document).ready(function () {const defaultSettings = { settings: { exchanges: 'binance', marketplaces: 'opensea', priceAs: 'fiat', currency: 'USD', displayETHTotal: false, isMasked: false }, address: { eth: [], sol: [], abs: [] }, token: { pengu: { total: 0 } }, collections: { pudgyrods: { contract_address: '0x062e691c2054de82f28008a8ccc6d7a1c8ce060d', slug: 'pudgyrods', qty: 0 }, lilpudgys: { contract_address: '0x524cab2ec69124574082676e6f654a18df49a048', slug: 'lilpudgys', qty: 0 }, pudgypenguins: { contract_address: '0xbd3531da5cf5857e7cfaa92426877b022e612cf8', slug: 'pudgypenguins', qty: 0 } } }; let userData = JSON.parse(localStorage.getItem('userData')); if (!userData) { userData = defaultSettings; localStorage.setItem('userData', JSON.stringify(userData)); let $popoverElement = $('#firstWelcomeLink'); $popoverElement.popover(); $popoverElement.popover('show'); setTimeout(function () { $popoverElement.popover('hide'); }, 5500); } function updateData() { const $dataElements = $('[data-sync-key]'); userData = JSON.parse(localStorage.getItem('userData')); $dataElements.addClass('skeleton-bg'); if (userData.settings.isMasked == false){ $('#pengu_amount').text(userData.token.pengu.total.toLocaleString('en-US')); $('#qty_pudgypenguins').text(userData.collections.pudgypenguins.qty); $('#qty_lilpudgys').text(userData.collections.lilpudgys.qty); $('#qty_pudgyrods').text(userData.collections.pudgyrods.qty); } $('#pengu_amount').data('original', userData.token.pengu.total.toLocaleString('en-US')); $('#qty_pudgypenguins').data('original', userData.collections.pudgypenguins.qty); $('#qty_lilpudgys').data('original', userData.collections.lilpudgys.qty); $('#qty_pudgyrods').data('original', userData.collections.pudgyrods.qty); $.ajax({ url: '/ajax/hb', method: 'POST', data: { huddle_xFkiLamdyJgamk:'e9d55c75c18c8ab8bb90df80fbff2646', data: userData, }, success: function (data) { var response = jQuery.parseJSON(data); if (userData.settings.isMasked == false){ $('#total_eth_amount').text(response?.data?.Z9W2M5X3); $('#total_fiat').text($('#total_fiat').data('prefix') + response?.data?.Y4C6L7J9); }else{ $('#total_fiat').data('original', response?.data?.Y4C6L7J9); $('#total_eth_amount').data('original', response?.data?.Z9W2M5X3); } $('#floor_pudgypenguins').text(response?.data?.J9B4M7K2); $('#floor_lilpudgys').text(response?.data?.O3F7M9X4); $('#floor_pudgyrods').text(response?.data?.T8B4J9P3); if (userData.settings.priceAs == 'fiat') { if (userData.settings.isMasked == false){ $('#total_pudgypenguins').text(response?.data?.M8D9C4N7); $('#total_lilpudgys').text(response?.data?.R1M3Y7L6); $('#total_pudgyrods').text(response?.data?.W3Y9X5M1); $('#total_pengu_fiat').text(response?.data?.E4L7C2Z6); } $('#total_pudgypenguins').data('original', response?.data?.M8D9C4N7); $('#total_lilpudgys').data('original', response?.data?.R1M3Y7L6); $('#total_pudgyrods').data('original', response?.data?.W3Y9X5M1); $('#total_pengu_fiat').data('original', response?.data?.E4L7C2Z6); }else{ if (userData.settings.isMasked == false){ $('#total_pudgypenguins').text(response?.data?.N2P6L1J3); $('#total_lilpudgys').text(response?.data?.S6X5C2N9); $('#total_pudgyrods').text(response?.data?.X2P4B8T6); $('#total_pengu_fiat').text(response?.data?.A5N3Y6V4); } $('#total_pudgypenguins').data('original', response?.data?.N2P6L1J3); $('#total_lilpudgys').data('original', response?.data?.S6X5C2N9); $('#total_pudgyrods').data('original', response?.data?.X2P4B8T6); $('#total_pengu_fiat').data('original', response?.data?.A5N3Y6V4); } $('#pengu_price_fiat').text(response?.data?.B9D6W3P8); $('#huddle_price').text(response?.data?.G3W5P8D2); $('#eth_price').text(response?.data?.H7C2X9M4); $('#sol_price').text(response?.data?.BJK79HBM); setTimeout(() => { $dataElements.removeClass('skeleton-bg'); }, 500); }, error: function () { $dataElements.removeClass('skeleton-bg'); } }); } let pollingInterval; const pollingTime = 5000; const pollingUrl = '/ajax/update'; function resetCountdownBar() { const $bar = $('#countdown-bar'); $bar.removeClass('animate'); void $bar[0].offsetWidth; $bar.addClass('animate'); } function startPolling() { resetCountdownBar(); updateData(); if (pollingInterval) return; pollingInterval = setInterval(() => { resetCountdownBar(); updateData(); }, pollingTime); } function stopPolling() { clearInterval(pollingInterval); pollingInterval = null; $('#countdown-bar').removeClass('animate'); } function updateCurrencyLabel() { const priceAs = userData.settings.priceAs; const currency = userData.settings.currency; $('.main_currency_label').text(currency); if (priceAs === 'fiat') { $('.currency_label').text(currency); $('.pengu_total_currency_label').text(currency); } else { $('.currency_label').text('ETH'); $('.pengu_total_currency_label').text('SOL'); } } function updateSetting(key, value) { userData.settings[key] = value; localStorage.setItem('userData', JSON.stringify(userData)); if (key !== 'isMasked') { updateData(); } } function getSelectedSettings() { return userData.settings; } function debounce(func, wait) { let timeout; return function (...args) { const later = () => { clearTimeout(timeout); func.apply(this, args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } function updatePillStyle($pill, selected) { const brandColor = $pill.data('brand-color'); const $img = $pill.find('img'); if ($img.length) { let src = $img.attr('src'); let srcset = $img.attr('srcset'); if (selected) { src = src.replace(/\/([^\/]+?)(?:_on)?(@\dx\.png)/, '/$1_on$2'); srcset = srcset.replace(/\/([^\/]+?)(?:_on)?(@\dx\.png)/g, '/$1_on$2'); } else { src = src.replace(/_on(?=@\dx\.png)/, ''); srcset = srcset.replace(/_on(?=@\dx\.png)/g, ''); } $img.attr('src', src); $img.attr('srcset', srcset); } $pill.css({ backgroundColor: selected ? brandColor : '#fff', border: selected ? `1px solid ${brandColor}` : '0px' }); } function restoreSelections() { const settings = userData.settings; ['exchanges', 'marketplaces', 'priceAs'].forEach(key => { const attr = key === 'priceAs' ? 'price-as' : key; $(`[data-${attr}]`).each(function () { const $pill = $(this); if ($pill.data(attr) === settings[key]) { $pill.addClass('selected'); updatePillStyle($pill, true); } }); }); $('#fm_currency').val(settings.currency); $('input[name="displayETHTotal"]').prop('checked', settings.displayETHTotal); $('#total_eth').toggle(settings.displayETHTotal); applyMasking(settings.isMasked); updateCurrencyLabel(); } function applyMasking(isMasked) { if (isMasked) { $('#showhideeye').removeClass('uil-eye').addClass('uil-eye-slash'); $('[data-maskable]').each(function () { const $this = $(this); const prefix = $this.data('prefix') || ''; const len = $this.data('len') || 6; const masked = '*'.repeat(len); $this.text(prefix + masked); }); } else { $('#showhideeye').removeClass('uil-eye-slash').addClass('uil-eye'); $('[data-maskable]').each(function () { const $this = $(this); const prefix = $this.data('prefix') || ''; const original = $this.data('original'); $this.text(prefix + original); }); } } function masking() { const isEyeVisible = $('#showhideeye').hasClass('uil-eye'); const newState = isEyeVisible; $('#showhideeye').toggleClass('uil-eye uil-eye-slash'); $('[data-maskable]').each(function () { const $this = $(this); const prefix = $this.data('prefix') || ''; const original = $this.data('original'); const len = $this.data('len') || 6; if (isEyeVisible) { const masked = '*'.repeat(len); $this.text(prefix + masked); } else { $this.text(prefix + original); } }); updateSetting('isMasked', newState); } $('#showhideeye').on('click', masking); $('.option-pill').on('click', function () { const $pill = $(this); const $row = $pill.closest('.option-row'); $row.find('.option-pill').each(function () { $(this).removeClass('selected'); updatePillStyle($(this), false); }); $pill.addClass('selected'); updatePillStyle($pill, true); ['exchanges', 'marketplaces', 'price-as'].forEach(attr => { const value = $pill.data(attr); if (value !== undefined) { const key = attr === 'price-as' ? 'priceAs' : attr; updateSetting(key, value); } }); updateCurrencyLabel(); }); $('#fm_currency').on('change', function () { updateSetting('currency', $(this).val()); updateCurrencyLabel(); }); $('input[name="displayETHTotal"]').on('change', function () { const isChecked = $(this).is(':checked'); updateSetting('displayETHTotal', isChecked); $('#total_eth').toggle(isChecked); }); $('#offcanvas-settings').on('shown.bs.offcanvas', function () { stopPolling(); }); $('#offcanvas-settings').on('hidden.bs.offcanvas', function () { startPolling(); }); $('#modal-wallet').on('shown.bs.modal', function () { stopPolling(); }); $('#modal-wallet').on('hidden.bs.modal', function () { startPolling(); }); restoreSelections(); startPolling(); $('#captureBtn').on('click', function () { const captureArea = document.querySelector('#captureArea'); html2canvas(captureArea).then(canvas => { canvas.toBlob(blob => { const imgFile = new File([blob], 'my-huddle-value.png', { type: 'image/png' }); if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) { if (navigator.canShare && navigator.canShare({ files: [imgFile] })) { navigator.share({ files: [imgFile], title: 'My Huddle Value' }).then(() => { $('#statusMessage').text('Image shared successfully!'); }).catch(err => { console.error('Sharing failed:', err); $('#statusMessage').text('Failed to share the image.'); }); } else { $('#statusMessage').text('Sharing not supported on this device.'); } } else { if (navigator.clipboard && navigator.clipboard.write) { const clipboardItem = new ClipboardItem({ 'image/png': blob }); navigator.clipboard.write([clipboardItem]).then(() => { $('#statusMessage').text('Image copied to clipboard!'); }).catch(err => { console.error('Failed to copy:', err); $('#statusMessage').text('Failed to copy image.'); }); } else { console.error('Clipboard API not supported.'); $('#statusMessage').text('Clipboard API not supported.'); } } }, 'image/png'); }).catch(err => { console.error('Error capturing the area:', err); $('#statusMessage').text('Error capturing the area.'); }); }); const $input = $('#fm_wallet_address'); const $button = $('#address_form button'); const $result = $('#wallet_result'); $input.on('input', debounce(function () { const address = $input.val().trim(); $button.prop('disabled', !(address.length >= 32 && address.length <= 44)); if (address.length < 32) return; let walletType = null; if (/^0x[a-fA-F0-9]{40}$/.test(address)) { walletType = 'eth'; } else if (/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address)) { walletType = 'sol'; } else { return; } $input.addClass('input-loading'); if (userData.address[walletType]?.some(w => w.wallet === address)) { $input.removeClass('input-loading'); return; } $.ajax({ url: '/ajax/wallet', method: 'POST', data: { huddle_xFkiLamdyJgamk:'e9d55c75c18c8ab8bb90df80fbff2646', address: address, walletType: walletType }, success: function (data) { $input.removeClass('input-loading'); var response = jQuery.parseJSON(data); if (!userData.address[response.return.type].some(w => w.wallet === response.return.wallet)) { const walletType = response.return.type; const wallet = response.return.wallet; const balances = response.return.balances; const balanceObj = {}; let iconsHTML = ""; balances.forEach(bal => { const quantity = parseInt(bal.quantity || 0); if (quantity === 0) return; if (bal.type === 'token') { userData.token.pengu.total += quantity; balanceObj[bal.name] = quantity; const penguFormatted = formatPengu(quantity); iconsHTML += createWalletIcon( "/assets/img/0xbd3531da5cf5857e7cfaa92426877b022e612cf8.avif", penguFormatted, "50%" ); } else if (bal.type === 'nft') { if (userData.collections[bal.name]) { userData.collections[bal.name].qty += quantity; balanceObj[bal.name] = quantity; const logoSlug = userData.collections[bal.name].contract_address; iconsHTML += createWalletIcon( `/assets/img/${logoSlug}.avif`, quantity, "5px" ); } } }); userData.address[walletType].push({ wallet: wallet, balance: balanceObj }); localStorage.setItem('userData', JSON.stringify(userData)); let walletLogo = "https://cdn.huddle.is/assets/img/eth-logo.png"; if (walletType === "sol") walletLogo = "https://cdn.huddle.is/assets/img/sol-logo.png"; else if (walletType === "abs") walletLogo = "https://cdn.huddle.is/assets/img/abs_logo.png"; const html = createWalletHTML(wallet, walletLogo, iconsHTML, walletType); $('#linked_wallets').append(html); $('#linked_wallet_area').show(); $('#fm_wallet_address').val(''); setTimeout(() => { if (typeof bootstrap !== 'undefined') { var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl); }); } }, 100); } updateData(); }, error: function () { $input.removeClass('input-loading'); } }); })); function formatPengu(pengu) { const num = parseFloat(pengu); if (num >= 1e6) return (num / 1e6).toFixed(1) + 'M'; if (num >= 1e3) return (num / 1e3).toFixed(1) + 'K'; return num.toString(); } function createWalletIcon(imgSrc, tooltip, radius) { return `
`; } function createWalletHTML(wallet, logoSrc, iconsHTML, walletType) { return `
${wallet.slice(0, 6)}...${wallet.slice(-4)}
${iconsHTML}
`; } let addressData = userData.address; let collections = userData.collections; const $container = $("#linked_wallets"); $container.empty(); const collectionLogos = { pudgypenguins: "0xbd3531da5cf5857e7cfaa92426877b022e612cf8.avif", lilpudgys: "0x524cab2ec69124574082676e6f654a18df49a048.avif", pudgyrods: "0x062e691c2054de82f28008a8ccc6d7a1c8ce060d.avif" }; (addressData.eth || []).forEach(function (walletObj) { const wallet = walletObj.wallet; const balances = walletObj.balance || {}; let iconsHTML = ""; ["pudgypenguins", "lilpudgys", "pudgyrods"].forEach(function (key) { const count = parseInt(balances[key] || 0); if (count > 0) { const logo = `/assets/img/${collectionLogos[key]}`; iconsHTML += createWalletIcon(logo, count, "5px"); } }); if (balances.pengu) { const penguValue = formatPengu(balances.pengu); const penguLogo = `/assets/img/${collectionLogos.pudgypenguins}`; iconsHTML += createWalletIcon(penguLogo, penguValue, "50%"); } const html = createWalletHTML(wallet, "https://cdn.huddle.is/assets/img/eth-logo.png", iconsHTML, 'eth'); $container.append(html); }); (addressData.sol || []).forEach(function (walletObj) { const wallet = walletObj.wallet; const pengu = walletObj.balance?.pengu || 0; const badgeText = formatPengu(pengu); const iconsHTML = createWalletIcon( '/assets/img/'+collectionLogos.pudgypenguins, badgeText, "50%" ); const html = createWalletHTML(wallet, "https://cdn.huddle.is/assets/img/sol-logo.png", iconsHTML, 'sol'); $container.append(html); }); if ($container.children().length > 0) { $("#linked_wallet_area").show(); } else { $("#linked_wallet_area").hide(); } setTimeout(() => { if (typeof bootstrap !== 'undefined') { var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl); }); } }, 100); $(document).on('click', '.uil-times-circle', function () { const $walletEntry = $(this).closest('.wallet-entry'); const walletAddress = $walletEntry.data('wallet-address'); const walletType = $walletEntry.data('wallet-type'); let userData = JSON.parse(localStorage.getItem('userData')) || {}; if (userData.address && userData.address[walletType]) { const walletIndex = userData.address[walletType].findIndex(w => w.wallet === walletAddress); if (walletIndex > -1) { const walletObj = userData.address[walletType][walletIndex]; const balances = walletObj.balance || {}; if (balances.pengu && userData.token && userData.token.pengu) { userData.token.pengu.total -= parseInt(balances.pengu); if (userData.token.pengu.total < 0) userData.token.pengu.total = 0; } Object.keys(balances).forEach(key => { if (userData.collections && userData.collections[key]) { userData.collections[key].qty -= parseInt(balances[key]); if (userData.collections[key].qty < 0 || isNaN(userData.collections[key].qty)) { userData.collections[key].qty = 0; } } }); userData.address[walletType].splice(walletIndex, 1); } localStorage.setItem('userData', JSON.stringify(userData)); updateData(); } $walletEntry.remove(); }); $(document).on('click', '.wallet-entry .uil-sync', function () { const $entry = $(this).closest('.wallet-entry'); const walletAddress = $entry.data('wallet-address'); const walletType = $entry.data('wallet-type'); $.ajax({ url: '/ajax/wallet', method: 'POST', data: { huddle_xFkiLamdyJgamk: 'e9d55c75c18c8ab8bb90df80fbff2646', address: walletAddress, walletType: walletType }, success: function (data) { const response = $.parseJSON(data); if (response.st === 1) { const result = response.return; if (userData.address[result.type]) { userData.address[result.type] = userData.address[result.type].filter(w => { if (w.wallet === result.wallet) { const balance = w.balance || {}; for (const [key, value] of Object.entries(balance)) { const qty = parseInt(value); if (key === 'pengu') { userData.token.pengu.total -= qty; if (userData.token.pengu.total < 0) userData.token.pengu.total = 0; } else if (userData.collections[key]) { userData.collections[key].qty -= qty; if (userData.collections[key].qty < 0) userData.collections[key].qty = 0; } } return false; } return true; }); } const balanceObj = {}; let iconsHTML = ''; result.balances.forEach(bal => { if (bal.type === 'token') { const qty = parseInt(bal.quantity); if (qty > 0) { balanceObj[bal.name] = qty; userData.token.pengu.total += qty; iconsHTML += createWalletIcon( "/assets/img/0xbd3531da5cf5857e7cfaa92426877b022e612cf8.avif", formatPengu(qty), "50%" ); } } else if (bal.type === 'nft') { const qty = parseInt(bal.quantity); if (qty > 0 && userData.collections[bal.name]) { balanceObj[bal.name] = qty; userData.collections[bal.name].qty += qty; const contract = userData.collections[bal.name].contract_address; iconsHTML += createWalletIcon(`/assets/img/${contract}.avif`, qty, "5px"); } } }); userData.address[result.type].push({ wallet: result.wallet, balance: balanceObj }); localStorage.setItem('userData', JSON.stringify(userData)); const updatedHTML = createWalletHTML(result.wallet, result.type === 'eth' ? 'https://cdn.huddle.is/assets/img/eth-logo.png' : result.type === 'sol' ? 'https://cdn.huddle.is/assets/img/sol-logo.png' : 'https://cdn.huddle.is/assets/img/abs-logo.png', iconsHTML, result.type ); $entry.replaceWith(updatedHTML); updateData(); setTimeout(() => { if (typeof bootstrap !== 'undefined') { var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl); }); } }, 100); } } }); }); $(window).on('beforeunload', stopPolling); });