Skip to content
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
55 changes: 40 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,56 @@
# Sign in with X

Sign in with X describes how blockchain accounts can authenticate with off-chain services using a standardized message format.
"Sign in with X" enables blockchain accounts to authenticate with off-chain services using a standardized message format, streamlining the verification of blockchain identities across various platforms.

## Supported Networks

SIWx currently supports three blockchain networks:
`SIWx` currently supports the following blockchain networks:

1. Ethereum (and by extension, all EIP-155 chains)
2. Solana
3. Stacks
4. Tezos
5. Starknet
- Ethereum (including all EIP-155 chains)
- Solana
- Stacks
- Tezos
- Starknet
- Fuel

It is on the roadmap to expand support for the following blockchain networks:
### Upcoming Network Support

1. Flow
We are planning to expand our support to the Flow network next.

If you have suggestions for any more, please create a specification for [CAIP-122 can be found here](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-122.md) over at [ChainAgnostic/namespaces](https://github.com/ChainAgnostic/namespaces) first and then create a pull request.
If you have suggestions for additional networks, please contribute a specification to [ChainAgnostic/namespaces](https://github.com/ChainAgnostic/namespaces) following the [CAIP-122 standard](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-122.md).

## Example
## Getting Started

See the `example` folder for a Next.js + NextAuth end to end example.
Follow these steps to set up `SIWx`:

## Specification
1. Clone the repository:
```bash
git clone <repository-url>
```
2. Set Up the Environment:
Navigate to the cloned directory, install dependencies, and build the project:
```bash
cd <repository-name>
pnpm install
pnpm build
3. Running Examples To see SIWx in action, proceed with the following commands in the examples directory:

The specification for Sign in with X [CAIP-122 can be found here](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-122.md).
```bash
cd examples
pnpm install
pnpm run dev

This setup initiates a development server where you can explore various implementation examples through your web browser.

## Example Implementation

Check out the example folder for a fully functional Next.js and NextAuth.js application demonstrating the end-to-end capabilities of SIWx.

Specifications
For a comprehensive understanding of the "Sign in with X" protocol, refer to the [CAIP-122](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-122.md) standard documentation.

## License

The library is licensed under the Apache 2.0 license.
This project is open-sourced under the Apache 2.0 License, allowing for widespread use and modification to meet a variety of needs.

This README is organized to provide a concise yet comprehensive overview of the project, installation instructions, and additional resources for users and contributors.
5 changes: 5 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@
},
"dependencies": {
"@airgap/beacon-types": "^4.0.4",
"@fuels/connectors": "^0.2.2",
"@fuels/react": "^0.18.1",
"@learnweb3dao/siwe": "workspace:^",
"@learnweb3dao/siws": "workspace:^",
"@learnweb3dao/siwstacks": "workspace:^",
"@learnweb3dao/siwstarknet": "workspace:^",
"@learnweb3dao/siwtezos": "workspace:^",
"@learnweb3dao/siwfuel": "workspace:^",
"@solana/web3.js": "^1.75.0",
"@stacks/connect": "^7.3.1",
"@stacks/network": "^6.5.2",
"@tanstack/react-query": "^5.34.1",
"@taquito/beacon-wallet": "^17.0.0",
"@taquito/taquito": "^17.0.0",
"@types/node": "^18.16.3",
Expand All @@ -28,6 +32,7 @@
"eslint": "8.39.0",
"eslint-config-next": "13.3.4",
"ethers": "^5",
"fuels": "0.82.0",
"next": "13.3.4",
"next-auth": "^4.12.1",
"postcss": "8.4.23",
Expand Down
75 changes: 75 additions & 0 deletions example/src/components/siwFuel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"use client";

import { FuelMessage } from "@learnweb3dao/siwfuel";
import { getCsrfToken, signIn } from "next-auth/react";
import React from "react";
import { useConnectUI } from "@fuels/react";
import { useIsConnected } from "@fuels/react";
import { Fuel } from "fuels";
import { defaultConnectors } from "@fuels/connectors";
import { useChain, useAccount } from "@fuels/react";

export const SIWFUEL: React.FC = () => {
const { connect } = useConnectUI();
const { isConnected } = useIsConnected();
const { chain } = useChain();
const { account } = useAccount();

const handleLogin = async () => {
try {
const fuel = new Fuel({
connectors: defaultConnectors({ devMode: true }),
});

const currentAccount = await fuel.currentAccount();

if (!currentAccount) {
connect();
return;
}

const message = new FuelMessage({
domain: window.location.host,
address: currentAccount,
statement: "Sign in with Ethereum to this application.",
uri: window.location.origin,
version: "1",
chainId: chain?.consensusParameters.chainId.toString(),
nonce: await getCsrfToken(),
issuedAt: new Date().toISOString(),
});

if (!account) {
return;
}

const wallet = await fuel.getWallet(account);
const signedMessage = await wallet.signMessage(message.toMessage());

await signIn("fuel", {
message: JSON.stringify(message),
signature: signedMessage,
redirect: false,
});
} catch (error) {
window.alert(error);
}
};

return (
<button
onClick={(e) => {
e.preventDefault();
if (!isConnected) {
connect();
handleLogin();
} else {
handleLogin();
}
}}
className="bg-blue-500 hover:bg-blue-700 transition-colors text-white font-bold py-2 px-4 rounded"
>
Sign in with Fuel
</button>
);
};
2 changes: 1 addition & 1 deletion example/src/components/siwTezos.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
import { SiwTezosMessage } from "@learnweb3dao/siwTezos";
import { SiwTezosMessage } from "@learnweb3dao/siwtezos";
import { TezosToolkit } from "@taquito/taquito";
import { BeaconWallet } from "@taquito/beacon-wallet";
import { getCsrfToken, signIn } from "next-auth/react";
Expand Down
18 changes: 15 additions & 3 deletions example/src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import "@/styles/globals.css";
import type { AppProps } from "next/app";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

import { wagmiClient } from "@/config/config";
import { WagmiConfig } from "wagmi";
import { SessionProvider } from "next-auth/react";
import { FuelProvider } from "@fuels/react";
import { defaultConnectors } from "@fuels/connectors";

const queryClient = new QueryClient();

export default function App({ Component, pageProps }: AppProps) {
return (
<SessionProvider>
<WagmiConfig client={wagmiClient}>
<Component {...pageProps} />
</WagmiConfig>
<QueryClientProvider client={queryClient}>
<FuelProvider
fuelConfig={{ connectors: defaultConnectors({ devMode: true }) }}
>
<WagmiConfig client={wagmiClient}>
<Component {...pageProps} />
</WagmiConfig>
</FuelProvider>
</QueryClientProvider>
</SessionProvider>
);
}
44 changes: 43 additions & 1 deletion example/src/pages/api/auth/[...nextauth].ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SiwTezosMessage } from "@learnweb3dao/siwTezos";
import { SiwTezosMessage } from "@learnweb3dao/siwtezos";
import { SiweMessage } from "@learnweb3dao/siwe";
import { SiwsMessage } from "@learnweb3dao/siws";
import { SiwStacksMessage } from "@learnweb3dao/siwstacks";
Expand All @@ -9,6 +9,7 @@ import { JWT } from "next-auth/jwt";
import NextAuth from "next-auth/next";
import CredentialsProvider from "next-auth/providers/credentials";
import { getCsrfToken } from "next-auth/react";
import { FuelMessage } from "@learnweb3dao/siwfuel";

export default async function auth(req: NextApiRequest, res: NextApiResponse) {
return NextAuth(req, res, getAuthOptions(req));
Expand Down Expand Up @@ -230,6 +231,47 @@ export const getAuthOptions = (req: NextApiRequest) => {
}
},
}),
CredentialsProvider({
id: "fuel",
name: "Fuel",
credentials: {
message: {
label: "Message",
type: "text",
placeholder: "0x0",
},
signature: {
label: "Signature",
type: "text",
placeholder: "0x0",
},
},

async authorize(credentials) {
try {
const fuel = new FuelMessage(
JSON.parse(credentials?.message || "{}")
);
const nextAuthUrl = new URL(process.env.NEXTAUTH_URL as string);
const result = await fuel.verify({
signature: credentials?.signature || "",
domain: nextAuthUrl.host,
nonce: await getCsrfToken({ req }),
});

console.log({ result });

if (!result.success) return null;

return {
id: fuel.address,
};
} catch (error) {
console.error(error);
return null;
}
},
}),
];

const isDefaultSigninPage =
Expand Down
2 changes: 2 additions & 0 deletions example/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { SIWTezos } from "@/components/siwTezos";
import { SIWE } from "@/components/siwe";
import { SIWS } from "@/components/siws";
import { SIWStacks } from "@/components/siwstacks";
import { SIWFUEL } from "@/components/siwFuel";
import { signOut, useSession } from "next-auth/react";

export default function Home() {
Expand Down Expand Up @@ -41,6 +42,7 @@ export default function Home() {
<SIWStacks />
<SIWTezos />
<SIWStarknet />
<SIWFUEL />
</main>
);
}
1 change: 1 addition & 0 deletions packages/fuel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# SIWx - Ethereum
Loading