diff --git a/examples/deposit-flow/src/App.tsx b/examples/deposit-flow/src/App.tsx
index 727a9ad74..4888e834b 100644
--- a/examples/deposit-flow/src/App.tsx
+++ b/examples/deposit-flow/src/App.tsx
@@ -4,19 +4,14 @@ import {
CoinKey,
DisabledUI,
HiddenUI,
- ItemPrice,
LiFiWidget,
} from '@lifi/widget'
import { useMemo } from 'react'
+import { DepositCard } from './components/DepositCard'
+import { contractTool } from './config'
-const depositAddress = '0xdde759c7cf032b1d0e633a7e9cfa6653d1911a22'
-const depositAmount = 5000000n
-
-export const contractTool = {
- logoURI:
- 'https://github.com/lifinance/widget/assets/18644653/eb043a91-18ba-4da7-91c4-029a53a25989',
- name: 'Immutable',
-}
+// EXAMPLE CONTRACT, DON'T DEPOSIT
+const depositAddress = '0x4bF3E32de155359D1D75e8B474b66848221142fc'
const contractCalls: ContractCall[] = []
@@ -30,7 +25,7 @@ export function App() {
},
subvariant: 'custom',
subvariantOptions: { custom: 'deposit' },
- integrator: 'Immutable',
+ integrator: 'ProtocolName',
disabledUI: [DisabledUI.ToAddress],
hiddenUI: [HiddenUI.Appearance, HiddenUI.Language],
useRecommendedRoute: true,
@@ -47,7 +42,7 @@ export function App() {
return (
diff --git a/examples/deposit-flow/src/components/DepositCard.tsx b/examples/deposit-flow/src/components/DepositCard.tsx
new file mode 100644
index 000000000..c3b1fac6d
--- /dev/null
+++ b/examples/deposit-flow/src/components/DepositCard.tsx
@@ -0,0 +1,84 @@
+import {
+ type ContractCall,
+ type TokenAmount,
+ useFieldActions,
+} from '@lifi/widget'
+import { Avatar, Box, Chip, Stack, Typography } from '@mui/material'
+import { useEffect } from 'react'
+import { contractTool } from '../config'
+
+export interface ItemPriceProps {
+ token: TokenAmount
+ contractCalls?: ContractCall[]
+}
+
+export const DepositCard: React.FC = ({
+ token,
+ contractCalls,
+}) => {
+ const { setFieldValue } = useFieldActions()
+
+ useEffect(() => {
+ if (token) {
+ setFieldValue('toChain', token.chainId, { isTouched: true })
+ setFieldValue('toToken', token.address, { isTouched: true })
+ }
+ if (contractCalls) {
+ setFieldValue('contractCalls', contractCalls, {
+ isTouched: true,
+ })
+ }
+ }, [contractCalls, setFieldValue, token])
+ return (
+
+
+
+
+ Protocol Name
+
+
+
+
+ TVL
+
+ $69M
+
+
+
+ Incentives
+
+ $4.2M
+
+
+
+
+ } />
+
+ }
+ />
+
+
+ )
+}
diff --git a/examples/deposit-flow/src/config.ts b/examples/deposit-flow/src/config.ts
new file mode 100644
index 000000000..4aa4da344
--- /dev/null
+++ b/examples/deposit-flow/src/config.ts
@@ -0,0 +1,4 @@
+export const contractTool = {
+ logoURI: 'https://gravatar.com/avatar/any?d=wavatar',
+ name: 'Protocol Name',
+}
diff --git a/examples/deposit-flow/src/main.tsx b/examples/deposit-flow/src/main.tsx
index daaa3ad04..fd76452db 100644
--- a/examples/deposit-flow/src/main.tsx
+++ b/examples/deposit-flow/src/main.tsx
@@ -2,7 +2,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import React from 'react'
import ReactDOM from 'react-dom/client'
import { http, WagmiProvider, createConfig } from 'wagmi'
-import { base, mainnet } from 'wagmi/chains'
+import { arbitrum, base, mainnet, optimism } from 'wagmi/chains'
import { injected } from 'wagmi/connectors'
import { App } from './App'
import { WalletHeader } from './components/WalletHeader'
@@ -12,11 +12,13 @@ const queryClient = new QueryClient()
const _projectId = import.meta.env.VITE_WALLET_CONNECT_PROJECT_ID
const config = createConfig({
- chains: [mainnet],
+ chains: [mainnet, base, optimism, arbitrum],
connectors: [injected()],
transports: {
[mainnet.id]: http(),
[base.id]: http(),
+ [optimism.id]: http(),
+ [arbitrum.id]: http(),
},
})
diff --git a/package.json b/package.json
index acc6b2690..f1cfee050 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "version": "3.12.6-alpha.0",
+ "version": "3.12.6-beta.0",
"private": true,
"sideEffects": false,
"type": "module",
diff --git a/packages/wallet-management/package.json b/packages/wallet-management/package.json
index da3904f97..987855618 100644
--- a/packages/wallet-management/package.json
+++ b/packages/wallet-management/package.json
@@ -1,6 +1,6 @@
{
"name": "@lifi/wallet-management",
- "version": "3.4.8-alpha.0",
+ "version": "3.4.8-beta.0",
"description": "LI.FI Wallet Management solution.",
"type": "module",
"main": "./src/index.ts",
diff --git a/packages/wallet-management/src/i18n/i18next.d.ts b/packages/wallet-management/src/i18n/i18next.d.ts
index 49e267140..ada8de6c2 100644
--- a/packages/wallet-management/src/i18n/i18next.d.ts
+++ b/packages/wallet-management/src/i18n/i18next.d.ts
@@ -2,13 +2,9 @@ import en from './en.json' with { type: 'json' }
const defaultResource = { translation: en }
-declare global {
- namespace WalletTranslation {
- declare module 'i18next' {
- interface CustomTypeOptions {
- defaultNS: 'translation'
- resources: typeof defaultResource
- }
- }
+declare module 'i18next' {
+ interface CustomTypeOptions {
+ defaultNS: 'translation'
+ resources: typeof defaultResource
}
}
diff --git a/packages/widget-embedded/src/config.ts b/packages/widget-embedded/src/config.ts
index cb0366583..c30152f8c 100644
--- a/packages/widget-embedded/src/config.ts
+++ b/packages/widget-embedded/src/config.ts
@@ -3,6 +3,7 @@ import './index.css'
export const widgetBaseConfig: WidgetConfig = {
subvariant: 'custom',
+
integrator: 'li.fi-playground',
hiddenUI: ['history'],
// buildUrl: true,
diff --git a/packages/widget/package.json b/packages/widget/package.json
index 40cf81e08..4b44eabb0 100644
--- a/packages/widget/package.json
+++ b/packages/widget/package.json
@@ -1,6 +1,6 @@
{
"name": "@lifi/widget",
- "version": "3.12.6-alpha.0",
+ "version": "3.12.6-beta.0",
"description": "LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.",
"type": "module",
"main": "./src/index.ts",
diff --git a/packages/widget/src/components/AmountInput/AmountInput.tsx b/packages/widget/src/components/AmountInput/AmountInput.tsx
index 603a9f42d..2ac23a3f6 100644
--- a/packages/widget/src/components/AmountInput/AmountInput.tsx
+++ b/packages/widget/src/components/AmountInput/AmountInput.tsx
@@ -70,6 +70,7 @@ export const AmountInputBase: React.FC<
...props
}) => {
const { t } = useTranslation()
+ const { subvariant, subvariantOptions } = useWidgetConfig()
const ref = useRef(null)
const amountKey = FormKeyHelper.getAmountKey(formType)
const { onChange, onBlur, value } = useFieldController({ name: amountKey })
@@ -98,9 +99,16 @@ export const AmountInputBase: React.FC<
}
}, [value])
+ const title =
+ subvariant === 'custom'
+ ? subvariantOptions?.custom === 'deposit'
+ ? t('header.amount')
+ : t('header.youPay')
+ : t('header.send')
+
return (
- {t('header.send')}
+ {title}
diff --git a/packages/widget/src/components/ContractComponent/ItemPrice.tsx b/packages/widget/src/components/ContractComponent/ItemPrice.tsx
index e02c83171..77899e541 100644
--- a/packages/widget/src/components/ContractComponent/ItemPrice.tsx
+++ b/packages/widget/src/components/ContractComponent/ItemPrice.tsx
@@ -1,5 +1,6 @@
import type { ContractCall } from '@lifi/sdk'
import { useEffect } from 'react'
+import { formatUnits } from 'viem'
import { useFieldActions } from '../../stores/form/useFieldActions.js'
import type { TokenAmount } from '../../types/token.js'
import { Token } from '../Token/Token.js'
@@ -19,9 +20,13 @@ export const ItemPrice: React.FC = ({
if (token) {
setFieldValue('toChain', token.chainId, { isTouched: true })
setFieldValue('toToken', token.address, { isTouched: true })
- setFieldValue('toAmount', token.amount?.toString(), {
- isTouched: true,
- })
+ setFieldValue(
+ 'toAmount',
+ token.amount ? formatUnits(token.amount, token.decimals) : '',
+ {
+ isTouched: true,
+ }
+ )
}
if (contractCalls) {
setFieldValue('contractCalls', contractCalls, {
diff --git a/packages/widget/src/components/ContractComponent/NFT/NFT.tsx b/packages/widget/src/components/ContractComponent/NFT/NFT.tsx
index adafc8eb0..5f66b1fdf 100644
--- a/packages/widget/src/components/ContractComponent/NFT/NFT.tsx
+++ b/packages/widget/src/components/ContractComponent/NFT/NFT.tsx
@@ -1,4 +1,5 @@
import { useEffect } from 'react'
+import { formatUnits } from 'viem'
import { useFieldActions } from '../../../stores/form/useFieldActions.js'
import { NFTBase } from './NFTBase.js'
import type { NFTProps } from './types.js'
@@ -18,9 +19,13 @@ export const NFT: React.FC = ({
if (token) {
setFieldValue('toChain', token.chainId, { isTouched: true })
setFieldValue('toToken', token.address, { isTouched: true })
- setFieldValue('toAmount', token.amount?.toString(), {
- isTouched: true,
- })
+ setFieldValue(
+ 'toAmount',
+ token.amount ? formatUnits(token.amount, token.decimals) : '',
+ {
+ isTouched: true,
+ }
+ )
}
if (contractCall) {
setFieldValue('contractCalls', [contractCall], {
diff --git a/packages/widget/src/components/RouteCard/RouteCard.tsx b/packages/widget/src/components/RouteCard/RouteCard.tsx
index bf545d131..903e20d60 100644
--- a/packages/widget/src/components/RouteCard/RouteCard.tsx
+++ b/packages/widget/src/components/RouteCard/RouteCard.tsx
@@ -26,7 +26,7 @@ export const RouteCard: React.FC<
...other
}) => {
const { t } = useTranslation()
- const { subvariant } = useWidgetConfig()
+ const { subvariant, subvariantOptions } = useWidgetConfig()
const [cardExpanded, setCardExpanded] = useState(defaulExpanded)
const handleExpand: MouseEventHandler = (e) => {
@@ -35,7 +35,7 @@ export const RouteCard: React.FC<
}
const token: TokenAmount =
- subvariant === 'custom'
+ subvariant === 'custom' && subvariantOptions?.custom !== 'deposit'
? { ...route.fromToken, amount: BigInt(route.fromAmount) }
: { ...route.toToken, amount: BigInt(route.toAmount) }
const impactToken: TokenAmount | undefined =
diff --git a/packages/widget/src/components/Routes/Routes.tsx b/packages/widget/src/components/Routes/Routes.tsx
index dc3777c5d..82881e45b 100644
--- a/packages/widget/src/components/Routes/Routes.tsx
+++ b/packages/widget/src/components/Routes/Routes.tsx
@@ -16,7 +16,8 @@ import { RouteNotFoundCard } from '../RouteCard/RouteNotFoundCard.js'
export const Routes: React.FC = (props) => {
const { t } = useTranslation()
const navigate = useNavigate()
- const { subvariant, useRecommendedRoute } = useWidgetConfig()
+ const { subvariant, subvariantOptions, useRecommendedRoute } =
+ useWidgetConfig()
const {
routes,
isLoading,
@@ -42,11 +43,16 @@ export const Routes: React.FC = (props) => {
const showAll =
!onlyRecommendedRoute && !routeNotFound && (routes?.length ?? 0) > 1
+ const title =
+ subvariant === 'custom'
+ ? subvariantOptions?.custom === 'deposit'
+ ? t('header.receive')
+ : t('header.youPay')
+ : t('header.receive')
+
return (
-
- {subvariant === 'custom' ? t('header.youPay') : t('header.receive')}
-
+ {title}
{
export const RoutesExpandedElement = () => {
const { t } = useTranslation()
const navigate = useNavigate()
- const { subvariant } = useWidgetConfig()
+ const { subvariant, subvariantOptions } = useWidgetConfig()
const routesRef = useRef()
const emitter = useWidgetEvents()
const routesActiveRef = useRef(false)
@@ -118,6 +118,13 @@ export const RoutesExpandedElement = () => {
emitter.emit(WidgetEvent.WidgetExpanded, expanded)
}, [emitter, expanded])
+ const title =
+ subvariant === 'custom'
+ ? subvariantOptions?.custom === 'deposit'
+ ? t('header.deposit')
+ : t('header.youPay')
+ : t('header.receive')
+
return (
{
flex: 1,
}}
>
- {subvariant === 'custom'
- ? t('header.youPay')
- : t('header.receive')}
+ {title}
= (props) => {
const { t } = useTranslation()
const navigate = useNavigate()
- const { disabledUI, hiddenUI, toAddress, toAddresses } = useWidgetConfig()
+ const {
+ disabledUI,
+ hiddenUI,
+ toAddress,
+ toAddresses,
+ subvariant,
+ subvariantOptions,
+ } = useWidgetConfig()
const { showSendToWallet } = useSendToWalletStore()
const [toAddressFieldValue, toChainId, toTokenAddress] = useFieldValues(
'toAddress',
@@ -114,6 +121,11 @@ export const SendToWalletButton: React.FC = (props) => {
const isOpenCollapse =
requiredToAddress || (showSendToWallet && !hiddenToAddress)
+ const title =
+ subvariant === 'custom' && subvariantOptions?.custom === 'deposit'
+ ? t('header.depositTo')
+ : t('header.sendToWallet')
+
return (
= (props) => {
sx={{ width: '100%', ...props.sx }}
>
- {t('header.sendToWallet')}
+ {title}
{
const toChain = getChainById(toChainId)
const fromChain = getChainById(fromChainId)
- const { accounts } = useAccount()
+ const { account: toAccount } = useAccount({ chainType: toChain?.chainType })
- const fromAccount = accounts.find(
- (account) => account.chainType === fromChain?.chainType
- )
-
- const toAccount = accounts.find(
- (account) => account.chainType === toChain?.chainType
- )
+ const effectiveToAddress = toAddress || toAccount?.address
- const isFromContractAddress = useIsContractAddress(
- fromAccount?.address,
- fromChainId,
- fromAccount?.chainType
- )
const isToContractAddress = useIsContractAddress(
- toAddress,
+ effectiveToAddress,
toChainId,
toChain?.chainType
)
const { token: destinationNativeToken } = useTokenBalance(
- toAddress || toAccount?.address,
+ effectiveToAddress,
toChainId ? toChain?.nativeToken : undefined
)
@@ -55,9 +44,8 @@ export const useGasRefuel = () => {
const isChainTypeSatisfied =
fromChain?.chainType !== toChain?.chainType ? Boolean(toAddress) : true
- const isToAddressSatisfied = isFromContractAddress
- ? toAddress && toAddress !== fromAccount?.address && !isToContractAddress
- : true
+ // We should not refuel to the contract address
+ const isToAddressSatisfied = effectiveToAddress && !isToContractAddress
const enabled = useMemo(() => {
if (
diff --git a/packages/widget/src/hooks/useIsContractAddress.ts b/packages/widget/src/hooks/useIsContractAddress.ts
index 36def167a..fb0b6e6b7 100644
--- a/packages/widget/src/hooks/useIsContractAddress.ts
+++ b/packages/widget/src/hooks/useIsContractAddress.ts
@@ -16,6 +16,7 @@ export const useIsContractAddress = (
enabled: Boolean(chainType === ChainType.EVM && chainId),
},
})
+
const isContractAddress = !!contractCode
return isContractAddress
}
diff --git a/packages/widget/src/hooks/useRoutes.ts b/packages/widget/src/hooks/useRoutes.ts
index 9a34de458..3abd62254 100644
--- a/packages/widget/src/hooks/useRoutes.ts
+++ b/packages/widget/src/hooks/useRoutes.ts
@@ -177,6 +177,7 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
signal,
}) => {
const fromAmount = parseUnits(fromTokenAmount, fromToken!.decimals)
+ const toAmount = parseUnits(toTokenAmount, toToken!.decimals)
const formattedSlippage = Number.parseFloat(slippage) / 100
const allowBridges = swapOnly
@@ -210,17 +211,18 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
fromAddress,
toAddress,
fromAmount,
+ toAmount,
slippage: formattedSlippage,
})
- if (subvariant === 'custom' && contractCalls && toTokenAmount) {
+ if (subvariant === 'custom' && contractCalls && toAmount) {
const contractCallQuote = await getContractCallsQuote(
{
// Contract calls are enabled only when fromAddress is set
fromAddress: fromAddress as string,
fromChain: fromChainId,
fromToken: fromTokenAddress,
- toAmount: toTokenAmount,
+ toAmount: toAmount.toString(),
toChain: toChainId,
toToken: toTokenAddress,
contractCalls,
@@ -265,8 +267,8 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
fromAddress: contractCallQuote.action.fromAddress,
toChainId: contractCallQuote.action.toChainId,
toAmountUSD: contractCallQuote.estimate.toAmountUSD || '',
- toAmount: toTokenAmount,
- toAmountMin: toTokenAmount,
+ toAmount: contractCallQuote.estimate.toAmount,
+ toAmountMin: contractCallQuote.estimate.toAmountMin,
toToken: toToken!,
toAddress:
contractCallQuote.action.toAddress ||
diff --git a/packages/widget/src/i18n/en.json b/packages/widget/src/i18n/en.json
index a0d8dffa2..51a57ea24 100644
--- a/packages/widget/src/i18n/en.json
+++ b/packages/widget/src/i18n/en.json
@@ -52,12 +52,14 @@
},
"header": {
"activeTransactions": "Active transactions",
+ "amount": "Amount",
"bookmarkedWallets": "Bookmarked wallets",
"bridge": "Bridge",
"checkout": "Checkout",
"checkoutDetails": "Checkout details",
"deposit": "Deposit",
"depositDetails": "Deposit details",
+ "depositTo": "Deposit to",
"exchange": "Exchange",
"from": "Exchange from",
"gas": "Gas",
@@ -265,13 +267,15 @@
"stepBridge": "Bridge",
"stepBridgeAndBuy": "Bridge and buy",
"stepBridgeAndDeposit": "Bridge and deposit",
+ "stepBuy": "Buy",
+ "stepDeposit": "Deposit",
"stepDetails": "{{tool}} via LI.FI",
"stepSwap": "Swap",
"stepSwapAndBridge": "Swap and bridge",
"stepSwapAndBuy": "Swap and buy",
"stepSwapAndDeposit": "Swap and deposit",
- "transferId": "Transfer ID",
"swapStepDetails": "Swap on {{chain}} via {{tool}}",
+ "transferId": "Transfer ID",
"tags": {
"cheapest": "Best Return",
"fastest": "Fastest"
diff --git a/packages/widget/src/i18n/i18next.d.ts b/packages/widget/src/i18n/i18next.d.ts
index 509d0fd72..ada8de6c2 100644
--- a/packages/widget/src/i18n/i18next.d.ts
+++ b/packages/widget/src/i18n/i18next.d.ts
@@ -2,13 +2,9 @@ import en from './en.json' with { type: 'json' }
const defaultResource = { translation: en }
-declare global {
- namespace GeneralTranslation {
- declare module 'i18next' {
- interface CustomTypeOptions {
- defaultNS: 'translation'
- resources: typeof defaultResource
- }
- }
+declare module 'i18next' {
+ interface CustomTypeOptions {
+ defaultNS: 'translation'
+ resources: typeof defaultResource
}
}
diff --git a/packages/widget/src/index.ts b/packages/widget/src/index.ts
index 31d7275d0..337237a9d 100644
--- a/packages/widget/src/index.ts
+++ b/packages/widget/src/index.ts
@@ -1,5 +1,5 @@
export type * from '@lifi/sdk'
-export { ChainType, ChainId } from '@lifi/sdk'
+export { ChainType, ChainId, CoinKey } from '@lifi/sdk'
export { App as LiFiWidget } from './App.js'
export type { WidgetDrawer } from './AppDrawer.js'
export * from './components/ContractComponent/ItemPrice.js'
diff --git a/packages/widget/src/pages/MainPage/MainPage.tsx b/packages/widget/src/pages/MainPage/MainPage.tsx
index f6b290941..d4fdc5327 100644
--- a/packages/widget/src/pages/MainPage/MainPage.tsx
+++ b/packages/widget/src/pages/MainPage/MainPage.tsx
@@ -31,22 +31,23 @@ export const MainPage: React.FC = () => {
: subvariant === 'refuel'
? t('header.gas')
: t('header.exchange')
+
useHeader(title)
+ const marginSx = { marginBottom: 2 }
+
return (
-
+
{custom ? (
-
- {contractComponent}
-
+ {contractComponent}
) : null}
- {!custom ? (
-
+ {!custom || subvariantOptions?.custom === 'deposit' ? (
+
) : null}
- {!wideVariant ? : null}
-
+ {!wideVariant ? : null}
+