diff --git a/frontend/packages/signless-transactions/src/components/create-session-modal/create-session-modal.tsx b/frontend/packages/signless-transactions/src/components/create-session-modal/create-session-modal.tsx index eb378aa55..57c700ca2 100644 --- a/frontend/packages/signless-transactions/src/components/create-session-modal/create-session-modal.tsx +++ b/frontend/packages/signless-transactions/src/components/create-session-modal/create-session-modal.tsx @@ -4,8 +4,9 @@ import { decodeAddress } from '@gear-js/api'; import { KeyringPair } from '@polkadot/keyring/types'; import { useMemo, useState } from 'react'; import { useForm } from 'react-hook-form'; +import { useRandomPairOr } from '@/hooks'; import { useSignlessTransactions } from '../../context'; -import { getMilliseconds, getRandomPair, getUnlockedPair } from '../../utils'; +import { getMilliseconds, getUnlockedPair } from '../../utils'; import styles from './create-session-modal.module.css'; import { SignlessParams } from '../signless-params-list'; import { AccountPair } from '../account-pair'; @@ -32,7 +33,7 @@ function CreateSessionModal({ close, onSessionCreate = async () => {}, shouldIss const { errors } = formState; const { savePair, storagePair, storageVoucher, storageVoucherBalance, createSession } = useSignlessTransactions(); - const pair = useMemo(() => storagePair || getRandomPair(), [storagePair]); + const pair = useRandomPairOr(storagePair); const [isLoading, setIsLoading] = useState(false); @@ -60,6 +61,8 @@ function CreateSessionModal({ close, onSessionCreate = async () => {}, shouldIss const formattedIssueVoucherValue = getFormattedBalance(issueVoucherValue); const onSubmit = async ({ password, durationMinutes }: typeof DEFAULT_VALUES) => { + if (!pair) throw new Error('Signless pair is not initialized'); + const duration = getMilliseconds(Number(durationMinutes)); const key = decodeAddress(pair.address); const allowedActions = ACTIONS; diff --git a/frontend/packages/signless-transactions/src/hooks/index.ts b/frontend/packages/signless-transactions/src/hooks/index.ts index a500652e6..53349ea92 100644 --- a/frontend/packages/signless-transactions/src/hooks/index.ts +++ b/frontend/packages/signless-transactions/src/hooks/index.ts @@ -5,6 +5,7 @@ import { SendSignlessMessageOptions, } from './use-signless-send-message'; import { useIsAvailable } from './use-is-available'; +import { useRandomPairOr } from './use-random-pair-or'; -export { useCreateSession, useSignlessSendMessage, useSignlessSendMessageHandler, useIsAvailable }; +export { useCreateSession, useSignlessSendMessage, useSignlessSendMessageHandler, useIsAvailable, useRandomPairOr }; export type { SendSignlessMessageOptions }; diff --git a/frontend/packages/signless-transactions/src/hooks/use-random-pair-or.ts b/frontend/packages/signless-transactions/src/hooks/use-random-pair-or.ts new file mode 100644 index 000000000..4dcf21545 --- /dev/null +++ b/frontend/packages/signless-transactions/src/hooks/use-random-pair-or.ts @@ -0,0 +1,24 @@ +import { GearKeyring } from '@gear-js/api'; +import { useAlert } from '@gear-js/react-hooks'; +import { KeyringPair$Json, KeyringPair } from '@polkadot/keyring/types'; +import { useState, useEffect } from 'react'; + +function useRandomPairOr(storagePair: KeyringPair$Json | undefined) { + const alert = useAlert(); + + const [pair, setPair] = useState(storagePair); + + useEffect(() => { + if (pair) return; + + GearKeyring.create('signlessPair') + .then(({ keyring }) => setPair(keyring)) + .catch(({ message }: Error) => alert.error(message)); + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return pair; +} + +export { useRandomPairOr }; diff --git a/frontend/packages/signless-transactions/src/utils.ts b/frontend/packages/signless-transactions/src/utils.ts index 8de1199c8..b3240af54 100644 --- a/frontend/packages/signless-transactions/src/utils.ts +++ b/frontend/packages/signless-transactions/src/utils.ts @@ -1,9 +1,8 @@ -import { decodeAddress, GearTransaction, IGearEvent, IGearVoucherEvent } from '@gear-js/api'; +import { decodeAddress, GearKeyring, GearTransaction, IGearEvent, IGearVoucherEvent } from '@gear-js/api'; import { AlertContainerFactory } from '@gear-js/react-hooks'; import { SubmittableExtrinsic } from '@polkadot/api/types'; -import { encodeAddress, Keyring } from '@polkadot/keyring'; +import { encodeAddress } from '@polkadot/keyring'; import { KeyringPair$Json, KeyringPair } from '@polkadot/keyring/types'; -import { mnemonicGenerate } from '@polkadot/util-crypto'; const MULTIPLIER = { MS: 1000, @@ -110,21 +109,6 @@ const copyToClipboard = async ({ } }; -const getRandomPair = () => { - const seed = mnemonicGenerate(); +const getUnlockedPair = (pair: KeyringPair$Json, password: string) => GearKeyring.fromJson(pair, password); - const keyring = new Keyring({ type: 'sr25519' }); - const pair = keyring.addFromMnemonic(seed); - - return pair; -}; - -const getUnlockedPair = (pair: KeyringPair$Json, password: string) => { - const keyring = new Keyring({ type: 'sr25519' }); - const result = keyring.addFromJson(pair); - - result.unlock(password); - return result; -}; - -export { getMilliseconds, getDHMS, getVaraAddress, shortenString, copyToClipboard, getRandomPair, getUnlockedPair }; +export { getMilliseconds, getDHMS, getVaraAddress, shortenString, copyToClipboard, getUnlockedPair };