Skip to content

Commit

Permalink
Merge pull request #5 from coinbase/updated-demo-app
Browse files Browse the repository at this point in the history
ONRAMP-4952 Update Quickstart demo app for OCB Fund Onchain Kit Component
  • Loading branch information
steveviselli-cb authored Feb 13, 2025
2 parents d44652d + f41eadf commit 935733c
Show file tree
Hide file tree
Showing 15 changed files with 876 additions and 449 deletions.
55 changes: 22 additions & 33 deletions app/components/ChainTokenSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Autocomplete, AutocompleteItem, Skeleton } from '@nextui-org/react';
import { Key, useEffect } from 'react';
import { Key, useEffect, useMemo } from 'react';
import { useCoinbaseRampTransaction } from '../contexts/CoinbaseRampTransactionContext';
import { generateBuyOptions, generateSellOptions } from '../queries';
import { generateSellOptions } from '../queries';

export interface Token {
id: string;
Expand Down Expand Up @@ -38,24 +38,6 @@ export const ChainTokenSelector = () => {
} = useCoinbaseRampTransaction();

useEffect(() => {
const getBuyOptions = async () => {
try {
setLoadingBuyOptions(true);
if (selectedCountry && !buyOptions) {
const buyOptions = await generateBuyOptions({
country: selectedCountry.id,
subdivision: selectedSubdivision ? selectedSubdivision : '',
});

setBuyOptions(buyOptions);
}
} catch (error) {
console.error('Error fetching buy options:', error);
} finally {
setLoadingBuyOptions(false);
}
};

const getSellOptions = async () => {
try {
setLoadingSellOptions(true);
Expand All @@ -74,7 +56,6 @@ export const ChainTokenSelector = () => {
}
};

getBuyOptions();
getSellOptions();
}, [
selectedCountry,
Expand All @@ -91,7 +72,7 @@ export const ChainTokenSelector = () => {
const handleTokenSelectionChange = (key: Key | null) => {
if (key) {
if (isOnrampActive) {
const selectedPurchaseCurrency = buyOptions?.purchase_currencies.find(
const selectedPurchaseCurrency = buyOptions?.purchaseCurrencies.find(
(pc) => pc.id === key
);

Expand Down Expand Up @@ -124,7 +105,7 @@ export const ChainTokenSelector = () => {
if (key) {
if (isOnrampActive) {
const selectedNetwork = selectedPurchaseCurrency?.networks.find(
(n) => n.display_name === key
(n) => n.displayName === key
);

if (selectedNetwork) {
Expand Down Expand Up @@ -152,6 +133,18 @@ export const ChainTokenSelector = () => {
: selectedSellCurrency?.id;
};

const networkDisplayNames = useMemo(() => {
if (isOnrampActive) {
return (selectedPurchaseCurrency?.networks ?? []).map(
({ displayName }) => displayName
);
}

return (selectedSellCurrency?.networks ?? []).map(
({ display_name }) => display_name
);
}, [isOnrampActive, selectedPurchaseCurrency, selectedSellCurrency]);

return (
<div className="flex flex-col gap-4">
{loadingBuyOptions ? (
Expand All @@ -172,7 +165,7 @@ export const ChainTokenSelector = () => {
>
{(
(isOnrampActive
? buyOptions?.purchase_currencies
? buyOptions?.purchaseCurrencies
: sellOptions?.sell_currencies) || []
).map((purchaseCurrency) => (
<AutocompleteItem
Expand All @@ -192,21 +185,17 @@ export const ChainTokenSelector = () => {
onSelectionChange={handleNetworkSelectionChange}
selectedKey={
isOnrampActive
? selectedPurchaseCurrencyNetwork?.display_name
? selectedPurchaseCurrencyNetwork?.displayName
: selectedSellCurrencyNetwork?.display_name
}
>
{(
(isOnrampActive
? selectedPurchaseCurrency?.networks
: selectedSellCurrency?.networks) || []
).map((network) => (
{networkDisplayNames.map((networkDisplayName) => (
<AutocompleteItem
key={network.display_name}
value={network.display_name}
key={networkDisplayName}
value={networkDisplayName}
className="capitalize"
>
{network.display_name}
{networkDisplayName}
</AutocompleteItem>
))}
</Autocomplete>
Expand Down
143 changes: 62 additions & 81 deletions app/components/CryptoRamp.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,38 @@
'use client';
import {
Divider,
Modal,
ModalBody,
ModalContent,
ModalHeader,
Tab,
Tabs,
} from '@nextui-org/react';
import Image from 'next/image';
fetchOnrampConfig,
fetchOnrampOptions,
} from '@coinbase/onchainkit/fund';
import { Tab, Tabs } from '@nextui-org/react';
import { useEffect, useState } from 'react';
import OrderHistoryIcon from '../assets/orderHistory.svg';
import {
Mode,
useCoinbaseRampTransaction,
} from '../contexts/CoinbaseRampTransactionContext';
import { generateBuyConfig } from '../queries';
import { AmountInput } from './AmountInput';
import { ChainTokenSelector } from './ChainTokenSelector';
import { CurrencySelector } from './CurrencySelector';
import { OrderHistory } from './OrderHistory';
import { RampTransactionSummary } from './RampTransactionSummary';
import { RegionSelector } from './RegionSelector';
import { WalletConnector } from './WalletConnector';
import { CustomIntegrationDemo } from './CustomIntegrationDemo';
import { FundButtonDemo } from './FundButtonDemo';
import { FundCardDemo } from './FundCardDemo';

interface ICryptoRampProps {
partnerUserId?: string;
}

export const CryptoRamp = ({ partnerUserId }: ICryptoRampProps) => {
const [step, setStep] = useState(1);
const [showOrderHistory, setShowOrderHistory] = useState(false);

const {
mode,
setMode,
setBuyConfig,
authenticated,
setPartnerUserId,
setLoadingBuyConfig,
setLoadingBuyOptions,
buyOptions,
setBuyOptions,
selectedCountry,
selectedSubdivision,
buyConfig,
} = useCoinbaseRampTransaction();

useEffect(() => {
Expand All @@ -60,20 +55,51 @@ export const CryptoRamp = ({ partnerUserId }: ICryptoRampProps) => {

useEffect(() => {
const getBuyconfig = async () => {
if (!buyConfig) {
try {
setLoadingBuyConfig(true);
const config = await fetchOnrampConfig();
setBuyConfig(config);
setLoadingBuyConfig(false);
} catch (error) {
console.error('Error generating buy config', error);
} finally {
setLoadingBuyConfig(false);
}
}
};

const getBuyOptions = async () => {
try {
setLoadingBuyConfig(true);
const config = await generateBuyConfig();
setBuyConfig(config);
setLoadingBuyConfig(false);
setLoadingBuyOptions(true);
if (selectedCountry && !buyOptions) {
const buyOptions = await fetchOnrampOptions({
country: selectedCountry.id,
subdivision: selectedSubdivision ? selectedSubdivision : '',
});

console.log('buyOptions', buyOptions);
setBuyOptions(buyOptions);
}
} catch (error) {
console.error('Error generating buy config', error);
console.error('Error fetching buy options:', error);
} finally {
setLoadingBuyConfig(false);
setLoadingBuyOptions(false);
}
};

getBuyconfig();
}, [setBuyConfig, setLoadingBuyConfig]);
getBuyOptions();
}, [
setBuyConfig,
setLoadingBuyConfig,
setBuyOptions,
selectedCountry,
selectedSubdivision,
setLoadingBuyOptions,
buyOptions,
buyConfig,
]);

useEffect(() => {
if (authenticated && step < 2) {
Expand All @@ -87,71 +113,26 @@ export const CryptoRamp = ({ partnerUserId }: ICryptoRampProps) => {
<div className="flex justify-center items-center min-h-screen bg-zinc-950">
<div className="crypto-ramp bg-black p-8 rounded-lg shadow-md w-full h-screen">
<div className="flex justify-between mb-6 min-h-20 flex-col md:flex-row gap-4">
<div className="flex gap-6 justify-center">
<div className="flex gap-6 justify-center items-center w-full flex-col">
<Tabs
aria-label="Options"
onSelectionChange={(key) => setMode(key as Mode)}
selectedKey={mode.toLowerCase()}
>
<Tab key="onramp" title="Buy"></Tab>
<Tab key="fund-card" title="Fund Card">
<FundCardDemo />
</Tab>
<Tab key="fund-button" title="Fund Button">
<FundButtonDemo />
</Tab>
<Tab key="custom-integration" title="Custom integration">
<CustomIntegrationDemo />
</Tab>
{/* TODO: Add offramp and enableSell Tab */}
{/* <Tab key="offramp" title="Sell"></Tab> */}
</Tabs>
<div className="hidden sm:block">
<RegionSelector />
</div>
</div>
<div className="flex gap-4 justify-center">
<WalletConnector />
{authenticated && (
<Image
onClick={() => setShowOrderHistory(true)}
className="cursor-pointer hover:opacity-50 active:opacity-30"
src={OrderHistoryIcon}
width={24}
height={24}
alt="Order History"
aria-label="Order History"
/>
)}
</div>
</div>
<Divider />

<div className="flex flex-col md:flex-row justify-around min-h-[750px] max-w-screen md:w-[1000px] m-auto gap-4 md:gap-0">
<div className="bloock sm:hidden mx-auto mt-4 mb-12">
<RegionSelector />
</div>
<div className="flex flex-col gap-4 grow">
<div>
<AmountInput />
<div className="flex flex-col md:flex-row gap-4 items-center justify-around">
<ChainTokenSelector />
<CurrencySelector />
</div>
</div>
</div>

<div className="flex justify-center items-center w-full md:w-[400px] my-8 md:my-0">
<RampTransactionSummary />
</div>
</div>

<Modal
isOpen={showOrderHistory}
onClose={() => setShowOrderHistory(false)}
>
<ModalContent className="h-[800px]">
<div>
<ModalHeader className="flex flex-col gap-1">
Order History
</ModalHeader>
<ModalBody>
<OrderHistory />
</ModalBody>
</div>
</ModalContent>
</Modal>
</div>
</div>
);
Expand Down
11 changes: 6 additions & 5 deletions app/components/CurrencySelector.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { OnrampPaymentMethod } from '@coinbase/onchainkit/fund';
import { Autocomplete, AutocompleteItem, Skeleton } from '@nextui-org/react';
import { Key, useState } from 'react';
import { useCoinbaseRampTransaction } from '../contexts/CoinbaseRampTransactionContext';
Expand Down Expand Up @@ -25,7 +26,7 @@ export const CurrencySelector = () => {
if (value) {
if (isOnrampActive && buyOptions) {
const newCurrency =
buyOptions.payment_currencies.find(
buyOptions.paymentCurrencies.find(
(currency) => currency.id === value
) || null;
setSelectedCurrency(newCurrency);
Expand All @@ -48,7 +49,7 @@ export const CurrencySelector = () => {
};

const handlePaymentMethodSelection = (key: Key | null) => {
const method = selectedCountry?.payment_methods.find(
const method = selectedCountry?.paymentMethods.find(
(method) => method.id === key
);

Expand All @@ -64,7 +65,7 @@ export const CurrencySelector = () => {
const getCurrencies = () => {
return (
(isOnrampActive
? buyOptions?.payment_currencies
? buyOptions?.paymentCurrencies
: sellOptions?.cashout_currencies) || []
);
};
Expand Down Expand Up @@ -104,8 +105,8 @@ export const CurrencySelector = () => {
onSelectionChange={handlePaymentMethodSelection}
selectedKey={rampTransaction?.paymentMethod}
>
{(selectedCountry?.payment_methods || []).map(
(paymentMethod) => (
{(selectedCountry?.paymentMethods || []).map(
(paymentMethod: OnrampPaymentMethod) => (
<AutocompleteItem
key={paymentMethod.id}
value={paymentMethod.id}
Expand Down
Loading

0 comments on commit 935733c

Please sign in to comment.