@canvas-js/signer-ethereum
The Ethers (v6) Ethereum signer takes an ethers
signer, or generates a random ethers.Wallet
, and uses it to sign a SIWE message authenticating a new session.
It also handles verification of messages matching this standard, and can be used in conjuction with @canvas-js/signer-ethereum-viem
.
Table of Contents
Installation
npm i @canvas-js/signer-ethereum
SIWESigner
The SIWESigner
class implements Sign-in With Ethereum (SIWE) functionality for Canvas. It allows users to authenticate using an Ethereum wallet by signing a standard SIWE message.
By default, SIWESigner is initialized in read-only mode. You should configure the signer with { burner: true }
to create a signer with a randomized burner address, or { signer: ethers.Signer }
to create a signer that uses a wallet.
SIWESigner works well with ethers.Signer instances provided by a browser wallet, since the signer is used to authorize a session key that signs individual actions.
Initialization
import { SIWESigner } from "@canvas-js/signer-ethereum";
// With an existing ethers signer
const signer = new SIWESigner({
signer: yourEthersSigner, // An ethers.js Signer instance
chainId: 1, // Optional, defaults to 1 (Ethereum mainnet)
});
// With a random burner wallet
const burnerSigner = new SIWESigner({
burner: true, // Creates a random ethers.Wallet for signing
chainId: 5, // Optional, specify a testnet chain ID
});
// Read-only mode (can only verify, not create sessions)
const readOnlySigner = new SIWESigner();
Usage Examples
Creating a Session
// Get a session for a specific topic
const session = await signer.getSession("my-app-topic");
// Later verify a session
signer.verifySession("my-app-topic", session);
Working with DIDs
// Get the DID for the current signer
const did = await signer.getDid();
// "did:pkh:eip155:1:0x123..."
// Extract the address from a DID
const address = signer.getAddressFromDid(did);
// "0x123..."
SIWFSigner
The SIWFSigner
class implements Sign-in With Farcaster (SIWF) functionality for Canvas. It allows Farcaster users to authenticate using their Farcaster account's custody address.
Initialization
import { SIWFSigner } from "@canvas-js/signer-ethereum";
// Basic initialization
const farcasterSigner = new SIWFSigner({
custodyAddress: "0x123...", // Optional, but required for creating messages
});
When you configure a SIWFSigner for your application, you will usually configure it without a custodyAddress initially. This will allow it to accept Farcaster signed messages from other users.
To allow the signer to write to the application, you should then replace it with a signer with the appropriate authorization data.
Authorizing
First, request a SIWF message using Farcaster AuthKit.
Then, use the static method SIWFSigner.parseSIWFMessage to obtain an authorization data:
You can now ask the Farcaster signer to manually create a new SIWF session for you:
const { authorizationData, topic, custodyAddress } = SIWFSigner.parseSIWFMessage(message, signature)
const signer = new SIWFSigner({ custodyAddress, privateKey: newSessionPrivateKey.slice(2) })
const address = await signer.getDid()
const timestamp = new Date(authorizationData.siweIssuedAt).valueOf()
const { payload, signer: delegateSigner } = await signer.newSIWFSession(
topic,
authorizationData,
timestamp,
getBytes(newSessionPrivateKey),
)
Now that you have a valid signer, you should remove the default read-only signer that you have attached to your application, and replace it with your newly created signer.
const otherSigners = app.signers.getAll().filter((signer) => signer.key !== "signer-ethereum-farcaster")
app.updateSigners([signer, ...otherSigners])
Finally, append the session you created to your app's message log.
app.messageLog.append(payload, { signer: delegateSigner })
Authorizing with a Frame
// Generate a nonce for frame-based authentication
const { nonce, privateKey } = SIWFSigner.newSIWFRequestNonce("my-app-topic");
// Later, with the SIWF message and signature from Farcaster frame auth
const { authorizationData, custodyAddress, topic } = SIWFSigner.parseSIWFMessage(
siwfMessage,
siwfSignature
);
// Create a new session using the auth data
const { payload: session, signer } = await farcasterSigner.newSIWFSession(
topic,
authorizationData,
Date.now(),
privateKey
);