Skip to content

Commit 7adb034

Browse files
committed
fix: force s-value normalization
Should fix flaky tests
1 parent e1ef0b7 commit 7adb034

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

examples/demo-app/components/WalletConfig.vue

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ watch(isReady, (ready) => {
252252
if (config.value.source === "browser-wallet") {
253253
config.value.connectedAddress = connectedAddress.value;
254254
}
255-
});
255+
}, { immediate: true, flush: "sync" });
256256
257257
/**
258258
* Connect to browser wallet (MetaMask, etc.)
@@ -317,9 +317,10 @@ function handleAccountsChanged(accounts) {
317317
}
318318
319319
/**
320-
* Detect network environment
320+
* Detect network environment and check for query parameters
321321
*/
322322
async function detectEnvironment() {
323+
// First, detect if we're on Anvil
323324
try {
324325
const response = await fetch("/contracts.json");
325326
if (response.ok) {
@@ -338,6 +339,24 @@ async function detectEnvironment() {
338339
// eslint-disable-next-line no-console
339340
console.warn("Could not load contracts.json:", err);
340341
}
342+
343+
// Then, check for fundingAccount query parameter (for E2E tests)
344+
// This must happen after we've detected isAnvil
345+
if (typeof window !== "undefined") {
346+
const urlParams = new URLSearchParams(window.location.search);
347+
const fundingAccountParam = urlParams.get("fundingAccount");
348+
if (fundingAccountParam !== null) {
349+
const accountIndex = parseInt(fundingAccountParam, 10);
350+
if (!isNaN(accountIndex) && accountIndex >= 0 && accountIndex <= 9) {
351+
// eslint-disable-next-line no-console
352+
console.log("Setting Anvil account from query parameter:", accountIndex);
353+
config.value.source = "anvil";
354+
config.value.anvilAccountIndex = accountIndex;
355+
// Since isAnvil might already be true from detectEnvironment,
356+
// the isReady computed property should now evaluate to true
357+
}
358+
}
359+
}
341360
}
342361
343362
// Initialize on mount

packages/sdk-platforms/web/src/webauthn-helpers.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,31 @@ function parseDerSignature(signatureBytes: Uint8Array): { r: Uint8Array; s: Uint
101101
throw new Error(`Invalid signature component length: r=${r.length}, s=${s.length}`);
102102
}
103103

104+
// Normalize s to low-s form for EVM compatibility
105+
// secp256r1 curve order (n): 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
106+
const secp256r1_n = BigInt("0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
107+
const secp256r1_n_half = secp256r1_n / 2n;
108+
109+
// Convert s to BigInt
110+
let sBigInt = 0n;
111+
for (let i = 0; i < s.length; i++) {
112+
sBigInt = (sBigInt << 8n) | BigInt(s[i]);
113+
}
114+
115+
// If s > n/2, use n - s instead (low-s form)
116+
if (sBigInt > secp256r1_n_half) {
117+
sBigInt = secp256r1_n - sBigInt;
118+
119+
// Convert back to Uint8Array
120+
const sBytes: number[] = [];
121+
let temp = sBigInt;
122+
while (temp > 0n) {
123+
sBytes.unshift(Number(temp & 0xFFn));
124+
temp = temp >> 8n;
125+
}
126+
s = new Uint8Array(sBytes);
127+
}
128+
104129
return { r, s };
105130
}
106131

0 commit comments

Comments
 (0)