Nexus Account Migration Guide
This guide explains how to upgrade Nexus smart accounts from older versions to the latest implementation. The migration process preserves your account's address, balance, and history while providing access to new features, security fixes, and performance improvements.
Why Upgrade?
Upgrading your Nexus smart account is recommended for several important reasons:
- Security Improvements: The latest implementation includes critical security enhancements.
- New Features: Access to the newest account abstraction capabilities.
- Performance Improvements: Enhanced gas efficiency and transaction processing.
- Compatibility: Ensure your smart account remains compatible with the latest AbstractJS SDK.
Migration Process Overview
The migration consists of these key steps:
- Update AbstractJS Package: Install the latest SDK version
- Connect to Existing Account: Use your existing account address
- Upgrade Implementation: Call
upgradeSmartAccount()
- Verify Upgrade: Test the account with a transaction
- Update Application: Adjust your application to use the latest features
Important Notes for Migration
CRITICAL: After migration, you must store your account address and use it with the
accountAddress
parameter intoNexusAccount()
for all future interactions. This is how you'll maintain access to your upgraded account and its balances.
Step 1: Update AbstractJS Package
First, update to the latest version of the AbstractJS SDK:
# npm
npm update @biconomy/abstractjs
# yarn
yarn upgrade @biconomy/abstractjs
# pnpm
pnpm update @biconomy/abstractjs
# bun
bun update @biconomy/abstractjs
Step 2: Connect to Your Existing Account
When connecting to an account created with an older SDK version, you'll need your existing account address:
import { privateKeyToAccount } from "viem/accounts";
import { createBicoBundlerClient, toNexusAccount } from "@biconomy/abstractjs";
import { baseSepolia } from "viem/chains";
import { http } from "viem";
const privateKey = "YOUR_PRIVATE_KEY";
const account = privateKeyToAccount(`0x${privateKey}`);
const bundlerUrl = "YOUR_BUNDLER_URL";
// First, get your existing account address if you don't already have it stored
// This is crucial - you MUST store this address for future use
const existingAccountAddress = "YOUR_EXISTING_ACCOUNT_ADDRESS";
// Connect to your existing account
const nexusAccount = await toNexusAccount({
signer: account,
chain: baseSepolia,
transport: http(),
accountAddress: existingAccountAddress // Use your existing account address
});
const bundlerClient = createBicoBundlerClient({
account: nexusAccount,
transport: http(bundlerUrl)
});
IMPORTANT: You must preserve your existing account address and use it with the
accountAddress
parameter in all future SDK interactions. This is the only way to access your account and its funds after migration.
Step 3: Upgrade the Smart Account
Call the upgradeSmartAccount()
method to upgrade your account to the latest implementation:
// Upgrade the account to the latest implementation
const hash = await bundlerClient.upgradeSmartAccount();
// Wait for the upgrade transaction to be processed
const receipt = await bundlerClient.waitForUserOperationReceipt({ hash });
console.log("Upgrade successful:", receipt.success);
// Verify the account has been upgraded by checking the accountId
const accountId = await bundlerClient.accountId();
console.log("New account ID:", accountId);
Step 4: Verify the Upgrade
After upgrading, verify that your account works correctly by performing a test transaction:
// Test with a simple transaction after upgrade
const testTxHash = await bundlerClient.sendUserOperation({
calls: [{
to: "0x0000000000000000000000000000000000000000",
value: 0n,
data: "0x"
}]
});
const testReceipt = await bundlerClient.waitForUserOperationReceipt({
hash: testTxHash
});
console.log("Test transaction successful:", testReceipt.success);
Step 5: Store Your Account Address
After successful migration, you MUST store your account address for future use:
// Get and store your account address
const accountAddress = await bundlerClient.account.getAddress();
console.log("IMPORTANT - Store this account address:", accountAddress);
// In your application, store this address securely
// (database, local storage, user profile, etc.)
storeAccountAddress(userIdentifier, accountAddress);
Complete Migration Example
Here's a full example that demonstrates the migration process:
import { privateKeyToAccount } from "viem/accounts";
import {
createBicoBundlerClient,
toNexusAccount
} from "@biconomy/abstractjs";
import { baseSepolia } from "viem/chains";
import { http } from "viem";
async function migrateNexusAccount() {
// Setup
const privateKey = "YOUR_PRIVATE_KEY";
const account = privateKeyToAccount(`0x${privateKey}`);
const bundlerUrl = "YOUR_BUNDLER_URL";
// Your existing account address - CRITICAL for migration
const existingAccountAddress = "YOUR_EXISTING_ACCOUNT_ADDRESS";
// Connect to your existing account
const nexusAccount = await toNexusAccount({
signer: account,
chain: baseSepolia,
transport: http(),
accountAddress: existingAccountAddress
});
const bundlerClient = createBicoBundlerClient({
account: nexusAccount,
transport: http(bundlerUrl)
});
// Check the account ID before upgrade
const oldAccountId = await bundlerClient.accountId();
console.log("Account ID before upgrade:", oldAccountId);
// Verify account is deployed
const isDeployed = await bundlerClient.account.isDeployed();
if (!isDeployed) {
console.log("Account not deployed. Please deploy the account first.");
return;
}
console.log("Starting account upgrade...");
// Upgrade the account to the latest implementation
const hash = await bundlerClient.upgradeSmartAccount();
console.log("Upgrade transaction submitted:", hash);
// Wait for the upgrade transaction to be processed
const receipt = await bundlerClient.waitForUserOperationReceipt({ hash });
console.log("Upgrade transaction completed. Success:", receipt.success);
if (!receipt.success) {
console.error("Upgrade failed. Please check gas, balance, and permissions.");
return;
}
// Verify the account has been upgraded
const newAccountId = await bundlerClient.accountId();
console.log("Account ID after upgrade:", newAccountId);
// CRITICAL: Verify and store the account address for future use
const accountAddress = await bundlerClient.account.getAddress();
console.log("STORE THIS ACCOUNT ADDRESS:", accountAddress);
// Test the upgraded account with a transaction
console.log("Testing upgraded account with a transaction...");
// Example: Simple transaction to verify everything works
try {
const testHash = await bundlerClient.sendUserOperation({
calls: [{
to: "0x0000000000000000000000000000000000000000",
value: 0n,
data: "0x"
}]
});
const testReceipt = await bundlerClient.waitForUserOperationReceipt({
hash: testHash
});
console.log("Test transaction successful:", testReceipt.success);
console.log("Migration completed successfully!");
} catch (error) {
console.error("Test transaction failed:", error);
}
}
migrateNexusAccount().catch(console.error);
Post-Migration: Future Account Access
After migration, ALL future interactions with your account must use the accountAddress
parameter:
// CORRECT WAY to access your account after migration
const nexusAccount = await toNexusAccount({
signer: account,
chain: baseSepolia,
transport: http(),
accountAddress: "YOUR_STORED_ACCOUNT_ADDRESS" // This is essential
});
// INCORRECT WAY - this will create a new account, not access your existing one
const incorrectAccount = await toNexusAccount({
signer: account,
chain: baseSepolia,
transport: http()
// Missing accountAddress
});
Troubleshooting
If you encounter issues during the migration:
Upgrade Transaction Fails
- Ensure the account has sufficient funds for gas
- Verify the account is properly deployed on-chain
- Check that your application is using the latest SDK version
Cannot Access Account After Upgrade
- Make sure you're using the correct account address in the
accountAddress
parameter - Verify the upgrade transaction completed successfully
- Ensure you're using the exact same address as your pre-migration account
Next Steps
After successfully migrating your Nexus account:
- STORE YOUR ACCOUNT ADDRESS in your application's persistent storage
- Update your application code to use the
accountAddress
parameter in all future interactions - Test thoroughly with real transactions to ensure everything works as expected
By following this migration guide and properly storing your account address, you've successfully upgraded your Nexus account to the latest implementation while preserving its address, balance, and history.