Skip to content

Commit

Permalink
add swap default component
Browse files Browse the repository at this point in the history
  • Loading branch information
alissacrane-cb committed Sep 30, 2024
1 parent 3ef9119 commit 231197f
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 1 deletion.
1 change: 1 addition & 0 deletions playground/nextjs-app-router/components/AppProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { WalletPreference } from './form/wallet-type';
export enum OnchainKitComponent {
Identity = 'identity',
Swap = 'swap',
SwapDefault = 'swap-default',
Transaction = 'transaction',
Wallet = 'wallet',
}
Expand Down
5 changes: 5 additions & 0 deletions playground/nextjs-app-router/components/Demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { WalletType } from '@/components/form/wallet-type';
import { useContext, useEffect, useState } from 'react';
import IdentityDemo from './demo/Identity';
import SwapDemo from './demo/Swap';
import SwapDefaultDemo from './demo/SwapDefault';
import TransactionDemo from './demo/Transaction';
import WalletDemo from './demo/Wallet';
import { ActiveComponent } from './form/active-component';
Expand Down Expand Up @@ -56,6 +57,10 @@ function Demo() {
return <WalletDemo />;
}

if (activeComponent === OnchainKitComponent.SwapDefault) {
return <SwapDefaultDemo />;
}

return <></>;
}

Expand Down
118 changes: 118 additions & 0 deletions playground/nextjs-app-router/components/demo/SwapDefault.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { ENVIRONMENT, ENVIRONMENT_VARIABLES } from '@/lib/constants';
import { type LifecycleStatus, SwapDefault } from '@coinbase/onchainkit/swap';
import type { SwapError } from '@coinbase/onchainkit/swap';
import type { Token } from '@coinbase/onchainkit/token';
import { useCallback, useContext } from 'react';
import type { TransactionReceipt } from 'viem';
import { base } from 'viem/chains';
import { AppContext } from '../AppProvider';

const DEFAULT_MAX_SLIPPAGE = 3;

function SwapDefaultComponent() {
const { chainId, defaultMaxSlippage, paymasters } = useContext(AppContext);

const degenToken: Token = {
name: 'DEGEN',
address: '0x4ed4e862860bed51a9570b96d89af5e1b0efefed',
symbol: 'DEGEN',
decimals: 18,
image:
'https://d3r81g40ycuhqg.cloudfront.net/wallet/wais/3b/bf/3bbf118b5e6dc2f9e7fc607a6e7526647b4ba8f0bea87125f971446d57b296d2-MDNmNjY0MmEtNGFiZi00N2I0LWIwMTItMDUyMzg2ZDZhMWNm',
chainId: base.id,
};

const ethToken: Token = {
name: 'ETH',
address: '',
symbol: 'ETH',
decimals: 18,
image:
'https://wallet-api-production.s3.amazonaws.com/uploads/tokens/eth_288.png',
chainId: base.id,
};

const usdcToken: Token = {
name: 'USDC',
address: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
symbol: 'USDC',
decimals: 6,
image:
'https://d3r81g40ycuhqg.cloudfront.net/wallet/wais/44/2b/442b80bd16af0c0d9b22e03a16753823fe826e5bfd457292b55fa0ba8c1ba213-ZWUzYjJmZGUtMDYxNy00NDcyLTg0NjQtMWI4OGEwYjBiODE2',
chainId: base.id,
};

const wethToken: Token = {
name: 'Wrapped Ether',
address: '0x4200000000000000000000000000000000000006',
symbol: 'WETH',
decimals: 6,
image:
'https://d3r81g40ycuhqg.cloudfront.net/wallet/wais/47/bc/47bc3593c2dec7c846b66b7ba5f6fa6bd69ec34f8ebb931f2a43072e5aaac7a8-YmUwNmRjZDUtMjczYy00NDFiLWJhZDUtMzgwNjFmYWM0Njkx',
chainId: base.id,
};

const to = [ethToken, degenToken, usdcToken, wethToken];
const from = [usdcToken, degenToken, ethToken, wethToken];

const handleOnStatus = useCallback((lifecycleStatus: LifecycleStatus) => {
console.log('Status:', lifecycleStatus);
}, []);

const handleOnSuccess = useCallback(
(transactionReceipt: TransactionReceipt) => {
console.log('Success:', transactionReceipt);
},
[],
);

const handleOnError = useCallback((swapError: SwapError) => {
console.log('Error:', swapError);
}, []);

return (
<div className="relative flex h-full w-full flex-col items-center">
{chainId !== base.id ? (
<div className="absolute top-0 left-0 z-10 flex h-full w-full flex-col justify-center rounded-xl bg-[#000000] bg-opacity-50 text-center">
<div className="mx-auto w-2/3 rounded-md bg-muted p-6 text-sm">
Swap Demo is only available on Base.
<br />
You're connected to a different network. Switch to Base to continue
using the app.
</div>
</div>
) : (
<></>
)}

{ENVIRONMENT_VARIABLES[ENVIRONMENT.ENVIRONMENT] === 'production' &&
chainId === base.id ? (
<div className="mb-5 italic">
Note: Swap is disabled on production. To test, run the app locally.
</div>
) : null}

<SwapDefault
config={{ maxSlippage: defaultMaxSlippage || DEFAULT_MAX_SLIPPAGE }}
className="border"
disabled={
ENVIRONMENT_VARIABLES[ENVIRONMENT.ENVIRONMENT] === 'production'
}
from={from}
isSponsored={paymasters != null}
onError={handleOnError}
onStatus={handleOnStatus}
onSuccess={handleOnSuccess}
to={to}
/>
</div>
);
}

export default function SwapDefaultDemo() {
return (
<div className="mx-auto">
<SwapDefaultComponent />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export function ActiveComponent() {
Transaction
</SelectItem>
<SelectItem value={OnchainKitComponent.Swap}>Swap</SelectItem>
<SelectItem value={OnchainKitComponent.SwapDefault}>
SwapDefault
</SelectItem>
<SelectItem value={OnchainKitComponent.Wallet}>Wallet</SelectItem>
</SelectContent>
</Select>
Expand Down
5 changes: 4 additions & 1 deletion src/swap/components/SwapButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export function SwapButton({ className, disabled = false }: SwapButtonReact) {
disabled ||
isLoading;

// disable swap if to and from token are the same
const isSwapInvalid = to.token?.address === from.token?.address;

// prompt user to connect wallet
if (!isDisabled && !address) {
return <ConnectWallet className="mt-4 w-full" />;
Expand All @@ -44,7 +47,7 @@ export function SwapButton({ className, disabled = false }: SwapButtonReact) {
className,
)}
onClick={() => handleSubmit()}
disabled={isDisabled}
disabled={isDisabled || isSwapInvalid}
data-testid="ockSwapButton_Button"
>
{isLoading ? (
Expand Down
63 changes: 63 additions & 0 deletions src/swap/components/SwapDefault.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { SwapDefaultReact } from '../types';
import { Swap } from './Swap';
import { SwapAmountInput } from './SwapAmountInput';
import { SwapButton } from './SwapButton';
import { SwapMessage } from './SwapMessage';
import { SwapSettings } from './SwapSettings';
import { SwapSettingsSlippageDescription } from './SwapSettingsSlippageDescription';
import { SwapSettingsSlippageInput } from './SwapSettingsSlippageInput';
import { SwapSettingsSlippageTitle } from './SwapSettingsSlippageTitle';
import { SwapToast } from './SwapToast';
import { SwapToggleButton } from './SwapToggleButton';

export function SwapDefault({
config,
className,
disabled,
experimental,
from,
isSponsored = false,
onError,
onStatus,
onSuccess,
title = 'Swap',
to,
}: SwapDefaultReact) {
return (
<Swap
className={className}
onStatus={onStatus}
onSuccess={onSuccess}
onError={onError}
config={config}
isSponsored={isSponsored}
title={title}
experimental={experimental}
>
<SwapSettings>
<SwapSettingsSlippageTitle>Max. slippage</SwapSettingsSlippageTitle>
<SwapSettingsSlippageDescription>
Your swap will revert if the prices change by more than the selected
percentage.
</SwapSettingsSlippageDescription>
<SwapSettingsSlippageInput />
</SwapSettings>
<SwapAmountInput
label="Sell"
swappableTokens={from}
token={from?.[0]}
type="from"
/>
<SwapToggleButton />
<SwapAmountInput
label="Buy"
swappableTokens={to}
token={to?.[0]}
type="to"
/>
<SwapButton disabled={disabled} />
<SwapMessage />
<SwapToast />
</Swap>
);
}
1 change: 1 addition & 0 deletions src/swap/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
export { Swap } from './components/Swap';
export { SwapAmountInput } from './components/SwapAmountInput';
export { SwapButton } from './components/SwapButton';
export { SwapDefault } from './components/SwapDefault';
export { SwapMessage } from './components/SwapMessage';
export { SwapSettings } from './components/SwapSettings';
export { SwapSettingsSlippageDescription } from './components/SwapSettingsSlippageDescription';
Expand Down
9 changes: 9 additions & 0 deletions src/swap/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,15 @@ export type SwapReact = {
title?: string; // Title for the Swap component. (default: "Swap")
};

/**
* Note: exported as public Type
*/
export type SwapDefaultReact = {
to: Token[]; // Swappable tokens
from: Token[]; // Swappable tokens
disabled?: boolean; // Disables swap button
} & Omit<SwapReact, 'children'>;

/**
* Note: exported as public Type
*/
Expand Down

0 comments on commit 231197f

Please sign in to comment.