<!DOCTYPE html>
<head>
- <meta lang="en" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <script>
- let Account, Bip44Wallet, Blake2bWallet, LedgerWallet, SendBlock, ReceiveBlock, ChangeBlock, rpc, Rolodex, Xel
- const observer = new MutationObserver((mutations) => {
- for (const mutation of mutations) {
- if (mutation.type === "attributes") {
- mutation.target.dispatchEvent(new Event('attributeschanged'))
- }
- }
- })
- function load () {
- loadUi().then(loadNemo).then(loadUx).then(() => { console.log('done') })
- }
- async function loadUi () {
- console.log('loading xel')
- Xel = await import('https://unpkg.com/xel@latest')
- await Xel.whenThemeReady
- setTimeout(() => {
- document.getElementsByTagName('body')[0].style.visibility = 'visible'
- }, 250)
- console.log('loaded xel')
- }
- async function loadNemo () {
- console.log('loading libnemo')
- await ({ Account, Bip44Wallet, Blake2bWallet, LedgerWallet, SendBlock, ReceiveBlock, ChangeBlock, Node: rpc, Rolodex } = await import('https://unpkg.com/libnemo@latest'))
- console.log('loaded libnemo')
- }
- async function loadUx () {
- if (location.hash) {
- const page = document.querySelector(location.hash)
- page.classList.add('show')
- } else {
- location += '#transact'
- }
- }
- function switchPage (evt) {
- console.log(evt)
- const oldHash = new URL(evt.oldURL)?.hash
- const newHash = new URL(evt.newURL)?.hash
- if (oldHash) {
- document.querySelector(oldHash).classList.remove('show')
- }
- if (newHash) {
- document.querySelector(newHash).classList.add('show')
- }
- }
- function getWalletType (type) {
- switch (type) {
- case 'blake2b': {
- return Blake2bWallet
- }
- case 'bip44':
- default: {
- return Bip44Wallet
- }
- }
- }
+ <meta lang="en" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <script>
+ let Account, Bip44Wallet, Blake2bWallet, LedgerWallet, SendBlock, ReceiveBlock, ChangeBlock, rpc, Rolodex, Xel
+ const observer = new MutationObserver((mutations) => {
+ for (const mutation of mutations) {
+ if (mutation.type === "attributes") {
+ mutation.target.dispatchEvent(new Event('attributeschanged'))
+ }
+ }
+ })
+ function load () {
+ loadUi().then(loadNemo).then(loadUx).then(() => { console.log('done') })
+ }
+ async function loadUi () {
+ console.log('loading xel')
+ Xel = await import('https://unpkg.com/xel@latest')
+ await Xel.whenThemeReady
+ setTimeout(() => {
+ document.getElementsByTagName('body')[0].style.visibility = 'visible'
+ }, 250)
+ console.log('loaded xel')
+ }
+ async function loadNemo () {
+ console.log('loading libnemo')
+ await ({ Account, Bip44Wallet, Blake2bWallet, LedgerWallet, SendBlock, ReceiveBlock, ChangeBlock, Node: rpc, Rolodex } = await import('https://unpkg.com/libnemo@latest'))
+ console.log('loaded libnemo')
+ }
+ async function loadUx () {
+ if (location.hash) {
+ const page = document.querySelector(location.hash)
+ page.classList.add('show')
+ } else {
+ location += '#transact'
+ }
+ }
+ function switchPage (evt) {
+ console.log(evt)
+ const oldHash = new URL(evt.oldURL)?.hash
+ const newHash = new URL(evt.newURL)?.hash
+ if (oldHash) {
+ document.querySelector(oldHash).classList.remove('show')
+ }
+ if (newHash) {
+ document.querySelector(newHash).classList.add('show')
+ }
+ }
+ function getWalletType (type) {
+ switch (type) {
+ case 'blake2b': {
+ return Blake2bWallet
+ }
+ case 'bip44':
+ default: {
+ return Bip44Wallet
+ }
+ }
+ }
- async function updateWallet () {
- const wallet = document.getElementById('wallet').value
- if (wallet !== '_new' && wallet !== '_import' && wallet !== '_ledger') {
- return await updateAccount()
- }
- if (wallet === '_ledger') {
- return await LedgerWallet.create()
- }
- const form = document.getElementById('wallet-form')
- const walletType = document.getElementById('wallet-form-wallet-type')
- const importType = document.getElementById('wallet-form-import-type')
- const importValue = document.getElementById('wallet-form-import-value')
- const salt = document.getElementById('wallet-form-salt')
- walletType.querySelector('x-radios').value = null
- importType.querySelector('x-select').value = null
- importValue.querySelector('x-input').value = null
- salt.querySelector('x-input').value = null
- if (wallet.value === '_new') {
- importType.classList.add('hide')
- importValue.classList.add('hide')
- salt.classList.remove('hide')
- }
- if (wallet.value === '_import') {
- importType.classList.remove('hide')
- importValue.classList.remove('hide')
- salt.classList.add('hide')
- }
- return await form.showModal()
- }
+ async function updateWallet () {
+ const wallet = document.querySelector('#wallet').value
+ if (wallet !== '_new' && wallet !== '_import' && wallet !== '_ledger') {
+ return await updateAccount()
+ }
+ if (wallet === '_ledger') {
+ return await LedgerWallet.create()
+ }
+ const form = document.querySelector('#wallet-form')
+ const walletType = document.querySelector('#wallet-form-wallet-type')
+ const importType = document.querySelector('#wallet-form-import-type')
+ const importValue = document.querySelector('#wallet-form-import-value')
+ const salt = document.querySelector('#wallet-form-salt')
+ walletType.querySelector('x-radios').value = null
+ importType.querySelector('x-select').value = null
+ importValue.querySelector('x-input').value = null
+ salt.querySelector('x-input').value = null
+ if (wallet.value === '_new') {
+ importType.classList.add('hide')
+ importValue.classList.add('hide')
+ salt.classList.remove('hide')
+ }
+ if (wallet.value === '_import') {
+ importType.classList.remove('hide')
+ importValue.classList.remove('hide')
+ salt.classList.add('hide')
+ }
+ return await form.showModal()
+ }
- function spinner (btn) {
- const label = btn.firstElementChild
- const spinner = document.createElement('x-throbber')
- spinner.size = 'small'
- spinner.style.width = `${label.scrollWidth}px`
- btn.replaceChildren(spinner)
- // at some point then...
- // btn.replaceChildren(label)
- }
+ function spinner (btn) {
+ const label = btn.firstElementChild
+ const spinner = document.createElement('x-throbber')
+ spinner.size = 'small'
+ spinner.style.width = `${label.scrollWidth}px`
+ btn.replaceChildren(spinner)
+ // at some point then...
+ // btn.replaceChildren(label)
+ }
- async function createWallet () {
- const walletSelect = document.getElementById('wallet')
- const form = document.getElementById('wallet-form')
- const name = form.querySelector('#wallet-form-name x-input').value
- if (name === '_new' || name === '_import' || name === '_ledger') {
- walletSelect.value = null
- notify.warn(`Invalid wallet name "${name}".`)
- return
- }
- const type = form.querySelector('#wallet-form-wallet-type x-radios').value
- const walletType = getWalletType(type)
- const salt = form.querySelector('#wallet-form-salt x-input')?.value
- const password = form.querySelector('#wallet-form-password x-input')?.value
- if (!password) {
- walletSelect.value = null
- notify.error('Password is required')
- return
- }
- let wallet
- try {
- wallet = await walletType.create(password, salt)
- const walletData = {
- id: wallet.id,
- name: name || wallet.id,
- type
- }
- await addToStorage(`wallets`, JSON.stringify(walletData))
+ async function createWallet () {
+ const walletSelect = document.querySelector('#wallet')
+ const form = document.querySelector('#wallet-form')
+ const name = form.querySelector('#wallet-form-name x-input').value
+ if (name === '_new' || name === '_import' || name === '_ledger') {
+ walletSelect.value = null
+ notify.warn(`Invalid wallet name "${name}".`)
+ return
+ }
+ const type = form.querySelector('#wallet-form-wallet-type x-radios').value
+ const walletType = getWalletType(type)
+ const salt = form.querySelector('#wallet-form-salt x-input')?.value
+ const password = form.querySelector('#wallet-form-password x-input')?.value
+ if (!password) {
+ walletSelect.value = null
+ notify.error('Password is required')
+ return
+ }
+ let wallet
+ try {
+ wallet = await walletType.create(password, salt)
+ const walletData = {
+ id: wallet.id,
+ name: name || wallet.id,
+ type
+ }
+ await addToStorage(`wallets`, JSON.stringify(walletData))
- const menu = document.querySelector('#wallet > x-menu')
- const menuitem = document.createElement('x-menuitem')
- menuitem.value = walletData.id
- if (menu.childElementCount >= 0) {
- menu.appendChild(menuitem)
- }
- const label = document.createElement('x-label')
- label.innerText = walletData.name
- menuitem.appendChild(label)
- walletSelect.value = walletData.id
- } catch (err) {
- label?.remove()
- menuitem?.remove()
- walletSelect.value = null
- notify.error(err.msg)
- } finally {
- await form.close()
- return wallet
- }
- }
+ const menu = document.querySelector('#wallet > x-menu')
+ const menuitem = document.createElement('x-menuitem')
+ menuitem.value = walletData.id
+ if (menu.childElementCount >= 0) {
+ menu.appendChild(menuitem)
+ }
+ const label = document.createElement('x-label')
+ label.innerText = walletData.name
+ menuitem.appendChild(label)
+ walletSelect.value = walletData.id
+ } catch (err) {
+ label?.remove()
+ menuitem?.remove()
+ walletSelect.value = null
+ notify.error(err.msg)
+ } finally {
+ await form.close()
+ return wallet
+ }
+ }
- function addToStorage (key, value) {
- if (typeof value !== 'string') {
- throw new TypeError(`Cannot add ${typeof value} to storage`)
- }
- const item = JSON.parse(sessionStorage.getItem(key) ?? '[]')
- if (!Array.isArray(item)) {
- throw new TypeError(`Storage item is not an array`)
- }
- item.push(value)
- return new Promise((resolve, reject) => {
- try {
- sessionStorage.setItem(key, JSON.stringify(item))
- resolve()
- } catch (err) {
- console.error(err)
- reject(err)
- }
- })
- }
- function updateWalletForm () {
- const form = document.getElementById('wallet-form')
- const walletTypeContainer = document.getElementById('wallet-form-wallet-type')
- const walletType = walletTypeContainer.firstChild
- const importTypeContainer = document.getElementById('wallet-form-import-type')
- const importType = importTypeContainer.firstChild
- const saltContainer = document.getElementById('wallet-form-salt')
- if (walletType.value === 'bip44' && importType.value === 'mnemonic') {
- saltContainer.classList.remove('hide')
- } else {
- saltContainer.classList.add('hide')
- }
- document.querySelector('#wallet-form-import-value x-label').innerText = importType.value
- }
- async function showWallets () {
- const card = document.getElementById('walletCard')
- const storedWalletData = JSON.parse(sessionStorage.getItem('wallets') ?? '[]')
- const wallets = []
- for (const walletData of storedWalletData) {
- const w = JSON.parse(walletData)
- console.dir(w)
- if (w.id && w.name && w.type) {
- const walletType = getWalletType(w.type)
- wallets.push(await walletType.restore(w.id))
- }
- }
- const walletElements = []
- for (const wallet of wallets) {
- const walletElement = document.createElement('x-label')
- await wallet.unlock('password')
- walletElement.innerText = `${wallet.name}: ${wallet.mnemonic}`
- await wallet.lock('password')
- walletElements.push(walletElement)
- }
- card.replaceChildren(...walletElements)
- }
+ function addToStorage (key, value) {
+ if (typeof value !== 'string') {
+ throw new TypeError(`Cannot add ${typeof value} to storage`)
+ }
+ const item = JSON.parse(sessionStorage.getItem(key) ?? '[]')
+ if (!Array.isArray(item)) {
+ throw new TypeError(`Storage item is not an array`)
+ }
+ item.push(value)
+ return new Promise((resolve, reject) => {
+ try {
+ sessionStorage.setItem(key, JSON.stringify(item))
+ resolve()
+ } catch (err) {
+ console.error(err)
+ reject(err)
+ }
+ })
+ }
+ function updateWalletForm () {
+ const form = document.querySelector('#wallet-form')
+ const walletTypeContainer = document.querySelector('#wallet-form-wallet-type')
+ const walletType = walletTypeContainer.firstChild
+ const importTypeContainer = document.querySelector('#wallet-form-import-type')
+ const importType = importTypeContainer.firstChild
+ const saltContainer = document.querySelector('#wallet-form-salt')
+ if (walletType.value === 'bip44' && importType.value === 'mnemonic') {
+ saltContainer.classList.remove('hide')
+ } else {
+ saltContainer.classList.add('hide')
+ }
+ document.querySelector('#wallet-form-import-value x-label').innerText = importType.value
+ }
+ async function showWallets () {
+ const card = document.querySelector('#walletCard')
+ const storedWalletData = JSON.parse(sessionStorage.getItem('wallets') ?? '[]')
+ const wallets = []
+ for (const walletData of storedWalletData) {
+ const w = JSON.parse(walletData)
+ console.dir(w)
+ if (w.id && w.name && w.type) {
+ const walletType = getWalletType(w.type)
+ wallets.push(await walletType.restore(w.id))
+ }
+ }
+ const walletElements = []
+ for (const wallet of wallets) {
+ const walletElement = document.createElement('x-label')
+ await wallet.unlock('password')
+ walletElement.innerText = `${wallet.name}: ${wallet.mnemonic}`
+ await wallet.lock('password')
+ walletElements.push(walletElement)
+ }
+ card.replaceChildren(...walletElements)
+ }
- async function deriveAccounts () {
- const wallet = document.querySelector('#wallet').value
- const form = btn.querySelector('#account-form')
- await console.log('deriveAccounts')
- }
- async function clearStorage () {
- sessionStorage.clear()
- notify.info(`Session storage cleared`)
- }
- const notify = {
- _show: (msg, color) => {
- const container = document.getElementById('notifications')
- const notification = document.createElement('x-card')
+ async function deriveAccounts () {
+ const wallet = document.querySelector('#wallet').value
+ const form = btn.querySelector('#account-form')
+ await console.log('deriveAccounts')
+ }
+ async function clearStorage () {
+ sessionStorage.clear()
+ notify.info(`Session storage cleared`)
+ }
+ const notify = {
+ _show: (msg, color) => {
+ const container = document.querySelector('#notifications')
+ const notification = document.createElement('x-card')
- notification.innerText = msg
- notification.style.color = color ?? notification.style.color
+ notification.innerText = msg
+ notification.style.color = color ?? notification.style.color
- notification.addEventListener('click', notification.remove)
- container.appendChild(notification)
- },
- info: (msg) => notify._show(`ℹ️ ${msg}`),
- ok: (msg) => notify._show(`☑️ ${msg}`, 'Cyan'),
- warn: (msg) => notify._show(`⚠️ ${msg}`, 'Gold'),
- error: (msg) => notify._show(`🚫 ${msg}`, 'Tomato')
- }
- </script>
- <meta name="xel-theme" content="https://unpkg.com/xel@latest/themes/adwaita-dark.css" />
- <meta name="xel-accent-color" content="blue" />
- <meta name="xel-icons" content="https://unpkg.com/bootstrap-icons@latest/bootstrap-icons.svg" />
- <style>
+ notification.addEventListener('click', notification.remove)
+ container.appendChild(notification)
+ },
+ info: (msg) => notify._show(`ℹ️ ${msg}`),
+ ok: (msg) => notify._show(`☑️ ${msg}`, 'Cyan'),
+ warn: (msg) => notify._show(`⚠️ ${msg}`, 'Gold'),
+ error: (msg) => notify._show(`🚫 ${msg}`, 'Tomato')
+ }
+ </script>
+ <meta name="xel-theme" content="https://unpkg.com/xel@latest/themes/adwaita-dark.css" />
+ <meta name="xel-accent-color" content="blue" />
+ <meta name="xel-icons" content="https://unpkg.com/bootstrap-icons@latest/bootstrap-icons.svg" />
+ <style>
body {
background-color: slategrey;
color: #209CE9;
<body onload="load()" onhashchange="switchPage(event)" style="visibility:hidden;">
<x-box id="notifications"></x-box>
- <header>
- <x-box id="wallets">
- <x-select id="wallet" style="width:100%;" onchange="updateWallet()">
- <x-menu>
- <x-menuitem value="_new">
- <x-label>New</x-label>
- </x-menuitem>
- <x-menuitem value="_import">
- <x-label>Import</x-label>
- </x-menuitem>
- <hr />
- <x-menuitem value="_ledger">
- <x-label>Ledger</x-label>
- </x-menuitem>
- <hr />
- </x-menu>
- </x-select>
- <dialog id="wallet-form">
- <x-box vertical>
- <x-box id="wallet-form-name">
- <x-label>Name</x-label>
- <x-input type="text"></x-input>
- </x-box>
- <x-box id="wallet-form-wallet-type">
- <x-radios required onchange="updateWalletForm()">
- <x-radio value="bip44"><x-label>BIP-44</x-label></x-radio>
- <x-radio value="blake2b"><x-label>BLAKE2b</x-label></x-radio>
- </x-radios>
- </x-box>
- <x-box id="wallet-form-import-type" class="hide">
- <x-select onchange="updateWalletForm()">
- <x-menu>
- <x-menuitem value="mnemonic"><x-label>Import mnemonic</x-label></x-menuitem>
- <x-menuitem value="seed"><x-label>Import seed</x-label></x-menuitem>
- </x-menu>
- </x-select>
- </x-box>
- <x-box id="wallet-form-import-value" class="hide">
- <x-label style="text-transform:capitalize"></x-label>
- <x-input type="password"></x-input>
- </x-box>
- <x-box id="wallet-form-salt" class="hide">
- <x-label>Salt</x-label>
- <x-input type="password">Optional</x-input>
- </x-box>
- <x-box id="wallet-form-password">
- <x-label>Lock</x-label>
- <x-input type="password" required><x-label>Password</x-label></x-input>
- </x-box>
- <x-box>
- <x-buttons>
- <x-button onclick="document.getElementById('wallet-form').close()">
- Cancel
- </x-button>
- <x-button onclick="createWallet().then(w => { console.log(w);showWallets() })">
- OK
- </x-button>
- </x-buttons>
- </x-box>
- </x-box>
- </dialog>
- </x-box><!-- end #wallets-->
- <x-box id="accounts">
- <x-select id="account" style="width:100%;" onchange="updateAccount()">
- <x-menu>
- <x-menuitem value="_new">
- <x-label>New</x-label>
- </x-menuitem>
- <x-menuitem value="_import">
- <x-label>Import</x-label>
- </x-menuitem>
- <hr />
- </x-menu>
- </x-select>
- <x-button>
- <x-icon href="#cash-stack"></x-icon>
- <x-label>New Account</x-label>
- <dialog id="account-form">
- <x-box vertical>
- <x-box>
- <x-label>Name</x-label>
- <x-input type="text"></x-input>
- </x-box>
- <x-box>
- <x-label>Index (optional)</x-label>
- <x-numberinput min="0" max="2147483647"></x-numberinput>
- </x-box>
- <x-buttons>
- <x-button onclick="document.getElementById('account-form').close()">
- Cancel
- </x-button>
- <x-button onclick="deriveAccounts(this).then(w => { console.log(w);showWallets() })">
- OK
- </x-button>
- </x-buttons>
- </x-box>
- </dialog>
- </x-button>
- </x-box><!-- end #accounts -->
- </header>
- <main>
- <x-box id="exchange" class="page">
- <h1>Exchange</h1>
- </x-box><!-- end #exchange -->
- <x-box id="history" class="page">
- <h1>History</h1>
- </x-box><!-- end #history -->
- <x-box id="transact" class="page">
- <h1>Transact</h1>
- <x-card id="walletCard">
- </x-card>
- </x-box><!-- end #transact -->
- <x-box id="rolodex" class="page">
- <h1>Rolodex</h1>
- </x-box><!-- end #rolodex -->
- <x-box id="settings" class="page">
- <h1>Settings</h1>
- <x-button onclick="clearStorage()">
- <x-label>Clear Storage</x-label>
- </x-button>
- </x-box><!-- end #settings -->
- </main>
- <nav>
- <a href="#exchange">
- <x-icon href="#currency-exchange"></x-icon>
- </a>
- <a href="#history">
- <x-icon href="#book-half"></x-icon>
- </a>
- <a href="#transact" id="xno">
- <svg width="0px" height="0px" viewBox="0 0 1080 1080" fill="none" xmlns="http://www.w3.org/2000/svg">
- <circle cx="540" cy="540" r="540" fill="currentcolor" />
- <path
- d="M792.911 881H740.396L541.099 570.561L338.761 881H286.68L513.452 529.3L306.882 206.222H360.42L541.95 490.393L727.322 206.222H777.555L568.762 528.379L792.911 881Z"
- fill="white" />
- <path
- d="M336.487 508.737H744.807V547.116H336.487V508.737ZM336.487 623.872H744.824V662.251H336.47L336.487 623.872Z"
- fill="white" />
- </svg>
- </a>
- <a href="#rolodex">
- <x-icon href="#person-rolodex"></x-icon>
- </a>
- <a href="#settings">
- <x-icon href="#gear"></x-icon>
- </a>
- </nav>
+ <header>
+ <x-box id="wallets">
+ <x-select id="wallet" style="width:100%;" onchange="updateWallet()">
+ <x-menu>
+ <x-menuitem value="_new">
+ <x-label>New</x-label>
+ </x-menuitem>
+ <x-menuitem value="_import">
+ <x-label>Import</x-label>
+ </x-menuitem>
+ <hr />
+ <x-menuitem value="_ledger">
+ <x-label>Ledger</x-label>
+ </x-menuitem>
+ <hr />
+ </x-menu>
+ </x-select>
+ <dialog id="wallet-form">
+ <x-box vertical>
+ <x-box id="wallet-form-name">
+ <x-label>Name</x-label>
+ <x-input type="text"></x-input>
+ </x-box>
+ <x-box id="wallet-form-wallet-type">
+ <x-radios required onchange="updateWalletForm()">
+ <x-radio value="bip44"><x-label>BIP-44</x-label></x-radio>
+ <x-radio value="blake2b"><x-label>BLAKE2b</x-label></x-radio>
+ </x-radios>
+ </x-box>
+ <x-box id="wallet-form-import-type" class="hide">
+ <x-select onchange="updateWalletForm()">
+ <x-menu>
+ <x-menuitem value="mnemonic"><x-label>Import mnemonic</x-label></x-menuitem>
+ <x-menuitem value="seed"><x-label>Import seed</x-label></x-menuitem>
+ </x-menu>
+ </x-select>
+ </x-box>
+ <x-box id="wallet-form-import-value" class="hide">
+ <x-label style="text-transform:capitalize"></x-label>
+ <x-input type="password"></x-input>
+ </x-box>
+ <x-box id="wallet-form-salt" class="hide">
+ <x-label>Salt</x-label>
+ <x-input type="password">Optional</x-input>
+ </x-box>
+ <x-box id="wallet-form-password">
+ <x-label>Lock</x-label>
+ <x-input type="password" required><x-label>Password</x-label></x-input>
+ </x-box>
+ <x-box>
+ <x-buttons>
+ <x-button onclick="document.querySelector('#wallet-form').close()">
+ Cancel
+ </x-button>
+ <x-button onclick="createWallet().then(w => { console.log(w);showWallets() })">
+ OK
+ </x-button>
+ </x-buttons>
+ </x-box>
+ </x-box>
+ </dialog>
+ </x-box><!-- end #wallets-->
+ <x-box id="accounts">
+ <x-select id="account" style="width:100%;" onchange="updateAccount()">
+ <x-menu>
+ <x-menuitem value="_new">
+ <x-label>New</x-label>
+ </x-menuitem>
+ <x-menuitem value="_import">
+ <x-label>Import</x-label>
+ </x-menuitem>
+ <hr />
+ </x-menu>
+ </x-select>
+ <x-button>
+ <x-icon href="#cash-stack"></x-icon>
+ <x-label>New Account</x-label>
+ <dialog id="account-form">
+ <x-box vertical>
+ <x-box>
+ <x-label>Name</x-label>
+ <x-input type="text"></x-input>
+ </x-box>
+ <x-box>
+ <x-label>Index (optional)</x-label>
+ <x-numberinput min="0" max="2147483647"></x-numberinput>
+ </x-box>
+ <x-buttons>
+ <x-button onclick="document.querySelector('#account-form').close()">
+ Cancel
+ </x-button>
+ <x-button onclick="deriveAccounts(this).then(w => { console.log(w);showWallets() })">
+ OK
+ </x-button>
+ </x-buttons>
+ </x-box>
+ </dialog>
+ </x-button>
+ </x-box><!-- end #accounts -->
+ </header>
+ <main>
+ <x-box id="exchange" class="page">
+ <h1>Exchange</h1>
+ </x-box><!-- end #exchange -->
+ <x-box id="history" class="page">
+ <h1>History</h1>
+ </x-box><!-- end #history -->
+ <x-box id="transact" class="page">
+ <h1>Transact</h1>
+ <x-card id="walletCard">
+ </x-card>
+ </x-box><!-- end #transact -->
+ <x-box id="rolodex" class="page">
+ <h1>Rolodex</h1>
+ </x-box><!-- end #rolodex -->
+ <x-box id="settings" class="page">
+ <h1>Settings</h1>
+ <x-button onclick="clearStorage()">
+ <x-label>Clear Storage</x-label>
+ </x-button>
+ </x-box><!-- end #settings -->
+ </main>
+ <nav>
+ <a href="#exchange">
+ <x-icon href="#currency-exchange"></x-icon>
+ </a>
+ <a href="#history">
+ <x-icon href="#book-half"></x-icon>
+ </a>
+ <a href="#transact" id="xno">
+ <svg width="0px" height="0px" viewBox="0 0 1080 1080" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <circle cx="540" cy="540" r="540" fill="currentcolor" />
+ <path
+ d="M792.911 881H740.396L541.099 570.561L338.761 881H286.68L513.452 529.3L306.882 206.222H360.42L541.95 490.393L727.322 206.222H777.555L568.762 528.379L792.911 881Z"
+ fill="white" />
+ <path
+ d="M336.487 508.737H744.807V547.116H336.487V508.737ZM336.487 623.872H744.824V662.251H336.47L336.487 623.872Z"
+ fill="white" />
+ </svg>
+ </a>
+ <a href="#rolodex">
+ <x-icon href="#person-rolodex"></x-icon>
+ </a>
+ <a href="#settings">
+ <x-icon href="#gear"></x-icon>
+ </a>
+ </nav>
</body>