Skip to content

Commit 313a656

Browse files
committed
feat(consolodation): hot and cold self managed
Ticket: WP-1338
1 parent 5947393 commit 313a656

File tree

8 files changed

+362
-100
lines changed

8 files changed

+362
-100
lines changed

src/containers/BuildUnsignedConsolidation/GenericEcdsaForm.tsx

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ import {
77
FormikTextarea,
88
FormikTextfield,
99
} from '~/components';
10+
import { getWalletTypeLabels, WalletType } from './useWalletTypeLabels';
11+
import { WalletTypeSelector } from './WalletTypeSelector';
1012

11-
const validationSchema = Yup.object({
12-
userKey: Yup.string(),
13-
backupKey: Yup.string(),
13+
const getValidationSchema = (walletType: WalletType) => Yup.object({
14+
walletType: Yup.string().oneOf(['cold', 'hot']).required(),
15+
userKey: Yup.string().required(),
16+
backupKey: Yup.string().required(),
1417
bitgoKey: Yup.string().required(),
15-
walletPassphrase: Yup.string(),
18+
walletPassphrase: walletType === 'hot' ? Yup.string().required() : Yup.string(),
1619
startingScanIndex: Yup.number(),
1720
endingScanIndex: Yup.number().moreThan(
1821
Yup.ref('startingScanIndex'),
@@ -21,7 +24,7 @@ const validationSchema = Yup.object({
2124
seed: Yup.string(),
2225
}).required();
2326

24-
export type EcdsaFormValues = Yup.Asserts<typeof validationSchema>;
27+
export type EcdsaFormValues = Yup.Asserts<ReturnType<typeof getValidationSchema>>;
2528

2629
export type GenericEcdsaFormValues = {
2730
onSubmit: (
@@ -34,6 +37,7 @@ export function GenericEcdsaForm({ onSubmit }: GenericEcdsaFormValues) {
3437
const formik = useFormik<EcdsaFormValues>({
3538
onSubmit,
3639
initialValues: {
40+
walletType: 'cold' as WalletType,
3741
userKey: '',
3842
backupKey: '',
3943
bitgoKey: '',
@@ -42,18 +46,43 @@ export function GenericEcdsaForm({ onSubmit }: GenericEcdsaFormValues) {
4246
endingScanIndex: 21,
4347
seed: undefined,
4448
},
49+
validate: (values) => {
50+
try {
51+
getValidationSchema(values.walletType as WalletType).validateSync(values, { abortEarly: false });
52+
return {};
53+
} catch (error: any) {
54+
const errors: Record<string, string> = {};
55+
error.inner?.forEach((err: any) => {
56+
if (err.path) {
57+
errors[err.path] = err.message;
58+
}
59+
});
60+
return errors;
61+
}
62+
},
4563
});
4664

65+
const {
66+
userKeyLabel,
67+
userKeyHelperText,
68+
backupKeyLabel,
69+
backupKeyHelperText,
70+
bitgoKeyLabel,
71+
bitgoKeyHelperText,
72+
showWalletPassphrase,
73+
} = getWalletTypeLabels(formik.values.walletType as WalletType);
74+
4775
return (
4876
<FormikProvider value={formik}>
4977
<Form>
5078
<h4 className="tw-text-body tw-font-semibold tw-border-b-0.5 tw-border-solid tw-border-gray-700 tw-mb-4">
5179
Self-managed cold or Hot wallet details
5280
</h4>
81+
<WalletTypeSelector />
5382
<div className="tw-mb-4">
5483
<FormikTextarea
55-
HelperText="Your user public key, as found on your recovery KeyCard. Required for hot wallets."
56-
Label="User Public Key (optional)"
84+
HelperText={userKeyHelperText}
85+
Label={userKeyLabel}
5786
name="userKey"
5887
Width="fill"
5988
/>
@@ -68,28 +97,30 @@ export function GenericEcdsaForm({ onSubmit }: GenericEcdsaFormValues) {
6897
</div>
6998
<div className="tw-mb-4">
7099
<FormikTextarea
71-
HelperText="The backup public key for the wallet, as found on your recovery KeyCard. Required for hot wallets."
72-
Label="Backup Public Key (optional)"
100+
HelperText={backupKeyHelperText}
101+
Label={backupKeyLabel}
73102
name="backupKey"
74103
Width="fill"
75104
/>
76105
</div>
77-
<div className="tw-mb-4">
78-
<FormikPasswordfield
79-
HelperText="Your wallet passphrase, required for hot wallets."
80-
Label="Wallet Passphrase (optional)"
81-
name="walletPassphrase"
82-
Width="fill"
83-
/>
84-
</div>
85106
<div className="tw-mb-4">
86107
<FormikTextfield
87-
HelperText="The BitGo public key for the wallet, as found on your recovery KeyCard."
88-
Label="BitGo Public Key"
108+
HelperText={bitgoKeyHelperText}
109+
Label={bitgoKeyLabel}
89110
name="bitgoKey"
90111
Width="fill"
91112
/>
92113
</div>
114+
{showWalletPassphrase && (
115+
<div className="tw-mb-4">
116+
<FormikPasswordfield
117+
HelperText="The wallet passphrase that you set when creating the wallet."
118+
Label="Wallet Passphrase"
119+
name="walletPassphrase"
120+
Width="fill"
121+
/>
122+
</div>
123+
)}
93124
<div className="tw-mb-4">
94125
<FormikTextfield
95126
HelperText="The starting index (inclusive) of addresses to consolidate"

src/containers/BuildUnsignedConsolidation/SolForm.tsx

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ import {
77
FormikTextarea,
88
FormikTextfield,
99
} from '~/components';
10+
import { getWalletTypeLabels, WalletType } from './useWalletTypeLabels';
11+
import { WalletTypeSelector } from './WalletTypeSelector';
1012

11-
const validationSchema = Yup.object({
12-
userKey: Yup.string(),
13-
backupKey: Yup.string(),
13+
const getValidationSchema = (walletType: WalletType) => Yup.object({
14+
walletType: Yup.string().oneOf(['cold', 'hot']).required(),
15+
userKey: Yup.string().required(),
16+
backupKey: Yup.string().required(),
1417
bitgoKey: Yup.string().required(),
15-
walletPassphrase: Yup.string(),
18+
walletPassphrase: walletType === 'hot' ? Yup.string().required() : Yup.string(),
1619
apiKey: Yup.string().test(
1720
'not-url-or-alchemy',
1821
'API key should not be a URL',
@@ -35,7 +38,7 @@ const validationSchema = Yup.object({
3538
seed: Yup.string(),
3639
}).required();
3740

38-
export type SolFormValues = Yup.Asserts<typeof validationSchema>;
41+
export type SolFormValues = Yup.Asserts<ReturnType<typeof getValidationSchema>>;
3942

4043
export type SolFormProps = {
4144
onSubmit: (
@@ -48,6 +51,7 @@ export function SolForm({ onSubmit }: SolFormProps) {
4851
const formik = useFormik<SolFormValues>({
4952
onSubmit,
5053
initialValues: {
54+
walletType: 'cold' as WalletType,
5155
userKey: '',
5256
backupKey: '',
5357
bitgoKey: '',
@@ -61,18 +65,43 @@ export function SolForm({ onSubmit }: SolFormProps) {
6165
endingScanIndex: 21,
6266
seed: undefined,
6367
},
68+
validate: (values) => {
69+
try {
70+
getValidationSchema(values.walletType as WalletType).validateSync(values, { abortEarly: false });
71+
return {};
72+
} catch (error: any) {
73+
const errors: Record<string, string> = {};
74+
error.inner?.forEach((err: any) => {
75+
if (err.path) {
76+
errors[err.path] = err.message;
77+
}
78+
});
79+
return errors;
80+
}
81+
},
6482
});
6583

84+
const {
85+
userKeyLabel,
86+
userKeyHelperText,
87+
backupKeyLabel,
88+
backupKeyHelperText,
89+
bitgoKeyLabel,
90+
bitgoKeyHelperText,
91+
showWalletPassphrase,
92+
} = getWalletTypeLabels(formik.values.walletType as WalletType);
93+
6694
return (
6795
<FormikProvider value={formik}>
6896
<Form>
6997
<h4 className="tw-text-body tw-font-semibold tw-border-b-0.5 tw-border-solid tw-border-gray-700 tw-mb-4">
7098
Self-managed cold or Hot wallet details
7199
</h4>
100+
<WalletTypeSelector />
72101
<div className="tw-mb-4">
73102
<FormikTextarea
74-
HelperText="Your user public key, as found on your recovery KeyCard. Required for hot wallets."
75-
Label="User Public Key (optional)"
103+
HelperText={userKeyHelperText}
104+
Label={userKeyLabel}
76105
name="userKey"
77106
Width="fill"
78107
/>
@@ -87,20 +116,12 @@ export function SolForm({ onSubmit }: SolFormProps) {
87116
</div>
88117
<div className="tw-mb-4">
89118
<FormikTextarea
90-
HelperText="The backup public key for the wallet, as found on your recovery KeyCard. Required for hot wallets."
91-
Label="Backup Public Key (optional)"
119+
HelperText={backupKeyHelperText}
120+
Label={backupKeyLabel}
92121
name="backupKey"
93122
Width="fill"
94123
/>
95124
</div>
96-
<div className="tw-mb-4">
97-
<FormikPasswordfield
98-
HelperText="Your wallet passphrase, required for hot wallets."
99-
Label="Wallet Passphrase (optional)"
100-
name="walletPassphrase"
101-
Width="fill"
102-
/>
103-
</div>
104125
<div className="tw-mb-4">
105126
<FormikTextarea
106127
HelperText="Public Keys for your durable Nonces"
@@ -120,12 +141,22 @@ export function SolForm({ onSubmit }: SolFormProps) {
120141
</div>
121142
<div className="tw-mb-4">
122143
<FormikTextfield
123-
HelperText="The BitGo public key for the wallet, as found on your recovery KeyCard."
124-
Label="BitGo Public Key"
144+
HelperText={bitgoKeyHelperText}
145+
Label={bitgoKeyLabel}
125146
name="bitgoKey"
126147
Width="fill"
127148
/>
128149
</div>
150+
{showWalletPassphrase && (
151+
<div className="tw-mb-4">
152+
<FormikPasswordfield
153+
HelperText="The wallet passphrase that you set when creating the wallet."
154+
Label="Wallet Passphrase"
155+
name="walletPassphrase"
156+
Width="fill"
157+
/>
158+
</div>
159+
)}
129160
<div className="tw-mb-4">
130161
<FormikTextfield
131162
HelperText="The starting index (inclusive) of addresses to consolidate"

src/containers/BuildUnsignedConsolidation/SolTokenForm.tsx

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@ import {
88
FormikTextarea,
99
FormikTextfield,
1010
} from '~/components';
11+
import { getWalletTypeLabels, WalletType } from './useWalletTypeLabels';
12+
import { WalletTypeSelector } from './WalletTypeSelector';
1113

12-
const validationSchema = Yup.object({
13-
userKey: Yup.string(),
14-
backupKey: Yup.string(),
14+
const getValidationSchema = (walletType: WalletType) => Yup.object({
15+
walletType: Yup.string().oneOf(['cold', 'hot']).required(),
16+
userKey: Yup.string().required(),
17+
backupKey: Yup.string().required(),
1518
bitgoKey: Yup.string().required(),
16-
walletPassphrase: Yup.string(),
19+
walletPassphrase: walletType === 'hot' ? Yup.string().required() : Yup.string(),
1720
apiKey: Yup.string().test(
1821
'not-url-or-alchemy',
1922
'API key should not be a URL',
@@ -38,7 +41,7 @@ const validationSchema = Yup.object({
3841
seed: Yup.string(),
3942
}).required();
4043

41-
export type SolFormValues = Yup.Asserts<typeof validationSchema>;
44+
export type SolFormValues = Yup.Asserts<ReturnType<typeof getValidationSchema>>;
4245

4346
export type SolFormProps = {
4447
onSubmit: (
@@ -51,6 +54,7 @@ export function SolTokenForm({ onSubmit }: SolFormProps) {
5154
const formik = useFormik<SolFormValues>({
5255
onSubmit,
5356
initialValues: {
57+
walletType: 'cold' as WalletType,
5458
userKey: '',
5559
backupKey: '',
5660
bitgoKey: '',
@@ -66,18 +70,43 @@ export function SolTokenForm({ onSubmit }: SolFormProps) {
6670
tokenProgramId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
6771
seed: undefined,
6872
},
73+
validate: (values) => {
74+
try {
75+
getValidationSchema(values.walletType as WalletType).validateSync(values, { abortEarly: false });
76+
return {};
77+
} catch (error: any) {
78+
const errors: Record<string, string> = {};
79+
error.inner?.forEach((err: any) => {
80+
if (err.path) {
81+
errors[err.path] = err.message;
82+
}
83+
});
84+
return errors;
85+
}
86+
},
6987
});
7088

89+
const {
90+
userKeyLabel,
91+
userKeyHelperText,
92+
backupKeyLabel,
93+
backupKeyHelperText,
94+
bitgoKeyLabel,
95+
bitgoKeyHelperText,
96+
showWalletPassphrase,
97+
} = getWalletTypeLabels(formik.values.walletType as WalletType);
98+
7199
return (
72100
<FormikProvider value={formik}>
73101
<Form>
74102
<h4 className="tw-text-body tw-font-semibold tw-border-b-0.5 tw-border-solid tw-border-gray-700 tw-mb-4">
75103
Self-managed cold or Hot wallet details
76104
</h4>
105+
<WalletTypeSelector />
77106
<div className="tw-mb-4">
78107
<FormikTextarea
79-
HelperText="Your user public key, as found on your recovery KeyCard. Required for hot wallets."
80-
Label="User Public Key (optional)"
108+
HelperText={userKeyHelperText}
109+
Label={userKeyLabel}
81110
name="userKey"
82111
Width="fill"
83112
/>
@@ -92,20 +121,12 @@ export function SolTokenForm({ onSubmit }: SolFormProps) {
92121
</div>
93122
<div className="tw-mb-4">
94123
<FormikTextarea
95-
HelperText="The backup public key for the wallet, as found on your recovery KeyCard. Required for hot wallets."
96-
Label="Backup Public Key (optional)"
124+
HelperText={backupKeyHelperText}
125+
Label={backupKeyLabel}
97126
name="backupKey"
98127
Width="fill"
99128
/>
100129
</div>
101-
<div className="tw-mb-4">
102-
<FormikPasswordfield
103-
HelperText="Your wallet passphrase, required for hot wallets."
104-
Label="Wallet Passphrase (optional)"
105-
name="walletPassphrase"
106-
Width="fill"
107-
/>
108-
</div>
109130
<div className="tw-mb-4">
110131
<FormikTextarea
111132
HelperText="Public Keys for your durable Nonces"
@@ -125,12 +146,22 @@ export function SolTokenForm({ onSubmit }: SolFormProps) {
125146
</div>
126147
<div className="tw-mb-4">
127148
<FormikTextfield
128-
HelperText="The BitGo public key for the wallet, as found on your recovery KeyCard."
129-
Label="BitGo Public Key"
149+
HelperText={bitgoKeyHelperText}
150+
Label={bitgoKeyLabel}
130151
name="bitgoKey"
131152
Width="fill"
132153
/>
133154
</div>
155+
{showWalletPassphrase && (
156+
<div className="tw-mb-4">
157+
<FormikPasswordfield
158+
HelperText="The wallet passphrase that you set when creating the wallet."
159+
Label="Wallet Passphrase"
160+
name="walletPassphrase"
161+
Width="fill"
162+
/>
163+
</div>
164+
)}
134165
<div className="tw-mb-4">
135166
<FormikTextfield
136167
HelperText="The address of the smart contract of the token to consolidate. This is unique to each token, and is NOT your wallet address."

0 commit comments

Comments
 (0)