Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eca2d15249 |
@@ -54,15 +54,6 @@ but the review is broader than any of them.
|
|||||||
`leavePrivkeyScreen()` in `tests/e2e/run.js` expects the address screen after
|
`leavePrivkeyScreen()` in `tests/e2e/run.js` expects the address screen after
|
||||||
Settings.
|
Settings.
|
||||||
|
|
||||||
- 2026-10-06: A token symbol or name read off a contract is no longer stored cut
|
|
||||||
between the two halves of an emoji
|
|
||||||
([#458](https://git.eeqj.de/sneak/AutistMask/issues/458)). `lookupTokenInfo()`
|
|
||||||
cut both by UTF-16 units; it now counts code points, as `displaySymbol()` has
|
|
||||||
since [#329](https://git.eeqj.de/sneak/AutistMask/issues/329).
|
|
||||||
`tests/tokenLookupTruncation.test.js` looks up a token whose symbol and name
|
|
||||||
are made of emoji outside the Basic Multilingual Plane. A symbol already
|
|
||||||
stored broken is not repaired.
|
|
||||||
|
|
||||||
- 2026-10-06: Reloading or closing the popup no longer logs a request it cancels
|
- 2026-10-06: Reloading or closing the popup no longer logs a request it cancels
|
||||||
as a failure in the transaction lists and ENS name lookups on the address and
|
as a failure in the transaction lists and ENS name lookups on the address and
|
||||||
token screens, the address scan after a wallet is created, the endpoint checks
|
token screens, the address scan after a wallet is created, the endpoint checks
|
||||||
|
|||||||
@@ -334,12 +334,9 @@ async function lookupTokenInfo(contractAddress, rpcUrl, networkId, signal) {
|
|||||||
name = symbol;
|
name = symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate to prevent storage of excessively long values from RPC.
|
// Truncate to prevent storage of excessively long values from RPC
|
||||||
// Counted in code points, as displaySymbol() counts them, so the cut never
|
name = String(name).slice(0, 64);
|
||||||
// falls between the two halves of an emoji and stores a half that renders
|
symbol = String(symbol).slice(0, 12);
|
||||||
// as U+FFFD.
|
|
||||||
name = Array.from(String(name)).slice(0, 64).join("");
|
|
||||||
symbol = Array.from(String(symbol)).slice(0, 12).join("");
|
|
||||||
|
|
||||||
log.infof("Token resolved:", symbol, "decimals", Number(decimals));
|
log.infof("Token resolved:", symbol, "decimals", Number(decimals));
|
||||||
return { name, symbol, decimals: Number(decimals) };
|
return { name, symbol, decimals: Number(decimals) };
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
// lookupTokenInfo() cuts the symbol and name it reads off a contract on
|
|
||||||
// code-point boundaries, as displaySymbol() counts them, so an emoji outside
|
|
||||||
// the Basic Multilingual Plane is never stored cut in half
|
|
||||||
// (https://git.eeqj.de/sneak/AutistMask/issues/458).
|
|
||||||
|
|
||||||
// An emoji outside the Basic Multilingual Plane: two UTF-16 units.
|
|
||||||
const FOX = "\u{1F98A}";
|
|
||||||
|
|
||||||
// The leading "A" puts every emoji at an odd UTF-16 offset, so a cut that
|
|
||||||
// counts UTF-16 units lands between the two halves of one.
|
|
||||||
const SYMBOL = "A" + FOX.repeat(12);
|
|
||||||
const NAME = "A" + FOX.repeat(64);
|
|
||||||
|
|
||||||
// The contract answers symbol(), decimals() and name() with the values above.
|
|
||||||
jest.doMock("ethers", () => ({
|
|
||||||
...jest.requireActual("ethers"),
|
|
||||||
Contract: function () {
|
|
||||||
return {
|
|
||||||
symbol: async () => SYMBOL,
|
|
||||||
decimals: async () => 18n,
|
|
||||||
name: async () => NAME,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const { lookupTokenInfo } = require("../src/shared/balances");
|
|
||||||
|
|
||||||
const ADDRESS = "0x1111111111111111111111111111111111111111";
|
|
||||||
const RPC_URL = "https://rpc.example.invalid";
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
// A token found is logged at info level, which is not under test.
|
|
||||||
jest.spyOn(console, "log").mockImplementation(() => {});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jest.restoreAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("the symbol is cut to 12 code points, never inside an emoji", async () => {
|
|
||||||
const { symbol } = await lookupTokenInfo(ADDRESS, RPC_URL, "mainnet");
|
|
||||||
expect(symbol).toBe("A" + FOX.repeat(11));
|
|
||||||
});
|
|
||||||
|
|
||||||
test("the name is cut to 64 code points, never inside an emoji", async () => {
|
|
||||||
const { name } = await lookupTokenInfo(ADDRESS, RPC_URL, "mainnet");
|
|
||||||
expect(name).toBe("A" + FOX.repeat(63));
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user