Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: drop siwe and ethers #225

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .changeset/mighty-berries-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
"@farcaster/auth-client": minor
"@farcaster/auth-kit": patch
"with-next-auth": patch
"frontend-only": patch
"@farcaster/auth-relay": patch
---

This release drops `ethers` and `siwe` dependency in favour of `viem/siwe`

---

**Breaking changes**:

- `@farcaster/auth-client`:
- `AppClient.verifySignInMessage` won't return `success` and instead will throw
an error if the verification hasn't succeeded.
- `issuedAt` is now of type `Date`, opposed to `string` in the past.
- `viem` peer dependency bumped to `2.x` version and won't support `1.x` versions.
4 changes: 1 addition & 3 deletions apps/relay/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@
"axios": "^1.7.4",
"dd-trace": "^5.21.0",
"dotenv": "^16.3.1",
"ethers": "^6.0.8",
"fastify": "^4.24.3",
"ioredis": "^5.3.2",
"neverthrow": "^6.1.0",
"siwe": "^2.1.4",
"viem": "^2.5.0"
"viem": "^2.21.12"
},
"devDependencies": {
"jest": "^29.7.0"
Expand Down
4 changes: 2 additions & 2 deletions apps/relay/src/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FastifyError, FastifyReply, FastifyRequest } from "fastify";
import type { Hex } from "viem";
import { AUTH_KEY, URL_BASE } from "./env";
import { generateNonce } from "siwe";
import { generateSiweNonce } from "viem/siwe";

export type CreateChannelRequest = {
siweUri: string;
Expand Down Expand Up @@ -56,7 +56,7 @@ export async function createChannel(request: FastifyRequest<{ Body: CreateChanne
const channel = await request.channels.open();
if (channel.isOk()) {
const channelToken = channel.value;
const nonce = request.body.nonce ?? generateNonce();
const nonce = request.body.nonce ?? generateSiweNonce();
const url = constructUrl(channelToken);

const update = await request.channels.update(channelToken, {
Expand Down
1 change: 0 additions & 1 deletion examples/frontend-only/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const config = {
function App() {
return (
<main style={{ fontFamily: 'Inter, "Inter Placeholder", sans-serif' }}>
{/* @ts-expect-error ethers version type incompat */}
<AuthKitProvider config={config}>
<div style={{ position: "fixed", top: "12px", right: "12px" }}>
<SignInButton />
Expand Down
1 change: 0 additions & 1 deletion examples/with-next-auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
},
"dependencies": {
"@farcaster/auth-kit": "*",
"ethers": "^6.12.0",
"next": "14.1.1",
"next-auth": "^4.24.5",
"react": "^18.2.0",
Expand Down
11 changes: 5 additions & 6 deletions examples/with-next-auth/pages/api/auth/[...nextauth].ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { createAppClient, viemConnector } from "@farcaster/auth-client";
import { NextApiRequest, NextApiResponse } from "next";
import { JsonRpcProvider } from "ethers";

export default (req: NextApiRequest, res: NextApiResponse) =>
NextAuth(req, res, {
Expand Down Expand Up @@ -43,23 +42,23 @@ export default (req: NextApiRequest, res: NextApiResponse) =>
ethereum: viemConnector(),
});

try {
const verifyResponse = await appClient.verifySignInMessage({
message: credentials?.message as string,
signature: credentials?.signature as `0x${string}`,
domain: "example.com",
nonce: csrfToken,
});
const { success, fid } = verifyResponse;

if (!success) {
return null;
}
const { fid } = verifyResponse;

return {
id: fid.toString(),
name: credentials?.name,
image: credentials?.pfp,
};
} catch {
return null;
}
},
}),
],
Expand Down
13 changes: 4 additions & 9 deletions packages/auth-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
"types": "./dist/index.d.ts"
}
},
"files": [
"dist"
],
"files": ["dist"],
"license": "MIT",
"scripts": {
"build": "tsup --config tsup.config.ts",
Expand All @@ -26,15 +24,12 @@
"prepublishOnly": "yarn run build"
},
"dependencies": {
"neverthrow": "^6.1.0",
"siwe": "^2.1.4"
"neverthrow": "^6.1.0"
},
"peerDependencies": {
"ethers": "5.x || 6.x",
"viem": "1.x || 2.x"
"viem": "^2.12.0"
},
"devDependencies": {
"ethers": "^6.12.0",
"viem": "^1.19.11"
"viem": "^2.21.12"
}
}
12 changes: 4 additions & 8 deletions packages/auth-client/src/actions/app/verifySignInMessage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,11 @@ import { createWalletClient } from "../../clients/createWalletClient";
import { viemConnector } from "../../clients/ethereum/viemConnector";
import { privateKeyToAccount, generatePrivateKey } from "viem/accounts";
import { AuthClientError } from "../../errors";
import { JsonRpcProvider } from "ethers";

describe("verifySignInMessage", () => {
const client = createAppClient(
{
ethereum: viemConnector(),
},
new JsonRpcProvider("https://mainnet.optimism.io/", 10),
);
const client = createAppClient({
ethereum: viemConnector(),
});

const walletClient = createWalletClient({
ethereum: viemConnector(),
Expand All @@ -23,7 +19,7 @@ describe("verifySignInMessage", () => {
domain: "example.com",
uri: "https://example.com/login",
version: "1",
issuedAt: "2023-10-01T00:00:00.000Z",
issuedAt: new Date("2023-10-01T00:00:00"),
nonce: "abcd1234",
};
const { nonce, domain } = siweParams;
Expand Down
11 changes: 6 additions & 5 deletions packages/auth-client/src/actions/app/verifySignInMessage.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { SiweMessage } from "siwe";
import { SiweMessage } from "viem/siwe";
import { Client } from "../../clients/createClient";
import { VerifyResponse, verify } from "../../messages/verify";
import { Unwrapped, unwrap } from "../../errors";
import type { Provider } from "ethers";
import type { ExactPartial, PublicClient, Transport } from "viem";
import { optimism } from "viem/chains";

export interface VerifySignInMessageArgs {
nonce: string;
domain: string;
message: string | Partial<SiweMessage>;
message: string | ExactPartial<SiweMessage>;
signature: `0x${string}`;
}

Expand All @@ -16,11 +17,11 @@ export type VerifySignInMessageResponse = Promise<Unwrapped<VerifyResponse>>;
export const verifySignInMessage = async (
client: Client,
{ nonce, domain, message, signature }: VerifySignInMessageArgs,
provider?: Provider,
publicClient: PublicClient<Transport, typeof optimism>,
): VerifySignInMessageResponse => {
const result = await verify(nonce, domain, message, signature, {
getFid: client.ethereum.getFid,
provider,
client: publicClient,
});
return unwrap(result);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createWalletClient } from "../../clients/createWalletClient";
import { viemConnector } from "../../clients/ethereum/viemConnector";
import { createSiweMessage } from "viem/siwe";

describe("buildSignInMessage", () => {
const client = createWalletClient({
Expand All @@ -13,6 +14,7 @@ describe("buildSignInMessage", () => {
uri: "https://example.com/login",
domain: "example.com",
nonce: "12345678",
issuedAt: new Date(),
fid: 1,
resources: ["https://example.com/resource"],
});
Expand All @@ -27,6 +29,6 @@ describe("buildSignInMessage", () => {
nonce: "12345678",
resources: ["farcaster://fid/1", "https://example.com/resource"],
});
expect(message).toBe(siweMessage.toMessage());
expect(message).toBe(createSiweMessage(siweMessage));
});
});
8 changes: 3 additions & 5 deletions packages/auth-client/src/clients/createAppClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import {
VerifySignInMessageResponse,
} from "../actions/app/verifySignInMessage";
import { Client, CreateClientArgs, createClient } from "./createClient";
import type { Provider } from "ethers";

export { Provider };

export interface AppClient extends Client {
createChannel: (args: CreateChannelArgs) => CreateChannelResponse;
Expand All @@ -18,13 +15,14 @@ export interface AppClient extends Client {
verifySignInMessage: (args: VerifySignInMessageArgs) => VerifySignInMessageResponse;
}

export const createAppClient = (config: CreateClientArgs, provider?: Provider): AppClient => {
export const createAppClient = (config: CreateClientArgs): AppClient => {
const client = createClient(config);
return {
...client,
createChannel: (args: CreateChannelArgs) => createChannel(client, args),
status: (args: StatusArgs) => status(client, args),
watchStatus: (args: WatchStatusArgs) => watchStatus(client, args),
verifySignInMessage: (args: VerifySignInMessageArgs) => verifySignInMessage(client, args, provider),
verifySignInMessage: (args: VerifySignInMessageArgs) =>
verifySignInMessage(client, args, client.ethereum.viemClient),
};
};
1 change: 0 additions & 1 deletion packages/auth-client/src/clients/createClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { EthereumConnector } from "./ethereum/connector";
import type { Provider } from "ethers";

export interface CreateClientArgs {
relay?: string;
Expand Down
6 changes: 4 additions & 2 deletions packages/auth-client/src/clients/ethereum/connector.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Hex } from "viem";
import type { Hex, PublicClient, Transport } from "viem";
import type { optimism } from "viem/chains";

export interface EthereumConnector {
getFid: (custody: Hex) => Promise<BigInt>;
getFid: (custody: Hex) => Promise<bigint>;
viemClient: PublicClient<Transport, typeof optimism>;
}
7 changes: 4 additions & 3 deletions packages/auth-client/src/clients/ethereum/viemConnector.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Hex, createPublicClient, http } from "viem";
import { type Hex, createPublicClient, http } from "viem";
import { optimism } from "viem/chains";
import { ID_REGISTRY_ADDRESS, idRegistryABI } from "../../contracts/idRegistry";
import { EthereumConnector } from "./connector";
import type { EthereumConnector } from "./connector";

interface ViemConfigArgs {
rpcUrl?: string;
Expand All @@ -13,7 +13,7 @@ export const viemConnector = (args?: ViemConfigArgs): EthereumConnector => {
transport: http(args?.rpcUrl),
});

const getFid = async (custody: Hex): Promise<BigInt> => {
const getFid = async (custody: Hex): Promise<bigint> => {
return publicClient.readContract({
address: ID_REGISTRY_ADDRESS,
abi: idRegistryABI,
Expand All @@ -24,5 +24,6 @@ export const viemConnector = (args?: ViemConfigArgs): EthereumConnector => {

return {
getFid,
viemClient: publicClient,
};
};
2 changes: 1 addition & 1 deletion packages/auth-client/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { generateNonce } from "siwe";
export { generateSiweNonce as generateNonce } from "viem/siwe";

export * from "./errors";
export * from "./actions";
Expand Down
7 changes: 4 additions & 3 deletions packages/auth-client/src/messages/build.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { build } from "./build";
import { createSiweMessage } from "viem/siwe";

const siweParams = {
domain: "example.com",
address: "0x63C378DDC446DFf1d831B9B96F7d338FE6bd4231",
uri: "https://example.com/login",
version: "1",
nonce: "12345678",
issuedAt: "2023-10-01T00:00:00.000Z",
};
issuedAt: new Date("2023-10-01T00:00:00"),
} as const;

describe("build", () => {
test("adds auth-specific parameters", () => {
Expand All @@ -23,7 +24,7 @@ describe("build", () => {
chainId: 10,
resources: ["farcaster://fid/5678"],
});
expect(message).toEqual(siweMessage.toMessage());
expect(message).toEqual(createSiweMessage(siweMessage));
});

test("handles additional resources", () => {
Expand Down
21 changes: 11 additions & 10 deletions packages/auth-client/src/messages/build.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
import { SiweMessage } from "siwe";
import { createSiweMessage, type SiweMessage } from "viem/siwe";
import { err, ok } from "neverthrow";
import { AuthClientResult } from "../errors";
import type { AuthClientResult } from "../errors";
import { validate } from "./validate";
import { STATEMENT, CHAIN_ID } from "./constants";

export type FarcasterResourceParams = {
fid: number;
};
export type SignInMessageParams = Partial<SiweMessage> & FarcasterResourceParams;
export type SignInMessageParams = Omit<SiweMessage, "chainId" | "version"> & FarcasterResourceParams;
export interface BuildResponse {
siweMessage: SiweMessage;
message: string;
}

export const build = (params: SignInMessageParams): AuthClientResult<BuildResponse> => {
const { fid, ...siweParams } = params;
const resources = siweParams.resources ?? [];
siweParams.version = "1";
siweParams.statement = STATEMENT;
siweParams.chainId = CHAIN_ID;
siweParams.resources = [buildFidResource(fid), ...resources];
const valid = validate(siweParams);
const valid = validate({
...siweParams,
version: "1",
statement: STATEMENT,
chainId: CHAIN_ID,
resources: [buildFidResource(fid), ...(siweParams.resources ?? [])],
});
if (valid.isErr()) return err(valid.error);
else {
const siweMessage = valid.value;
return ok({ siweMessage, message: siweMessage.toMessage() });
return ok({ siweMessage, message: createSiweMessage(siweMessage) });
}
};

Expand Down
6 changes: 3 additions & 3 deletions packages/auth-client/src/messages/validate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ const siweParams = {
uri: "https://example.com/login",
version: "1",
nonce: "12345678",
issuedAt: "2023-10-01T00:00:00.000Z",
};
issuedAt: new Date("2023-10-01T00:00:00"),
} as const;

const authParams = {
...siweParams,
Expand All @@ -26,7 +26,7 @@ describe("validate", () => {
test("propagates SIWE message errors", () => {
const result = validate({
...authParams,
address: "Invalid address",
address: "0xInvalid address",
});
expect(result.isErr()).toBe(true);
expect(result._unsafeUnwrapErr().errCode).toEqual("bad_request.validation_failure");
Expand Down
Loading
Loading