Invisible Web3
Creating a seamless user onboarding experience is essential for the success of any dApp* A well-designed onboarding process can increase user retention and foster a positive first impression, which is crucial for encouraging users to come back for more* In this recipe, we will demonstrate how to set up an efficient onboarding system using the @skaleboarder/safe-tools npm package.
Tooling
To build our onboarding system, we will use https://hardhat.org/%5Bhardhat%5D and https://github.com/wighawag/hardhat-deploy%5Bhardhat-deploy%5D along with https://www.rainbowkit.com/%5Brainbowkit%5D and https://nextjs.org/%5Bnextjs%5D* These tools provide a solid foundation for creating a user-friendly and efficient onboarding process.
Getting Started
-
Initialize a new Hardhat project by running
hardhat init
in the terminal* This will create a new directory with the basic structure of a Hardhat project. -
Install the @skaleboarder/safe-tools package:
npm install --save @skaleboarder/safe-tools
. -
In the
hardhat.config.ts
file, import the necessary modules and configurations as shown
If you are deploying to production
MAKE SURE you are either on a chain that has already deployed the
create2 deployer or that you have allowed
0x1aB62e2DDa7a02923A06904413A007f8e257e0D0 to deploy contracts.see:
https://docs.skale.network/develop/skale-chain-access-control
|
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "hardhat-deploy";
import { BigNumber } from 'ethers'
const config: HardhatUserConfig = {
defaultNetwork: "hardhat",
solidity: "0.8.17",
external: {
contracts: [{
artifacts: ["node_modules/@skaleboarder/safe-tools/artifacts", "node_modules/@skaleboarder/safe-tools/gnosis-safe-artifacts"],
deploy: "node_modules/@skaleboarder/safe-tools/hardhat/deploy",
}],
},
deterministicDeployment: (_network: string) => {
return {
deployer: "0x1aB62e2DDa7a02923A06904413A007f8e257e0D0",
factory: "0xf461635EbfA16074b07322781fCcaAA43F852a17",
signedTx: "0xf901188085174876e800830192ba8080b8c66080604052348015600f57600080fd5b5060a88061001e6000396000f3fe6080604052348015600f57600080fd5b5060003660606000807f94bfd9af14ef450884c8a7ddb5734e2e1e14e70a1c84f0801cc5a29e34d26428905060203603602060003760003560203603600034f5915081605a57600080fd5b8160005260003560205260008160406000a26014600cf3fea2646970667358221220575a90b3fd3629fb06acbbed667e4e921c5fd5d07bd5ef77421d3165bcfa875164736f6c634300081200331ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222",
funding: BigNumber.from(278361).mul(100000000000).toString(),
}
},
namedAccounts: {
deployer: {
default: 0,
},
}
};
export default config;
-
Create a new Next.js app using
npx create-next-app
and navigate to the newly created directory. -
Install the required dependencies, including ethers, and RainbowKit.
-
Update the
_app.tsx
file with the provided example, which demonstrates how to integrate RainbowKit and the Safe Tools package into the Next.js app.
import type { AppProps } from 'next/app'
import { ChakraProvider } from '@chakra-ui/react'
import ethers, { BigNumber, providers } from "ethers"
import '@rainbow-me/rainbowkit/styles.css';
import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
import {
coinbaseWallet,
injectedWallet,
metaMaskWallet,
walletConnectWallet,
} from '@rainbow-me/rainbowkit/wallets';
import {
connectorsForWallets,
RainbowKitProvider,
} from '@rainbow-me/rainbowkit';
import { configureChains, createClient, WagmiConfig } from 'wagmi';
import { mainnet, polygon, optimism, arbitrum } from 'wagmi/chains';
import { createChain, RainbowKitWalletWrapper, WagmiWrapperConfig } from '@skaleboarder/rainbowkit';
import addresses from "../addresses.json"
const skaleMainnet = createChain({
id: BigNumber.from('0x3d91725c').toNumber(),
name: 'Crypto Rome',
rpcUrls: {
default: {
http: ["https://mainnet.skalenodes.com/v1/haunting-devoted-deneb"],
webSocket: ["wss://mainnet.skalenodes.com/v1/ws/haunting-devoted-deneb"],
},
public: {
http: ["https://mainnet.skalenodes.com/v1/haunting-devoted-deneb"],
webSocket: ["wss://mainnet.skalenodes.com/v1/ws/haunting-devoted-deneb"],
}
},
explorer: "https://haunting-devoted-deneb.explorer.mainnet.skalenodes.com/"
})
const localDev = createChain({
id: 31337,
name: 'Local Rome',
rpcUrls: {
default: {
http: ['http://localhost:8545'],
},
public: {
http: ['http://localhost:8545'],
}
},
explorer: "http://no.explorer"
})
// you can setup a
const skaleProvider = new providers.StaticJsonRpcProvider(localDev.rpcUrls.default.http[0])
const wrapperConfigs:WagmiWrapperConfig = {
ethers,
provider: skaleProvider,
chainId: localDev.id.toString(),
deploys: addresses.contracts,
faucet: async (address, _signer) => {
const resp = await fetch(`/api/localFaucet`, { body: JSON.stringify({ address }), method: "POST" })
const json = await resp.json()
console.log("resp: ", json)
},
}
const wrapper = new RainbowKitWalletWrapper(wrapperConfigs)
const { chains, provider } = configureChains(
[mainnet, polygon, optimism, arbitrum, skaleMainnet],
[
jsonRpcProvider({
rpc: (_chain) => ({
http: skaleProvider.connection.url,
}),
}),
]
);
const connectors = () => {
const connects = connectorsForWallets([
{
groupName: 'Recommended',
wallets: [
injectedWallet({ chains, shimDisconnect: true }),
metaMaskWallet({ chains, shimDisconnect: true }),
coinbaseWallet({ appName: "Empire Gambit", chains }),
walletConnectWallet({ chains }),
].map((wallet) => wrapper.wrapWallet(wallet)),
},
])
return connects()
}
const wagmiClient = createClient({
autoConnect: false,
connectors: connectors,
provider
})
export default function App({ Component, pageProps }: AppProps) {
return (
<ChakraProvider>
<WagmiConfig client={wagmiClient}>
<RainbowKitProvider chains={chains}>
<Component {...pageProps} />
</RainbowKitProvider>
</WagmiConfig>
</ChakraProvider>
)
}
Next you can add any UI you want to your app and a standard rainbowkit
<ConnectButton />
Run your contracts locally using npx hardhat node
Start the Next.js development server by running npm run dev
.
You now have a fully functional onboarding system for your dApp* The @skaleboarder/safe-tools package makes it easy to implement a non-custodial sign-in system that allows in-browser transaction relay without requiring users to switch their wallets* By combining this with the user-friendly interface provided by RainbowKit, you can create an engaging and seamless onboarding experience for your users.
Remember to continuously iterate and refine your onboarding process to cater to the needs of your users* A well-designed onboarding experience can significantly impact the success of your dApp and encourage users to explore and engage with your platform* Happy coding!
More examples
Need more info? Checkout the Demo contracts Demo site readme
Tooling Overview
The skaleboarding tooling is a system to allow easy sign up, and signature-free transactions on the SKALE network* Its repo can be found here: https://github.com/quorumcontrol/skale-boarder .
Overall what it does is:
-
Create a Gnosis SAFE for users owned by a main account
-
Create an in-device wallet (for instance, a localsStorage saved wallet)
-
Allow that account to send transactions through the Gnosis Safe
-
Provide tooling to easily integrate this system into your dApp
Key components
The skaleboarding tooling consists of several key components:
-
@skaleboarder/safe-tools: A package that simplifies the creation and management of Gnosis Safes on the SKALE network* It provides functions for creating Safes, managing owners, and submitting transactions through the Safe.
-
@skaleboarder/rainbowkit: A package that extends the functionality of RainbowKit to work with the SKALE network and the Gnosis Safes* It includes a wallet wrapper for integrating with various wallet providers and a custom chain configuration to ease using the SKALE network.
-
@skaleboarder/wagmi: A package that integrates skaleboarder with the WAGMI framework* It wraps wagmi so that the signer provided is a skaleboarder gnosis safe relayer, but the address still appears to be the main, owner, wallet.
-
Demo contracts: A set of example contracts that demonstrate how to use the skaleboarding system.
-
Demo dApp: An example using the demo contracts and skaleboarder along with nextjs and rainbowkit to create a seamless signin experience.