Simplify user onboarding with “preferred placement”
Overview
For the best onboarding experience, we recommend adding a highly visible ‘Create’ or ‘Create Wallet’ button to your dapp’s homepage (referred to as “preferred placement” - see example images below).
For new users, navigating through “Connect” in order to get started is unintuitive, and requires them to understand that they do not need a Coinbase Wallet yet to create one.
This difficulty can be prevented by streamlining the onboarding experience and adding 'preferred placement' aka 'create wallet' button to a page. This simplifies the choices for a new user and gets them ready to use your dapp in a few seconds. Plus, we're offering additional incentives to dapps who implement this new approach.
We recommend two paths for implementation:
- Match our branded Create Wallet button
- Match your own apps look and feel in the Create button
Example:

Implementation
With wagmi
To implement the Create Wallet button with wagmi, all you need to do to trigger the create is call connect
.
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useConnect } from "wagmi";
import { CoinbaseWalletLogo } from "./CoinbaseWalletLogo";
const GRADIENT_BORDER_WIDTH = 2;
const buttonStyles = {
background: "transparent",
border: "1px solid transparent",
boxSizing: "border-box",
};
const contentWrapperStyle = {
position: "relative",
};
function Gradient({ children, style, isAnimationDisabled = false }) {
const [isAnimating, setIsAnimating] = useState(false);
const gradientStyle = useMemo(() => {
const rotate = isAnimating ? "720deg" : "0deg";
return {
transform: `rotate(${rotate})`,
transition: isAnimating
? "transform 2s cubic-bezier(0.27, 0, 0.24, 0.99)"
: "none",
...style,
};
}, [isAnimating, style]);
const handleMouseEnter = useCallback(() => {
if (isAnimationDisabled || isAnimating) return;
setIsAnimating(true);
}, [isAnimationDisabled, isAnimating, setIsAnimating]);
useEffect(() => {
if (!isAnimating) return;
const animationTimeout = setTimeout(() => {
setIsAnimating(false);
}, 2000);
return () => {
clearTimeout(animationTimeout);
};
}, [isAnimating]);
return (
<div style={contentWrapperStyle} onMouseEnter={handleMouseEnter}>
<div className="gradient-background" style={gradientStyle} />
{children}
</div>
);
}
export function BlackCreateWalletButton({ height = 66, width = 200 }) {
const { connectors, connect } = useConnect();
const minButtonHeight = 48;
const minButtonWidth = 200;
const buttonHeight = Math.max(minButtonHeight, height);
const buttonWidth = Math.max(minButtonWidth, width);
const gradientDiameter = Math.max(buttonHeight, buttonWidth);
const styles = useMemo(
() => ({
gradientContainer: {
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: "black",
borderRadius: buttonHeight / 2,
height: buttonHeight,
width: buttonWidth,
boxSizing: "border-box",
overflow: "hidden",
},
gradient: {
background:
"conic-gradient(from 180deg, #45E1E5 0deg, #0052FF 86.4deg, #B82EA4 165.6deg, #FF9533 255.6deg, #7FD057 320.4deg, #45E1E5 360deg)",
position: "absolute",
top: -buttonHeight - GRADIENT_BORDER_WIDTH,
left: -GRADIENT_BORDER_WIDTH,
width: gradientDiameter,
height: gradientDiameter,
},
buttonBody: {
display: "flex",
justifyContent: "center",
alignItems: "center",
boxSizing: "border-box",
backgroundColor: "#000000",
height: buttonHeight - GRADIENT_BORDER_WIDTH * 2,
width: buttonWidth - GRADIENT_BORDER_WIDTH * 2,
fontFamily: "Arial, sans-serif",
fontWeight: "bold",
fontSize: 18,
borderRadius: buttonHeight / 2,
position: "relative",
paddingRight: 10,
},
}),
[buttonHeight, buttonWidth, gradientDiameter]
);
const createWallet = useCallback(() => {
const coinbaseWalletConnector = connectors.find(
(connector) => connector.id === "coinbaseWalletSDK"
);
if (coinbaseWalletConnector) {
connect({ connector: coinbaseWalletConnector });
}
}, [connectors, connect]);
return (
<button style={buttonStyles} onClick={createWallet}>
<div style={styles.gradientContainer}>
<Gradient style={styles.gradient}>
<div style={styles.buttonBody}>
<CoinbaseWalletLogo containerStyles={{ paddingRight: 10 }} />
Create Wallet
</div>
</Gradient>
</div>
</button>
);
}
Notes
- For more detail, view the
useConnect
documentation. - Upon successful connection, account information can be accessed via data
returned from
useConnect
, or viauseAccount
.
With CoinbaseWalletSDK only
To implement the Create Wallet button using only the SDK, all you need to do is send an eth_requestAccounts
request.
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { CoinbaseWalletSDK } from "@coinbase/wallet-sdk";
import { CoinbaseWalletLogo } from "./CoinbaseWalletLogo";
const GRADIENT_BORDER_WIDTH = 2;
const buttonStyles = {
background: "transparent",
border: "1px solid transparent",
boxSizing: "border-box",
};
const contentWrapperStyle = {
position: "relative",
};
function Gradient({ children, style, isAnimationDisabled = false }) {
const [isAnimating, setIsAnimating] = useState(false);
const gradientStyle = useMemo(() => {
const rotate = isAnimating ? "720deg" : "0deg";
return {
transform: `rotate(${rotate})`,
transition: isAnimating
? "transform 2s cubic-bezier(0.27, 0, 0.24, 0.99)"
: "none",
...style,
};
}, [isAnimating, style]);
const handleMouseEnter = useCallback(() => {
if (isAnimationDisabled || isAnimating) return;
setIsAnimating(true);
}, [isAnimationDisabled, isAnimating, setIsAnimating]);
useEffect(() => {
if (!isAnimating) return;
const animationTimeout = setTimeout(() => {
setIsAnimating(false);
}, 2000);
return () => {
clearTimeout(animationTimeout);
};
}, [isAnimating]);
return (
<div style={contentWrapperStyle} onMouseEnter={handleMouseEnter}>
<div className="gradient-background" style={gradientStyle} />
{children}
</div>
);
}
const sdk = new CoinbaseWalletSDK({
appName: "My Dapp With Vanilla SDK",
appLogoUrl: "https://example.com/logo.png",
appChainIds: [84532],
});
const provider = sdk.makeWeb3Provider();
export function BlackCreateWalletButton({ height = 66, width = 200 }) {
const minButtonHeight = 48;
const minButtonWidth = 200;
const buttonHeight = Math.max(minButtonHeight, height);
const buttonWidth = Math.max(minButtonWidth, width);
const gradientDiameter = Math.max(buttonHeight, buttonWidth);
const styles = useMemo(
() => ({
gradientContainer: {
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: "black",
borderRadius: buttonHeight / 2,
height: buttonHeight,
width: buttonWidth,
boxSizing: "border-box",
overflow: "hidden",
},
gradient: {
background:
"conic-gradient(from 180deg, #45E1E5 0deg, #0052FF 86.4deg, #B82EA4 165.6deg, #FF9533 255.6deg, #7FD057 320.4deg, #45E1E5 360deg)",
position: "absolute",
top: -buttonHeight - GRADIENT_BORDER_WIDTH,
left: -GRADIENT_BORDER_WIDTH,
width: gradientDiameter,
height: gradientDiameter,
},
buttonBody: {
display: "flex",
justifyContent: "center",
alignItems: "center",
boxSizing: "border-box",
backgroundColor: "#000000",
height: buttonHeight - GRADIENT_BORDER_WIDTH * 2,
width: buttonWidth - GRADIENT_BORDER_WIDTH * 2,
fontFamily: "Arial, sans-serif",
fontWeight: "bold",
fontSize: 18,
borderRadius: buttonHeight / 2,
position: "relative",
paddingRight: 10,
},
}),
[buttonHeight, buttonWidth, gradientDiameter]
);
const createWallet = useCallback(async () => {
try {
const [address] = await provider.request({
method: "eth_requestAccounts",
});
handleSuccess(address);
} catch (error) {
handleError(error);
}
}, [handleSuccess, handleError]);
return (
<button style={buttonStyles} onClick={createWallet}>
<div style={styles.gradientContainer}>
<Gradient style={styles.gradient}>
<div style={styles.buttonBody}>
<CoinbaseWalletLogo containerStyles={{ paddingRight: 10 }} />
Create Wallet
</div>
</Gradient>
</div>
</button>
);
}
Benefits for you:
By integrating a create wallet button on the front page of your app, you are eligible for:
- Increased volume of gas credits via our Cloud paymaster
- Comarketing and promotional opportunities with Coinbase
- Featured placement in our dapp listings on homebase.coinbase.com
For more information, please fill out the form on coinbase.com/smart-wallet so our team can get in touch with you.