fix: anypay (#3507)

* fix android CI

* fix: handle the parser seeing chainless QRs in the old flow as belonging to the current wallet, causing the error jack reported

* fix: handle network switch when anypay is interrupted mid flow and currency is changed
This commit is contained in:
David Adegoke
2026-08-12 01:14:39 +02:00
committed by GitHub
parent 3a71f6ad33
commit 414b2eadee
7 changed files with 490 additions and 52 deletions
+12 -10
View File
@@ -283,8 +283,8 @@ class ERC681URI extends PaymentURI {
} else {
final valueParam = uri.queryParameters["value"];
if (valueParam != null) {
final normalized = _normalizeToIntegerWei(valueParam);
formatedAmount = formatFixed(BigInt.parse(normalized), 18);
final normalized = BigInt.tryParse(_normalizeToIntegerWei(valueParam));
formatedAmount = normalized != null ? formatFixed(normalized, 18) : "";
} else {
formatedAmount = uri.queryParameters["amount"] ?? "";
}
@@ -313,9 +313,7 @@ class ERC681URI extends PaymentURI {
final targetAddress = contractAddress ?? address;
uri += targetAddress;
if (chainId != 1) {
uri += "@$chainId";
}
uri += "@$chainId";
if (contractAddress != null) {
uri += "/transfer";
@@ -364,14 +362,18 @@ class ERC681URI extends PaymentURI {
}
}
static int _getChainID(String path) => int.parse(
static int _getChainID(String path) =>
int.tryParse(
RegExp(r"@\d*").firstMatch(path)?.group(0)?.replaceAll("@", "") ?? "1",
);
) ??
1;
static (bool, String) _getTargetAddress(String path) {
final targetAddress =
RegExp(r"^(0x)?[0-9a-f]{40}", caseSensitive: false).firstMatch(path)!.group(0)!;
return (path.contains("/"), targetAddress);
// I saw in the schema (thanks Konsti) that EIP-681 allows an optional "pay-" prefix before the target address, so adding a check for it here
final cleaned = path.startsWith("pay-") ? path.substring(4) : path;
final match = RegExp(r"^(0x)?[0-9a-f]{40}", caseSensitive: false).firstMatch(cleaned);
final targetAddress = match?.group(0) ?? cleaned.split("@").first.split("/").first;
return (cleaned.contains("/"), targetAddress);
}
/// Normalize an input amount into an integer wei string.
+20 -5
View File
@@ -78,13 +78,13 @@ void main() {
const recipient = "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6";
const contract = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
test("builds a plain native transfer on mainnet", () {
test("includes the mainnet chainId on a plain native transfer", () {
final uri = ERC681URI(chainId: 1, address: recipient, amount: "", contractAddress: null);
expect(uri.toString(), "ethereum:$recipient");
expect(uri.toString(), "ethereum:$recipient@1");
});
test("appends the chainId for non-mainnet native transfers", () {
test("appends the chainId for native transfers", () {
final uri = ERC681URI(chainId: 137, address: recipient, amount: "", contractAddress: null);
expect(uri.toString(), "ethereum:$recipient@137");
@@ -93,7 +93,22 @@ void main() {
test("emits the native amount in ERC-681 scientific notation", () {
final uri = ERC681URI(chainId: 1, address: recipient, amount: "1", contractAddress: null);
expect(uri.toString(), "ethereum:$recipient?value=1.0e18");
expect(uri.toString(), "ethereum:$recipient@1?value=1.0e18");
});
test("includes the mainnet chainId in the transfer form", () {
final uri = ERC681URI(
chainId: 1,
address: recipient,
amount: "200.172148",
contractAddress: contract,
tokenDecimals: 6,
);
expect(
uri.toString(),
"ethereum:$contract@1/transfer?address=$recipient&amount=200.172148",
);
});
test("builds the transfer form for a token", () {
@@ -189,7 +204,7 @@ void main() {
rawTokenAmount: "1000000",
);
expect(uri.toString(), "ethereum:$contract/transfer?address=$recipient&uint256=1000000");
expect(uri.toString(), "ethereum:$contract@1/transfer?address=$recipient&uint256=1000000");
});
test("parses a scientific notation value", () {