From 1f66a2f4a1eee545e805f029166d8f345c7dfe90 Mon Sep 17 00:00:00 2001 From: Polybius93 Date: Tue, 19 Nov 2024 17:24:40 +0100 Subject: [PATCH] feat: add dfns credentials register form and logic --- config.testnet.json | 2 + .../components/dfns-modal-connect-button.tsx | 19 ------ .../dfns-modal-credentials-form.tsx | 62 +++++++++++++++++++ .../components/dfns-modal-error-box.tsx | 17 +++++ .../dfns-modal/components/dfns-modal-form.tsx | 12 +--- ...stack.tsx => dfns-modal-loading-stack.tsx} | 0 .../dfns-modal-navigator-button-stack.tsx | 28 +++++++++ .../components/dfns-modal-address-button.tsx} | 0 .../dfns-modal-select-address-menu.tsx} | 7 +-- ...s-icon.tsx => dfns-modal-success-icon.tsx} | 0 .../components/ledger-modal-error-box.tsx | 35 ----------- ...elect-address-menu-account-index-input.tsx | 54 ---------------- ...-select-address-menu-address-paginator.tsx | 35 ----------- ...modal-select-address-menu-table-header.tsx | 27 -------- .../modals/dfns-modal/dfns-modal.tsx | 47 +++++++++++--- .../select-bitcoin-wallet-modal.tsx | 2 - src/app/hooks/use-dfns.ts | 49 +++++++++++---- src/shared/models/configuration.ts | 2 + 18 files changed, 187 insertions(+), 211 deletions(-) delete mode 100644 src/app/components/modals/dfns-modal/components/dfns-modal-connect-button.tsx create mode 100644 src/app/components/modals/dfns-modal/components/dfns-modal-credentials-form.tsx create mode 100644 src/app/components/modals/dfns-modal/components/dfns-modal-error-box.tsx rename src/app/components/modals/dfns-modal/components/{ledger-modal-loading-stack.tsx => dfns-modal-loading-stack.tsx} (100%) create mode 100644 src/app/components/modals/dfns-modal/components/dfns-modal-navigator-button-stack.tsx rename src/app/components/modals/dfns-modal/components/{ledger-modal-select-address-menu/components/ledger-modal-address-button.tsx => dfns-modal-select-address-menu/components/dfns-modal-address-button.tsx} (100%) rename src/app/components/modals/dfns-modal/components/{ledger-modal-select-address-menu/ledger-modal-select-address-menu.tsx => dfns-modal-select-address-menu/dfns-modal-select-address-menu.tsx} (69%) rename src/app/components/modals/dfns-modal/components/{ledger-modal-success-icon.tsx => dfns-modal-success-icon.tsx} (100%) delete mode 100644 src/app/components/modals/dfns-modal/components/ledger-modal-error-box.tsx delete mode 100644 src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-account-index-input.tsx delete mode 100644 src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-address-paginator.tsx delete mode 100644 src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-table-header.tsx diff --git a/config.testnet.json b/config.testnet.json index ac5dad86..56e8a5b8 100644 --- a/config.testnet.json +++ b/config.testnet.json @@ -12,6 +12,8 @@ "rippleIssuerAddress": "ra3oyRVfy4yD4NJPrVcewvDtisZ3FhkcYL", "xrplWebsocket": "wss://testnet.xrpl-labs.com/", "ledgerApp": "Bitcoin Test", + "dfnsAppID": "ap-7pvrc-mei7e-9u3pfedu9tidiq6p", + "dfnsBaseURL": "http://localhost:3000/dfns-proxy/", "merchants": [ { "name": "Amber", diff --git a/src/app/components/modals/dfns-modal/components/dfns-modal-connect-button.tsx b/src/app/components/modals/dfns-modal/components/dfns-modal-connect-button.tsx deleted file mode 100644 index af425148..00000000 --- a/src/app/components/modals/dfns-modal/components/dfns-modal-connect-button.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { Button } from '@chakra-ui/react'; - -interface DFNSModalConnectButtonProps { - error: string | undefined; - connectDFNSWallet: () => void; -} - -export function DFNSModalConnectButton({ - error, - connectDFNSWallet, -}: DFNSModalConnectButtonProps): React.JSX.Element | false { - return ( - !!error && ( - - ) - ); -} diff --git a/src/app/components/modals/dfns-modal/components/dfns-modal-credentials-form.tsx b/src/app/components/modals/dfns-modal/components/dfns-modal-credentials-form.tsx new file mode 100644 index 00000000..ac3da033 --- /dev/null +++ b/src/app/components/modals/dfns-modal/components/dfns-modal-credentials-form.tsx @@ -0,0 +1,62 @@ +import { Button, FormControl, FormErrorMessage, FormLabel, Input, VStack } from '@chakra-ui/react'; +import { useForm } from '@tanstack/react-form'; + +interface DFNSModalRegisterFormProps { + onSubmit: (credentialCode: string) => Promise; +} + +export function DFNSModalRegisterForm({ onSubmit }: DFNSModalRegisterFormProps): React.JSX.Element { + const formAPI = useForm({ + defaultValues: { + credentialCode: '', + }, + onSubmit: async ({ value }) => { + await onSubmit(value.credentialCode); + }, + }); + + return ( + +
{ + e.preventDefault(); + e.stopPropagation(); + void formAPI.handleSubmit(); + }} + > + + { + if (!value) return 'Credential Code is required'; + if (value.length < 9) return 'Credential Code must be at least 9 characters'; + return undefined; + }, + }} + children={field => ( + + Credential Code + field.handleChange(e.target.value)} + placeholder="xxxxxxxxx" + /> + {field.state.meta.errorMap.onChange} + + )} + /> + [state.canSubmit]} + children={([canSubmit]) => ( + + )} + /> + +
+
+ ); +} diff --git a/src/app/components/modals/dfns-modal/components/dfns-modal-error-box.tsx b/src/app/components/modals/dfns-modal/components/dfns-modal-error-box.tsx new file mode 100644 index 00000000..95f8d20d --- /dev/null +++ b/src/app/components/modals/dfns-modal/components/dfns-modal-error-box.tsx @@ -0,0 +1,17 @@ +import { HStack, Text } from '@chakra-ui/react'; + +interface DFNSModalErrorBoxProps { + error: string | undefined; +} + +export function DFNSModalErrorBox({ error }: DFNSModalErrorBoxProps): React.JSX.Element | false { + return ( + !!error && ( + + + {error} + + + ) + ); +} diff --git a/src/app/components/modals/dfns-modal/components/dfns-modal-form.tsx b/src/app/components/modals/dfns-modal/components/dfns-modal-form.tsx index 883df1e4..fd1c3218 100644 --- a/src/app/components/modals/dfns-modal/components/dfns-modal-form.tsx +++ b/src/app/components/modals/dfns-modal/components/dfns-modal-form.tsx @@ -1,12 +1,4 @@ -import { - Box, - Button, - FormControl, - FormErrorMessage, - FormLabel, - Input, - VStack, -} from '@chakra-ui/react'; +import { Button, FormControl, FormErrorMessage, FormLabel, Input, VStack } from '@chakra-ui/react'; import { useForm } from '@tanstack/react-form'; interface DFNSModalLoginFormProps { @@ -21,7 +13,6 @@ export function DFNSModalLoginForm({ onSubmit }: DFNSModalLoginFormProps): React }, onSubmit: async ({ value }) => { await onSubmit(value.username, value.organizationId); - console.log('Form submitted:', value); }, }); @@ -78,7 +69,6 @@ export function DFNSModalLoginForm({ onSubmit }: DFNSModalLoginFormProps): React )} /> - [state.canSubmit]} children={([canSubmit]) => ( diff --git a/src/app/components/modals/dfns-modal/components/ledger-modal-loading-stack.tsx b/src/app/components/modals/dfns-modal/components/dfns-modal-loading-stack.tsx similarity index 100% rename from src/app/components/modals/dfns-modal/components/ledger-modal-loading-stack.tsx rename to src/app/components/modals/dfns-modal/components/dfns-modal-loading-stack.tsx diff --git a/src/app/components/modals/dfns-modal/components/dfns-modal-navigator-button-stack.tsx b/src/app/components/modals/dfns-modal/components/dfns-modal-navigator-button-stack.tsx new file mode 100644 index 00000000..61a7dc2b --- /dev/null +++ b/src/app/components/modals/dfns-modal/components/dfns-modal-navigator-button-stack.tsx @@ -0,0 +1,28 @@ +import { Button, Text, VStack } from '@chakra-ui/react'; + +interface DFNSModalNavigatorButtonProps { + isRegister: boolean; + setIsRegister: (isRegister: boolean) => void; + isVisible: boolean; +} + +export function DFNSModalNavigatorButton({ + isRegister, + setIsRegister, + isVisible, +}: DFNSModalNavigatorButtonProps): React.JSX.Element | false { + if (!isVisible) return false; + + return ( + + + {!isRegister + ? 'New user? Click the button below to register with your DFNS credential code' + : 'Existing user? Sign in with your username and organization ID'} + + + + ); +} diff --git a/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-address-button.tsx b/src/app/components/modals/dfns-modal/components/dfns-modal-select-address-menu/components/dfns-modal-address-button.tsx similarity index 100% rename from src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-address-button.tsx rename to src/app/components/modals/dfns-modal/components/dfns-modal-select-address-menu/components/dfns-modal-address-button.tsx diff --git a/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/ledger-modal-select-address-menu.tsx b/src/app/components/modals/dfns-modal/components/dfns-modal-select-address-menu/dfns-modal-select-address-menu.tsx similarity index 69% rename from src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/ledger-modal-select-address-menu.tsx rename to src/app/components/modals/dfns-modal/components/dfns-modal-select-address-menu/dfns-modal-select-address-menu.tsx index 3cb07d6a..7e17b070 100644 --- a/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/ledger-modal-select-address-menu.tsx +++ b/src/app/components/modals/dfns-modal/components/dfns-modal-select-address-menu/dfns-modal-select-address-menu.tsx @@ -1,7 +1,6 @@ import { ButtonGroup, Text, VStack } from '@chakra-ui/react'; -import { DFNSModalAddressButton } from './components/ledger-modal-address-button'; -import { DFNSModalSelectAddressMenuAddressPaginator } from './components/ledger-modal-select-address-menu-address-paginator'; +import { DFNSModalAddressButton } from './components/dfns-modal-address-button'; interface DFNSModalSelectAddressMenuProps { taprootAddresses: { address: string | undefined; walletID: string }[] | undefined; @@ -33,10 +32,6 @@ export function DFNSModalSelectAddressMenu({ /> ))} - {/* */} ) ); diff --git a/src/app/components/modals/dfns-modal/components/ledger-modal-success-icon.tsx b/src/app/components/modals/dfns-modal/components/dfns-modal-success-icon.tsx similarity index 100% rename from src/app/components/modals/dfns-modal/components/ledger-modal-success-icon.tsx rename to src/app/components/modals/dfns-modal/components/dfns-modal-success-icon.tsx diff --git a/src/app/components/modals/dfns-modal/components/ledger-modal-error-box.tsx b/src/app/components/modals/dfns-modal/components/ledger-modal-error-box.tsx deleted file mode 100644 index 9ee0c172..00000000 --- a/src/app/components/modals/dfns-modal/components/ledger-modal-error-box.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { HStack, Text } from '@chakra-ui/react'; - -interface LedgerModalErrorBoxProps { - error: string | undefined; -} - -function formatErrorMessage(error: string): string { - const errorMessages: Record = { - '0x6985': 'Action Rejected by User', - '0x5515': 'Locked Device', - '0x6a80': - "Invalid data received. Please ensure your Ledger hardware's firmware and Bitcoin app are up to date", - }; - - for (const [code, message] of Object.entries(errorMessages)) { - if (error.includes(code)) { - return message; - } - } - return error; -} - -export function LedgerModalErrorBox({ - error, -}: LedgerModalErrorBoxProps): React.JSX.Element | false { - return ( - !!error && ( - - - {formatErrorMessage(error || '')} - - - ) - ); -} diff --git a/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-account-index-input.tsx b/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-account-index-input.tsx deleted file mode 100644 index c78fa1d7..00000000 --- a/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-account-index-input.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { useState } from 'react'; - -import { Button, HStack, NumberInput, NumberInputField, Text } from '@chakra-ui/react'; - -interface LedgerModalSelectAddressMenuAccountIndexInputProps { - walletAccountIndex: number; - setWalletAccountIndex: React.Dispatch>; -} - -export function LedgerModalSelectAddressMenuAccountIndexInput({ - walletAccountIndex, - setWalletAccountIndex, -}: LedgerModalSelectAddressMenuAccountIndexInputProps): React.JSX.Element { - const [currentWalletAccountIndex, setCurrentWalletAccountIndex] = useState(walletAccountIndex); - - return ( - - - Account Index: - - setCurrentWalletAccountIndex(Number(walletAccountIndex))} - > - - - - - - - ); -} diff --git a/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-address-paginator.tsx b/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-address-paginator.tsx deleted file mode 100644 index 911968b9..00000000 --- a/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-address-paginator.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { ArrowBackIcon, ArrowForwardIcon } from '@chakra-ui/icons'; -import { HStack, IconButton, Text } from '@chakra-ui/react'; - -interface LedgerModalSelectAddressMenuAddressPaginatorProps { - displayedAddressesStartIndex: number; - setDisplayedAddressesStartIndex: React.Dispatch>; -} - -export function DFNSModalSelectAddressMenuAddressPaginator({ - displayedAddressesStartIndex, - setDisplayedAddressesStartIndex, -}: LedgerModalSelectAddressMenuAddressPaginatorProps): React.JSX.Element { - return ( - - } - onClick={() => setDisplayedAddressesStartIndex(displayedAddressesStartIndex - 5)} - /> - - {displayedAddressesStartIndex + 1} - {displayedAddressesStartIndex + 5} - - } - onClick={() => setDisplayedAddressesStartIndex(displayedAddressesStartIndex + 5)} - /> - - ); -} diff --git a/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-table-header.tsx b/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-table-header.tsx deleted file mode 100644 index 17d0ff5b..00000000 --- a/src/app/components/modals/dfns-modal/components/ledger-modal-select-address-menu/components/ledger-modal-select-address-menu-table-header.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { HStack, Stack, Text } from '@chakra-ui/react'; - -export function LedgerModalSelectAddressMenuTableHeader(): React.JSX.Element { - return ( - - - - - address - - - - - balance - - - - - ); -} diff --git a/src/app/components/modals/dfns-modal/dfns-modal.tsx b/src/app/components/modals/dfns-modal/dfns-modal.tsx index d078fbea..fc43d79d 100644 --- a/src/app/components/modals/dfns-modal/dfns-modal.tsx +++ b/src/app/components/modals/dfns-modal/dfns-modal.tsx @@ -6,26 +6,29 @@ import { BitcoinWalletContext, BitcoinWalletContextState, } from '@providers/bitcoin-wallet-context-provider'; -import { DFNSDLCHandler } from 'dlc-btc-lib'; import { delay } from 'dlc-btc-lib/utilities'; import { ModalComponentProps } from '../components/modal-container'; +import { DFNSModalRegisterForm } from './components/dfns-modal-credentials-form'; +import { DFNSModalErrorBox } from './components/dfns-modal-error-box'; import { DFNSModalLoginForm } from './components/dfns-modal-form'; import { DFNSModalLayout } from './components/dfns-modal-layout'; -import { DFNSModalLoadingStack } from './components/ledger-modal-loading-stack'; -import { DFNSModalSelectAddressMenu } from './components/ledger-modal-select-address-menu/ledger-modal-select-address-menu'; -import { DFNSModalSuccessIcon } from './components/ledger-modal-success-icon'; +import { DFNSModalLoadingStack } from './components/dfns-modal-loading-stack'; +import { DFNSModalNavigatorButton } from './components/dfns-modal-navigator-button-stack'; +import { DFNSModalSelectAddressMenu } from './components/dfns-modal-select-address-menu/dfns-modal-select-address-menu'; +import { DFNSModalSuccessIcon } from './components/dfns-modal-success-icon'; export function DFNSModal({ isOpen, handleClose }: ModalComponentProps): React.JSX.Element { - const { connectDFNSWallet, selectWallet, isLoading } = useDFNS(); + const { connectDFNSWallet, registerCredentials, selectWallet, isLoading } = useDFNS(); - const { setBitcoinWalletContextState, dlcHandler } = useContext(BitcoinWalletContext); + const { setBitcoinWalletContextState } = useContext(BitcoinWalletContext); const [taprootAddresses, setTaprootAddresses] = useState< { address: string | undefined; walletID: string }[] | undefined >(undefined); const [isSuccesful, setIsSuccesful] = useState(false); + const [isRegister, setIsRegister] = useState(false); const [isLoadingAddressList, setIsLoadingAddressList] = useState(true); const [dfnsError, setDFNSError] = useState(undefined); @@ -36,13 +39,28 @@ export function DFNSModal({ isOpen, handleClose }: ModalComponentProps): React.J setDFNSError(undefined); } + async function setError(error: string) { + setDFNSError(error); + await delay(5000); + setDFNSError(undefined); + } + async function connectDFNSWalletAndGetAddresses(username: string, organizationID: string) { try { const taprootAddresses = await connectDFNSWallet(username, organizationID); setTaprootAddresses(taprootAddresses); setIsLoadingAddressList(false); } catch (error: any) { - setDFNSError(error.message); + await setError(error.message); + } + } + + async function handleRegisterCredentials(code: string) { + try { + await registerCredentials(code); + setIsRegister(false); + } catch (error: any) { + await setError(error.message); } } @@ -55,7 +73,7 @@ export function DFNSModal({ isOpen, handleClose }: ModalComponentProps): React.J setBitcoinWalletContextState(BitcoinWalletContextState.READY); handleClose(); } catch (error: any) { - setDFNSError(error.message); + await setError(error.message); } } @@ -63,7 +81,11 @@ export function DFNSModal({ isOpen, handleClose }: ModalComponentProps): React.J - + {!isRegister ? ( + + ) : ( + + )} - {/* */} + + ); } diff --git a/src/app/components/modals/select-bitcoin-wallet-modal/select-bitcoin-wallet-modal.tsx b/src/app/components/modals/select-bitcoin-wallet-modal/select-bitcoin-wallet-modal.tsx index 66e521ac..64c7d8b4 100644 --- a/src/app/components/modals/select-bitcoin-wallet-modal/select-bitcoin-wallet-modal.tsx +++ b/src/app/components/modals/select-bitcoin-wallet-modal/select-bitcoin-wallet-modal.tsx @@ -3,7 +3,6 @@ import { useDispatch } from 'react-redux'; import { VStack, useToast } from '@chakra-ui/react'; import { ModalComponentProps } from '@components/modals/components/modal-container'; import { ModalLayout } from '@components/modals/components/modal.layout'; -import { useDFNS } from '@hooks/use-dfns'; import { useLeather } from '@hooks/use-leather'; import { useUnisat } from '@hooks/use-unisat'; import { BitcoinWalletType, bitcoinWallets } from '@models/wallet'; @@ -20,7 +19,6 @@ export function SelectBitcoinWalletModal({ const toast = useToast(); const { connectLeatherWallet } = useLeather(); const { connectUnisatWallet } = useUnisat(); - const { connectDFNSWallet } = useDFNS(); async function handleLogin(walletType: BitcoinWalletType) { switch (walletType) { diff --git a/src/app/hooks/use-dfns.ts b/src/app/hooks/use-dfns.ts index 6836ac01..5293cf1c 100644 --- a/src/app/hooks/use-dfns.ts +++ b/src/app/hooks/use-dfns.ts @@ -1,6 +1,6 @@ import { useContext, useState } from 'react'; -import { DfnsAuthenticator } from '@dfns/sdk'; +import { DfnsApiClient, DfnsAuthenticator } from '@dfns/sdk'; import { WebAuthnSigner } from '@dfns/sdk-browser'; import { BitcoinWalletType } from '@models/wallet'; import { BitcoinWalletContext } from '@providers/bitcoin-wallet-context-provider'; @@ -16,6 +16,7 @@ interface UseDFNSReturnType { userName: string, organizationID: string ) => Promise<{ address: string | undefined; walletID: string }[]>; + registerCredentials: (code: string) => Promise; selectWallet: (walletId: string) => Promise; handleFundingTransaction: ( dlcHandler: DFNSDLCHandler, @@ -55,8 +56,8 @@ export function useDFNS(): UseDFNSReturnType { const signer = new WebAuthnSigner(); const authApi = new DfnsAuthenticator({ - appId: 'ap-7pvrc-mei7e-9u3pfedu9tidiq6p', - baseUrl: 'http://localhost:3000/dfns-proxy/', + appId: appConfiguration.dfnsAppID, + baseUrl: appConfiguration.dfnsBaseURL, signer, }); @@ -66,8 +67,8 @@ export function useDFNS(): UseDFNSReturnType { }); const dfnsDLCHandler = new DFNSDLCHandler( - 'ap-7pvrc-mei7e-9u3pfedu9tidiq6p', - 'http://localhost:3000/dfns-proxy/', + appConfiguration.dfnsAppID, + appConfiguration.dfnsBaseURL, token, BITCOIN_NETWORK_MAP[appConfiguration.bitcoinNetwork], appConfiguration.bitcoinBlockchainURL, @@ -108,9 +109,34 @@ export function useDFNS(): UseDFNSReturnType { } } - // async function registerCredentials(): Promise { - // const dnfsAPIClient = new DfnsApiClient({}); - // } + async function registerCredentials(code: string): Promise { + const signer = new WebAuthnSigner(); + const dfnsAPI = new DfnsApiClient({ + appId: appConfiguration.dfnsAppID, + authToken: undefined, + baseUrl: appConfiguration.dfnsBaseURL, + signer, + }); + + const challenge = await dfnsAPI.auth.createCredentialChallengeWithCode({ + body: { code, credentialKind: 'Fido2' }, + }); + + if (challenge.kind !== 'Fido2') { + throw Error('Not a Fido2 challenge'); // this check is meant for proper typescript type inferrence + } + + const attestation = await new WebAuthnSigner().create(challenge); + + await dfnsAPI.auth.createCredentialWithCode({ + body: { + credentialName: 'iBTC App - ' + new Date().toISOString(), + challengeIdentifier: challenge.challengeIdentifier, + credentialKind: attestation.credentialKind, + credentialInfo: attestation.credentialInfo, + }, + }); + } /** * Creates the Funding Transaction and signs it with Leather Wallet. @@ -132,8 +158,7 @@ export function useDFNS(): UseDFNSReturnType { vault, BigInt(shiftValue(bitcoinAmount)), attestorGroupPublicKey, - feeRateMultiplier, - 500n + feeRateMultiplier ); setIsLoading([true, 'Sign Funding Transaction in your DFNS Wallet']); @@ -193,8 +218,7 @@ export function useDFNS(): UseDFNSReturnType { BigInt(shiftValue(withdrawAmount)), attestorGroupPublicKey, vault.fundingTxId, - feeRateMultiplier, - 500n + feeRateMultiplier ); setIsLoading([true, 'Sign Withdraw Transaction in your DFNS Wallet']); @@ -213,6 +237,7 @@ export function useDFNS(): UseDFNSReturnType { return { connectDFNSWallet, + registerCredentials, selectWallet, handleFundingTransaction, handleDepositTransaction, diff --git a/src/shared/models/configuration.ts b/src/shared/models/configuration.ts index 14ef6743..847bf7c7 100644 --- a/src/shared/models/configuration.ts +++ b/src/shared/models/configuration.ts @@ -42,6 +42,8 @@ export interface Configuration { bitcoinBlockchainFeeEstimateURL: string; rippleIssuerAddress: string; ledgerApp: string; + dfnsAppID: string; + dfnsBaseURL: string; merchants: Merchant[]; protocols: Protocol[]; }