commit
48e9ee1fd7
@ -1017,7 +1017,7 @@ h3 {
|
|||||||
#queried_address_transactions {
|
#queried_address_transactions {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-bottom: 1.5rem;
|
padding-bottom: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pagination_wrapper {
|
#pagination_wrapper {
|
||||||
|
|||||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -952,7 +952,7 @@ h3 {
|
|||||||
#queried_address_transactions {
|
#queried_address_transactions {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-bottom: 1.5rem;
|
padding-bottom: 4rem;
|
||||||
}
|
}
|
||||||
#pagination_wrapper {
|
#pagination_wrapper {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|||||||
79
index.html
79
index.html
@ -208,7 +208,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<section class="grid gap-1">
|
<section class="grid gap-1">
|
||||||
<div class="flex align-center space-between sticky top-0"
|
<div class="flex align-center space-between sticky top-0"
|
||||||
style="background-color: rgba(var(--foreground-color), 1);">
|
style="background-color: rgba(var(--foreground-color), 1);transition: background-color .3s;">
|
||||||
<h4>Transactions</h4>
|
<h4>Transactions</h4>
|
||||||
<sm-chips id="filter_selector" class="hidden">
|
<sm-chips id="filter_selector" class="hidden">
|
||||||
<sm-chip value="sent" selected>Sent</sm-chip>
|
<sm-chip value="sent" selected>Sent</sm-chip>
|
||||||
@ -1218,24 +1218,24 @@
|
|||||||
pagesData.params = params
|
pagesData.params = params
|
||||||
switch (pageId) {
|
switch (pageId) {
|
||||||
case 'search': {
|
case 'search': {
|
||||||
const { type, query, page = 1 } = params
|
let { type, query, page = 1 } = params
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'address':
|
case 'address':
|
||||||
try {
|
try {
|
||||||
|
page = parseInt(page)
|
||||||
if (floGlobals.query.string !== query) {
|
if (floGlobals.query.string !== query) {
|
||||||
checkBalance(query)
|
checkBalance(query)
|
||||||
renderElem(getRef('queried_address_transactions'), html`
|
|
||||||
<div class="grid gap-1 justify-items-center text-center" style="margin: 3rem 0">
|
|
||||||
<sm-spinner></sm-spinner>
|
|
||||||
<span>Loading transactions...</span>
|
|
||||||
</div>
|
|
||||||
`)
|
|
||||||
fetchTransactions(query).then(() => {
|
fetchTransactions(query).then(() => {
|
||||||
filterFetchedTransactions()
|
filterFetchedTransactions()
|
||||||
render.paginatedTransactions(parseInt(page))
|
render.paginatedTransactions(page)
|
||||||
|
})
|
||||||
|
} else if (page % Math.ceil(1000 / txsPerPage) === 0 && floGlobals.query.transactions.length <= page * txsPerPage) {
|
||||||
|
fetchTransactions(query, true).then(() => {
|
||||||
|
filterFetchedTransactions()
|
||||||
|
render.paginatedTransactions(page)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
render.paginatedTransactions(parseInt(page))
|
render.paginatedTransactions(page)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify(err, 'error')
|
notify(err, 'error')
|
||||||
@ -1914,10 +1914,14 @@
|
|||||||
return clone
|
return clone
|
||||||
},
|
},
|
||||||
paginatedTransactions(page = 1) {
|
paginatedTransactions(page = 1) {
|
||||||
const startingIndex = ((page - 1) * 20)
|
const { transactions, string: address, filteredTransactions } = floGlobals.query
|
||||||
const endingIndex = startingIndex + 20
|
let startingIndex = ((page - 1) * txsPerPage)
|
||||||
const { transactions, string: address } = floGlobals.query
|
if (filteredTransactions && startingIndex > filteredTransactions.length) {
|
||||||
const renderedTransactions = transactions
|
startingIndex = 0;
|
||||||
|
window.history.replaceState({}, '', `#/search?type=address&query=${address}&page=1`)
|
||||||
|
}
|
||||||
|
const endingIndex = startingIndex + txsPerPage
|
||||||
|
const renderedTransactions = (filteredTransactions || transactions)
|
||||||
.slice(startingIndex, endingIndex)
|
.slice(startingIndex, endingIndex)
|
||||||
.map(transaction => render.transactionCard(transaction))
|
.map(transaction => render.transactionCard(transaction))
|
||||||
renderElem(getRef('queried_address_transactions'), html`${renderedTransactions}`)
|
renderElem(getRef('queried_address_transactions'), html`${renderedTransactions}`)
|
||||||
@ -1930,7 +1934,7 @@
|
|||||||
} else {
|
} else {
|
||||||
getRef('filter_selector').classList.add('hidden')
|
getRef('filter_selector').classList.add('hidden')
|
||||||
}
|
}
|
||||||
const paginationSegments = transactions ? Math.ceil(transactions.length / renderTransactions) : 0;
|
const paginationSegments = (filteredTransactions || transactions) ? Math.ceil((filteredTransactions || transactions).length / txsPerPage) : 0;
|
||||||
let pagination = []
|
let pagination = []
|
||||||
let startingPage = page - 2;
|
let startingPage = page - 2;
|
||||||
let showTill = page + 2;
|
let showTill = page + 2;
|
||||||
@ -2144,8 +2148,7 @@
|
|||||||
closePopup()
|
closePopup()
|
||||||
})
|
})
|
||||||
|
|
||||||
getRef('filter_selector').addEventListener('change', async e => {
|
getRef('filter_selector').addEventListener('change', e => {
|
||||||
floGlobals.query.transactions = (await floWebWallet.readTransactions(floGlobals.query.string)).reverse();
|
|
||||||
filterFetchedTransactions()
|
filterFetchedTransactions()
|
||||||
render.paginatedTransactions()
|
render.paginatedTransactions()
|
||||||
})
|
})
|
||||||
@ -2547,26 +2550,50 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let renderTransactions = 20;
|
|
||||||
floGlobals.query = {
|
floGlobals.query = {
|
||||||
transactions: [],
|
transactions: [],
|
||||||
string: '',
|
string: '',
|
||||||
|
filteredTransactions: null
|
||||||
}
|
}
|
||||||
async function fetchTransactions(address) {
|
const txsPerPage = 25;
|
||||||
|
async function fetchTransactions(address, loadOlder = false) {
|
||||||
try {
|
try {
|
||||||
floGlobals.query.transactions = [];
|
renderElem(getRef('pagination_wrapper'), html``)
|
||||||
await floWebWallet.syncTransactions(address);
|
renderElem(getRef('queried_address_transactions'), html`
|
||||||
floGlobals.query.transactions = (await floWebWallet.readTransactions(address)).reverse();
|
<div class="grid gap-1 justify-items-center text-center" style="margin: 3rem 0">
|
||||||
floGlobals.query.string = address;
|
<sm-spinner></sm-spinner>
|
||||||
|
<span>Loading transactions...</span>
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
if (loadOlder) {
|
||||||
|
const { items, initItem } = await floWebWallet.listTransactions.syncOld(address, floGlobals.query.initItem)
|
||||||
|
floGlobals.query = {
|
||||||
|
transactions: [...items, ...floGlobals.query.transactions],
|
||||||
|
string: address,
|
||||||
|
initItem,
|
||||||
|
filteredTransactions: null
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const { items, lastItem, initItem } = await floWebWallet.listTransactions(address)
|
||||||
|
floGlobals.query = {
|
||||||
|
transactions: items,
|
||||||
|
string: address,
|
||||||
|
lastItem,
|
||||||
|
initItem,
|
||||||
|
filteredTransactions: null
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
renderElem(getRef('queried_address_transactions'), html` <span>Failed to load transactions</span> `)
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function filterFetchedTransactions() {
|
function filterFetchedTransactions() {
|
||||||
const filter = getRef('filter_selector').value;
|
const filter = getRef('filter_selector').value;
|
||||||
if (filter !== 'all') {
|
if (filter !== 'all') {
|
||||||
floGlobals.query.transactions = floGlobals.query.transactions.filter(t => filter === 'sent' ? t.sender === floGlobals.query.string : t.receiver === floGlobals.query.string)
|
floGlobals.query.filteredTransactions = floGlobals.query.transactions.filter(t => filter === 'sent' ? t.sender === floGlobals.query.string : t.receiver === floGlobals.query.string)
|
||||||
|
} else {
|
||||||
|
floGlobals.query.filteredTransactions = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function processQuery() {
|
async function processQuery() {
|
||||||
|
|||||||
@ -30,10 +30,10 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//get balance of addr using API : resolves (balance)
|
//get balance of address using API : resolves (balance)
|
||||||
floWebWallet.getBalance = function (addr) {
|
floWebWallet.getBalance = function (address) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
floBlockchainAPI.getBalance(addr)
|
floBlockchainAPI.getBalance(address)
|
||||||
.then(txid => resolve(txid))
|
.then(txid => resolve(txid))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
@ -48,45 +48,52 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//sync new transactions from blockchain using API and stores in IDB : resolves Array(newItems)
|
function listTransactions_raw(address, options = {}) {
|
||||||
floWebWallet.syncTransactions = function (addr) {
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
compactIDB.readData('lastSync', addr).then(lastSync => {
|
options.latest = true;
|
||||||
const old_support = Number.isInteger(lastSync); //backward support
|
floBlockchainAPI.readTxs(address, options).then(response => {
|
||||||
let fetch_options = {};
|
const result = {}
|
||||||
if (typeof lastSync == 'string' && /^[a-f0-9]{64}$/i.test(lastSync)) //txid as lastSync
|
result.items = response.items.map(({ time, txid, floData, isCoinBase, vin, vout }) => ({
|
||||||
fetch_options.after = lastSync;
|
time, txid, floData, isCoinBase,
|
||||||
floBlockchainAPI.readAllTxs(addr, fetch_options).then(response => {
|
sender: isCoinBase ? `(mined)${vin[0].coinbase}` : vin[0].addr,
|
||||||
let newItems = response.items.map(({ time, txid, floData, isCoinBase, vin, vout }) => ({
|
receiver: isCoinBase ? address : vout[0].scriptPubKey.addresses[0]
|
||||||
time, txid, floData, isCoinBase,
|
}));
|
||||||
sender: isCoinBase ? `(mined)${vin[0].coinbase}` : vin[0].addr,
|
result.lastItem = response.lastItem;
|
||||||
receiver: isCoinBase ? addr : vout[0].scriptPubKey.addresses[0]
|
result.initItem = response.initItem;
|
||||||
})).reverse();
|
resolve(result);
|
||||||
compactIDB.readData('transactions', addr).then(IDBresult => {
|
|
||||||
if ((IDBresult === undefined || old_support))//backward support
|
|
||||||
IDBresult = [];
|
|
||||||
compactIDB.writeData('transactions', IDBresult.concat(newItems), addr).then(result => {
|
|
||||||
compactIDB.writeData('lastSync', response.lastItem, addr)
|
|
||||||
.then(result => resolve(newItems))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//read transactions stored in IDB : resolves Array(storedItems)
|
|
||||||
floWebWallet.readTransactions = function (addr) {
|
floWebWallet.listTransactions = function (address) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
compactIDB.readData('transactions', addr)
|
listTransactions_raw(address)
|
||||||
.then(IDBresult => resolve(IDBresult))
|
.then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//get address-label pairs from IDB : resolves Object(addr:label)
|
|
||||||
|
floWebWallet.listTransactions.syncNew = function (address, lastItem) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
listTransactions_raw(address, { after: lastItem }).then(result => {
|
||||||
|
delete result.initItem;
|
||||||
|
resolve(result);
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
floWebWallet.listTransactions.syncOld = function (address, initItem) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
listTransactions_raw(address, { before: initItem }).then(result => {
|
||||||
|
delete result.lastItem;
|
||||||
|
resolve(result);
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//get address-label pairs from IDB : resolves Object(floID:label)
|
||||||
floWebWallet.getLabels = function () {
|
floWebWallet.getLabels = function () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
compactIDB.readAllData('labels')
|
compactIDB.readAllData('labels')
|
||||||
|
|||||||
@ -843,7 +843,7 @@
|
|||||||
query_params.to = options.to;
|
query_params.to = options.to;
|
||||||
}
|
}
|
||||||
if (!isUndefined(options.latest))
|
if (!isUndefined(options.latest))
|
||||||
query_params.latest = latest;
|
query_params.latest = options.latest;
|
||||||
if (!isUndefined(options.mempool))
|
if (!isUndefined(options.mempool))
|
||||||
query_params.mempool = options.mempool;
|
query_params.mempool = options.mempool;
|
||||||
promisedAPI(api, query_params)
|
promisedAPI(api, query_params)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user