Skip to main content

Sign-in with Ronin

Overview​

This guide shows you how to integrate "Sign-In with Ronin" into your dApp. "Sign-In with Ronin" is a standard extended from Sign-In with Ethereum (SIWE) to help users sign in to your dApp easily, providing a better user experience and improved security.

From the end user's perspective, the sign-in process is as follows:

  1. Connect Ronin Wallet: The user connects their Ronin Wallet to your dApp.
  2. Accept terms of service: The user accepts your terms of service by signing a message with their Ronin Wallet.
  3. Solve the challenge: The user solves a security challenge to prove they are human.
1. Connect Ronin Wallet2. Accept terms of service

Prerequisites​

npm or yarn for package installation.

Steps​

Step 1. Install dependencies​

Firstly, you will need to get the @sky-mavis/tanto-connect package to connect to Ronin Wallet, you can follow the steps from Install Tanto Connect

The dependency needed for signing in is the siwe package. It helps you generate a formatted sign-in message more easily.

  1. Install the package using yarn or npm:
yarn add siwe@1.1.6 ethers@5.6.9
npm i siwe@1.1.6 ethers@5.6.9
  1. Import the package in your component:
import { SiweMessage } from "siwe";

Step 2. Generate a SIWE message​

Using the SiweMessage class, you can generate a formatted sign-in message. The message includes the following parameters:

  • domain: The domain of your dApp.
  • address: The user's Ronin address.
  • uri: The URI of your dApp.
  • version: The version of the SIWE message.
  • chainId: The chain ID of the network. For the Ronin mainnet, use 2020. For the Saigon testnet, use 202601.
  • nonce: A unique nonce for the message.
  • statement: The terms of service that the user agrees to.
  • expirationTime: The expiration time of the message.

The following code snippet shows how to generate a SIWE message:

Live Editor
function SIWERequest() {
  const [connector, setConnector] = useState(null);
  const [signature, setSignature] = useState();

  useEffect(() => {
    requestRoninWalletConnector().then((connector) => {
      setConnector(connector);
    });
  }, []);

  async function onClickSignIn() {
    if (!connector) {
      return;
    }

    const accounts = await connector.requestAccounts();

    if (!accounts) {
      return;
    }

    const currentAccount = accounts[0];

    const currentDate = new Date();
    currentDate.setDate(currentDate.getDate() + 1);

    const siweMessage = new SiweMessage({
      domain: window.location.hostname,
      address: currentAccount,
      uri: window.location.origin,
      version: "1",
      chainId: 2020,
      nonce: "12345678",
      statement:
        "I accept the dApp's Terms of Service: https://example-dapp.com/terms-of-use",
      expirationTime: currentDate.toISOString(),
    });

    const provider = await connector.getProvider();
    const sig = await provider.request({
      method: "personal_sign",
      params: [siweMessage.toMessage(), currentAccount],
    });
    setSignature(sig);
  }

  if (signature) {
    return (
      <div>
        <div>🎉 Congratulations! You are signed in.</div>
        <button onClick={() => setSignature(undefined)}>Reload</button>
      </div>
    );
  }

  return <button onClick={onClickSignIn}>Sign in with Ronin</button>;
}
Result
Loading...