Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
bhavidhingra committed Aug 8, 2024
2 parents a1cc27d + 6745a44 commit e217c19
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 140 deletions.
82 changes: 41 additions & 41 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
}
},
"dependencies": {
"@bitgo-beta/sdk-coin-sui": "^1.4.1-alpha.161",
"@bitgo-beta/sdk-coin-sui": "^1.4.1-alpha.165",
"@bitgo/abstract-cosmos": "10.0.24",
"@bitgo/abstract-utxo": "8.9.0",
"@bitgo/sdk-api": "1.50.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,54 +117,7 @@ function Form() {
);
case 'sui':
case 'tsui':
return (
<SuiForm
key={coin}
onSubmit={async (values, { setSubmitting }) => {
setAlert(undefined);
setSubmitting(true);
try {
await window.commands.setBitGoEnvironment(bitGoEnvironment, coin);
const chainData = await window.queries.getChain(coin);
const broadcastResult =
await window.commands.broadcastTransaction(coin, {
serializedSignedTransaction: values.serializedSignedTx,
signature: values.signature,
});
const showSaveDialogData = await window.commands.showSaveDialog({
filters: [
{
name: 'Custom File Type',
extensions: ['json'],
},
],
defaultPath: `~/${chainData}-broadcast-transaction-${Date.now()}.json`,
});

if (!showSaveDialogData.filePath) {
throw new Error('No file path selected');
}

await window.commands.writeFile(
showSaveDialogData.filePath,
JSON.stringify(broadcastResult, null, 2),
{ encoding: 'utf-8' }
);

navigate(
`/${bitGoEnvironment}/broadcast-transaction/${coin}/success`
);
} catch (err) {
if (err instanceof Error) {
setAlert(err.message);
} else {
console.error(err);
}
setSubmitting(false);
}
}}
/>
);
return ( <SuiForm /> );

default:
throw new Error(`Unsupported coin: ${String(coin)}`);
Expand Down
161 changes: 111 additions & 50 deletions src/containers/BroadcastTransactionCoin/SuiForm.tsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,129 @@
import { Form, FormikHelpers, FormikProvider, useFormik } from 'formik';
import { Link } from 'react-router-dom';
import { Form, FormikProvider, useFormik } from 'formik';
import { useNavigate, useParams } from 'react-router-dom';
import * as Yup from 'yup';
import { Button, FormikTextfield } from '~/components';
import { Button } from '~/components';
import { FormikFilefield } from '~/components/FormikFilefield';
import { useAlertBanner } from '~/contexts';
import { assert, safeEnv } from '~/helpers';
import {
BroadcastTransactionResult,
suiBroadcastTransactionParameters,
} from '~/utils/types';

const validationSchema = Yup.object({
serializedSignedTx: Yup.string().required(),
signature: Yup.string().required(),
}).required();

export type SuiFormProps = {
onSubmit: (
values: SuiFormValues,
formikHelpers: FormikHelpers<SuiFormValues>
) => void | Promise<void>;
};
function hasBroadcastableTransactions(
json: unknown
): json is
| suiBroadcastTransactionParameters {
const data = json as
| suiBroadcastTransactionParameters;
return (
data &&
data.transactions !== undefined &&
data.transactions.length > 0
);
}

type SuiFormValues = Yup.Asserts<typeof validationSchema>;
export function SuiForm() {
const { env, coin } = useParams<'env' | 'coin'>();
const [, setAlert] = useAlertBanner();

export function SuiForm({ onSubmit }: SuiFormProps) {
const formik = useFormik<SuiFormValues>({
onSubmit,
const environment = safeEnv(env);
const navigate = useNavigate();
const formik = useFormik<{ file?: File }>({
initialValues: {
serializedSignedTx: '',
signature: '',
file: undefined,
},
validationSchema,
onSubmit: async (values, formikHelpers) => {
if (values.file) {
formikHelpers.setSubmitting(true);
await window.commands.setBitGoEnvironment(environment);
const fileReader = new FileReader();
fileReader.readAsText(values.file, 'UTF-8');
fileReader.onload = async event => {
try {
const data = JSON.parse(event.target?.result as string) as
| suiBroadcastTransactionParameters;

console.log(data);
assert(hasBroadcastableTransactions(data), 'Broadcastable transactions not found');

const chainData = await window.queries.getChain(coin!);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const broadcastResult: Error | BroadcastTransactionResult =
await window.commands.broadcastTransaction(
coin!,
data
);

if (broadcastResult instanceof Error) {
throw broadcastResult;
}

const showSaveDialogData = await window.commands.showSaveDialog({
filters: [
{
name: 'Custom File Type',
extensions: ['json'],
},
],
defaultPath: `~/${chainData}-broadcast-transaction-${Date.now()}.json`,
});
if (!showSaveDialogData.filePath) {
throw new Error('No file path selected');
}

await window.commands.writeFile(
showSaveDialogData.filePath,
JSON.stringify(broadcastResult, null, 2),
{ encoding: 'utf8' }
);
navigate(
`/${environment}/broadcast-transaction/${coin}/success`
);
} catch (error) {
if (error instanceof Error) {
formikHelpers.setFieldError('file', error.message);
setAlert(error.message);
} else {
console.log(error);
}
formikHelpers.setSubmitting(false);
}
};
} else {
formikHelpers.setFieldError('file', 'File is required');
}
},
validationSchema: Yup.object({
file: Yup.mixed().required('File is required'),
}).required(),
});

return (
<FormikProvider value={formik}>
<Form>
<h4 className="tw-text-body tw-font-semibold tw-border-b-0.5 tw-border-solid tw-border-gray-700 tw-mb-4">
Transaction
</h4>
<div className="tw-mb-4">
<FormikTextfield
HelperText="Your built and signed recovery transaction in base64 format."
Label="Serialized and Signed Recovery Transaction"
name="serializedSignedTx"
<FormikFilefield
name="file"
accept=".json"
Width="fill"
Label="Upload Broadcast Transaction(s)"
onChange={event => {
formik
.setFieldValue('file', event.currentTarget.files?.[0])
.catch(console.error);
}}
/>
</div>
<div className="tw-mb-4">
<FormikTextfield
HelperText="Transaction signature in base64 format."
Label="Signature"
name="signature"
Width="fill"
/>
</div>
<div className="tw-flex tw-flex-col-reverse sm:tw-justify-between sm:tw-flex-row tw-gap-1 tw-mt-4">
<Button Tag={Link} to="/" Variant="secondary" Width="hug">
Cancel
</Button>
<Button
Variant="primary"
Width="hug"
type="submit"
Disabled={formik.isSubmitting}
disabled={formik.isSubmitting}
>
{formik.isSubmitting ? 'Broadcasting...' : 'Broadcast Transaction'}
</Button>
</div>
<Button
Variant="primary"
Width="fill"
type="submit"
Disabled={formik.isSubmitting || !formik.values.file}
disabled={formik.isSubmitting || !formik.values.file}
>
Broadcast Transaction(s)
</Button>
</Form>
</FormikProvider>
);
Expand Down
4 changes: 4 additions & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export type BroadcastableSweepTransaction = Awaited<
>
>;

export type suiBroadcastTransactionParameters =
| Parameters<Sui['broadcastTransaction']>[0]
| Parameters<Tsui['broadcastTransaction']>[0];

export type BroadcastTransactionOptions = Awaited<
| Parameters<Hbar['broadcastTransaction']>[0]
| Parameters<Thbar['broadcastTransaction']>[0]
Expand Down

0 comments on commit e217c19

Please sign in to comment.