diff --git a/.changeset/quiet-melons-jump.md b/.changeset/quiet-melons-jump.md
new file mode 100644
index 00000000000..69b75588455
--- /dev/null
+++ b/.changeset/quiet-melons-jump.md
@@ -0,0 +1,5 @@
+---
+"thirdweb": patch
+---
+
+Handle wallet chain mismatch on post onramp flow
diff --git a/apps/playground-web/src/components/pay/embed.tsx b/apps/playground-web/src/components/pay/embed.tsx
index ed85fe3d6b5..18bba36327a 100644
--- a/apps/playground-web/src/components/pay/embed.tsx
+++ b/apps/playground-web/src/components/pay/embed.tsx
@@ -18,10 +18,6 @@ export function StyledPayEmbedPreview() {
{
const { fromToken, toToken, amount } = input;
+ const wallet = props.payer.wallet;
+
+ // in case the wallet is not on the same chain as the fromToken, switch to it
+ if (wallet.getChain()?.id !== fromToken.chainId) {
+ await wallet.switchChain(getCachedChain(fromToken.chainId));
+ }
+
+ const account = wallet.getAccount();
+
+ if (!account) {
+ throw new Error("Payer wallet has no account");
+ }
+
// always get a fresh quote before executing
const quote = await getBuyWithCryptoQuote({
fromChainId: fromToken.chainId,
@@ -641,12 +654,12 @@ function useSwapMutation(props: {
toAmount: amount,
toChainId: toToken.chainId,
toTokenAddress: toToken.tokenAddress,
- fromAddress: props.payer.account.address,
- toAddress: props.payer.account.address,
+ fromAddress: account.address,
+ toAddress: account.address,
client: props.client,
});
- const canBatch = props.payer.account.sendBatchTransaction;
+ const canBatch = account.sendBatchTransaction;
const tokenContract = getContract({
client: props.client,
address: quote.swapDetails.fromToken.tokenAddress,
@@ -656,14 +669,14 @@ function useSwapMutation(props: {
quote.approvalData &&
(await allowance({
contract: tokenContract,
- owner: props.payer.account.address,
+ owner: account.address,
spender: quote.approvalData.spenderAddress,
})) < BigInt(quote.approvalData.amountWei);
if (approveTxRequired && quote.approvalData && !canBatch) {
trackPayEvent({
event: "prompt_swap_approval",
client: props.client,
- walletAddress: props.payer.account.address,
+ walletAddress: account.address,
walletType: props.payer.wallet.id,
fromToken: quote.swapDetails.fromToken.tokenAddress,
fromAmount: quote.swapDetails.fromAmountWei,
@@ -680,7 +693,7 @@ function useSwapMutation(props: {
});
const tx = await sendTransaction({
- account: props.payer.account,
+ account,
transaction,
});
@@ -689,7 +702,7 @@ function useSwapMutation(props: {
trackPayEvent({
event: "swap_approval_success",
client: props.client,
- walletAddress: props.payer.account.address,
+ walletAddress: account.address,
walletType: props.payer.wallet.id,
fromToken: quote.swapDetails.fromToken.tokenAddress,
fromAmount: quote.swapDetails.fromAmountWei,
@@ -703,7 +716,7 @@ function useSwapMutation(props: {
trackPayEvent({
event: "prompt_swap_execution",
client: props.client,
- walletAddress: props.payer.account.address,
+ walletAddress: account.address,
walletType: props.payer.wallet.id,
fromToken: quote.swapDetails.fromToken.tokenAddress,
fromAmount: quote.swapDetails.fromAmountWei,
@@ -723,12 +736,12 @@ function useSwapMutation(props: {
});
_swapTx = await sendBatchTransaction({
- account: props.payer.account,
+ account,
transactions: [approveTx, tx],
});
} else {
_swapTx = await sendTransaction({
- account: props.payer.account,
+ account,
transaction: tx,
});
}
@@ -738,7 +751,7 @@ function useSwapMutation(props: {
trackPayEvent({
event: "swap_execution_success",
client: props.client,
- walletAddress: props.payer.account.address,
+ walletAddress: account.address,
walletType: props.payer.wallet.id,
fromToken: quote.swapDetails.fromToken.tokenAddress,
fromAmount: quote.swapDetails.fromAmountWei,
diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx
index 02fb5cac559..b14c201afee 100644
--- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx
+++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx
@@ -160,6 +160,19 @@ export function SwapConfirmationScreen(props: {
fullWidth
disabled={status === "pending"}
onClick={async () => {
+ const wallet = props.payer.wallet;
+
+ // in case the wallet is not on the same chain as the fromToken, switch to it
+ if (wallet.getChain()?.id !== props.fromChain.id) {
+ await wallet.switchChain(props.fromChain);
+ }
+
+ const account = wallet.getAccount();
+
+ if (!account) {
+ throw new Error("Payer wallet has no account");
+ }
+
if (step === "approval" && props.quote.approvalData) {
try {
setStatus("pending");
@@ -167,8 +180,8 @@ export function SwapConfirmationScreen(props: {
trackPayEvent({
event: "prompt_swap_approval",
client: props.client,
- walletAddress: props.payer.account.address,
- walletType: props.payer.wallet.id,
+ walletAddress: account.address,
+ walletType: wallet.id,
fromToken: props.quote.swapDetails.fromToken.tokenAddress,
fromAmount: props.quote.swapDetails.fromAmountWei,
toToken: props.quote.swapDetails.toToken.tokenAddress,
@@ -188,7 +201,7 @@ export function SwapConfirmationScreen(props: {
});
const tx = await sendTransaction({
- account: props.payer.account,
+ account: account,
transaction,
});
@@ -197,8 +210,8 @@ export function SwapConfirmationScreen(props: {
trackPayEvent({
event: "swap_approval_success",
client: props.client,
- walletAddress: props.payer.account.address,
- walletType: props.payer.wallet.id,
+ walletAddress: account.address,
+ walletType: wallet.id,
fromToken: props.quote.swapDetails.fromToken.tokenAddress,
fromAmount: props.quote.swapDetails.fromAmountWei,
toToken: props.quote.swapDetails.toToken.tokenAddress,
@@ -221,8 +234,8 @@ export function SwapConfirmationScreen(props: {
trackPayEvent({
event: "prompt_swap_execution",
client: props.client,
- walletAddress: props.payer.account.address,
- walletType: props.payer.wallet.id,
+ walletAddress: account.address,
+ walletType: wallet.id,
fromToken: props.quote.swapDetails.fromToken.tokenAddress,
fromAmount: props.quote.swapDetails.fromAmountWei,
toToken: props.quote.swapDetails.toToken.tokenAddress,
@@ -233,7 +246,7 @@ export function SwapConfirmationScreen(props: {
const tx = props.quote.transactionRequest;
let _swapTx: WaitForReceiptOptions;
// check if we can batch approval and swap
- const canBatch = props.payer.account.sendBatchTransaction;
+ const canBatch = account.sendBatchTransaction;
if (
canBatch &&
props.quote.approvalData &&
@@ -250,12 +263,12 @@ export function SwapConfirmationScreen(props: {
});
_swapTx = await sendBatchTransaction({
- account: props.payer.account,
+ account: account,
transactions: [approveTx, tx],
});
} else {
_swapTx = await sendTransaction({
- account: props.payer.account,
+ account: account,
transaction: tx,
});
}
@@ -263,8 +276,8 @@ export function SwapConfirmationScreen(props: {
trackPayEvent({
event: "swap_execution_success",
client: props.client,
- walletAddress: props.payer.account.address,
- walletType: props.payer.wallet.id,
+ walletAddress: account.address,
+ walletType: wallet.id,
fromToken: props.quote.swapDetails.fromToken.tokenAddress,
fromAmount: props.quote.swapDetails.fromAmountWei,
toToken: props.quote.swapDetails.toToken.tokenAddress,
diff --git a/packages/thirdweb/src/wallets/smart/index.ts b/packages/thirdweb/src/wallets/smart/index.ts
index 0adcc53e5d7..9f26a788fbb 100644
--- a/packages/thirdweb/src/wallets/smart/index.ts
+++ b/packages/thirdweb/src/wallets/smart/index.ts
@@ -264,11 +264,12 @@ async function createSmartAccount(
executeOverride: options.overrides?.execute,
});
+ const chain = getCachedChain(transaction.chainId);
const result = await _sendUserOp({
executeTx,
options: {
...options,
- chain: getCachedChain(transaction.chainId),
+ chain,
accountContract,
overrides: {
...options.overrides,
@@ -278,7 +279,7 @@ async function createSmartAccount(
});
trackTransaction({
client: options.client,
- chainId: options.chain.id,
+ chainId: chain.id,
transactionHash: result.transactionHash,
walletAddress: options.accountContract.address,
walletType: "smart",
@@ -292,17 +293,25 @@ async function createSmartAccount(
transactions,
executeBatchOverride: options.overrides?.executeBatch,
});
+ if (transactions.length === 0) {
+ throw new Error("No transactions to send");
+ }
+ const firstTx = transactions[0];
+ if (!firstTx) {
+ throw new Error("No transactions to send");
+ }
+ const chain = getCachedChain(firstTx.chainId);
const result = await _sendUserOp({
executeTx,
options: {
...options,
- chain: getCachedChain(transactions[0]?.chainId ?? options.chain.id),
+ chain,
accountContract,
},
});
trackTransaction({
client: options.client,
- chainId: options.chain.id,
+ chainId: chain.id,
transactionHash: result.transactionHash,
walletAddress: options.accountContract.address,
walletType: "smart",