Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f800202356 |
No files matched your search
@@ -1573,8 +1573,8 @@ The popup refreshes balances every ten seconds while it is open
|
|||||||
(`doRefreshAndRender()` in `src/popup/index.js`). Each refresh that returns
|
(`doRefreshAndRender()` in `src/popup/index.js`). Each refresh that returns
|
||||||
draws the wallet list again and, when AddressDetail or AddressToken is up, that
|
draws the wallet list again and, when AddressDetail or AddressToken is up, that
|
||||||
screen's USD total and balance lines; its transaction list is left alone. No
|
screen's USD total and balance lines; its transaction list is left alone. No
|
||||||
other screen is drawn again by a refresh, since the rest show no balances or
|
other screen is drawn again by a refresh, DeleteAddress and its balance lines
|
||||||
hold what the user typed.
|
included.
|
||||||
|
|
||||||
A network switch leaves every screen on the page showing the previous network.
|
A network switch leaves every screen on the page showing the previous network.
|
||||||
The user makes it in Settings, or approves a site's request and the background
|
The user makes it in Settings, or approves a site's request and the background
|
||||||
@@ -2090,10 +2090,11 @@ view would leave a wallet one click from deletion.
|
|||||||
**AddressDetail**. The token's balance is not known until a balance
|
**AddressDetail**. The token's balance is not known until a balance
|
||||||
refresh that started with it tracked has fetched every address's token
|
refresh that started with it tracked has fetched every address's token
|
||||||
balances; until then its balance line reads `quantity unknown`, never
|
balances; until then its balance line reads `quantity unknown`, never
|
||||||
`0.0000`, unless the explorer had already listed a holding of it. A
|
`0.0000`, unless the explorer had already listed a holding of it. That
|
||||||
refresh that returns draws AddressDetail's balances again (see
|
holds after the popup is closed and opened again, as the tokens still
|
||||||
Navigation), so the fetched balance shows without the screen being
|
waiting for a fetch are stored with the profile. A refresh that returns
|
||||||
reopened
|
draws AddressDetail's balances again (see Navigation), so the fetched
|
||||||
|
balance shows without the screen being reopened
|
||||||
- "Add" with a token already tracked, a scam-listed address, or a failed
|
- "Add" with a token already tracked, a scam-listed address, or a failed
|
||||||
contract lookup → flash message, no screen change
|
contract lookup → flash message, no screen change
|
||||||
- "Add", then a network switch in Settings before the contract lookup
|
- "Add", then a network switch in Settings before the contract lookup
|
||||||
|
|||||||
+4
-4
@@ -21,7 +21,6 @@ const {
|
|||||||
showSaveFailureBanner,
|
showSaveFailureBanner,
|
||||||
pushCurrentView,
|
pushCurrentView,
|
||||||
goBack,
|
goBack,
|
||||||
tokensNotFetched,
|
|
||||||
} = require("./views/helpers");
|
} = require("./views/helpers");
|
||||||
const { applyTheme } = require("./theme");
|
const { applyTheme } = require("./theme");
|
||||||
const {
|
const {
|
||||||
@@ -86,8 +85,7 @@ let refreshTimer = null;
|
|||||||
//
|
//
|
||||||
// Once the save is done, the wallet list is drawn again, and so are the
|
// Once the save is done, the wallet list is drawn again, and so are the
|
||||||
// balances on AddressDetail or AddressToken when that is the screen up. No
|
// balances on AddressDetail or AddressToken when that is the screen up. No
|
||||||
// other screen is drawn again, since the rest show no balances or hold what the
|
// other screen is drawn again, DeleteAddress and its balance lines included.
|
||||||
// user typed.
|
|
||||||
async function doRefreshAndRender() {
|
async function doRefreshAndRender() {
|
||||||
if (refreshInFlight) return;
|
if (refreshInFlight) return;
|
||||||
refreshInFlight = true;
|
refreshInFlight = true;
|
||||||
@@ -140,7 +138,9 @@ async function doRefreshAndRender() {
|
|||||||
// Each token this refresh asked about is now fetched for every
|
// Each token this refresh asked about is now fetched for every
|
||||||
// address.
|
// address.
|
||||||
if (allTokenBalancesFetched) {
|
if (allTokenBalancesFetched) {
|
||||||
for (const token of tokens) tokensNotFetched.delete(token);
|
state.tokensNotFetched = state.tokensNotFetched.filter(
|
||||||
|
(token) => !tokens.includes(token),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
state.lastBalanceRefresh = Date.now();
|
state.lastBalanceRefresh = Date.now();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ const {
|
|||||||
nativeCurrency,
|
nativeCurrency,
|
||||||
balanceLine,
|
balanceLine,
|
||||||
unknownableAmount,
|
unknownableAmount,
|
||||||
tokensNotFetched,
|
|
||||||
renderAddressHtml,
|
renderAddressHtml,
|
||||||
attachCopyHandlers,
|
attachCopyHandlers,
|
||||||
goBack,
|
goBack,
|
||||||
@@ -165,7 +164,7 @@ function renderBalance() {
|
|||||||
// token just added: no quantity to show, and none to price.
|
// token just added: no quantity to show, and none to price.
|
||||||
// balanceLine() states that rather than printing 0.0000.
|
// balanceLine() states that rather than printing 0.0000.
|
||||||
if (tb) amount = unknownableAmount(tb.balance);
|
if (tb) amount = unknownableAmount(tb.balance);
|
||||||
else amount = tokensNotFetched.has(id) ? null : 0;
|
else amount = state.tokensNotFetched.includes(id) ? null : 0;
|
||||||
price = getPrice(currentSymbol);
|
price = getPrice(currentSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -380,20 +380,16 @@ function balanceLine(symbol, amount, price, tokenId) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contract addresses, lowercased, of the tokens the user added that no balance
|
|
||||||
// refresh has fetched yet. An address with no balance row for one of them has
|
|
||||||
// no known balance of it, so its line says the quantity is unknown rather than
|
|
||||||
// 0.0000. trackToken() adds a token here, and doRefreshAndRender() in
|
|
||||||
// src/popup/index.js takes it off once a refresh that started with it tracked
|
|
||||||
// has fetched every address's token balances
|
|
||||||
// (https://git.eeqj.de/sneak/AutistMask/issues/516).
|
|
||||||
const tokensNotFetched = new Set();
|
|
||||||
|
|
||||||
// Tracks `token` on the active network, as every add path on AddToken and
|
// Tracks `token` on the active network, as every add path on AddToken and
|
||||||
// SettingsAddToken does. No refresh has fetched its balance yet.
|
// SettingsAddToken does, and lists it in `state.tokensNotFetched`: no refresh
|
||||||
|
// has fetched its balance yet. An address with no balance row for it has no
|
||||||
|
// known balance of it, so its line says the quantity is unknown rather than
|
||||||
|
// 0.0000. doRefreshAndRender() in src/popup/index.js takes it off once a
|
||||||
|
// refresh that started with it tracked has fetched every address's token
|
||||||
|
// balances (https://git.eeqj.de/sneak/AutistMask/issues/516).
|
||||||
function trackToken(token) {
|
function trackToken(token) {
|
||||||
state.trackedTokens.push(token);
|
state.trackedTokens.push(token);
|
||||||
tokensNotFetched.add(token.address.toLowerCase());
|
state.tokensNotFetched.push(token.address.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
function balanceLinesForAddress(addr, trackedTokens, showZero) {
|
function balanceLinesForAddress(addr, trackedTokens, showZero) {
|
||||||
@@ -429,7 +425,7 @@ function balanceLinesForAddress(addr, trackedTokens, showZero) {
|
|||||||
if (seen.has(id)) continue;
|
if (seen.has(id)) continue;
|
||||||
html += balanceLine(
|
html += balanceLine(
|
||||||
t.symbol,
|
t.symbol,
|
||||||
tokensNotFetched.has(id) ? null : 0,
|
state.tokensNotFetched.includes(id) ? null : 0,
|
||||||
getPrice(t.symbol),
|
getPrice(t.symbol),
|
||||||
id,
|
id,
|
||||||
);
|
);
|
||||||
@@ -803,7 +799,6 @@ module.exports = {
|
|||||||
flashCopyFeedback,
|
flashCopyFeedback,
|
||||||
balanceLine,
|
balanceLine,
|
||||||
balanceLinesForAddress,
|
balanceLinesForAddress,
|
||||||
tokensNotFetched,
|
|
||||||
trackToken,
|
trackToken,
|
||||||
addressHoldsFunds,
|
addressHoldsFunds,
|
||||||
keyMaterialName,
|
keyMaterialName,
|
||||||
|
|||||||
@@ -28,6 +28,13 @@ const DEFAULT_STATE = {
|
|||||||
// others are restored from when the active network changes. See
|
// others are restored from when the active network changes. See
|
||||||
// applyChainSwitchFields().
|
// applyChainSwitchFields().
|
||||||
networkTrackedTokens: {},
|
networkTrackedTokens: {},
|
||||||
|
// Contract addresses, lowercased, of the tokens the user added that no
|
||||||
|
// balance refresh has fetched yet. trackToken() in
|
||||||
|
// src/popup/views/helpers.js adds one, and doRefreshAndRender() in
|
||||||
|
// src/popup/index.js takes it off. Stored, so a token added just before
|
||||||
|
// the popup closed still reads `quantity unknown` when it opens again
|
||||||
|
// (https://git.eeqj.de/sneak/AutistMask/issues/516).
|
||||||
|
tokensNotFetched: [],
|
||||||
networkId: "mainnet",
|
networkId: "mainnet",
|
||||||
rpcUrl: DEFAULT_RPC_URL,
|
rpcUrl: DEFAULT_RPC_URL,
|
||||||
blockscoutUrl: DEFAULT_BLOCKSCOUT_URL,
|
blockscoutUrl: DEFAULT_BLOCKSCOUT_URL,
|
||||||
@@ -412,6 +419,8 @@ function normalizePersisted(saved) {
|
|||||||
// so a stored string walks through the `|| []` and a stored number walks
|
// so a stored string walks through the `|| []` and a stored number walks
|
||||||
// through an Array.isArray().
|
// through an Array.isArray().
|
||||||
out.fraudContracts = textList(saved.fraudContracts);
|
out.fraudContracts = textList(saved.fraudContracts);
|
||||||
|
// Contract addresses too, read with `includes()` and `filter()`.
|
||||||
|
out.tokensNotFetched = textList(saved.tokensNotFetched);
|
||||||
out.tokenHolderCache = structuredClone(saved.tokenHolderCache || {});
|
out.tokenHolderCache = structuredClone(saved.tokenHolderCache || {});
|
||||||
out.theme = saved.theme || "system";
|
out.theme = saved.theme || "system";
|
||||||
out.debugMode = saved.debugMode !== undefined ? saved.debugMode : false;
|
out.debugMode = saved.debugMode !== undefined ? saved.debugMode : false;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
// After "Add" on AddToken, AddressDetail lists the new token, and its line reads
|
// After "Add" on AddToken, AddressDetail lists the new token, and its line reads
|
||||||
// `quantity unknown`, not 0.0000, until a balance refresh that asked the
|
// `quantity unknown`, not 0.0000, until a balance refresh that asked the
|
||||||
// explorer about the token has returned for every address; so does a token
|
// explorer about the token has returned for every address, the popup closing
|
||||||
// added on SettingsAddToken, wherever it is listed. A refresh that
|
// and opening again meanwhile included; so does a token added on
|
||||||
// returns draws the balances on AddressDetail or AddressToken again, so the
|
// SettingsAddToken, wherever it is listed. A refresh that returns draws the
|
||||||
// fetched balance shows without the screen being reopened
|
// balances on AddressDetail or AddressToken again, so the fetched balance shows
|
||||||
|
// without the screen being reopened
|
||||||
// (https://git.eeqj.de/sneak/AutistMask/issues/516). Driven through the real
|
// (https://git.eeqj.de/sneak/AutistMask/issues/516). Driven through the real
|
||||||
// popup over a stored profile on Ethereum Mainnet, with "Show tracked tokens
|
// popup over a stored profile on Ethereum Mainnet, with "Show tracked tokens
|
||||||
// with zero balance" on, as it is by default.
|
// with zero balance" on, as it is by default.
|
||||||
@@ -163,6 +164,29 @@ test("a refresh already running when the token is added does not count as fetchi
|
|||||||
expect(newTokenRow(page)).toContain("0.0000");
|
expect(newTokenRow(page)).toContain("0.0000");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("closed and opened again before any refresh has fetched it, the new token's line still reads quantity unknown", async () => {
|
||||||
|
const closed = await bootOnAddress();
|
||||||
|
holdNextRefresh(closed);
|
||||||
|
await addNewToken(closed);
|
||||||
|
cleanupPopup();
|
||||||
|
|
||||||
|
// The refresh this boot starts gets no token balances back: the boot's
|
||||||
|
// stub of refreshBalances() writes none.
|
||||||
|
const page = await bootPopup(undefined, { storage: closed.storage });
|
||||||
|
expect(page.visibleViews()).toEqual(["address"]);
|
||||||
|
const row = newTokenRow(page);
|
||||||
|
expect(row).toContain("quantity unknown");
|
||||||
|
expect(row).not.toContain("0.0000");
|
||||||
|
|
||||||
|
const finish = holdNextRefresh(page);
|
||||||
|
const ticking = page.tick();
|
||||||
|
await page.settle();
|
||||||
|
await finish([MILLION]);
|
||||||
|
await ticking;
|
||||||
|
|
||||||
|
expect(newTokenRow(page)).toContain("1000000.0000");
|
||||||
|
});
|
||||||
|
|
||||||
test("a refresh in which the explorer did not answer leaves the new token's line quantity unknown", async () => {
|
test("a refresh in which the explorer did not answer leaves the new token's line quantity unknown", async () => {
|
||||||
const page = await bootOnAddress();
|
const page = await bootOnAddress();
|
||||||
const finish = holdNextRefresh(page);
|
const finish = holdNextRefresh(page);
|
||||||
|
|||||||
@@ -248,6 +248,13 @@ const CONTRACT = [
|
|||||||
floorOnly: [[42], [null], [{}], [[TOKEN_ADDRESS]]],
|
floorOnly: [[42], [null], [{}], [[TOKEN_ADDRESS]]],
|
||||||
holds: (v) => everyEntry(v, isText),
|
holds: (v) => everyEntry(v, isText),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: "tokensNotFetched",
|
||||||
|
kind: KIND.ENTRIES,
|
||||||
|
hostile: [42, "notalist", { a: 1 }],
|
||||||
|
floorOnly: [[42], [null], [{}], [[TOKEN_ADDRESS]]],
|
||||||
|
holds: (v) => everyEntry(v, isText),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: "viewStack",
|
field: "viewStack",
|
||||||
kind: KIND.ENTRIES,
|
kind: KIND.ENTRIES,
|
||||||
|
|||||||
Reference in new issue
Block a user