Skip to content

Commit

Permalink
fix: integration issues (#170)
Browse files Browse the repository at this point in the history
* fix: prevent spurious rerenders

* feat: export more types

* feat: more permissive jsonRpcUrlMap type

* fix: export Currency

* fix: permissive jsonRpcUrlMap

* fix: max slippage as string

* fix: popper max size

* fix: permissive jsonRpcUrlMap

* fix: export trade type

* fix: annotate maxWidth

* fix: omit unnecessary jsonRpcUrlMap type

* fix: fallback chain id warnings

* fix: clarify jsonRpcUrlMap mutations

* test: make jsonRpcUrlMap test more explicit
  • Loading branch information
zzmp authored Aug 25, 2022
1 parent cd6265c commit d4c05ba
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 31 deletions.
12 changes: 12 additions & 0 deletions e2e/connect.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ describe('connect', () => {
tokenSelect = (await component.findAllByTestId('token-select'))[0]
await waitFor(() => expect(tokenSelect).toHaveProperty('disabled', false))
})

describe('with singleton jsonRpcUrlMap', () => {
it('expects widget not to be disabled', async () => {
const component = renderWidget(<SwapWidget tokenList={tokens} jsonRpcUrlMap={{ 1: hardhat.url }} />)
let tokenSelect = (await component.findAllByTestId('token-select'))[0]
expect(tokenSelect).toHaveProperty('disabled', true)
const toolbar = await component.findByTestId('toolbar')
await waitFor(() => expect(toolbar.textContent).not.toBe('Connecting…'))
tokenSelect = (await component.findAllByTestId('token-select'))[0]
await waitFor(() => expect(tokenSelect).toHaveProperty('disabled', false))
})
})
})

describe('with wallet provider', () => {
Expand Down
4 changes: 3 additions & 1 deletion src/components/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,11 @@ export default function Popover({ content, show, children, placement, offset, co
requires: ['maxSize'],
fn({ state }) {
const { width } = state.modifiersData.maxSize
// width is sometimes too small, so expand it to the clientWidth:
const maxWidth = Math.max(width, (boundary?.clientWidth ?? 16) - 16)
state.styles.popper = {
...state.styles.popper,
maxWidth: `${width}px`,
maxWidth: `${maxWidth}px`,
}
},
}
Expand Down
5 changes: 2 additions & 3 deletions src/components/Swap/Settings/MaxSlippageSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,8 @@ export default function MaxSlippageSelect() {
}, [focus, slippage, setSlippage])

const processInput = useCallback(
(input: string | undefined) => {
setMaxSlippageInput(input || '')
const max = input ? +input : undefined
(max: string | undefined) => {
setMaxSlippageInput(max || '')
const percent = toPercent(max)
const warning = getSlippageWarning(percent)
const auto = !percent || warning === 'error'
Expand Down
2 changes: 1 addition & 1 deletion src/components/Swap/Settings/TransactionTtlInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default function TransactionTtlInput() {
<IntegerInput
placeholder={placeholder}
value={ttl?.toString() ?? ''}
onChange={(value) => setTtl(value ? parseFloat(value) : 0)}
onChange={(value) => setTtl(value ? parseFloat(value) : undefined)}
size={Math.max(ttl?.toString().length || 0, placeholder.length)}
ref={input}
/>
Expand Down
24 changes: 16 additions & 8 deletions src/components/Widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export interface WidgetProps extends BrandingSettings, TransactionEventHandlers
theme?: Theme
locale?: SupportedLocale
provider?: Eip1193Provider | JsonRpcProvider
jsonRpcUrlMap?: { [chainId: number]: string[] }
jsonRpcUrlMap?: { [chainId: number]: string | string[] }
defaultChainId?: SupportedChainId
tokenList?: string | TokenInfo[]
width?: string | number
Expand Down Expand Up @@ -139,22 +139,30 @@ export function TestableWidget(props: PropsWithChildren<TestableWidgetProps>) {
const defaultChainId = useMemo(() => {
if (!props.defaultChainId) return DEFAULT_CHAIN_ID
if (!ALL_SUPPORTED_CHAIN_IDS.includes(props.defaultChainId)) {
console.warn(`Unsupported chainId: ${props.defaultChainId}. Falling back to 1 (Ethereum Mainnet).`)
console.warn(
`Unsupported chainId: ${props.defaultChainId}. Falling back to ${DEFAULT_CHAIN_ID} (${SupportedChainId[DEFAULT_CHAIN_ID]}).`
)
return DEFAULT_CHAIN_ID
}
return props.defaultChainId
}, [props.defaultChainId])
const jsonRpcUrlMap: string | JsonRpcProvider | { [chainId: number]: string[] } = useMemo(() => {
const jsonRpcUrlMapWithFallbacks = useMemo(() => {
if (!props.jsonRpcUrlMap) return JSON_RPC_FALLBACK_ENDPOINTS
const fallbackChains: [string, string[]][] = []
for (const supportedChainId of ALL_SUPPORTED_CHAIN_IDS) {
if (!Object.keys(props.jsonRpcUrlMap).includes(`${supportedChainId}`)) {
const fallbackRpc = JSON_RPC_FALLBACK_ENDPOINTS[supportedChainId as number]
console.warn(
`Did not provide a jsonRpcUrlMap for chainId: ${supportedChainId}. Falling back to public RPC endpoint ${fallbackRpc}, which may be unreliable and severly rate-limited.`
)
const chainId: number = supportedChainId
const fallbackRpc = JSON_RPC_FALLBACK_ENDPOINTS[chainId]
fallbackChains.push([SupportedChainId[chainId], fallbackRpc])
props.jsonRpcUrlMap[supportedChainId as number] = fallbackRpc
}
}
if (fallbackChains.length) {
console.warn(
`jsonRpcUrlMap is missing urls for some chains. Falling back to public endpoints, which may be unreliable and severely rate-limited:`,
...fallbackChains.map(([chain, urls]) => `${chain}: ${urls}`)
)
}
return props.jsonRpcUrlMap
}, [props.jsonRpcUrlMap])

Expand All @@ -171,7 +179,7 @@ export function TestableWidget(props: PropsWithChildren<TestableWidgetProps>) {
<AtomProvider initialValues={props.initialAtomValues}>
<ActiveWeb3Provider
provider={props.provider}
jsonRpcUrlMap={jsonRpcUrlMap}
jsonRpcUrlMap={jsonRpcUrlMapWithFallbacks}
defaultChainId={defaultChainId}
>
<BlockNumberProvider>
Expand Down
26 changes: 18 additions & 8 deletions src/hooks/connectWeb3/useWeb3React.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,36 +64,46 @@ function getConnectionFromWalletConnect(
)
}

const onError = (error: Error) => console.error(error)

interface ActiveWeb3ProviderProps {
provider?: Eip1193Provider | JsonRpcProvider
jsonRpcUrlMap: { [chainId: number]: string[] }
jsonRpcUrlMap: { [chainId: number]: string | string[] }
defaultChainId: SupportedChainId
}

export function ActiveWeb3Provider({
provider,
jsonRpcUrlMap,
jsonRpcUrlMap: propsJsonRpcUrlMap,
defaultChainId: propsDefaultChainId,
provider,
children,
}: PropsWithChildren<ActiveWeb3ProviderProps>) {
const onError = console.error
const jsonRpcUrlMap = useMemo(
() =>
Object.entries(propsJsonRpcUrlMap).reduce(
(urlMap, [id, urls]) => ({ ...urlMap, [id]: Array.isArray(urls) ? urls : [urls] }),
{}
),
[propsJsonRpcUrlMap]
)

const [defaultChainId, setDefaultChainId] = useAtom(defaultChainIdAtom)
useEffect(() => {
if (propsDefaultChainId !== defaultChainId) setDefaultChainId(propsDefaultChainId)
}, [propsDefaultChainId, defaultChainId, setDefaultChainId])

const integratorConnection = useMemo(() => getConnectionFromProvider(onError, provider), [onError, provider])
const integratorConnection = useMemo(() => getConnectionFromProvider(onError, provider), [provider])
const metaMaskConnection = useMemo(
() => toWeb3Connection(initializeConnector<MetaMask>((actions) => new MetaMask({ actions, onError }))),
[onError]
[]
)
const walletConnectConnectionQR = useMemo(
() => getConnectionFromWalletConnect(false, jsonRpcUrlMap, defaultChainId, onError),
[jsonRpcUrlMap, defaultChainId, onError]
[jsonRpcUrlMap, defaultChainId]
) // WC via tile QR code scan
const walletConnectConnectionPopup = useMemo(
() => getConnectionFromWalletConnect(true, jsonRpcUrlMap, defaultChainId, onError),
[jsonRpcUrlMap, defaultChainId, onError]
[jsonRpcUrlMap, defaultChainId]
) // WC via built-in popup

const networkConnection = useMemo(
Expand Down
16 changes: 10 additions & 6 deletions src/hooks/transactions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,14 @@ export function usePendingApproval(token?: Token, spender?: string): string | un
)?.info.response.hash
}

export type OnTxSubmit = (hash: string, tx: Transaction) => void
export type OnTxSuccess = (hash: string, receipt: TransactionReceipt) => void
export type OnTxFail = (hash: string, receipt: TransactionReceipt) => void

export interface TransactionEventHandlers {
onTxSubmit?: (txHash: string, tx: Transaction) => void
onTxSuccess?: (txHash: string, receipt: TransactionReceipt) => void
onTxFail?: (error: Error, receipt: TransactionReceipt) => void
onTxSubmit?: OnTxSubmit
onTxSuccess?: OnTxSuccess
onTxFail?: OnTxFail
}

export function TransactionsUpdater({ onTxSubmit, onTxSuccess, onTxFail }: TransactionEventHandlers) {
Expand All @@ -91,10 +95,10 @@ export function TransactionsUpdater({ onTxSubmit, onTxSuccess, onTxFail }: Trans
tx.receipt = receipt
}
})
if (receipt?.status === 0) {
onTxFail?.(new Error('Transaction failed'), receipt)
if (receipt.status === 0) {
onTxFail?.(hash, receipt)
} else {
onTxSuccess?.(receipt.transactionHash, receipt)
onTxSuccess?.(hash, receipt)
}
},
[updateTxs, onTxFail, onTxSuccess]
Expand Down
5 changes: 3 additions & 2 deletions src/hooks/useSlippage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { useMemo } from 'react'
import { InterfaceTrade } from 'state/routing/types'
import { slippageAtom } from 'state/swap/settings'

export function toPercent(maxSlippage: number | undefined): Percent | undefined {
export function toPercent(maxSlippage: string | undefined): Percent | undefined {
if (!maxSlippage) return undefined
const numerator = Math.floor(maxSlippage * 100)
if (Number.isNaN(maxSlippage)) return undefined
const numerator = Math.floor(Number(maxSlippage) * 100)
return new Percent(numerator, 10_000)
}

Expand Down
4 changes: 3 additions & 1 deletion src/hooks/useSyncWidgetEventHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { useUpdateAtom } from 'jotai/utils'
import { useEffect } from 'react'
import { onConnectWalletClickAtom } from 'state/wallet'

export type OnConnectWalletClick = () => void | Promise<boolean>

export interface WidgetEventHandlers {
onConnectWalletClick?: () => void | Promise<boolean>
onConnectWalletClick?: OnConnectWalletClick
}

export default function useSyncWidgetEventHandlers({ onConnectWalletClick }: WidgetEventHandlers): void {
Expand Down
18 changes: 18 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,32 @@ import 'polyfills'
import Swap, { SwapProps } from 'components/Swap'
import Widget, { WidgetProps } from 'components/Widget'
export type { Provider as EthersProvider } from '@ethersproject/abstract-provider'
export type { Currency, TradeType } from '@uniswap/sdk-core'
export type { TokenInfo } from '@uniswap/token-lists'
export type { Provider as Eip1193Provider } from '@web3-react/types'
export type { ErrorHandler } from 'components/Error/ErrorBoundary'
export { SupportedChainId } from 'constants/chains'
export type { SupportedLocale } from 'constants/locales'
export { DEFAULT_LOCALE, SUPPORTED_LOCALES } from 'constants/locales'
export type { SwapController } from 'hooks/swap/useSyncController'
export type { SwapSettingsController } from 'hooks/swap/useSyncController'
export type { FeeOptions } from 'hooks/swap/useSyncConvenienceFee'
export type { DefaultAddress, TokenDefaults } from 'hooks/swap/useSyncTokenDefaults'
export type { OnTxFail, OnTxSubmit, OnTxSuccess, TransactionEventHandlers } from 'hooks/transactions'
export type { OnConnectWalletClick, WidgetEventHandlers } from 'hooks/useSyncWidgetEventHandlers'
export type {
Field,
OnAmountChange,
OnReviewSwapClick,
OnSettingsReset,
OnSlippageChange,
OnSwitchTokens,
OnTokenChange,
OnTokenSelectorClick,
OnTransactionDeadlineChange,
SwapEventHandlers,
} from 'state/swap'
export type { Slippage } from 'state/swap/settings'
export type { Theme } from 'theme'
export { darkTheme, defaultTheme, lightTheme } from 'theme'

Expand Down
2 changes: 1 addition & 1 deletion src/state/swap/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { pickAtom } from '../atoms'

export interface Slippage {
auto: boolean // if true, slippage will use the default calculation
max: number | undefined // expressed as a percent (eg 0.42 is 0.42%)
max: string | undefined // expressed as a percent (eg '0.42' is 0.42%)
}

export interface Settings {
Expand Down

1 comment on commit d4c05ba

@vercel
Copy link

@vercel vercel bot commented on d4c05ba Aug 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

widgets – ./

widgets-seven-tau.vercel.app
widgets-uniswap.vercel.app
widgets-git-main-uniswap.vercel.app

Please sign in to comment.