Skip to content

Commit 50fbffd

Browse files
authored
Merge pull request #66 from lidofinance/feature/post-testnet
Tesnet v1.1
2 parents e1b4f2c + 0993688 commit 50fbffd

File tree

284 files changed

+4109
-5891
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

284 files changed

+4109
-5891
lines changed

config/external-config/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export type ManifestConfig = {
1818
};
1919
};
2020
};
21-
21+
// TODO adjust for vaults routing
2222
export enum ManifestConfigPageEnum {
2323
main = '/',
2424
overview = '/overview',

config/external-config/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const isPagesValid = (config: object) => {
2323
const pages = config.pages as ManifestConfig['pages'];
2424
if (pages && typeof pages === 'object') {
2525
// INFO: exclude possible issue when main page can be deactivated
26-
return !pages[ManifestConfigPageEnum.main]?.shouldDisable;
26+
return !pages['/']?.shouldDisable;
2727
}
2828

2929
return false;

consts/routing.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { Address } from 'viem';
2+
3+
export const appPaths = {
4+
myVaults: '/',
5+
vaults: {
6+
all: '/vaults',
7+
create: '/vaults/create',
8+
vault: (vaultAddress: Address) =>
9+
({
10+
overview: `/vaults/${vaultAddress}`,
11+
eth: (mode: 'supply' | 'withdraw') =>
12+
`/vaults/${vaultAddress}/eth/${mode}` as const,
13+
steth: (mode: 'mint' | 'repay') =>
14+
`/vaults/${vaultAddress}/steth/${mode}` as const,
15+
claim: `/vaults/${vaultAddress}/claim`,
16+
settings: `/vaults/${vaultAddress}/settings`,
17+
validators: `/vaults/${vaultAddress}/validators`,
18+
}) as const,
19+
},
20+
} as const;
21+
22+
type StringValues<T> =
23+
T extends Record<string, infer U> ? (U extends string ? U : never) : never;
24+
25+
type ObjectValues<T> = T extends string
26+
? T
27+
: T extends Record<string, infer U>
28+
? StringValues<T> | ObjectValues<U> | FunctionValues<U>
29+
: never;
30+
31+
type FunctionValues<T> = T extends (...args: any[]) => infer R
32+
? ObjectValues<R>
33+
: never;
34+
35+
export type AppPathsType = ObjectValues<typeof appPaths>;

consts/urls.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// TODO: path + basePath
2-
export { ManifestConfigPageEnum as AppPaths } from 'config/external-config';
3-
41
export const getPathWithoutFirstSlash = (path: string): string => {
52
if (path.length === 0 || path[0] !== '/') return path;
63

features/adjustment/adjustment-tabs.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@ import { useAdjustment } from 'features/adjustment/contexts/adjustment-provider'
22
import { useVaultInfo } from 'modules/vaults';
33

44
import { Switch } from 'shared/components/switch';
5-
import { ManifestConfigPageEnum } from 'config/external-config';
65

76
import { Mint } from './mint';
87
import { Repay } from './repay';
9-
import { adjustmentToggleList } from './const';
108
import { FormBlock, PageWrapper } from './styles';
9+
import { appPaths } from 'consts/routing';
10+
import { zeroAddress } from 'viem';
1111

1212
export const AdjustmentTabs = () => {
1313
const { isMintTab } = useAdjustment();
14-
const { activeVault } = useVaultInfo();
14+
const { vaultAddress } = useVaultInfo();
1515

1616
// TODO: improve creation of the path
1717
const mintRoutes = [
1818
{
19-
path: `/${activeVault?.address}${ManifestConfigPageEnum.adjustment}/${adjustmentToggleList[0].value}`,
20-
name: adjustmentToggleList[0].label,
19+
path: appPaths.vaults.vault(vaultAddress ?? zeroAddress).steth('mint'),
20+
name: 'Mint',
2121
},
2222
{
23-
path: `/${activeVault?.address}${ManifestConfigPageEnum.adjustment}/${adjustmentToggleList[1].value}`,
24-
name: adjustmentToggleList[1].label,
23+
path: appPaths.vaults.vault(vaultAddress ?? zeroAddress).steth('repay'),
24+
name: 'Repay',
2525
},
2626
];
2727

features/adjustment/const.ts

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,3 @@ export const TOKENS_TO_MINT = {
66
} as const;
77

88
export type TOKENS_TO_MINT = keyof typeof TOKENS_TO_MINT;
9-
10-
export enum ADJUSTMENT_PATHS {
11-
mint = 'mint',
12-
repay = 'repay',
13-
}
14-
15-
export type AdjustmentPaths = 'mint' | 'repay';
16-
17-
export const adjustmentToggleList: { value: AdjustmentPaths; label: string }[] =
18-
[
19-
{
20-
value: ADJUSTMENT_PATHS.mint,
21-
label: 'Mint',
22-
},
23-
{
24-
value: ADJUSTMENT_PATHS.repay,
25-
label: 'Repay',
26-
},
27-
];

features/adjustment/mint/form/submit-button/submit-button.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { OracleReportButton } from 'features/report';
21
import { useVaultInfo, type VAULT_OWNER_ROLES } from 'modules/vaults';
32
import { MultiplePermissionedSubmitButton } from 'modules/vaults/components';
43
import { useMemo } from 'react';
@@ -39,14 +38,12 @@ export const SubmitButton = () => {
3938
const disabled = isSubmitting && !isValid;
4039

4140
return (
42-
<OracleReportButton action="minting">
43-
<MultiplePermissionedSubmitButton
44-
dashboardRoles={roles}
45-
type="submit"
46-
disabled={disabled}
47-
>
48-
Mint
49-
</MultiplePermissionedSubmitButton>
50-
</OracleReportButton>
41+
<MultiplePermissionedSubmitButton
42+
dashboardRoles={roles}
43+
type="submit"
44+
disabled={disabled}
45+
>
46+
Mint
47+
</MultiplePermissionedSubmitButton>
5148
);
5249
};

features/adjustment/mint/hooks/use-mint.ts

Lines changed: 49 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,63 @@
1+
import invariant from 'tiny-invariant';
12
import { useCallback } from 'react';
2-
import {
3-
useConfig,
4-
useWriteContract,
5-
usePublicClient,
6-
useEstimateGas,
7-
useAccount,
8-
} from 'wagmi';
9-
import { Address, encodeFunctionData } from 'viem';
3+
import { useEstimateGas, useAccount } from 'wagmi';
4+
import { type Address, encodeFunctionData } from 'viem';
5+
6+
import { useSendTransaction, withSuccess } from 'modules/web3';
107

118
import { dashboardAbi } from 'abi/dashboard-abi';
12-
import { useDappStatus } from 'modules/web3/hooks/use-dapp-status';
13-
import { useVaultInfo } from 'modules/vaults';
14-
import {
15-
SubmitPayload,
16-
SubmitStepEnum,
17-
} from 'shared/components/submit-modal/types';
18-
import invariant from 'tiny-invariant';
19-
import { useVaultPermission } from 'modules/vaults/hooks/use-vault-permissions';
9+
import { useVaultInfo, useVaultPermission } from 'modules/vaults';
10+
2011
import { fallbackedAddress } from 'utils/fallbacked-address';
2112

22-
export const useMint = (onMutate = () => {}) => {
23-
const { chainId } = useDappStatus();
24-
const wagmiConfig = useConfig();
13+
import { useReportStatus } from 'features/report';
14+
import { GoToVault } from 'modules/vaults/components/go-to-vault';
15+
16+
export const useMint = () => {
2517
const { activeVault } = useVaultInfo();
26-
const publicClient = usePublicClient();
27-
const { data: mintTx, writeContractAsync } = useWriteContract({
28-
config: wagmiConfig,
29-
mutation: {
30-
onMutate,
31-
},
32-
});
18+
const { isReportAvailable, prepareReportCall } = useReportStatus();
19+
const { sendTX, ...rest } = useSendTransaction();
3320

34-
const callMint = useCallback(
35-
async (
36-
recipient: Address,
37-
amount: bigint,
38-
token: string,
39-
setModalState: (submitStep: SubmitPayload) => void,
40-
) => {
41-
invariant(publicClient, '[useMintDashboard] publicClient is undefined');
21+
return {
22+
mint: useCallback(
23+
async (recipient: Address, amount: bigint, token: string) => {
24+
invariant(activeVault?.owner, '[useMint] owner is undefined');
4225

43-
setModalState({ step: SubmitStepEnum.confirming });
44-
const tx = await writeContractAsync({
45-
abi: dashboardAbi,
46-
address: activeVault?.owner as Address,
47-
functionName: token === 'stETH' ? 'mintStETH' : 'mintWstETH',
48-
args: [recipient, amount],
49-
chainId,
50-
});
26+
const loadingActionText = `Minting ${token} backed by vault`;
27+
const mainActionCompleteText = `Minted ${token} backed by vault`;
5128

52-
setModalState({ step: SubmitStepEnum.submitting, tx });
53-
await publicClient.waitForTransactionReceipt({
54-
hash: tx,
55-
});
29+
const mintCall = {
30+
to: activeVault.owner,
31+
data: encodeFunctionData({
32+
abi: dashboardAbi,
33+
functionName: token === 'stETH' ? 'mintStETH' : 'mintWstETH',
34+
args: [recipient, amount],
35+
}),
36+
loadingActionText,
37+
};
5638

57-
return tx;
58-
},
59-
[chainId, writeContractAsync, activeVault?.owner, publicClient],
60-
);
39+
// if we have to post report, there will be extra modal due to async fetch
40+
const transactions = isReportAvailable
41+
? async () => {
42+
return [await prepareReportCall(), mintCall];
43+
}
44+
: [mintCall];
6145

62-
return {
63-
callMint,
64-
mintTx,
46+
const { success } = await withSuccess(
47+
sendTX({
48+
transactions,
49+
forceAtomic: true,
50+
mainActionLoadingText: loadingActionText,
51+
mainActionCompleteText,
52+
renderSuccessContent: GoToVault,
53+
}),
54+
);
55+
56+
return success;
57+
},
58+
[activeVault?.owner, prepareReportCall, sendTX, isReportAvailable],
59+
),
60+
...rest,
6561
};
6662
};
6763

features/adjustment/mint/mint-form-context/mint-form-provider.tsx

Lines changed: 13 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,15 @@ import {
55
useCallback,
66
createContext,
77
useContext,
8-
useState,
98
} from 'react';
109
import { FormProvider, useForm } from 'react-hook-form';
1110
import invariant from 'tiny-invariant';
1211

13-
import { useFormControllerRetry } from 'shared/hook-form/form-controller/use-form-controller-retry-delegate';
1412
import { useVaultInfo } from 'modules/vaults';
1513
import { useMint } from 'features/adjustment/mint/hooks';
1614

17-
import {
18-
FormController,
19-
FormControllerContext,
20-
FormControllerContextValueType,
21-
} from 'shared/hook-form/form-controller';
15+
import { FormController } from 'shared/hook-form/form-controller';
2216
import { MintFormSchema } from 'features/adjustment/mint/types';
23-
import { SubmitModal } from 'shared/components';
24-
import {
25-
SubmitPayload,
26-
SubmitStep,
27-
SubmitStepEnum,
28-
} from 'shared/components/submit-modal/types';
2917
import { Address } from 'viem';
3018

3119
type MintDataContextValue = {
@@ -48,20 +36,17 @@ export const useMintFormData = () => {
4836
};
4937

5038
export const MintFormProvider: FC<{ children: ReactNode }> = ({ children }) => {
51-
const [submitStep, setSubmitStep] = useState<{
52-
step: SubmitStep;
53-
tx?: Address;
54-
}>(() => ({ step: SubmitStepEnum.edit }));
5539
const formObject = useForm<MintFormSchema>({
5640
defaultValues: {
5741
amount: undefined,
5842
token: 'stETH',
5943
recipient: '' as Address,
6044
},
6145
mode: 'all',
46+
// TODO: validation
6247
reValidateMode: 'onChange',
6348
});
64-
const { callMint } = useMint();
49+
const { mint, retryEvent } = useMint();
6550
const { activeVault } = useVaultInfo();
6651

6752
const mintData = useMemo(() => {
@@ -76,55 +61,25 @@ export const MintFormProvider: FC<{ children: ReactNode }> = ({ children }) => {
7661
};
7762
}, [activeVault]);
7863

79-
const { retryEvent, retryFire } = useFormControllerRetry();
80-
const setModalState = useCallback((submitStep: SubmitPayload) => {
81-
setSubmitStep(submitStep);
82-
}, []);
83-
8464
const onSubmit = useCallback(
8565
async ({ recipient, amount, token }: MintFormSchema) => {
86-
if (amount && recipient) {
87-
try {
88-
setModalState({ step: SubmitStepEnum.initiate });
89-
const tx = await callMint(recipient, amount, token, setModalState);
90-
setModalState({ step: SubmitStepEnum.overview, tx });
91-
return true;
92-
} catch (err) {
93-
if (
94-
err instanceof Error &&
95-
err.message.includes('User rejected the request')
96-
) {
97-
setModalState({ step: SubmitStepEnum.reject });
98-
} else {
99-
setModalState({ step: SubmitStepEnum.error });
100-
}
101-
}
102-
}
66+
// TODO: add validation, remove stub
67+
if (!recipient || !amount) return false;
68+
invariant(recipient, '[MintFormProvider] recipient is undefined');
69+
invariant(amount, '[MintFormProvider] amount is undefined');
70+
invariant(token, '[MintFormProvider] token is undefined');
10371

104-
return false;
72+
return await mint(recipient, amount, token);
10573
},
106-
// eslint-disable-next-line react-hooks/exhaustive-deps
107-
[callMint],
74+
[mint],
10875
);
10976

110-
const formControllerValue: FormControllerContextValueType<MintFormSchema> =
111-
useMemo(
112-
() => ({
113-
onSubmit,
114-
retryEvent,
115-
retryFire,
116-
onReset: formObject.reset,
117-
}),
118-
[retryFire, retryEvent, onSubmit, formObject.reset],
119-
);
120-
12177
return (
12278
<MintDataContext.Provider value={mintData}>
12379
<FormProvider {...formObject}>
124-
<FormControllerContext.Provider value={formControllerValue}>
125-
<FormController>{children}</FormController>
126-
<SubmitModal submitStep={submitStep} setModalState={setModalState} />
127-
</FormControllerContext.Provider>
80+
<FormController onSubmit={onSubmit} retryEvent={retryEvent}>
81+
{children}
82+
</FormController>
12883
</FormProvider>
12984
</MintDataContext.Provider>
13085
);

0 commit comments

Comments
 (0)