Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sui): broadcast transaction #465

3 changes: 3 additions & 0 deletions electron/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Dot, Tdot } from '@bitgo/sdk-coin-dot';
import { Sol, Tsol } from '@bitgo/sdk-coin-sol';
import { Hbar, Thbar } from '@bitgo/sdk-coin-hbar';
import { Algo, Talgo } from '@bitgo/sdk-coin-algo';
import { Sui, Tsui } from '@bitgo-beta/sdk-coin-sui';

export type createAdaBroadcastableSweepTransactionParameters =
| Parameters<Ada['createBroadcastableSweepTransaction']>[0]
Expand Down Expand Up @@ -34,6 +35,8 @@ export type BroadcastTransactionOptions = Awaited<
| Parameters<Thbar['broadcastTransaction']>[0]
| Parameters<Algo['broadcastTransaction']>[0]
| Parameters<Talgo['broadcastTransaction']>[0]
| Parameters<Sui['broadcastTransaction']>[0]
| Parameters<Tsui['broadcastTransaction']>[0]
>;

export type BroadcastTransactionResult = Awaited<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { broadcastTransactionCoins } from '~/helpers/config';
import { HederaForm } from './HederaForm';
import { BackToHomeHelperText } from '~/components/BackToHomeHelperText';
import { AlgorandForm } from '~/containers/BroadcastTransactionCoin/AlgorandForm';
import { SuiForm } from '~/containers/BroadcastTransactionCoin/SuiForm';

function Form() {
const { env, coin } = useParams<'env' | 'coin'>();
Expand Down Expand Up @@ -114,6 +115,9 @@ function Form() {
}}
/>
);
case 'sui':
case 'tsui':
return ( <SuiForm /> );

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

function hasBroadcastableTransactions(
json: unknown
): json is
| suiBroadcastTransactionParameters {
const data = json as
| suiBroadcastTransactionParameters;
return (
data &&
data.transactions &&
data.transactions.length > 0
);
}

export function SuiForm() {
const { env, coin } = useParams<'env' | 'coin'>();
const [, setAlert] = useAlertBanner();

const environment = safeEnv(env);
const navigate = useNavigate();
const formik = useFormik<{ file?: File }>({
initialValues: {
file: undefined,
},
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>
<div className="tw-mb-4">
<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>
<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>
);
}
4 changes: 2 additions & 2 deletions src/helpers/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -859,8 +859,8 @@ export const broadcastTransactionCoins: Record<
BitgoEnv,
readonly CoinMetadata[]
> = {
prod: [allCoinMetas.hbar, allCoinMetas.algo] as const,
test: [allCoinMetas.thbar, allCoinMetas.talgo] as const,
prod: [allCoinMetas.hbar, allCoinMetas.algo, allCoinMetas.sui] as const,
test: [allCoinMetas.thbar, allCoinMetas.talgo, allCoinMetas.tsui] as const,
};

export type WalletMetadata = {
Expand Down
11 changes: 10 additions & 1 deletion src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '@bitgo/sdk-coin-trx';
import { Hbar, Thbar } from '@bitgo/sdk-coin-hbar';
import { Algo, Talgo } from '@bitgo/sdk-coin-algo';
import { Sui, Tsui } from '@bitgo-beta/sdk-coin-sui';

export type createAdaBroadcastableSweepTransactionParameters =
| Parameters<Ada['createBroadcastableSweepTransaction']>[0]
Expand All @@ -29,19 +30,27 @@ 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]
| Parameters<Algo['broadcastTransaction']>[0]
| Parameters<Talgo['broadcastTransaction']>[0]
| Parameters<Sui['broadcastTransaction']>[0]
| Parameters<Tsui['broadcastTransaction']>[0]
>;

export type BroadcastTransactionResult = Awaited<
ReturnType<
| Hbar['broadcastTransaction']
| Thbar['broadcastTransaction']
| Algo['broadcastTransaction']
| Talgo['broadcastTransaction']>
| Talgo['broadcastTransaction']
| Sui['broadcastTransaction']
| Tsui['broadcastTransaction']>
>;

export type AdaRecoveryConsolidationRecoveryOptions =
Expand Down