SDK
Guides
Safe Auth

Integration with SafeAuth

This guide demonstrates creating an externally-owned account using your email or social media account. Once authenticated, you can sign transactions and interact with your Safe accounts.

The SafeAuthPack is an authentication system that utilizes the Web3Auth (opens in a new tab) MPC technology. It was developed in collaboration with Web3Auth to create a smooth onboarding experience for web2 users across different dapps.

Prerequisites

Steps

Install dependencies


_10
yarn add @safe-global/auth-kit @web3auth/safeauth-embed

Imports

Here are all the necessary imports for this guide.


_10
import { ethers } from 'ethers'
_10
import {
_10
SafeAuthPack,
_10
SafeAuthConfig,
_10
SafeAuthInitOptions,
_10
} from '@safe-global/auth-kit'

Create a SafeAuthPack instance

We will use the SafeAuthPack exported from the @safe-global/auth-kit package.

Create an instance of the SafeAuthPack (opens in a new tab) using the required SafeAuthConfig configuration object.

Supported networks:

  • Production: Ethereum, Polygon, BSC, Avalanche, Optimism, Celo, Arbitrum, Gnosis chain
  • Test: Sepolia, Polygon Mumbai, BSC Testnet, Avalanche Testnet, Arbitrum Testnet, Optimism Testnet

_18
const safeAuthConfig: SafeAuthConfig = {
_18
txServiceUrl: 'https://safe-transaction-mainnet.safe.global',
_18
}
_18
const safeAuthInitOptions: SafeAuthInitOptions = {
_18
enableLogging: true,
_18
showWidgetButton: false,
_18
chainConfig: {
_18
chainId: '0x1',
_18
rpcTarget: RPC_URL
_18
}
_18
}
_18
_18
// You can also pass the SafeAuthConfig as a parameter to the SafeAuthPack constructor if you are using a custom txServiceUrl domain
_18
// e.g. const safeAuthConfig: SafeAuthConfig = {
_18
// txServiceUrl: 'https://safe-transaction-mainnet.safe.global'
_18
// }
_18
const safeAuthPack = new SafeAuthPack(safeAuthConfig)
_18
await safeAuthPack.init(safeAuthInitOptions)

Sign in to an Ethereum account

After creating your SafeAuthPack instance, initiate the authentication process by calling the signIn() method. Typically, this method is called when the user clicks a "Sign In" button on the web page.

After successfully signing in, you will create a new Ethereum Wallet. This wallet will be used for all future logins and can be shared across different applications.


_10
// The signIn() method returns the user's Ethereum address and the associated Safe addresses
_10
// The `await` will last until the user is authenticated. Therefore, it will be active while the authentication popup is being displayed.
_10
const authKitSignData = await safeAuthPack.signIn()

The returned authKitSignData data contains the following properties:


_10
AuthKitSignInData {
_10
eoa: string // The safe signer
_10
safes?: string[] // The list of associated Safe addresses in the chain
_10
}

The signOut() method removes the current session.


_10
await safeAuthPack.signOut()

After the user is authenticated, call getProvider() to get an Ethereum EIP-1193 (opens in a new tab) compatible provider.


_10
safeAuthPack.getProvider()

We offer two methods for listening to events, subscribe() and unsubscribe().


_10
const accountChangedHandler = (accounts: string[]) => {
_10
console.log('Signer accounts:', accounts)
_10
}
_10
_10
safeAuthPack.subscribe('accountsChanged', accountChangedHandler)
_10
safeAuthPack.unsubscribe('accountsChanged', accountChangedHandler)

The SafeAuthPack instantiation will return the list of associated Safe addresses as part of the response from the signIn() method when the txServiceUrl is provided.


_10
const safeAuthPack = new SafeAuthPack()

Sign and execute transactions

The SafeAuthPack can be used with the Protocol Kit to establish a connection to a Safe using the provider. We don't need to pass the signer property in the create() method as it will be automatically taken from the passed provider.

After connecting, you can use any of the methods provided in the Protocol Kit.


_23
// Instantiate the Protocol Kit
_23
const protocolKit = await Safe.init({
_23
provider: safeAuthPack.getProvider(),
_23
safeAddress,
_23
})
_23
_23
// Create a Safe transaction with the provided parameters
_23
const safeTransactionData: MetaTransactionData = {
_23
to: `${ethAddress}`,
_23
data: '0x',
_23
value: ethers.parseUnits('0.0001', 'ether').toString(),
_23
}
_23
_23
const safeTransaction = await protocolKit.createTransaction({
_23
transactions: [safeTransactionData],
_23
})
_23
_23
// Sign the transaction if the Safe have several owners
_23
// safeTransaction = await protocolKit1.signTransaction(safeTransaction)
_23
// safeTransaction = await protocolKit2.signTransaction(safeTransaction)
_23
_23
// Execute the transaction
_23
await protocolKit.executeTransaction(safeTransaction)

Sign messages

You can also sign any arbitrary message or transaction as a regular Signing Account with your favorite web3 library:


_16
// Using web3
_16
const web3 = new Web3(safeAuthPack.getProvider())
_16
_16
await web3.eth.sendTransaction(tx)
_16
await web3.eth.signTransaction(tx)
_16
const message = 'hello world'
_16
const address = '0x...'
_16
await web3.eth.personal.sign(message, address)
_16
_16
// Using ethers
_16
const provider = new ethers.BrowserProvider(safeAuthPack.getProvider())
_16
const signer = provider.getSigner()
_16
_16
await signer.sendTransaction(tx)
_16
await signer.signTransaction(tx)
_16
await signer.signMessage(message)

Examples

Was this page helpful?