@frak-labs/core-sdk
Version:
Core SDK of the Frak wallet, low level library to interact directly with the frak ecosystem.
287 lines (241 loc) • 9.85 kB
text/typescript
import { beforeEach, vi } from "vitest";
vi.mock("../displayModal", () => ({
displayModal: vi.fn(),
}));
import type { Address, Hex } from "viem";
import { describe, expect, it } from "../../../tests/vitest-fixtures";
import type { FrakClient } from "../../types";
import { siweAuthenticate } from "./siweAuthenticate";
describe("siweAuthenticate", () => {
const mockClient = {
config: {
domain: "example.com",
metadata: {
name: "Test App",
},
},
request: vi.fn(),
} as unknown as FrakClient;
const mockClientWithoutDomain = {
config: {
metadata: {
name: "Test App",
},
},
request: vi.fn(),
} as unknown as FrakClient;
beforeEach(() => {
vi.stubGlobal("window", {
location: {
host: "window.example.com",
},
});
});
describe("basic usage", () => {
it("should call displayModal with SIWE params", async () => {
const { displayModal } = await import("../displayModal");
const mockResponse = {
login: {
wallet: "0x1234567890123456789012345678901234567890" as Address,
},
siweAuthenticate: {
message: "Sign in to Test App",
signature: "0xsignature" as Hex,
},
};
vi.mocked(displayModal).mockResolvedValue(mockResponse as any);
await siweAuthenticate(mockClient, {});
expect(displayModal).toHaveBeenCalledWith(mockClient, {
metadata: undefined,
steps: {
login: {},
siweAuthenticate: {
siwe: expect.objectContaining({
domain: "example.com",
nonce: expect.stringMatching(/^[0-9a-f]{96}$/),
uri: "https://example.com",
version: "1",
}),
},
},
});
});
it("should return SIWE authentication result", async () => {
const { displayModal } = await import("../displayModal");
const mockSiweResult = {
message: "I confirm that I want to use my Frak wallet",
signature:
"0xsig1234567890123456789012345678901234567890123456789012345678901234" as Hex,
};
vi.mocked(displayModal).mockResolvedValue({
login: {},
siweAuthenticate: mockSiweResult,
} as any);
const result = await siweAuthenticate(mockClient, {});
expect(result).toEqual(mockSiweResult);
});
});
describe("SIWE parameter handling", () => {
it("should use default statement when not provided", async () => {
const { displayModal } = await import("../displayModal");
vi.mocked(displayModal).mockResolvedValue({
login: {},
siweAuthenticate: { message: "", signature: "0x" as Hex },
} as any);
await siweAuthenticate(mockClient, {});
expect(displayModal).toHaveBeenCalledWith(
mockClient,
expect.objectContaining({
steps: expect.objectContaining({
siweAuthenticate: expect.objectContaining({
siwe: expect.objectContaining({
statement:
"I confirm that I want to use my Frak wallet on: Test App",
}),
}),
}),
})
);
});
it("should use custom statement when provided", async () => {
const { displayModal } = await import("../displayModal");
vi.mocked(displayModal).mockResolvedValue({
login: {},
siweAuthenticate: { message: "", signature: "0x" as Hex },
} as any);
await siweAuthenticate(mockClient, {
siwe: { statement: "Custom sign in message" },
});
expect(displayModal).toHaveBeenCalledWith(
mockClient,
expect.objectContaining({
steps: expect.objectContaining({
siweAuthenticate: expect.objectContaining({
siwe: expect.objectContaining({
statement: "Custom sign in message",
}),
}),
}),
})
);
});
it("should use custom nonce when provided", async () => {
const { displayModal } = await import("../displayModal");
vi.mocked(displayModal).mockResolvedValue({
login: {},
siweAuthenticate: { message: "", signature: "0x" as Hex },
} as any);
await siweAuthenticate(mockClient, {
siwe: { nonce: "custom-nonce" },
});
expect(displayModal).toHaveBeenCalledWith(
mockClient,
expect.objectContaining({
steps: expect.objectContaining({
siweAuthenticate: expect.objectContaining({
siwe: expect.objectContaining({
nonce: "custom-nonce",
}),
}),
}),
})
);
});
it("should use window.location.host when domain not in config", async () => {
const { displayModal } = await import("../displayModal");
vi.mocked(displayModal).mockResolvedValue({
login: {},
siweAuthenticate: { message: "", signature: "0x" as Hex },
} as any);
await siweAuthenticate(mockClientWithoutDomain, {});
expect(displayModal).toHaveBeenCalledWith(
mockClientWithoutDomain,
expect.objectContaining({
steps: expect.objectContaining({
siweAuthenticate: expect.objectContaining({
siwe: expect.objectContaining({
domain: "window.example.com",
uri: "https://window.example.com",
}),
}),
}),
})
);
});
it("should use custom uri when provided", async () => {
const { displayModal } = await import("../displayModal");
vi.mocked(displayModal).mockResolvedValue({
login: {},
siweAuthenticate: { message: "", signature: "0x" as Hex },
} as any);
await siweAuthenticate(mockClient, {
siwe: { uri: "https://custom-uri.com" },
});
expect(displayModal).toHaveBeenCalledWith(
mockClient,
expect.objectContaining({
steps: expect.objectContaining({
siweAuthenticate: expect.objectContaining({
siwe: expect.objectContaining({
uri: "https://custom-uri.com",
}),
}),
}),
})
);
});
it("should use custom version when provided", async () => {
const { displayModal } = await import("../displayModal");
vi.mocked(displayModal).mockResolvedValue({
login: {},
siweAuthenticate: { message: "", signature: "0x" as Hex },
} as any);
await siweAuthenticate(mockClient, {
siwe: { version: "2" as any },
});
expect(displayModal).toHaveBeenCalledWith(
mockClient,
expect.objectContaining({
steps: expect.objectContaining({
siweAuthenticate: expect.objectContaining({
siwe: expect.objectContaining({
version: "2",
}),
}),
}),
})
);
});
});
describe("with metadata", () => {
it("should pass metadata to displayModal", async () => {
const { displayModal } = await import("../displayModal");
vi.mocked(displayModal).mockResolvedValue({
login: {},
siweAuthenticate: { message: "", signature: "0x" as Hex },
} as any);
const metadata = {
header: {
title: "Sign In",
},
context: "Sign in to access your account",
};
await siweAuthenticate(mockClient, { metadata });
expect(displayModal).toHaveBeenCalledWith(mockClient, {
metadata,
steps: expect.any(Object),
});
});
});
describe("error handling", () => {
it("should propagate errors from displayModal", async () => {
const { displayModal } = await import("../displayModal");
vi.mocked(displayModal).mockRejectedValue(
new Error("SIWE authentication rejected")
);
await expect(siweAuthenticate(mockClient, {})).rejects.toThrow(
"SIWE authentication rejected"
);
});
});
});