Compare commits

...
Author SHA1 Message Date
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
882fd3dcbd Version Packages (#6519)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-03-22 04:59:50 -07:00
Joaquim VergesandGitHub 744491f853 [SDK] fix: Handle wallet chain mismatch on post onramp flow (#6518) 2025-03-22 04:52:59 -07:00
d3f788471b [Portal] Neb Changes (#6451)
Signed-off-by: samina <[email protected]>
Co-authored-by: Manan Tank <[email protected]>
2025-03-22 00:48:04 -07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
6db81ef68d Version Packages (#6516)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-03-22 00:39:59 -07:00
Alberto GarcíaandGitHub f8b2bdc64b [Dashboard] Fix: wrong URL (#6510) 2025-03-22 00:18:06 -07:00
Joaquim VergesandGitHub c407bd10c7 [SDK] fix: Fetch fresh quotes before post onramp step in PayEmbed (#6515) 2025-03-22 00:14:45 -07:00
11 changed files with 112 additions and 60 deletions
@@ -22,7 +22,7 @@ Send native and ERC-20 currencies
### Deploy
Deploy published contracts
- Deploy a Token ERC20 Contract
- Deploy a Token ERC20 Contract with name "Hello World" and description "My Hello Contract" on Ethereum.
- Deploy a Split contract with two recipients.
- Deploy an ERC1155 Contract named 'Hello World' with description 'Hello badges on Ethereum'
@@ -30,7 +30,7 @@ Deploy published contracts
Retrieve information about smart contracts.
- What ERC standards are implemented by contract address 0x59325733eb952a92e069C87F0A6168b29E80627f on Ethereum?
- What functions can I use to mint more of my contract's NFTs?
- What is the total supply of NFTs for my contract?
- What is the total supply of NFTs on 0x8a90CAb2b38dba80c64b7734e58Ee1dB38B8992e?
### Interact
Query wallet balances, addresses, and token holdings.
@@ -79,7 +79,7 @@ export const CredentialForm = ({
<DialogTitle>{title}</DialogTitle>
<DialogDescription>
<TrackedLinkTW
href="https://portal.thirdweb.com/infrastructure/engine/features/wallet-credentials"
href="https://portal.thirdweb.com/engine/features/wallet-credentials"
target="_blank"
label="learn-more"
category="engine"
@@ -65,7 +65,7 @@ export const WalletCredentialsSection: React.FC<WalletCredentialsProps> = ({
<p className="text-muted-foreground text-sm leading-relaxed">
Manage your wallet credentials for different providers.{" "}
<Link
href="https://portal.thirdweb.com/infrastructure/engine/features/wallet-credentials"
href="https://portal.thirdweb.com/engine/features/wallet-credentials"
target="_blank"
>
Learn more about wallet credentials.
@@ -20,8 +20,8 @@ Maximize the potential of Nebula. Whether you’re new to blockchain development
|-----------------------------|----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Bridge & Swap** | Bridge and swap native currencies | • "Swap 1 USDC to 1 USDT on the Ethereum Mainnet"<br/>• "Bridge 0.5 ETH from Ethereum Mainnet to Polygon"<br/> |
| **Transfer** | Send native and ERC-20 currencies | • "Send 0.1 ETH to vitalik.eth"<br/>• "Transfer 1 USDC to saminacodes.eth on Base"<br/> |
| **Deploy** | Deploy published contracts | • "Deploy a Token ERC20 Contract"<br/>• "Deploy a Split contract with two recipients."<br/>• "Deploy an ERC1155 Contract named 'Hello World' with description 'Hello badges on Ethereum'"<br/>|
| **Understand** | Retrieve information about smart contracts. | • "What ERC standards are implemented by contract address 0x59325733eb952a92e069C87F0A6168b29E80627f on Ethereum?"<br/>• "What functions can I use to mint more of my contract's NFTs?"<br/>• "What is the total supply of NFTs for my contract?" |
| **Deploy** | Deploy published contracts | • "Deploy a Token ERC20 Contract with name "Hello World" and description "My Hello Contract" on Ethereum."<br/>• "Deploy a Split contract with two recipients."<br/>• "Deploy an ERC1155 Contract named 'Hello World' with description 'Hello badges on Ethereum'"<br/>|
| **Understand** | Retrieve information about smart contracts. | • "What ERC standards are implemented by contract address 0x59325733eb952a92e069C87F0A6168b29E80627f on Ethereum?"<br/>• "What functions can I use to mint more of my contract's NFTs?"<br/>• "What is the total supply of NFTs on 0x8a90CAb2b38dba80c64b7734e58Ee1dB38B8992e?" |
| **Interact** | Query wallet balances, addresses, and token holdings. | • "How much ETH is in my wallet?"<br/>• "What is the wallet address of vitalik.eth?"<br/>• "Does my wallet hold USDC on Base?" |
| **Explore** | Access blockchain-specific data. | • "What is the last block on zkSync?"<br/>• "What is the current gas price on Avalanche C-Chain?"<br/>• "Can you show me transaction details for 0xdfc450bb39e44bd37c22e0bfd0e5212edbea571e4e534d87b5cbbf06f10b9e04 on Optimism?" |
| **Research** | Obtain details about tokens, their addresses, and current prices. | • "What is the address of USDC on Ethereum?"<br/>• "Is there a UNI token on Arbitrum?"<br/>• "What is the current price of ARB?" |
+12
View File
@@ -1,5 +1,17 @@
# thirdweb
## 5.93.3
### Patch Changes
- [#6518](https://github.com/thirdweb-dev/js/pull/6518) [`744491f`](https://github.com/thirdweb-dev/js/commit/744491f85307444f227c14381629cdf27987ee62) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Handle wallet chain mismatch on post onramp flow
## 5.93.2
### Patch Changes
- [#6515](https://github.com/thirdweb-dev/js/pull/6515) [`c407bd1`](https://github.com/thirdweb-dev/js/commit/c407bd10c7b16f56c2a08cfdb2ed7e56a1c75f52) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Always fetch fresh quotes before post onramp step in PayEmbed
## 5.93.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "thirdweb",
"version": "5.93.1",
"version": "5.93.3",
"repository": {
"type": "git",
"url": "git+https://github.com/thirdweb-dev/js.git#main"
@@ -6,7 +6,7 @@ import type { ThirdwebClient } from "../../../../../../../client/client.js";
import { getContract } from "../../../../../../../contract/contract.js";
import { allowance } from "../../../../../../../extensions/erc20/__generated__/IERC20/read/allowance.js";
import { approve } from "../../../../../../../extensions/erc20/write/approve.js";
import type { BuyWithCryptoQuote } from "../../../../../../../pay/buyWithCrypto/getQuote.js";
import { getBuyWithCryptoQuote } from "../../../../../../../pay/buyWithCrypto/getQuote.js";
import type { BuyWithCryptoStatus } from "../../../../../../../pay/buyWithCrypto/getStatus.js";
import type { BuyWithFiatQuote } from "../../../../../../../pay/buyWithFiat/getQuote.js";
import {
@@ -17,6 +17,7 @@ import {
type OnRampStep,
getOnRampSteps,
} from "../../../../../../../pay/buyWithFiat/isSwapRequiredPostOnramp.js";
import type { PayTokenInfo } from "../../../../../../../pay/utils/commonTypes.js";
import { sendBatchTransaction } from "../../../../../../../transaction/actions/send-batch-transaction.js";
import { sendTransaction } from "../../../../../../../transaction/actions/send-transaction.js";
import type { WaitForReceiptOptions } from "../../../../../../../transaction/actions/wait-for-tx-receipt.js";
@@ -28,7 +29,6 @@ import type { Wallet } from "../../../../../../../wallets/interfaces/wallet.js";
import { isSmartWallet } from "../../../../../../../wallets/smart/is-smart-wallet.js";
import { spacing } from "../../../../../../core/design-system/index.js";
import { useChainName } from "../../../../../../core/hooks/others/useChainQuery.js";
import { useBuyWithCryptoQuote } from "../../../../../../core/hooks/pay/useBuyWithCryptoQuote.js";
import { useBuyWithCryptoStatus } from "../../../../../../core/hooks/pay/useBuyWithCryptoStatus.js";
import { useBuyWithFiatStatus } from "../../../../../../core/hooks/pay/useBuyWithFiatStatus.js";
import { useConnectedWallets } from "../../../../../../core/hooks/wallets/useConnectedWallets.js";
@@ -319,20 +319,6 @@ function useOnRampScreenState(props: {
// Get quote for current swap/bridge step if needed
const previousStep = onRampSteps[currentStepIndex - 1];
const currentStep = onRampSteps[currentStepIndex];
const swapQuoteQuery = useBuyWithCryptoQuote(
previousStep && currentStep
? {
fromChainId: previousStep.token.chainId,
fromTokenAddress: previousStep.token.tokenAddress,
toAmount: currentStep.amount,
toChainId: currentStep.token.chainId,
toTokenAddress: currentStep.token.tokenAddress,
fromAddress: props.payer.account.address,
toAddress: props.payer.account.address,
client: props.client,
}
: undefined,
);
// Handle swap execution
const swapMutation = useSwapMutation({
@@ -375,9 +361,9 @@ function useOnRampScreenState(props: {
status = "completed";
} else if (index === currentStepIndex) {
// Current step - could be swap or bridge
if (swapQuoteQuery.isLoading || swapMutation.isPending) {
if (swapMutation.isPending) {
status = "pending";
} else if (swapQuoteQuery.error || swapMutation.error) {
} else if (swapMutation.error) {
status = "failed";
} else if (swapTxHash) {
status = swapStatus;
@@ -418,11 +404,13 @@ function useOnRampScreenState(props: {
type: "fiat",
intentId: props.quote.intentId,
});
} else if (swapQuoteQuery.data && !swapTxHash) {
} else if (previousStep && currentStep && !swapTxHash) {
// Execute swap/bridge
try {
const result = await swapMutation.mutateAsync({
quote: swapQuoteQuery.data,
fromToken: previousStep.token,
toToken: currentStep.token,
amount: currentStep.amount,
});
setSwapTxHash({
hash: result.transactionHash,
@@ -435,23 +423,22 @@ function useOnRampScreenState(props: {
// retry the quote step
setSwapTxHash(undefined);
swapMutation.reset();
await swapQuoteQuery.refetch();
}
}, [
isDone,
currentStepIndex,
swapQuoteQuery.data,
swapTxHash,
props.quote,
props.onDone,
swapMutation,
props.theme,
isFailed,
swapQuoteQuery.refetch,
swapMutation.reset,
props.client,
props.payer.account.address,
props.payer.wallet.id,
currentStep,
previousStep,
]);
// Auto-progress effect
@@ -467,7 +454,6 @@ function useOnRampScreenState(props: {
!isFailed &&
currentStepIndex > 0 &&
currentStepIndex < onRampSteps.length &&
swapQuoteQuery.data &&
!swapTxHash
) {
handleContinue();
@@ -475,7 +461,6 @@ function useOnRampScreenState(props: {
}, [
props.isAutoMode,
currentStepIndex,
swapQuoteQuery.data,
swapTxHash,
onRampSteps.length,
handleContinue,
@@ -643,9 +628,38 @@ function useSwapMutation(props: {
}) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: { quote: BuyWithCryptoQuote }) => {
const { quote } = input;
const canBatch = props.payer.account.sendBatchTransaction;
mutationFn: async (input: {
fromToken: PayTokenInfo;
toToken: PayTokenInfo;
amount: string;
}) => {
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,
fromTokenAddress: fromToken.tokenAddress,
toAmount: amount,
toChainId: toToken.chainId,
toTokenAddress: toToken.tokenAddress,
fromAddress: account.address,
toAddress: account.address,
client: props.client,
});
const canBatch = account.sendBatchTransaction;
const tokenContract = getContract({
client: props.client,
address: quote.swapDetails.fromToken.tokenAddress,
@@ -655,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,
@@ -679,7 +693,7 @@ function useSwapMutation(props: {
});
const tx = await sendTransaction({
account: props.payer.account,
account,
transaction,
});
@@ -688,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,
@@ -702,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,
@@ -722,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,
});
}
@@ -737,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,
@@ -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,
+13 -4
View File
@@ -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",
+4
View File
@@ -1,5 +1,9 @@
# @thirdweb-dev/wagmi-adapter
## 0.2.38
## 0.2.37
## 0.2.36
## 0.2.35
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/wagmi-adapter",
"version": "0.2.36",
"version": "0.2.38",
"repository": {
"type": "git",
"url": "git+https://github.com/thirdweb-dev/js.git#main"