diff --git a/electron/types.ts b/electron/types.ts index 8378ec4f..542b317f 100644 --- a/electron/types.ts +++ b/electron/types.ts @@ -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[0] @@ -34,6 +35,8 @@ export type BroadcastTransactionOptions = Awaited< | Parameters[0] | Parameters[0] | Parameters[0] + | Parameters[0] + | Parameters[0] >; export type BroadcastTransactionResult = Awaited< diff --git a/src/containers/BroadcastTransactionCoin/BroadcastTransactionCoin.tsx b/src/containers/BroadcastTransactionCoin/BroadcastTransactionCoin.tsx index e028223c..1bd86c7d 100644 --- a/src/containers/BroadcastTransactionCoin/BroadcastTransactionCoin.tsx +++ b/src/containers/BroadcastTransactionCoin/BroadcastTransactionCoin.tsx @@ -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'>(); @@ -114,6 +115,9 @@ function Form() { }} /> ); + case 'sui': + case 'tsui': + return ( ); default: throw new Error(`Unsupported coin: ${String(coin)}`); diff --git a/src/containers/BroadcastTransactionCoin/SuiForm.tsx b/src/containers/BroadcastTransactionCoin/SuiForm.tsx new file mode 100644 index 00000000..22b6a4de --- /dev/null +++ b/src/containers/BroadcastTransactionCoin/SuiForm.tsx @@ -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 ( + +
+
+ { + formik + .setFieldValue('file', event.currentTarget.files?.[0]) + .catch(console.error); + }} + /> +
+ +
+
+ ); +} diff --git a/src/helpers/config.ts b/src/helpers/config.ts index 2a251933..5a0b5d53 100644 --- a/src/helpers/config.ts +++ b/src/helpers/config.ts @@ -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 = { diff --git a/src/utils/types.ts b/src/utils/types.ts index 81a7ae74..8d7b1853 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -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[0] @@ -29,11 +30,17 @@ export type BroadcastableSweepTransaction = Awaited< > >; +export type suiBroadcastTransactionParameters = + | Parameters[0] + | Parameters[0]; + export type BroadcastTransactionOptions = Awaited< | Parameters[0] | Parameters[0] | Parameters[0] | Parameters[0] + | Parameters[0] + | Parameters[0] >; export type BroadcastTransactionResult = Awaited< @@ -41,7 +48,9 @@ export type BroadcastTransactionResult = Awaited< | Hbar['broadcastTransaction'] | Thbar['broadcastTransaction'] | Algo['broadcastTransaction'] - | Talgo['broadcastTransaction']> + | Talgo['broadcastTransaction'] + | Sui['broadcastTransaction'] + | Tsui['broadcastTransaction']> >; export type AdaRecoveryConsolidationRecoveryOptions =