Skip to content

Commit

Permalink
Updates
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardysun committed Sep 28, 2024
1 parent 55246f8 commit 8afb2c4
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 102 deletions.
7 changes: 7 additions & 0 deletions packages/thirdweb/src/pay/buyWithFiat/getQuote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ export type BuyWithFiatQuote = {
*
*/
onRampLink: string;

/**
* If enabled, this onramp transaction is eligible for "single-step execution",
* in which an entire intent is executed end-to-end from the source token/chain
* to the desired destination token or transaction.
*/
isSingleStepExecutionEnabled?: boolean;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useQueryClient } from "@tanstack/react-query";
import { useCallback, useMemo, useState } from "react";
import { trackPayEvent } from "../../../../../../analytics/track.js";
import type { Chain } from "../../../../../../chains/types.js";
import { getCachedChain } from "../../../../../../chains/utils.js";
import type { ThirdwebClient } from "../../../../../../client/client.js";
import { NATIVE_TOKEN_ADDRESS } from "../../../../../../constants/addresses.js";
import type { GetBuyWithCryptoQuoteParams } from "../../../../../../pay/buyWithCrypto/getQuote.js";
Expand Down Expand Up @@ -58,6 +59,7 @@ import { WalletSelectorButton } from "./WalletSelectorButton.js";
import { CurrencySelection } from "./fiat/CurrencySelection.js";
import { FiatFlow } from "./fiat/FiatFlow.js";
import type { CurrencyMeta } from "./fiat/currencies.js";
import { useDeploySmartWallet } from "./fiat/useDeploySmartWallet.js";
import type { SelectedScreen } from "./main/types.js";
import {
type PaymentMethods,
Expand Down Expand Up @@ -1347,6 +1349,7 @@ function FiatScreenContent(props: {
defaultRecipientAddress || props.payer.account.address;
const { drawerRef, drawerOverlayRef, isOpen, setIsOpen } = useDrawer();
const [drawerScreen, setDrawerScreen] = useState<"fees">("fees");
const { deploySmartWallet } = useDeploySmartWallet(props.client);

const buyWithFiatOptions = props.payOptions.buyWithFiat;

Expand All @@ -1369,17 +1372,55 @@ function FiatScreenContent(props: {
: undefined,
);

function handleSubmit() {
const executeSmartWalletDeploy = async () => {
if (!fiatQuoteQuery.data) {
return;
}

try {
const chain = getCachedChain(
fiatQuoteQuery.data.onRampToken.token.chainId,
);
const result = await deploySmartWallet({
chain,
intentId: fiatQuoteQuery.data.intentId,
onRampTokenMeta: {
tokenAddress: fiatQuoteQuery.data.onRampToken.token.tokenAddress,
},
onRampTokenAmount: fiatQuoteQuery.data.estimatedToAmountMinWei,
});
console.log("result is ", result);
console.log("Smart wallet deployed:", result);

return {
onRampLink: result.onRampLink,
};
} catch (err) {
console.error("Failed to deploy smart wallet:", err);
// Continue
}
};

const handleSubmit = async () => {
if (!fiatQuoteQuery.data) {
return;
}

const smartWalletDeployData = await executeSmartWalletDeploy();
// const smartWalletDeployData = fiatQuoteQuery.data
// .isSingleStepExecutionEnabled
// ? await executeSmartWalletDeploy()
// : undefined;

const onRampLink =
smartWalletDeployData?.onRampLink || fiatQuoteQuery.data.onRampLink;

const hasTwoSteps = isSwapRequiredPostOnramp(fiatQuoteQuery.data);
let openedWindow: Window | null = null;

if (!hasTwoSteps) {
openedWindow = openOnrampPopup(
fiatQuoteQuery.data.onRampLink,
onRampLink,
typeof props.theme === "string" ? props.theme : props.theme.type,
);

Expand All @@ -1394,7 +1435,7 @@ function FiatScreenContent(props: {
quote: fiatQuoteQuery.data,
openedWindow,
});
}
};

function showFees() {
if (!fiatQuoteQuery.data) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,12 @@ import {
TriangleDownIcon,
} from "@radix-ui/react-icons";
import { useMemo } from "react";
import type { Chain } from "../../../../../../../chains/types.js";
import { getCachedChain } from "../../../../../../../chains/utils.js";
import type { ThirdwebClient } from "../../../../../../../client/client.js";
import { NATIVE_TOKEN_ADDRESS } from "../../../../../../../constants/addresses.js";
import { getContract } from "../../../../../../../contract/contract.js";
import { addSessionKey } from "../../../../../../../extensions/erc4337/account/addSessionKey.js";
import type { BuyWithFiatQuote } from "../../../../../../../pay/buyWithFiat/getQuote.js";
import type { BuyWithFiatStatus } from "../../../../../../../pay/buyWithFiat/getStatus.js";
import { getPayBaseUrl } from "../../../../../../../pay/utils/definitions.js";
import { formatNumber } from "../../../../../../../utils/formatNumber.js";
import { createAndSignUserOp } from "../../../../../../../wallets/smart/lib/userop.js";
import { hexlifyUserOp } from "../../../../../../../wallets/smart/lib/utils.js";
import { smartWallet } from "../../../../../../../wallets/smart/smart-wallet.js";
import {
type Theme,
fontSize,
Expand All @@ -28,8 +21,6 @@ import {
useChainExplorers,
useChainName,
} from "../../../../../../core/hooks/others/useChainQuery.js";
import { useActiveAccount } from "../../../../../../core/hooks/wallets/useActiveAccount.js";
import { useSwitchActiveWalletChain } from "../../../../../../core/hooks/wallets/useSwitchActiveWalletChain.js";
import type { TokenInfo } from "../../../../../../core/utils/defaultTokens.js";
import { Spacer } from "../../../../components/Spacer.js";
import { Spinner } from "../../../../components/Spinner.js";
Expand All @@ -45,6 +36,7 @@ import {
getBuyWithFiatStatusMeta,
} from "../pay-transactions/statusMeta.js";
import { getCurrencyMeta } from "./currencies.js";
import { useDeploySmartWallet } from "./useDeploySmartWallet.js";

export type BuyWithFiatPartialQuote = {
intentId: string;
Expand Down Expand Up @@ -117,97 +109,24 @@ export function FiatSteps(props: {
intentId,
} = props.partialQuote;

const account = useActiveAccount();
const switchChain = useSwitchActiveWalletChain();

const deploySmartWallet = async ({ chain }: { chain: Chain }) => {
if (!account) return;

await switchChain(chain);

const smartWalletHandle = smartWallet({
chain,
sponsorGas: true,
});

const smartAccount = await smartWalletHandle.connect({
client: props.client,
personalAccount: account,
});
console.log("smartAccount", smartAccount);

const smartAccountContract = getContract({
client: props.client,
chain,
address: smartAccount.address,
});

console.log("onRampTokenAmount", props.partialQuote.onRampTokenAmount);
const sessionKeyTx = addSessionKey({
contract: smartAccountContract,
account: account,
// TODO: Env var this.
// // prod
// sessionKeyAddress: "0x1629Ce9Df01B10E7CF8837f559037A49d983aA10", // pay engine backend wallet
// dev
sessionKeyAddress: "0x32DC86f866e9F5Ed59A60b18c3B0f9b972a928F0", // dev engine backend wallet
permissions: {
approvedTargets: "*", // the addresses of allowed contracts, or '*' for any contract
permissionStartTimestamp: new Date(), // the date when the session key becomes active
permissionEndTimestamp: new Date(Date.now() + 24 * 60 * 60 * 1000), // the date when the session key expires
// TODO: Perhaps add a buffer here to be safe?
nativeTokenLimitPerTransaction: props.partialQuote.onRampTokenAmount,
},
});

const signedUserOp = await createAndSignUserOp({
transactions: [sessionKeyTx],
adminAccount: account,
client: props.client,
smartWalletOptions: {
const { deploySmartWallet, isLoading, error } = useDeploySmartWallet(
props.client,
);

const handleDeploySmartWallet = async ({ chain }) => {
try {
const result = await deploySmartWallet({
chain,
sponsorGas: true,
},
});

const hexlifiedUserOp = hexlifyUserOp(signedUserOp);
console.log("signedUserOp", signedUserOp);
console.log("hexlifiedUserOp", hexlifiedUserOp);
console.log("sessionKeyTx", sessionKeyTx);

console.log("chainId", chain.id);
console.log("intentId", intentId);
console.log("toAddress", account.address);
const response = await fetch(
`${getPayBaseUrl()}/v2/intent-wallets/deploy`,
{
method: "POST",
body: JSON.stringify({
chainId: chain.id,
intentId: intentId,
intentType: "buyWithFiat",
signedUserOps: [hexlifiedUserOp],
toAddress: account.address,
smartWalletAddress: smartAccount.address,
}),
headers: {
"Content-Type": "application/json",
"x-client-id": process.env.NEXT_PUBLIC_THIRDWEB_CLIENT_ID as string,
},
},
);

const data = await response.json();
console.log("response from server", data);

props.setOnRampLinkOverride?.(data.onRampLink);

return {
smartWalletAddress: smartAccount.address,
userAddress: account.address,
};
intentId: props.partialQuote.intentId,
onRampTokenMeta: props.partialQuote.onRampToken,
onRampTokenAmount: props.partialQuote.onRampTokenAmount,
setOnRampLinkOverride: props.setOnRampLinkOverride,
});
console.log("Smart wallet deployed:", result);
} catch (err) {
console.error("Failed to deploy smart wallet:", err);
}
};

const currency = getCurrencyMeta(fromCurrencySymbol);
const isPartialSuccess = statusMeta?.progressStatus === "partialSuccess";

Expand Down Expand Up @@ -417,7 +336,7 @@ export function FiatSteps(props: {
<Spacer y="lg" />

{/* Step 1 */}
<button onClick={() => deploySmartWallet({ chain: onRampChain })}>
<button onClick={() => handleDeploySmartWallet({ chain: onRampChain })}>
Deploy smart wallet with session key
</button>

Expand Down
Loading

0 comments on commit 8afb2c4

Please sign in to comment.