-
Notifications
You must be signed in to change notification settings - Fork 192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Swap component refactor #522
Merged
Merged
Changes from 18 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
d32e47c
add swap component
abcrane123 2113b5f
update swap component types
abcrane123 eb7776e
update docs
abcrane123 c2fae82
add onsubmit
abcrane123 5cd8a44
refactor swap component
abcrane123 fbafe15
continue refactor
abcrane123 cb4a4f8
update type
abcrane123 e92d617
remove unused code
abcrane123 a284173
fix type
abcrane123 fd80163
add comment and fix type
abcrane123 76fd5b6
temp commit
abcrane123 e2f94c1
simplify and refactor
abcrane123 7b4ee10
update docs
abcrane123 a1d60e6
address pr comments
abcrane123 1906bd5
cleanup types
abcrane123 8b4ce11
expand funtionality and add onsuccess / onerror
abcrane123 0f76402
update imports
abcrane123 15aa579
address pr comments
abcrane123 54ffb47
move func to utils
abcrane123 dc7899c
enable quote for from and to token
abcrane123 e8378d9
move handleSubmit to SwapButton
abcrane123 9e0a929
refactor swap quote into hook
abcrane123 34fc7f4
remove error handling
abcrane123 0823347
remove useCallback and update types
abcrane123 4eebdfb
cleanup hook
abcrane123 0c0c4b3
refactor swap quote
abcrane123 0b6e86b
reorder types
abcrane123 8057359
rename SwapAmountInput and remove old version
abcrane123 2adc86c
add tests
abcrane123 16ae400
update docs
abcrane123 79ba44b
remove imports
abcrane123 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { Swap, SwapAmountInputV2, SwapButton } from '../../../../src/swap'; | ||
import App from '../App'; | ||
|
||
# `<Swap />` | ||
|
||
The `Swap` component is a comprehensive interface for users to execute token swaps. It includes two instances of the `SwapAmountInputV2` component, enabling users to specify the amount of tokens to sell and buy. Additionally, the component features a "Swap" button for initiating the transaction. | ||
|
||
## Usage | ||
|
||
```tsx [code] | ||
<Swap account={account} onError={onError} onSuccess={onSuccess}> | ||
<SwapAmountInputV2 label="Sell" token={fromToken} type="from" /> | ||
<SwapAmountInputV2 label="Buy" token={toToken} type="to" /> | ||
<SwapButton /> | ||
</Swap> | ||
``` | ||
|
||
<App> | ||
<Swap> | ||
<SwapAmountInputV2 | ||
label="Sell" | ||
token={{ | ||
name: 'Ethereum', | ||
address: '', | ||
symbol: 'ETH', | ||
decimals: 18, | ||
image: 'https://wallet-api-production.s3.amazonaws.com/uploads/tokens/eth_288.png', | ||
chainId: 8453, | ||
}} | ||
type="from" | ||
/> | ||
<SwapAmountInputV2 | ||
label="Buy" | ||
token={{ | ||
name: 'USDC', | ||
address: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', | ||
symbol: 'USDC', | ||
decimals: 6, | ||
image: | ||
'https://d3r81g40ycuhqg.cloudfront.net/wallet/wais/44/2b/442b80bd16af0c0d9b22e03a16753823fe826e5bfd457292b55fa0ba8c1ba213-ZWUzYjJmZGUtMDYxNy00NDcyLTg0NjQtMWI4OGEwYjBiODE2', | ||
chainId: 8453, | ||
}} | ||
type="to" | ||
/> | ||
<SwapButton /> | ||
</Swap> | ||
</App> | ||
|
||
## Props | ||
|
||
[`SwapReact`](/swap/types#SwapReact) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { useCallback, useEffect, useMemo, useState } from 'react'; | ||
import { buildSwapTransaction } from '../core/buildSwapTransaction'; | ||
import { getSwapQuote } from '../core/getSwapQuote'; | ||
import { cn } from '../../lib/utils'; | ||
import { SwapContext } from '../context'; | ||
import type { SwapError, SwapReact } from '../types'; | ||
import type { Token } from '../../token'; | ||
|
||
function isSwapError(response: unknown): response is SwapError { | ||
return response !== null && typeof response === 'object' && 'error' in response; | ||
} | ||
|
||
export function Swap({ account, children, onError, onSuccess }: SwapReact) { | ||
const [fromAmount, setFromAmount] = useState(''); | ||
const [fromToken, setFromToken] = useState<Token>(); | ||
const [toAmount, setToAmount] = useState(''); | ||
const [toToken, setToToken] = useState<Token>(); | ||
const [swapQuoteError, setSwapQuoteError] = useState(''); | ||
const [swapTransactionError, setSwapTransactionError] = useState(''); | ||
|
||
const handleSubmit = useCallback(async () => { | ||
setSwapQuoteError(''); | ||
setSwapTransactionError(''); | ||
if (account && fromToken && toToken && fromAmount) { | ||
try { | ||
const response = await buildSwapTransaction({ | ||
amount: fromAmount, | ||
fromAddress: account.address, | ||
from: fromToken, | ||
to: toToken, | ||
}); | ||
if (isSwapError(response)) { | ||
setSwapTransactionError(response.error); | ||
onError?.(response); | ||
} else { | ||
onSuccess?.(response); | ||
} | ||
} catch (error) { | ||
onError?.(error as SwapError); | ||
} | ||
} | ||
}, [account, fromAmount, fromToken, toToken]); | ||
|
||
const handleGetSwapQuote = useCallback(async () => { | ||
setSwapQuoteError(''); | ||
setSwapTransactionError(''); | ||
if (fromToken && toToken && fromAmount) { | ||
try { | ||
const response = await getSwapQuote({ from: fromToken, to: toToken, amount: fromAmount }); | ||
if (isSwapError(response)) { | ||
setSwapQuoteError(response.error); | ||
} else { | ||
setToAmount(response?.toAmount); | ||
} | ||
} catch (error) { | ||
onError?.(error as SwapError); | ||
} | ||
} | ||
}, [fromAmount, fromToken, toToken]); | ||
|
||
useEffect(() => { | ||
if (fromToken && toToken && fromAmount) { | ||
handleGetSwapQuote(); | ||
} | ||
}, [fromAmount, fromToken, toToken]); | ||
|
||
const value = useMemo(() => { | ||
return { | ||
fromAmount, | ||
fromToken, | ||
onSubmit: handleSubmit, | ||
setFromAmount, | ||
setFromToken, | ||
setToAmount, | ||
setToToken, | ||
toAmount, | ||
toToken, | ||
}; | ||
}, [ | ||
fromAmount, | ||
fromToken, | ||
handleSubmit, | ||
setFromAmount, | ||
setToAmount, | ||
setToToken, | ||
toAmount, | ||
toToken, | ||
]); | ||
|
||
return ( | ||
<SwapContext.Provider value={value}> | ||
<div className="flex w-[400px] flex-col rounded-xl bg-white"> | ||
<label | ||
className={cn( | ||
'box-border w-full border-b border-solid p-4 text-base', | ||
'font-semibold leading-6 text-[#030712]', | ||
)} | ||
> | ||
Swap | ||
</label> | ||
{(swapQuoteError || swapTransactionError) && ( | ||
<p className={cn('p-4 text-center text-[14px] text-[red]')}> | ||
{swapQuoteError || swapTransactionError} | ||
</p> | ||
)} | ||
{children} | ||
</div> | ||
</SwapContext.Provider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { useCallback, useContext, useEffect, useMemo } from 'react'; | ||
|
||
import { isValidAmount } from '../utils'; | ||
import { TokenChip } from '../../token'; | ||
import { cn } from '../../lib/utils'; | ||
import { SwapContext } from '../context'; | ||
import type { SwapAmountInputReact } from '../types'; | ||
|
||
export function SwapAmountInputV2({ label, token, type }: SwapAmountInputReact) { | ||
const { fromAmount, setFromAmount, setFromToken, setToAmount, setToToken, toAmount } = | ||
useContext(SwapContext); | ||
|
||
const amount = useMemo(() => { | ||
if (type === 'to') { | ||
return toAmount; | ||
} | ||
return fromAmount; | ||
}, [type, toAmount, fromAmount]); | ||
|
||
const setAmount = useMemo(() => { | ||
if (type === 'to') { | ||
return setToAmount; | ||
} | ||
return setFromAmount; | ||
}, [type, setToAmount, setFromAmount]); | ||
|
||
const setToken = useMemo(() => { | ||
if (type === 'to') { | ||
return setToToken; | ||
} | ||
return setFromToken; | ||
}, [type, setFromToken, setToToken]); | ||
|
||
useEffect(() => { | ||
if (token) { | ||
setToken(token); | ||
} | ||
}, [token]); | ||
|
||
const handleAmountChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => { | ||
if (isValidAmount(event.target.value)) { | ||
setAmount?.(event.target.value); | ||
} | ||
}, []); | ||
|
||
return ( | ||
<div | ||
className={cn( | ||
'box-border flex w-full flex-col items-start', | ||
'gap-[11px] border-b border-solid bg-[#FFF] p-4', | ||
)} | ||
data-testid="ockSwapAmountInput_Container" | ||
> | ||
<div className="flex w-full items-center justify-between"> | ||
<label className="text-sm font-semibold text-[#030712]">{label}</label> | ||
</div> | ||
<div className="flex w-full items-center justify-between"> | ||
<TokenChip token={token} /> | ||
</div> | ||
<input | ||
className="w-full border-[none] bg-transparent text-5xl text-[black]" | ||
data-testid="ockSwapAmountInput_Input" | ||
onChange={handleAmountChange} | ||
placeholder="0" | ||
value={amount} | ||
/> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { useCallback, useContext } from 'react'; | ||
import { cn } from '../../lib/utils'; | ||
import { SwapContext } from '../context'; | ||
|
||
export function SwapButton() { | ||
const { onSubmit, fromAmount, fromToken, toAmount, toToken } = useContext(SwapContext); | ||
|
||
const handleSubmit = useCallback(() => { | ||
onSubmit(); | ||
}, [onSubmit]); | ||
|
||
return ( | ||
<div className="w-full p-4"> | ||
<button | ||
className={cn( | ||
'w-full rounded-[100px] bg-blue-700', | ||
'px-4 py-3 text-base font-medium leading-6 text-white', | ||
)} | ||
onClick={handleSubmit} | ||
disabled={!fromAmount || !fromToken || !toAmount || !toToken} | ||
> | ||
Swap | ||
</button> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { createContext } from 'react'; | ||
import { SwapContextType } from './types'; | ||
|
||
export const SwapContext = createContext<SwapContextType>({ | ||
fromAmount: '', | ||
setFromAmount: () => {}, | ||
toAmount: '', | ||
setToAmount: () => {}, | ||
account: undefined, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move utils in their own file.