console.log('loading data')
const walletSelect = document.querySelector('#wallet')
const accountSelect = document.querySelector('#account')
- const wallets = await getFromStorage('wallets')
- for (const wallet of wallets) {
- const { id, name, accounts } = JSON.parse(wallet)
- const walletOption = new Option(name, id)
- walletSelect.add(walletOption)
- for (const a of accounts ?? []) {
- const { id, name } = JSON.parse(a)
- const accountOption = new Option(name, id)
- accountSelect.add(accountOption)
- }
- }
+ await reloadWalletSelect()
if (walletSelect.value.substring(0, 1) === '_') {
walletSelect.value = ''
- } else {
- updateWalletSelect()
}
- if (accountSelect.value.substring(0, 1) === '_') {
+ await reloadAccountSelect()
+ if (walletSelect.value === '' || accountSelect.value.substring(0, 1) === '_') {
accountSelect.setAttribute('disabled', '')
accountSelect.value = ''
}
}
}
- async function updateWalletSelect () {
- const select = document.querySelector('#wallet')
- switch (select.value) {
+ async function selectWallet () {
+ const walletSelect = document.getElementById('wallet')
+ switch (walletSelect.value) {
+ case undefined:
+ case null:
case '': {
- await updateAccountSelect('')
- return
+ break
}
case '_new': {
try {
- await document.querySelector('#wallet-new').showModal()
+ await document.getElementById('wallet-new').showModal()
} catch (err) {
- select.value = ''
- notify.error(`Error creating wallet: ${err}`)
+ walletSelect.value = ''
+ console.error(err)
+ notify.error(`Error creating wallet`)
} finally {
- return
+ break
}
}
case '_import': {
try {
- await document.querySelector('#wallet-import').showModal()
+ await document.getElementById('wallet-import').showModal()
} catch (err) {
- select.value = ''
- notify.error(`Error importing wallet: ${err}`)
+ walletSelect.value = ''
+ console.error(err)
+ notify.error(`Error importing wallet`)
} finally {
- return
+ break
}
}
case '_ledger': {
try {
- return await LedgerWallet.create()
+ await LedgerWallet.create()
} catch (err) {
- select.value = ''
- notify.error(`Error importing wallet: ${err}`)
- return
+ walletSelect.value = ''
+ console.error(err)
+ notify.error(`Error opening Ledger`)
+ } finally {
+ break
}
}
default: {
try {
- const wallet = await loadWallet(select.value)
- await updateAccountSelect(wallet)
+ await reloadAccountSelect()
} catch (err) {
- select.value = ''
- notify.error(`Error loading wallet: ${err}`)
- return
+ walletSelect.value = ''
+ console.error(err)
+ notify.error(`Error loading wallet accounts`)
+ } finally {
+ break
}
}
}
+ return await selectAccount()
}
- async function loadWallet (walletId) {
- walletId ??= document.querySelector('#wallet')?.value
- if (!walletId) {
- throw new TypeError(`Wallet ID not found`)
- }
+ async function loadWallets () {
const wallets = await getFromStorage('wallets')
- const walletData = wallets.find(w => {
- const { id, algorithm } = JSON.parse(w)
- return id === walletId
- })
- const { id, algorithm } = JSON.parse(walletData)
- const walletClass = getWalletClass(algorithm)
- const wallet = await walletClass.restore(id)
- return wallet
+ return wallets.map(w => JSON.parse(w))
+ }
+
+ async function loadWallet () {
+ const walletSelect = document.getElementById('wallet')
+ if (walletSelect?.value) {
+ const wallets = await loadWallets()
+ const { id, algorithm } = wallets.find(w => w.id === walletSelect.value)
+ const walletClass = getWalletClass(algorithm)
+ const wallet = await walletClass.restore(id)
+ return wallet
+ }
+ throw new TypeError(`Wallet not found`)
}
async function createWallet () {
- const walletSelect = document.querySelector('#wallet')
- const form = document.querySelector('#wallet-new')
- const name = form.querySelector('#wallet-new-name input').value
+ const walletSelect = document.getElementById('wallet')
+ const form = document.getElementById('wallet-new')
+ const name = document.getElementById('wallet-new-name-input').value
if (name.substring(0, 1) === '_') {
notify.error(`Wallet name cannot start with an underscore`)
return
}
- const algorithm = form.querySelector('#wallet-new-algorithm select').value
+ const algorithm = document.getElementById('wallet-new-algorithm-select').value
const walletClass = getWalletClass(algorithm)
- const salt = form.querySelector('#wallet-new-salt input')?.value
- const password = form.querySelector('#wallet-new-password input')?.value
+ const salt = document.getElementById('wallet-new-salt-input')?.value
+ const password = document.getElementById('wallet-new-password-input')?.value
if (!password) {
notify.error('Password is required')
return
}
await addToStorage(`wallets`, JSON.stringify(walletData))
- const select = document.querySelector('#wallet')
+ const select = document.getElementById('wallet')
const option = new Option(walletData.name, walletData.id, false, true)
select.add(option)
- await updateWalletSelect()
+ await selectWallet()
} catch (err) {
option?.remove()
notify.error(err.msg)
}
function updateWalletForm (id) {
- const form = document.querySelector(id)
+ const form = document.getElementById(id)
if (!form) {
notify.error(`Form ID not found, contact developer`)
return
}
- const algorithmContainer = document.querySelector(`${id} -algorithm`)
- const algorithm = document.querySelector(`${id} -algorithm select`)
- const typeContainer = document.querySelector(`${id} -type`)
- const type = document.querySelector(`${id} -type select`)
- const saltContainer = document.querySelector(`${id} -salt`)
- const salt = document.querySelector(`${id} -salt input`)
+ const algorithmContainer = document.getElementById(`${id}-algorithm`)
+ const algorithm = document.getElementById(`${id}-algorithm-select`)
+ const typeContainer = document.getElementById(`${id}-type`)
+ const type = document.getElementById(`${id}-type-select`)
+ const saltContainer = document.getElementById(`${id}-salt`)
+ const salt = document.getElementById(`${id}-salt-input`)
if (algorithm.value === 'bip44' && type?.value !== 'seed') {
saltContainer.classList.remove('hide')
} else {
saltContainer.classList.add('hide')
}
- const importValue = document.querySelector(`${id} -value input`)
- const importValueLabel = document.querySelector(`${id} -value label`)
+ const importValue = document.getElementById(`${id}-value-input`)
+ const importValueLabel = document.querySelector(`${id}-value label`)
if (importValueLabel) {
importValueLabel.innerText = type.value
}
}
- async function updateAccountSelect (wallet) {
+ async function selectAccount () {
const accountSelect = document.querySelector('#account')
- wallet ??= loadWallet()
- if (wallet == null || wallet === '') {
+ const walletId = document.querySelector('#wallet')?.value
+ if (walletId == null || walletId === '') {
accountSelect.value = ''
accountSelect.setAttribute('disabled', '')
return
}
- switch (accountSelect.value) {
- case '': {
- accountSelect.removeAttribute('disabled')
+ accountSelect.removeAttribute('disabled')
+ if (accountSelect.value === '_new') {
+ try {
+ return await document.querySelector('#account-new').showModal()
+ } catch (err) {
+ accountSelect.value = ''
+ console.error(err)
+ notify.error(`Error creating account`)
return
}
- case '_new': {
- try {
- return await document.querySelector('#account-new').showModal()
- } catch (err) {
- accountSelect.value = ''
- notify.error(`Error creating account: ${err}`)
- return
+ }
+ }
+
+ async function reloadWalletSelect () {
+ const wallets = await loadWallets()
+ const walletOptions = wallets.map(w => {
+ return { text: w.name, value: w.id }
+ })
+ await resetSelectOptions('wallet', walletOptions)
+ }
+
+ async function reloadAccountSelect () {
+ const accounts = await loadAccounts()
+ const accountOptions = accounts.map(a => {
+ return { text: a.name, value: a.index }
+ })
+ await resetSelectOptions('account', accountOptions)
+ }
+
+ async function resetSelectOptions (id, options) {
+ try {
+ if (!Array.isArray(options)) {
+ options = [options]
+ }
+ const select = document.getElementById(id)
+ if (!select) {
+ throw new TypeError(`Select ${id} not found`)
+ }
+ const oldOptions = [select.children].filter(o => o.tagName === 'option')
+ for (const oldOption of oldOptions) {
+ if (oldOption.value.substring(0, 1) === '_') {
+ oldOption.remove()
}
}
- default: {
- accountSelect.removeAttribute('disabled')
- return await wallet.accounts(accountSelect.value)
+ const newOptions = options.map(o => new Option(o.text, o.value))
+ if (newOptions.length > 0) {
+ select.add(...newOptions)
}
+ } catch (err) {
+ console.error(err)
+ notify.error(`Error resetting options for select ${id}`)
}
}
- async function createAccount (wallet) {
- const accountSelect = document.querySelector('#account')
+ async function loadAccounts () {
+ walletSelect = document.getElementById('wallet')
+ if (walletSelect?.value) {
+ const accounts = await getFromStorage('accounts')
+ const accountData = accounts.filter(a => {
+ console.log(JSON.parse(a))
+ const { walletId } = JSON.parse(a)
+ return walletId === walletSelect.value
+ })
+ return accountData
+ }
+ return []
+ }
+
+ async function createAccount () {
+ let account, option, wallet
+ const accountSelect = document.getElementById('account')
try {
- wallet ??= await loadWallet()
+ wallet = await loadWallet()
} catch (err) {
- notify.error(`Error creating account: ${err}`)
+ console.error(err)
+ notify.error(`Error creating account`)
return
}
- const form = document.querySelector('#account-new')
- const name = form.querySelector('#account-new-name input').value
- if (name.substring(0, 1) === '_') {
+ const form = document.getElementById('account-new')
+ const name = document.getElementById('account-new-name-input')?.value
+ if (name?.substring(0, 1) === '_') {
notify.error(`Account name cannot start with an underscore`)
return
}
- const index = form.querySelector('#account-new-index input')?.value
- const password = form.querySelector('#account-new-password input')?.value
+ const index = document.getElementById('account-new-index-input')?.value
+ const password = document.getElementById('account-new-password-input')?.value
try {
- console.log(`locked wallet: ${wallet}`)
- const unlockResult = await wallet.unlock(password)
- console.log(`unlockResult: ${unlockResult}`)
- console.log(`unlocked wallet: ${wallet}`)
- const account = await wallet.accounts(index)
- console.log(`account: ${account}`)
- const lockResult = await wallet.lock(password)
- console.log(`lockResult: ${lockResult}`)
- console.log(`locked wallet: ${wallet}`)
+ await wallet.unlock(password)
+ const account = await wallet.accounts(+index)
+ await wallet.lock(password)
const accountData = {
- id: index,
- name: name || index
+ walletId: wallet.id,
+ index: account.index,
+ name: `${index}${name ? ': ' : ''}${name}`
}
await addToStorage(`accounts`, JSON.stringify(accountData))
- const option = new Option(accountData.name, accountData.id, false, true)
- select.add(option)
- await updateAccountSelect(wallet)
+ option = new Option(accountData.name, accountData.id, false, true)
+ accountSelect.add(option)
+ await selectAccount()
} catch (err) {
+ accountSelect.value = ''
option?.remove()
- notify.error(err.msg)
+ console.error(err)
+ notify.error(`Error creating account`)
} finally {
await form.close()
return account
}
async function cancelDialog (id) {
- const dialog = document.getElementById(id)
- const fields = dialog.querySelectorAll('input, select')
+ await resetDialogInputs()
+ await document.getElementById(id).close()
+ }
+
+ async function resetDialogInputs () {
+ const fields = document.querySelectorAll('dialog input, dialog select')
for (const field of fields) {
field.value = ''
}
- const wallet = document.querySelector('#wallet')
+ const wallet = document.getElementById('wallet')
if (wallet.value.substring(0, 1) === '_') {
wallet.value = ''
}
- const account = document.querySelector('#account')
- if (account.value.substring(0, 1) === '_') {
+ const account = document.getElementById('account')
+ if (wallet.value === '' || account.value.substring(0, 1) === '_') {
account.value = ''
}
- await dialog.close()
- }
-
- 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 = getWalletClass(w.type)
- wallets.push(await walletType.restore(w.id))
- }
- }
- const walletElements = []
- for (const wallet of wallets) {
- const walletElement = document.createElement('label')
- await wallet.unlock('password')
- walletElement.innerText = `${wallet.name}: ${wallet.mnemonic} `
- await wallet.lock('password')
- walletElements.push(walletElement)
- }
- card.replaceChildren(...walletElements)
}
async function clearStorage () {
}
document.querySelector('#wallet').value = ''
document.querySelector('#account').value = ''
- await updateWalletSelect()
+ await selectWallet()
notify.ok(`Session storage cleared`)
btn.removeAttribute('disabled')
}
<div id="wallets" class="grid-x">
<label for="wallet" class="grid x-3">Wallet</label>
- <select id="wallet" class="grid x-9" onchange="updateWalletSelect()">
+ <select id="wallet" class="grid x-9" onchange="selectWallet()">
<option disabled selected value>Choose...</option>
<hr />
<option value="_new">New</option>
<div id="wallet-new-algorithm" class="flex x-left x-mid">
<label for="wallet-new-algorithm-select">Algorithm</label>
<select id="wallet-new-algorithm-select" name="wallet-new-algorithm" autocomplete="off"
- onchange="updateWalletForm('#wallet-new')" required>
+ onchange="updateWalletForm('wallet-new')" required>
<option disabled selected value>Choose...</option>
<option value="bip44">BIP-44</option>
<option value="blake2b">BLAKE2b</option>
<div id="wallet-import-algorithm" class="flex x-left x-mid">
<label for="wallet-import-algorithm-select">Algorithm</label>
<select id="wallet-import-algorithm-select" name="wallet-import-algorithm" autocomplete="off"
- onchange="updateWalletForm('#wallet-import')" required>
+ onchange="updateWalletForm('wallet-import')" required>
<option disabled selected value>Choose...</option>
<option value="bip44">BIP-44</option>
<option value="blake2b">BLAKE2b</option>
<div id="wallet-import-type" class="flex x-left x-mid hide">
<label for="wallet-import-type-select">Type</label>
<select id="wallet-import-type-select" name="wallet-import-type" autocomplete="off"
- onchange="updateWalletForm('#wallet-import')" required>
+ onchange="updateWalletForm('wallet-import')" required>
<option disabled selected value>Choose...</option>
<option value="mnemonic">Import mnemonic</option>
<option value="seed">Import seed</option>
<div class="grid x-4"></div>
<button id="wallet-import-cancel" class="cancel grid x-4">Cancel</button>
<button id="wallet-import-ok" class="grid x-4"
- onclick="importWallet().then(w => { console.log(w);showWallets() })">OK</button>
+ onclick="importWallet().then(w => { console.log(w) })">OK</button>
</div>
</div>
</dialog>
<div id="accounts" class="grid-x">
<label for="account" class="grid x-3">Account</label>
- <select id="account" class="grid x-9" disabled onchange="updateAccountSelect()">
+ <select id="account" class="grid x-9" disabled onchange="selectAccount()">
<option disabled selected value>Choose...</option>
<hr />
<option value="_new">New</option>
<div id="account-new-index" class="flex x-left x-mid">
<label for="account-new-index-input">Index</label>
<input id="account-new-index-input" name="account-new-index" type="number" autocomplete="off" min="0"
- max="2147483647" required />
+ max="2147483647" required value="0" />
</div>
<div id="account-new-password" class="flex x-left x-mid">
<label for="account-new-password-input">Unlock</label>
<div class="grid x-4"></div>
<button id="account-new-cancel" class="cancel grid x-4">Cancel</button>
<button id="account-new-ok" class="grid x-4"
- onclick="createAccount().then(w => { console.log(w) })">OK</button>
+ onclick="createAccount().then(a => { console.log(a) })">OK</button>
</div>
</div>
</dialog>