diff --git a/README.md b/README.md index 5644f98b8..c2e68e379 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,7 @@ The file `common.ts` with type [`AppConfig`](src/config/types.ts) contains impor - `selectedConnectors`: List of connectors to make available by default in the wallet selection modal that will be shown even if the connector is not injected. - `blockedConnectors`: List of EIP-6963 injected connectors names to block in the wallet selection modal. - `isSimulatorEnabled`: Flag to enable the simulation page. +- `showStrategyRoi`: Optional flag to show the Strategy ROI in the Strategy Block. ROI is hidden by default. - `network` - `name`: Network name. - `logoUrl`: Network logo URL. @@ -265,7 +266,7 @@ The file `common.ts` with type [`AppConfig`](src/config/types.ts) contains impor - `popularTokens`: List of popular tokens to be used in the app when opening the token selection modal. - `addresses`/`carbon` and `addresses/utils`: CarbonController, Voucher and multicall3 contract addresses. - `tokenListOverride`: Token list override to be used in the app when fetching the token list. Tokens in the list will override any other token with the same address. -- `tokenLists`: List of token lists including the uri and the parser to be used to parse the token list. +- `tokenLists`: List of token lists including the uri and the parser name to be used to parse the token list. Please update the tokenParserMap in the `src/config/utils.ts` file to include the parser name and the parser function. - `sdk`/`cacheTTL`: When the app loads, it will ignore any cached data if it is older than the cacheTTL time in milliseconds. If set to 0, the app will always ignore the cache data and fetch new data on load. #### Gas token different than native token diff --git a/e2e/screenshots/simulator/recurring/Recurring_limit_range/form.png b/e2e/screenshots/simulator/recurring/Recurring_limit_range/form.png index 54cbc496d..c26dc5bac 100644 Binary files a/e2e/screenshots/simulator/recurring/Recurring_limit_range/form.png and b/e2e/screenshots/simulator/recurring/Recurring_limit_range/form.png differ diff --git a/e2e/screenshots/simulator/recurring/Recurring_range_limit/simulator-input-price.png b/e2e/screenshots/simulator/recurring/Recurring_range_limit/simulator-input-price.png index d9546b0d3..4d6d4fb7e 100644 Binary files a/e2e/screenshots/simulator/recurring/Recurring_range_limit/simulator-input-price.png and b/e2e/screenshots/simulator/recurring/Recurring_range_limit/simulator-input-price.png differ diff --git a/e2e/screenshots/strategy/disposable/Disposable_buy_limit/create/form.png b/e2e/screenshots/strategy/disposable/Disposable_buy_limit/create/form.png index d012724ae..3b2bdac69 100644 Binary files a/e2e/screenshots/strategy/disposable/Disposable_buy_limit/create/form.png and b/e2e/screenshots/strategy/disposable/Disposable_buy_limit/create/form.png differ diff --git a/e2e/screenshots/strategy/disposable/Disposable_buy_limit/undercut/form.png b/e2e/screenshots/strategy/disposable/Disposable_buy_limit/undercut/form.png index e0ffd028c..f5d89df50 100644 Binary files a/e2e/screenshots/strategy/disposable/Disposable_buy_limit/undercut/form.png and b/e2e/screenshots/strategy/disposable/Disposable_buy_limit/undercut/form.png differ diff --git a/e2e/screenshots/strategy/disposable/Disposable_buy_range/create/form.png b/e2e/screenshots/strategy/disposable/Disposable_buy_range/create/form.png index 01bccea18..2ac84b336 100644 Binary files a/e2e/screenshots/strategy/disposable/Disposable_buy_range/create/form.png and b/e2e/screenshots/strategy/disposable/Disposable_buy_range/create/form.png differ diff --git a/e2e/screenshots/strategy/disposable/Disposable_buy_range/duplicate/form.png b/e2e/screenshots/strategy/disposable/Disposable_buy_range/duplicate/form.png index 1c105efb7..5055e9ee6 100644 Binary files a/e2e/screenshots/strategy/disposable/Disposable_buy_range/duplicate/form.png and b/e2e/screenshots/strategy/disposable/Disposable_buy_range/duplicate/form.png differ diff --git a/e2e/screenshots/strategy/overlapping/Overlapping/create/my-strategy.png b/e2e/screenshots/strategy/overlapping/Overlapping/create/my-strategy.png index 62f54338d..995d5e871 100644 Binary files a/e2e/screenshots/strategy/overlapping/Overlapping/create/my-strategy.png and b/e2e/screenshots/strategy/overlapping/Overlapping/create/my-strategy.png differ diff --git a/e2e/screenshots/strategy/overlapping/Overlapping/withdraw/form.png b/e2e/screenshots/strategy/overlapping/Overlapping/withdraw/form.png index ab60f2da7..454add18d 100644 Binary files a/e2e/screenshots/strategy/overlapping/Overlapping/withdraw/form.png and b/e2e/screenshots/strategy/overlapping/Overlapping/withdraw/form.png differ diff --git a/e2e/screenshots/strategy/recurring/Recurring_limit_limit/deposit/form.png b/e2e/screenshots/strategy/recurring/Recurring_limit_limit/deposit/form.png index 20f5e1b83..5e6358bb2 100644 Binary files a/e2e/screenshots/strategy/recurring/Recurring_limit_limit/deposit/form.png and b/e2e/screenshots/strategy/recurring/Recurring_limit_limit/deposit/form.png differ diff --git a/e2e/screenshots/strategy/recurring/Recurring_limit_range/create/form.png b/e2e/screenshots/strategy/recurring/Recurring_limit_range/create/form.png index 64f442ea7..5563723e5 100644 Binary files a/e2e/screenshots/strategy/recurring/Recurring_limit_range/create/form.png and b/e2e/screenshots/strategy/recurring/Recurring_limit_range/create/form.png differ diff --git a/e2e/screenshots/strategy/recurring/Recurring_limit_range/create/my-strategy.png b/e2e/screenshots/strategy/recurring/Recurring_limit_range/create/my-strategy.png index 43ccb6519..c3a5b7494 100644 Binary files a/e2e/screenshots/strategy/recurring/Recurring_limit_range/create/my-strategy.png and b/e2e/screenshots/strategy/recurring/Recurring_limit_range/create/my-strategy.png differ diff --git a/e2e/screenshots/strategy/recurring/Recurring_limit_range/deposit/form.png b/e2e/screenshots/strategy/recurring/Recurring_limit_range/deposit/form.png index 5cc16c78c..8f1ade80d 100644 Binary files a/e2e/screenshots/strategy/recurring/Recurring_limit_range/deposit/form.png and b/e2e/screenshots/strategy/recurring/Recurring_limit_range/deposit/form.png differ diff --git a/e2e/screenshots/strategy/recurring/Recurring_limit_range/renew/form.png b/e2e/screenshots/strategy/recurring/Recurring_limit_range/renew/form.png index 22995cc8b..9b0ceea46 100644 Binary files a/e2e/screenshots/strategy/recurring/Recurring_limit_range/renew/form.png and b/e2e/screenshots/strategy/recurring/Recurring_limit_range/renew/form.png differ diff --git a/e2e/screenshots/strategy/recurring/Recurring_range_limit/renew/form.png b/e2e/screenshots/strategy/recurring/Recurring_range_limit/renew/form.png index 332ea572d..31e78a83e 100644 Binary files a/e2e/screenshots/strategy/recurring/Recurring_range_limit/renew/form.png and b/e2e/screenshots/strategy/recurring/Recurring_range_limit/renew/form.png differ diff --git a/e2e/screenshots/strategy/recurring/Recurring_range_range/create/form.png b/e2e/screenshots/strategy/recurring/Recurring_range_range/create/form.png index d3e1e1e4f..c6dec19f6 100644 Binary files a/e2e/screenshots/strategy/recurring/Recurring_range_range/create/form.png and b/e2e/screenshots/strategy/recurring/Recurring_range_range/create/form.png differ diff --git a/e2e/screenshots/strategy/recurring/Recurring_range_range/create/my-strategy.png b/e2e/screenshots/strategy/recurring/Recurring_range_range/create/my-strategy.png index 9806983f8..a96eaefd9 100644 Binary files a/e2e/screenshots/strategy/recurring/Recurring_range_range/create/my-strategy.png and b/e2e/screenshots/strategy/recurring/Recurring_range_range/create/my-strategy.png differ diff --git a/e2e/screenshots/strategy/recurring/Recurring_range_range/duplicate/form.png b/e2e/screenshots/strategy/recurring/Recurring_range_range/duplicate/form.png index 916100a35..724d3887e 100644 Binary files a/e2e/screenshots/strategy/recurring/Recurring_range_range/duplicate/form.png and b/e2e/screenshots/strategy/recurring/Recurring_range_range/duplicate/form.png differ diff --git a/package.json b/package.json index 4438035e9..e3584eae3 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "tailwindcss": "3.4.3", "typechain": "^8.1.0", "typescript": "^5.3.3", - "valibot": "^0.28.1", + "valibot": "^0.34.0", "viem": "2.x", "vite": "5.3.2", "vite-plugin-svgr": "^2.4.0", diff --git a/src/components/activity/ActivityProvider.tsx b/src/components/activity/ActivityProvider.tsx index 33e130606..a5f43d68b 100644 --- a/src/components/activity/ActivityProvider.tsx +++ b/src/components/activity/ActivityProvider.tsx @@ -59,8 +59,8 @@ type ParamsKey = Extract; export const ActivityProvider: FC = ({ children, params }) => { const nav = useNavigate(); const searchParams: ActivitySearchParams = useSearch({ strict: false }); - const limit = searchParams.limit ?? 10; - const offset = searchParams.offset ?? 0; + const limit = searchParams.limit; + const offset = searchParams.offset; const queryParams = getQueryParams(params, searchParams); // Query the list diff --git a/src/components/activity/utils.ts b/src/components/activity/utils.ts index 60701ac29..a221f2398 100644 --- a/src/components/activity/utils.ts +++ b/src/components/activity/utils.ts @@ -4,7 +4,7 @@ import { SearchParamsValidator, validArrayOf, validLiteral, - validNumberType, + validNumber, validString, validateSearchParams, } from 'libs/routing/utils'; @@ -45,10 +45,21 @@ export const activityValidators: SearchParamsValidator = { pairs: validArrayOf(validString), start: validString, end: validString, - limit: validNumberType, - offset: validNumberType, + limit: validNumber, + offset: validNumber, +}; +export const validateActivityParams = ( + search: Record +): ActivitySearchParams => { + const rawSearch = validateSearchParams(activityValidators)(search); + const limit = Number(rawSearch.limit ?? 10); + const offset = Number(rawSearch.offset ?? 0); + return { + ...rawSearch, + limit, + offset, + }; }; -export const validateActivityParams = validateSearchParams(activityValidators); export const activityHasPairs = (activity: Activity, pairs: string[] = []) => { if (pairs.length === 0) return true; diff --git a/src/components/common/approval/ApproveToken.tsx b/src/components/common/approval/ApproveToken.tsx index f3ea18af8..15c653b0b 100644 --- a/src/components/common/approval/ApproveToken.tsx +++ b/src/components/common/approval/ApproveToken.tsx @@ -39,7 +39,7 @@ export const ApproveToken: FC = ({ const { getTokenById } = useTokens(); const token = getTokenById(data?.address || ''); const mutation = useSetUserApproval(); - // Gasprice on SEI is cheap, best practice is to use exact amount approval + // When gasprice is cheap, best practice is to use exact amount approval const [isLimited, setIsLimited] = useState( !!config.network.defaultLimitedApproval ); diff --git a/src/components/core/error/ErrorUserBlocked.tsx b/src/components/core/error/ErrorUserBlocked.tsx index 9e7d8468c..f308c5239 100644 --- a/src/components/core/error/ErrorUserBlocked.tsx +++ b/src/components/core/error/ErrorUserBlocked.tsx @@ -3,6 +3,7 @@ import { NewTabLink, externalLinks } from 'libs/routing'; import { ErrorWrapper } from 'components/core/error/ErrorWrapper'; import { Button } from 'components/common/button'; import { ReactComponent as IconWarning } from 'assets/icons/warning.svg'; +import config from 'config'; export const ErrorUserBlocked = () => { const { disconnect } = useWagmi(); @@ -11,7 +12,7 @@ export const ErrorUserBlocked = () => { } title="Wallet Blocked" - text="For compliance reasons, this wallet has been blocked from using the Carbon App." + text={`For compliance reasons, this wallet has been blocked from using the ${config.appName} App.`} variant="error" >
diff --git a/src/components/debug/DebugConfig.tsx b/src/components/debug/DebugConfig.tsx new file mode 100644 index 000000000..def02243d --- /dev/null +++ b/src/components/debug/DebugConfig.tsx @@ -0,0 +1,97 @@ +import { FormEvent, useLayoutEffect, useRef, useState } from 'react'; +import { lsService } from 'services/localeStorage'; +import { Button } from 'components/common/button'; +import { Warning } from 'components/common/WarningMessageWithIcon'; +import { defaultConfig } from 'config'; +import { AppConfigSchema } from 'config/configSchema'; +import { AppConfig } from 'config/types'; +import * as v from 'valibot'; + +const formatConfig = (config?: Partial) => + JSON.stringify(config, undefined, 4); + +export const DebugConfig = () => { + const savedConfigOverride = formatConfig(lsService.getItem('configOverride')); + const [configOverride, setConfigOverride] = useState(savedConfigOverride); + const [error, setError] = useState(''); + const textAreaRef = useRef(null); + + const errorMessage = 'Failed parsing JSON file'; + const saveConfigOverride = (configOverride?: string) => { + try { + if (!configOverride) { + setConfigOverride(''); + lsService.removeItem('configOverride'); + } else { + const parsedConfig = JSON.parse(configOverride || ''); + v.parse(v.partial(AppConfigSchema), parsedConfig); + lsService.setItem('configOverride', parsedConfig); + } + setError(''); + window?.location.reload(); + } catch (error) { + setError(errorMessage); + } + }; + + const handleConfigChange = (e: React.ChangeEvent) => { + setConfigOverride(e.target.value); + }; + + useLayoutEffect(() => { + if (!textAreaRef.current) return; + textAreaRef.current.style.height = 'inherit'; // to reduce on delete + const defaultHeight = 5; // px + const newHeight = Math.max(textAreaRef.current.scrollHeight, defaultHeight); // px + textAreaRef.current.style.height = `${newHeight}px`; + }, [configOverride]); + + const handleLoadDefault = () => { + const parsedDefaultConfig = formatConfig(defaultConfig); + setConfigOverride(parsedDefaultConfig); + }; + + const submit = (e: FormEvent) => { + e.preventDefault(); + saveConfigOverride(configOverride); + }; + + const reset = (e: FormEvent) => { + e.preventDefault(); + saveConfigOverride(); + }; + + return ( +
+

Set Config

+ + +
+