Migrate from Dynamic to Web3Auth
In this guide, we'll compare Dynamic and Web3Auth and explain how to migrate your existing users from Dynamic to Web3Auth.
We'll start by comparing both services based on several key parameters: wallet management architecture, authentication options, and multi-chain and multi-platform support. If you're ready to jump straight to the migration process, you can find the instructions here.
Why choose Web3Auth?
Both Web3Auth and Dynamic have made significant strides in addressing the Web3 onboarding challenge. However, Web3Auth stands out by offering more customizable authentication options, along with superior support for multi-chain and multi-platform integrations.
Parameter | Dynamic | Web3Auth |
---|---|---|
Wallet Management | Dynamic use Turnkey's non-custodial infrastructure which is based on secure enclave storage. Hence, it has single point of failure. | Web3Auth supports SSS and MPC TSS based key management, distributed across a network of nodes, with no single point of failure. |
Multi-chain support | Currently, Dynamic supports a range of networks including EVM-compatible networks, Solana, Bitcoin, Flow, StarkNet, Cosmos, and Algorand. Despite both Solana and Algorand utilizing the same ed25519 curve, Dynamic currently does not support other chains that use the same curve, such as Aptos. | Web3Auth is chain agnostic. Moreover, Web3Auth MPC TSS also supports both curves to integrate all supported chains using secp256k1 and ed25519 curves. |
Multi-platform support | Dynamic only supports Web, and React Native. | Web3Auth supports multiple platforms, including Web, React Native, Unity, Unreal, Flutter, Swift, and Android. Checkout documentation for more details. |
Additional Features | Dynamic provides additional features as Dynamic bridge, and on ramp service apart from embedded wallet. | Web3Auth also offers additional services such as NFT checkout, Fiat On Ramp, and Prebuilt Wallet UI. All of these services could be added in your project with few lines code. |
Ease of Integration | Dynamic is easy to integrate where basic integration takes less than 15 minutes | Web3Auth is also easy to integrate where basic integration takes less than 15 minutes. |
Whitelabel | Dynamic has end to end white-labelling options. | Web3Auth also has end to end white-labelling options. Web3Auth also has advanced integration options where it can be totally hidden which is not possible with Dynamic. |
How to migrate to Web3Auth
Now that we've discussed the advantages of Web3Auth, let's explore the steps to migrate from Dynamic to Web3Auth. We'll cover most scenarios, but if we miss any, please don't hesitate to reach out to us in comments.
Embedded Wallet
If you are using Dynmaic embedded wallet, there are couple of options which can be preferred for the migration.
Using Plug And Play SDK
If you want to use the Plug and Play SDK, you can first check whether the user is an existing user or if they have any wallet balance. For new users or those with empty wallets, you can simply generate a new wallet for them to replace the old one.
For existing users with non-empty wallets, you have two options:
Migration tool
You can create a migration tool to transfer funds to the newly generated Web3Auth embedded wallet. To facilitate the fund transfer using the migration tool, you can utilize our Wallet Pregeneration feature to determine the user's wallet address without integrating our SDKs. By leveraging wallet pregeneration, you can handle the migration in the backend seamlessly. Afterward, you can use the PnP/ SFA SDK to log users in through Web3Auth.
Let's see how you can use the Wallet Pregeneration API.
const apiUrl = "https://lookup.web3auth.io/lookup";
const params = new URLSearchParams({
verifier: "YOUR_VERIFIER_NAME",
verifierId: "YOUR_VERIFIER_ID",
web3AuthNetwork: "sapphire_mainnet",
clientId: "YOUR_WEB3AUTH_CLIENT_ID",
});
const url = `${apiUrl}?${params.toString()}`;
// Response
// {
// "data": {
// "evmAddress": "0x172b0Ca9405BcE41A0D6FB3B44f91098d3a4AB14",
// "X": "a3350640a380f772434a18952fa53c6a8c200e9e3d30e1097edbd92be6dd9fe0",
// "Y": "1ded08adccba8e394f9a9d7ee55658aab8f2aef17866983c0bdcd68d31b59341",
// "isMfaEnabled": false
// },
// "success": true
// }
Please ensure that the useCoreKitKey parameter is set to true when using the Wallet Pregeneration API and the PnP SDK. This will ensure that the same address is generated when user logs in for the first time.
const chainConfig = YOUR_CUSTOM_CHAIN_CONFIG;
const ethereumPrivateKeyProvider = EthereumPrivateKeyProvider({
config: { chainConfig },
});
const web3auth = new Web3Auth({
clientId: "YOUR_WEB3AUTH_CLIENT_ID",
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
privateKeyProvider: ethereumPrivateKeyProvider,
useCoreKitKey: true,
});
Manual Migration
The other option would be to show a prompt to users, asking them to migrate their funds from the old wallet to the new Web3Auth embedded wallet. It's totally upto users how they want to migrate.
You can also suggest your users to use tools like Token Bulksender. Again, DYOR.
Using MPC Core Kit SDK
If you have existing users with a Dynamic embedded wallet, you can seamlessly transition them to Web3Auth while retaining the same account.
Using the MPC Core Kit is the recommended approach for migrating users from Dynamic embedded wallet to Web3Auth.
The first step is to export the Dynamic embedded wallet private key. To do this, you can use the
initExportProcess
method from the useEmbeddedReveal
hook. This will open the modal for users to
copy their private key.
For more details on exporting accounts, learn more here.
Please note that there is no internal method to export the private key in Dynamic. Only the user can
access their full private key. When you use the initExportProcess
method, it will display the
wallet UI for the user to copy their private key. Once the key is copied, you can prompt them to
import it using an input field.
import { useEmbeddedReveal } from "@dynamic-labs/sdk-react-core";
const { initExportProcess } = useEmbeddedReveal();
<button onClick={() => initExportProcess()}></button>;
You can now show the prompt to enter the private key they copied. Once you have the private key, you
can simply import it into Web3AuthMpCoreKit
. When you import the private key, it is split into
multiple partial keys, which are never stored together in one place. Furthermore, in the MPC
architecture, the private key is never reconstructed, enhancing security. The partial keys are
stored in different locations and the user's device. These partial keys are used to create partial
signatures for messages and transactions. These partial signatures are then combined using Threshold
Signature Scheme (TSS) to produce a final signature, which can be used for transactions on the
blockchain. MPC Core Kit supports both secp256k1 and ed25519 curves, so you can generate both ECDSA
and EdDSA signatures.
Learn more about MPC Core Kit.
// Your own logic to retrive google login id Token
const idTokenLoginParams = {
verifier: "w3a-google-demo",
verifierId: parsedIdToken.email,
idToken: parsedIdToken,
// Use the exported private key from previous step
importTssKey: dynamicPrivateKey,
} as IdTokenLoginParams;
const coreKitInstance = new Web3AuthMPCCoreKit({
web3AuthClientId: "YOUR_WEB3AUTH_CLIENT_ID",
web3AuthNetwork: WEB3AUTH_NETWORK.DEVNET,
baseUrl: "http://localhost:3000",
});
await coreKitInstance.init();
await coreKitInstance.loginWithJWT(idTokenLoginParams);
AA Wallet
Web3Auth is compatible with all major Account Abstraction (AA) SDKs, including Alchemy, Biconomy, Pimlico, ZeroDev, and Safe. To learn more, please check out our AA Demo.
If you are using a Dynamic embedded wallet as a signer for an ERC 4337 (Account Abstraction) wallet, you can easily add the Web3Auth embedded wallet as an additional signer. This will enable existing users to seamlessly migrate to the Web3Auth embedded wallet. Alternatively, you can prompt users to remove the Dynamic signer if preferred.
- ZeroDev
- Biconomy
- AccountKit (Alchmey)
Considering you have already created the ECDSAProvider
instance using Dynamic signer, you can simply use the changeOwner
method to change the
Smart Account owner.
Learn more about transfering ownership of Smart account in ZeroDev.
import { providerToSmartAccountSigner } from "permissionless";
import { EIP1193Provider } from "viem";
const { hash } = await dynamicEcdsaProvider.changeOwner("WEB3AUTH_EMBEDDED_WALLET_ADDRESS");
// Considering you have setup the Web3Auth instance
const web3authProvider = web3auth.provider;
if (!web3authProvider) {
throw new Error("No provider found");
}
// Create the smart account signer from the provider and signer address
const smartAccountSigner = await providerToSmartAccountSigner(web3authProvider as EIP1193Provider);
// Generate the ZeroDev wallet for new signer.
const web3AuthEcdsaProvider = await signerToEcdsaValidator(publicClient, {
signer: smartAccountSigner,
entryPoint: ENTRYPOINT_ADDRESS_V07,
});
Considering you have already created the smart account instance using Dynamic signer, you can simply use the transferOwnership
method to change the
Smart Account owner.
Learn more about transfering ownership of Smart account in Biconomy.
// Considering you have setup the Web3Auth instance
const provider = new ethers.providers.Web3Provider(web3Auth.provider);
const web3AuthSigner = await ethersProvider.getSigner();
const newOwner = web3AuthSigner.getAddress();
const smartAccountAddress = await dynamicSmartAccount.getAccountAddress();
const response = await dynamicSmartAccount.transferOwnership(
newOwner,
DEFAULT_ECDSA_OWNERSHIP_MODULE,
{
paymasterServiceData: { mode: PaymasterMode.SPONSORED },
},
);
const receipt = await response.wait();
// Recreate the smart account client with the new owner and specify the address of the smart account
let smartAccount = await createSmartAccountClient({
signer: web3AuthSigner,
paymasterUrl,
bundlerUrl,
accountAddress: smartAccountAddress,
});
Considering you have already created the LightAccount
instance using Dynamic signer, you can simply use the transferOwnership
method to change the
Smart Account owner.
Learn more about transfering ownership of Smart account in AccountKit(Alchemy).
import { Web3AuthSigner } from "@alchemy/aa-signers/web3auth";
import { CHAIN_NAMESPACES } from "@web3auth/base";
// Learn more about Web3AuthSigner: https://accountkit.alchemy.com/packages/aa-signers/web3auth/constructor
const web3AuthSigner = const web3AuthSigner = new Web3AuthSigner({
clientId: "YOUR_WEB3AUTH_CLIENT_ID",
chainConfig: {
chainNamespace: CHAIN_NAMESPACES.EIP155,
},
});
const newOwner = web3AuthSigner.getAddress();
const accountAddress = dynamicLightAccountClient.getAddress();
const hash = dynamicLightAccountClient.transferOwnership({
newOwner,
waitForTxn: true,
});
// After transaction is mined on the network,
// create a new light account client for the transferred Light Account
const transferredClient = await createLightAccountClient({
transport: custom(dynamicLightAccountClient),
chain: dynamicLightAccountClient.chain,
signer: web3AuthSigner,
// NOTE: You MUST specify the original smart account address to connect using the new owner/signer
accountAddress,
// NOTE: If the version of the light account is not v1.1.0, it must be specified here
version: "v2.0.0",
});
If we have missed any AA provider, please don't hesitate to reach out to us in comments.
External Wallets
If you are using Dynamic with external wallets and are looking to integrate with Web3Auth, the migration process is quite straightforward. Web3Auth offers external multiple adapters to connect with external wallets, along with social login options for added convenience. Along with external wallets, Web3Auth also supports application wallets like Torus wallet.
If you are using EVM branded wallets previously with Dynamic, you can simply configure the
@web3auth/default-evm-adapter
for your Web3Auth instance.
Read more about default-evm-adapter.
import { getDefaultExternalAdapters } from "@web3auth/default-evm-adapter";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
// This can be your custom chain as well.
const chainConfig = {
chainId: "0x1",
rpcTarget: "https://rpc.ankr.com/eth",
displayName: "Ethereum Mainnet",
blockExplorerUrl: "https://etherscan.io/",
ticker: "ETH",
tickerName: "Ethereum",
logo: "https://images.toruswallet.io/eth.svg",
};
const privateKeyProvider = new EthereumPrivateKeyProvider({ config: { chainConfig } });
const web3AuthOptions: Web3AuthOptions = {
"YOUR_WEB3AUTH_CLIENT_ID",
chainConfig: { ...chainConfig, chainNamespace: CHAIN_NAMESPACES.EIP155 },
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
privateKeyProvider: privateKeyProvider,
};
const web3Auth = new Web3Auth(web3AuthOptions);
const adapters = await getDefaultExternalAdapters({ options: web3AuthOptions });
adapters.forEach((adapter) => {
web3auth.configureAdapter(adapter);
});
If you are a fan boy of wagmi, we have got your covered. You can use our web3auth-wagmi-connector to initialize a wagmi client that will seamlessly manage the interaction of your dApp with Web3Auth.Read more about web3auth-wagmi-connector.
import { Web3AuthConnector } from "@web3auth/web3auth-wagmi-connector";
import { Web3Auth } from "@web3auth/modal";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { CHAIN_NAMESPACES, WEB3AUTH_NETWORK, WALLET_ADAPTERS } from "@web3auth/base";
import { Chain } from "wagmi/chains";
import { WalletServicesPlugin } from "@web3auth/wallet-services-plugin";
export default function Web3AuthConnectorInstance(chains: Chain[]) {
const chainConfig = {
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: "0x" + chains[0].id.toString(16),
rpcTarget: chains[0].rpcUrls.default.http[0],
displayName: chains[0].name,
tickerName: chains[0].nativeCurrency?.name,
ticker: chains[0].nativeCurrency?.symbol,
blockExplorerUrl: chains[0].blockExplorers?.default.url[0] as string,
};
const privateKeyProvider = new EthereumPrivateKeyProvider({ config: { chainConfig } });
const web3AuthInstance = new Web3Auth({
clientId: "YOUR_WEB3AUTH_CLIENT_ID",
chainConfig,
privateKeyProvider,
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
enableLogging: true,
});
const modalConfig = {
[WALLET_ADAPTERS.OPENLOGIN]: {
label: "openlogin",
loginMethods: {
facebook: {
// It will hide the facebook option from the Web3Auth modal.
name: "facebook login",
showOnModal: false,
},
},
// Setting it to false will hide all social login methods from modal.
showOnModal: true,
},
};
return Web3AuthConnector({
web3AuthInstance,
modalConfig,
});
}
The above code snippet is for Web3Auth Modal SDK, if you are looking No Modal SDK, you can checkout wagmi no modal sample.
Conclusion
In conclusion, migrating from Dynamic to Web3Auth offers enhanced security through Multi-Party Computation, broader multi-chain and multi-platform support, and additional features like NFT services. For any specific migration scenarios not covered, book a call with the Web3Auth team, we are happy to assist you.