Skip to content

Commit 81bd358

Browse files
committed
test(auth-client): add engine verifyContext wiring regression
1 parent fc60034 commit 81bd358

3 files changed

Lines changed: 149 additions & 0 deletions

File tree

packages/auth-client/src/utils/verifyContext.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ export const buildVerifyContext = async (
1414
attestationId: string,
1515
metadata: AuthClientTypes.Metadata,
1616
): Promise<Verify.Context> => {
17+
if (!metadata?.url) {
18+
const context: Verify.Context = {
19+
verified: { verifyUrl: "", validation: "UNKNOWN", origin: "" },
20+
};
21+
try {
22+
const attestation = await resolve({ attestationId });
23+
if (typeof attestation === "object" && attestation?.isScam) {
24+
context.verified.isScam = true;
25+
}
26+
} catch (e) {
27+
logError?.(e);
28+
}
29+
return context;
30+
}
31+
1732
const context: Verify.Context = {
1833
verified: {
1934
verifyUrl: metadata.verifyUrl || "",
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { expect, describe, it, vi, beforeEach } from "vitest";
2+
import { AuthEngine } from "../src/controllers/engine";
3+
import { AuthClientTypes } from "../src/types";
4+
5+
const WALLET_URL = "https://mywallet.app";
6+
const DAPP_URL = "https://app.uniswap.org";
7+
8+
const walletMetadata: AuthClientTypes.Metadata = {
9+
name: "My Wallet",
10+
description: "",
11+
url: WALLET_URL,
12+
icons: [],
13+
};
14+
15+
const dappMetadata: AuthClientTypes.Metadata = {
16+
name: "Uniswap",
17+
description: "",
18+
url: DAPP_URL,
19+
icons: [],
20+
};
21+
22+
const authRequestPayload = {
23+
id: 1,
24+
jsonrpc: "2.0" as const,
25+
method: "wc_authRequest" as const,
26+
params: {
27+
requester: {
28+
publicKey: "abc123",
29+
metadata: dappMetadata,
30+
},
31+
payloadParams: {
32+
type: "eip4361" as const,
33+
chainId: "eip155:1",
34+
domain: "app.uniswap.org",
35+
aud: "https://app.uniswap.org/login",
36+
version: "1",
37+
nonce: "deadbeef",
38+
iat: new Date().toISOString(),
39+
},
40+
},
41+
};
42+
43+
function createMockClient(verifyResolveReturn: unknown) {
44+
return {
45+
metadata: walletMetadata,
46+
logger: {
47+
info: vi.fn(),
48+
error: vi.fn(),
49+
debug: vi.fn(),
50+
},
51+
requests: {
52+
set: vi.fn().mockResolvedValue(undefined),
53+
},
54+
core: {
55+
verify: {
56+
resolve: vi.fn().mockResolvedValue(verifyResolveReturn),
57+
},
58+
pairing: {
59+
register: vi.fn(),
60+
},
61+
},
62+
emit: vi.fn(),
63+
} as any;
64+
}
65+
66+
describe("AuthEngine.onAuthRequest verifyContext wiring", () => {
67+
it("produces VALID when attested origin matches requester (dApp) URL", async () => {
68+
const mockClient = createMockClient({ origin: DAPP_URL });
69+
const engine = new AuthEngine(mockClient);
70+
71+
await (engine as any).onAuthRequest("topic", authRequestPayload);
72+
73+
const [eventName, eventArgs] = mockClient.emit.mock.calls[0];
74+
expect(eventName).toBe("auth_request");
75+
expect(eventArgs.verifyContext.verified.validation).toBe("VALID");
76+
expect(eventArgs.verifyContext.verified.origin).toBe(DAPP_URL);
77+
});
78+
79+
it("produces INVALID when attested origin matches wallet URL but not requester URL (regression guard)", async () => {
80+
const mockClient = createMockClient({ origin: WALLET_URL });
81+
const engine = new AuthEngine(mockClient);
82+
83+
await (engine as any).onAuthRequest("topic", authRequestPayload);
84+
85+
const [eventName, eventArgs] = mockClient.emit.mock.calls[0];
86+
expect(eventName).toBe("auth_request");
87+
expect(eventArgs.verifyContext.verified.validation).toBe("INVALID");
88+
expect(eventArgs.verifyContext.verified.origin).toBe(WALLET_URL);
89+
});
90+
});

packages/auth-client/test/verifyContext.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,48 @@ describe("buildVerifyContext", () => {
121121
);
122122
expect(ctx.verified.validation).toBe("VALID");
123123
});
124+
125+
it("returns UNKNOWN with empty origin when metadata is undefined", async () => {
126+
const ctx = await buildVerifyContext(
127+
{ resolve: () => Promise.resolve(undefined), logError: noopLog },
128+
"hash",
129+
undefined as any,
130+
);
131+
expect(ctx.verified.validation).toBe("UNKNOWN");
132+
expect(ctx.verified.origin).toBe("");
133+
expect(ctx.verified.verifyUrl).toBe("");
134+
});
135+
136+
it("returns UNKNOWN with empty origin when metadata is null", async () => {
137+
const ctx = await buildVerifyContext(
138+
{ resolve: () => Promise.resolve(undefined), logError: noopLog },
139+
"hash",
140+
null as any,
141+
);
142+
expect(ctx.verified.validation).toBe("UNKNOWN");
143+
expect(ctx.verified.origin).toBe("");
144+
});
145+
146+
it("returns UNKNOWN with empty origin when metadata.url is empty string", async () => {
147+
const ctx = await buildVerifyContext(
148+
{ resolve: () => Promise.resolve(undefined), logError: noopLog },
149+
"hash",
150+
{ name: "x", description: "", url: "", icons: [] },
151+
);
152+
expect(ctx.verified.validation).toBe("UNKNOWN");
153+
expect(ctx.verified.origin).toBe("");
154+
});
155+
156+
it("propagates isScam even when metadata is undefined", async () => {
157+
const ctx = await buildVerifyContext(
158+
{
159+
resolve: () => Promise.resolve({ origin: "https://attacker.com", isScam: true }),
160+
logError: noopLog,
161+
},
162+
"hash",
163+
undefined as any,
164+
);
165+
expect(ctx.verified.isScam).toBe(true);
166+
expect(ctx.verified.validation).toBe("UNKNOWN");
167+
});
124168
});

0 commit comments

Comments
 (0)