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/dfns #207

Closed
wants to merge 43 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
10dbed3
feat: add xrpl
Polybius93 Oct 1, 2024
f073de6
feat: modify vault query
Polybius93 Oct 2, 2024
82cb209
feat: modify use nft hook to make it more stable
Polybius93 Oct 3, 2024
49591c0
wip: adding xrpl conditions
Polybius93 Oct 8, 2024
c850a07
feat: modfiy isConnected conditions
Polybius93 Oct 9, 2024
e3c6075
wip: modify flow
Polybius93 Oct 10, 2024
e324bab
feat: remove ethereum observer, modify vault fetching
Polybius93 Oct 11, 2024
4d9a5f3
feat: modify balance fetching
Polybius93 Oct 11, 2024
7a2052a
feat: add ledger support
Polybius93 Oct 14, 2024
07215b7
feat: add working ledger wallet for xrpl
Polybius93 Oct 15, 2024
ca81126
feat: add gem wallet as xrp wallet option
Polybius93 Oct 16, 2024
c31c722
fix: modify value handling in form
Polybius93 Oct 17, 2024
39fa672
chore: change dlc-btc-lib package version
Polybius93 Oct 17, 2024
b023bc8
feat: modify xrpl related texts and lib version
Polybius93 Oct 18, 2024
a5e8265
fix: modify xrpl issuer address
Polybius93 Oct 18, 2024
8ac4d54
feat: modify loading states of xrpl wallets and abstract functions
Polybius93 Oct 21, 2024
bd056d0
chore: modify dlc-btc-lib version
Polybius93 Oct 21, 2024
402fd15
feat: modify form value validation, modify button navigation
Polybius93 Oct 22, 2024
6061294
chore: merge branch 'dev' into feat/xrpl-extended
Polybius93 Oct 23, 2024
0bb0f02
feat: modify devnet config
Polybius93 Oct 23, 2024
e21a79e
feat: modify dlc-btc-lib version, and related functions
Polybius93 Oct 23, 2024
d0ed713
feat: import attestor request functions from dlc-btc-lib
Polybius93 Oct 24, 2024
fb56040
chore: revert "feat: import attestor request functions from dlc-btc-lib"
Polybius93 Oct 24, 2024
f796e0a
feat: modify dlc-btc-lib and update related function arguments
Polybius93 Oct 24, 2024
0d18f11
chore: merge branch 'dev' into feat/multi-chain
Polybius93 Oct 24, 2024
3da007d
feat: add network connection context provider
Polybius93 Oct 24, 2024
012c759
feat: add enums for network, mint, redeem and tabs
Polybius93 Oct 30, 2024
5aa1195
feat: modify issuer address
Polybius93 Oct 30, 2024
2baa634
chore: merge branch 'dev' into feat/multi-chain
Polybius93 Nov 4, 2024
058d4c7
wip: add authenticate
Polybius93 Nov 5, 2024
16fb05c
wip: auth
Polybius93 Nov 5, 2024
8833f18
wip: modify token auth
Polybius93 Nov 5, 2024
7586bec
wip: add credentials
Polybius93 Nov 5, 2024
cd0d135
wip: add remaining psbt handlers for dfns
Polybius93 Nov 6, 2024
1d99500
feat: add dfns modal
Polybius93 Nov 7, 2024
11c4fe1
feat: add logs
Polybius93 Nov 7, 2024
2739246
feat: modify withdraw handling
Polybius93 Nov 19, 2024
f326029
feat: modify withdraw and deposit dfns functions
Polybius93 Nov 19, 2024
1f66a2f
feat: add dfns credentials register form and logic
Polybius93 Nov 19, 2024
3286ffc
feat: add dfns network map
Polybius93 Nov 20, 2024
b8335b8
chore: merge branch 'dev' into feat/dfns
Polybius93 Dec 2, 2024
ada07dd
feat: modify dfns modal form and config
Polybius93 Dec 3, 2024
1c807ea
feat: add organization dropdown to dfns modal
Polybius93 Dec 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions config.devnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@
"rippleIssuerAddress": "rLTBw1MEy45uE5qmkWseinbj7h4zmdQuR8",
"xrplWebsocket": "wss://s.altnet.rippletest.net:51233",
"ledgerApp": "Bitcoin Test",
"dfnsConfiguration": {
"dfnsBaseURL": "https://api.dfns.ninja",
"dfnsCustomerConfigurations": [
{
"name": "Tungsten",
"organizationID": "or-3pqgf-ugmhq-8969lp77c7f8uf81",
"applicationID": "ap-513sv-f5knb-811qggt4oh6hd5s9"
}
]
},
"merchants": [
{
"name": "Amber",
Expand Down
10 changes: 10 additions & 0 deletions config.mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@
"rippleIssuerAddress": "rGcyRGrZPaJAZbZDi4NqRFLA5GQH63iFpD",
"xrplWebsocket": "wss://xrpl.ws/",
"ledgerApp": "Bitcoin",
"dfnsConfiguration": {
"dfnsBaseURL": "https://api.dfns.ninja",
"dfnsCustomerConfigurations": [
{
"name": "Tungsten",
"organizationID": "or-3pqgf-ugmhq-8969lp77c7f8uf81",
"applicationID": "ap-513sv-f5knb-811qggt4oh6hd5s9"
}
]
},
"merchants": [
{
"name": "Amber",
Expand Down
10 changes: 10 additions & 0 deletions config.testnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@
"rippleIssuerAddress": "ra3oyRVfy4yD4NJPrVcewvDtisZ3FhkcYL",
"xrplWebsocket": "wss://testnet.xrpl-labs.com/",
"ledgerApp": "Bitcoin Test",
"dfnsConfiguration": {
"dfnsBaseURL": "https://api.dfns.ninja",
"dfnsCustomerConfigurations": [
{
"name": "Tungsten",
"organizationID": "or-3pqgf-ugmhq-8969lp77c7f8uf81",
"applicationID": "ap-513sv-f5knb-811qggt4oh6hd5s9"
}
]
},
"merchants": [
{
"name": "Amber",
Expand Down
38 changes: 38 additions & 0 deletions netlify/functions/get-dfns-auth-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { DfnsAuthenticator } from '@dfns/sdk';
import { WebAuthnSigner } from '@dfns/sdk-browser';
import { Handler } from '@netlify/functions';

const handler: Handler = async event => {
try {
const dfnsAuth = new DfnsAuthenticator({
appId: 'ap-7perp-pnqr6-8f5pgmmr6dtgh4n3',
baseUrl: 'https://app.dfns.ninja',
signer: new WebAuthnSigner(),
});

const { token } = await dfnsAuth.login({
username: 'us-12nks-o4ogd-943qhq5l5020410m',
orgId: 'or-4bcun-fj3tb-8np9ivfu5jnstkks',
});

console.log(
'tokeEEEEEEEEEEEEEEEEEEEEEEEEEEnEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE',
token
);

return {
statusCode: 200,
body: token,
};
} catch (error) {
console.error(error);
return {
statusCode: 500,
body: JSON.stringify({
error: error.message,
}),
};
}
};

export { handler };
34 changes: 34 additions & 0 deletions netlify/functions/get-wallets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { DfnsAuthenticator, DfnsDelegatedApiClient } from '@dfns/sdk';
import { WebAuthnSigner } from '@dfns/sdk-browser';
import { Handler } from '@netlify/functions';

const handler: Handler = async event => {
try {
const dfnsDelegated = new DfnsDelegatedApiClient({
baseUrl: 'https://app.dfns.ninja',
appId: 'ap-7perp-pnqr6-8f5pgmmr6dtgh4n3', // ID of the Application registered with DFNS
authToken:
'eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJhdXRoLmRmbnMubmluamEiLCJhdWQiOiJkZm5zOmF1dGg6dXNlciIsInN1YiI6Im9yLTRiY3VuLWZqM3RiLThucDlpdmZ1NWpuc3Rra3MiLCJqdGkiOiJ1ai0xNDJmay02aHZvZi05M2Q5cGY3NzE3cm1sZjYxIiwic2NvcGUiOiIiLCJwZXJtaXNzaW9ucyI6WyJBdXRoOkFjdGlvbjpTaWduIiwiQXV0aDpBcHBzOkNyZWF0ZSIsIkF1dGg6QXBwczpSZWFkIiwiQXV0aDpBcHBzOlVwZGF0ZSIsIkF1dGg6Q3JlZHM6Q3JlYXRlIiwiQXV0aDpDcmVkczpSZWFkIiwiQXV0aDpDcmVkczpVcGRhdGUiLCJBdXRoOkNyZWRzOkNvZGU6Q3JlYXRlIiwiQXV0aDpUeXBlczpBcHBsaWNhdGlvbiIsIkF1dGg6VHlwZXM6RW1wbG95ZWUiLCJBdXRoOlR5cGVzOkVuZFVzZXIiLCJBdXRoOlR5cGVzOlBhdCIsIkF1dGg6VHlwZXM6U2VydmljZUFjY291bnQiLCJBdXRoOlVzZXJzOkNyZWF0ZSIsIkF1dGg6VXNlcnM6RGVsZWdhdGUiLCJBdXRoOlVzZXJzOlJlYWQiLCJBdXRoOlVzZXJzOlVwZGF0ZSIsIkV4Y2hhbmdlczpDcmVhdGUiLCJFeGNoYW5nZXM6UmVhZCIsIkV4Y2hhbmdlczpEZWxldGUiLCJFeGNoYW5nZXM6RGVwb3NpdHM6Q3JlYXRlIiwiRXhjaGFuZ2VzOldpdGhkcmF3YWxzOkNyZWF0ZSIsIk9yZ3M6UmVhZCIsIk9yZ3M6VXBkYXRlIiwiT3JnczpTZXR0aW5nczpSZWFkIiwiT3JnczpTZXR0aW5nczpVcGRhdGUiLCJQZXJtaXNzaW9uQXNzaWdubWVudHM6Q3JlYXRlIiwiUGVybWlzc2lvbkFzc2lnbm1lbnRzOlJlYWQiLCJQZXJtaXNzaW9uQXNzaWdubWVudHM6UmV2b2tlIiwiUGVybWlzc2lvblByZWRpY2F0ZXM6QXJjaGl2ZSIsIlBlcm1pc3Npb25QcmVkaWNhdGVzOkNyZWF0ZSIsIlBlcm1pc3Npb25QcmVkaWNhdGVzOlJlYWQiLCJQZXJtaXNzaW9uUHJlZGljYXRlczpVcGRhdGUiLCJQZXJtaXNzaW9uczpBcmNoaXZlIiwiUGVybWlzc2lvbnM6Q3JlYXRlIiwiUGVybWlzc2lvbnM6UmVhZCIsIlBlcm1pc3Npb25zOlVwZGF0ZSIsIlBvbGljaWVzOkFyY2hpdmUiLCJQb2xpY2llczpDcmVhdGUiLCJQb2xpY2llczpSZWFkIiwiUG9saWNpZXM6VXBkYXRlIiwiUG9saWNpZXM6QXBwcm92YWxzOlJlYWQiLCJQb2xpY2llczpBcHByb3ZhbHM6QXBwcm92ZSIsIlNpZ25lcnM6TGlzdFNpZ25lcnMiLCJXYWxsZXRzOkJyb2FkY2FzdFRyYW5zYWN0aW9uIiwiV2FsbGV0czpDcmVhdGUiLCJXYWxsZXRzOkRlbGVnYXRlIiwiV2FsbGV0czpFeHBvcnQiLCJXYWxsZXRzOkdlbmVyYXRlU2lnbmF0dXJlIiwiV2FsbGV0czpJbXBvcnQiLCJXYWxsZXRzOlJlYWQiLCJXYWxsZXRzOlJlYWRTaWduYXR1cmUiLCJXYWxsZXRzOlJlYWRUcmFuc2FjdGlvbiIsIldhbGxldHM6UmVhZFRyYW5zZmVyIiwiV2FsbGV0czpUcmFuc2ZlckFzc2V0IiwiV2FsbGV0czpVcGRhdGUiLCJXYWxsZXRzOlRhZ3M6QWRkIiwiV2FsbGV0czpUYWdzOkRlbGV0ZSIsIldlYmhvb2tzOkNyZWF0ZSIsIldlYmhvb2tzOlJlYWQiLCJXZWJob29rczpVcGRhdGUiLCJXZWJob29rczpEZWxldGUiLCJXZWJob29rczpQaW5nIiwiV2ViaG9va3M6RXZlbnRzOlJlYWQiXSwiaHR0cHM6Ly9jdXN0b20vdXNlcm5hbWUiOiJkYW5pQGRsYy5saW5rIiwiaHR0cHM6Ly9jdXN0b20vYXBwX21ldGFkYXRhIjp7InVzZXJJZCI6InVzLTEybmtzLW80b2dkLTk0M3FocTVsNTAyMDQxMG0iLCJvcmdJZCI6Im9yLTRiY3VuLWZqM3RiLThucDlpdmZ1NWpuc3Rra3MiLCJ0b2tlbktpbmQiOiJUb2tlbiJ9LCJpYXQiOjE3MzA3OTY3MDUsImV4cCI6MTczMDgxODMwNX0.MplBRIoMls9sxUakQn1bXfwXxOK6u4TGosoOYlREY5oX4A_7VInLzfQ9-uU8P_TAgX-lnf9nCH6_UtjDTqC9Bg', // Auth token of the User
});

console.log('dfnsDelegated', dfnsDelegated);

const wallets = await dfnsDelegated.wallets.listWallets();
console.log('wallets', wallets);

return {
statusCode: 200,
body: JSON.stringify(wallets),
};
} catch (error) {
console.error(error);
return {
statusCode: 500,
body: JSON.stringify({
error: error.message,
}),
};
}
};

export { handler };
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
"dependencies": {
"@chakra-ui/icons": "^2.1.1",
"@chakra-ui/react": "^2.8.2",
"@dfns/sdk": "^0.5.9",
"@dfns/sdk-browser": "^0.5.9",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@fontsource-variable/onest": "^5.0.3",
Expand All @@ -46,7 +48,7 @@
"concurrently": "^8.2.2",
"d3": "^7.9.0",
"decimal.js": "^10.4.3",
"dlc-btc-lib": "2.4.18",
"dlc-btc-lib": "2.4.19-dfns-beta",
"dotenv": "^16.3.1",
"ethers": "5.7.2",
"formik": "^2.4.5",
Expand Down
1 change: 1 addition & 0 deletions public/images/logos/dfns-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/app/components/modals/components/modal-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AnyAction } from '@reduxjs/toolkit';
import { RootState } from '@store/index';
import { modalActions } from '@store/slices/modal/modal.actions';

import { DFNSModal } from '../dfns-modal/dfns-modal';
import { LedgerModal } from '../ledger-modal/ledger-modal';
import { SelectBitcoinWalletModal } from '../select-bitcoin-wallet-modal/select-bitcoin-wallet-modal';
import { SuccessfulFlowModal } from '../successful-flow-modal/successful-flow-modal';
Expand All @@ -21,6 +22,7 @@ export function ModalContainer(): React.JSX.Element {
isSuccesfulFlowModalOpen,
isSelectBitcoinWalletModalOpen,
isLedgerModalOpen,
isDFNSModalOpen,
} = useSelector((state: RootState) => state.modal);

const handleClosingModal = (actionCreator: () => AnyAction) => {
Expand Down Expand Up @@ -60,6 +62,10 @@ export function ModalContainer(): React.JSX.Element {
isOpen={isLedgerModalOpen}
handleClose={() => handleClosingModal(modalActions.toggleLedgerModalVisibility)}
/>
<DFNSModal
isOpen={isDFNSModalOpen}
handleClose={() => handleClosingModal(modalActions.toggleDFNSModalVisibility)}
/>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Button, FormControl, FormErrorMessage, FormLabel, Input, VStack } from '@chakra-ui/react';
import { DFNSCustomerConfiguration } from '@models/configuration';
import { useForm } from '@tanstack/react-form';

interface DFNSModalRegisterFormProps {
onSubmit: (
credentialCode: string,
selectedDFNSOrganization: DFNSCustomerConfiguration
) => Promise<void>;
selectedDFNSOrganization: DFNSCustomerConfiguration;
}

export function DFNSModalRegisterForm({
onSubmit,
selectedDFNSOrganization,
}: DFNSModalRegisterFormProps): React.JSX.Element {
const formAPI = useForm({
defaultValues: {
credentialCode: '',
},
onSubmit: async ({ value }) => {
await onSubmit(value.credentialCode, selectedDFNSOrganization);
},
});

return (
<VStack w={'100%'}>
<form
onSubmit={e => {
e.preventDefault();
e.stopPropagation();
void formAPI.handleSubmit();
}}
>
<VStack spacing={4} w={'100%'}>
<formAPI.Field
name="credentialCode"
validators={{
onChange: ({ value }) => {
if (!value) return 'Credential Code is required';
if (value.length < 9) return 'Credential Code must be at least 9 characters';
return undefined;
},
}}
children={field => (
<FormControl isInvalid={!!field.state.meta.errorMap.onChange}>
<FormLabel color={'white.01'} fontSize={'md'}>
Credential Code
</FormLabel>
<Input
type="string"
value={field.state.value}
onChange={e => field.handleChange(e.target.value)}
placeholder="xxxxxxxxx"
/>
<FormErrorMessage>{field.state.meta.errorMap.onChange}</FormErrorMessage>
</FormControl>
)}
/>
<formAPI.Subscribe
selector={state => [state.canSubmit]}
children={([canSubmit]) => (
<Button variant={'dfns'} type="submit" isDisabled={!canSubmit}>
Submit
</Button>
)}
/>
</VStack>
</form>
</VStack>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { HStack, Text } from '@chakra-ui/react';

interface DFNSModalErrorBoxProps {
error: string | undefined;
}

export function DFNSModalErrorBox({ error }: DFNSModalErrorBoxProps): React.JSX.Element | false {
return (
!!error && (
<HStack
p={'5%'}
w={'375px'}
spacing={4}
border={'1px solid'}
borderRadius={'md'}
borderColor={'red'}
justifyContent={'center'}
>
<Text fontFamily={'Inter'} fontSize={'xs'} fontWeight={'600'}>
{error}
</Text>
</HStack>
)
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Button, FormControl, FormErrorMessage, FormLabel, Input, VStack } from '@chakra-ui/react';
import { DFNSCustomerConfiguration } from '@models/configuration';
import { useForm } from '@tanstack/react-form';

interface DFNSModalLoginFormProps {
onSubmit: (email: string, selectedDFNSOrganization: DFNSCustomerConfiguration) => Promise<void>;
selectedDFNSOrganization: DFNSCustomerConfiguration;
}

const validateEmail = (email: string) => {
if (!email) return 'Email address is required';

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) return 'Please enter a valid email address';

const [localPart] = email.split('@');
if (localPart.length > 64) return 'Local part of email cannot exceed 64 characters';
if (email.length > 254) return 'Email address cannot exceed 254 characters';

return undefined;
};

export function DFNSModalLoginForm({
onSubmit,
selectedDFNSOrganization,
}: DFNSModalLoginFormProps): React.JSX.Element {
const formAPI = useForm({
defaultValues: {
email: '',
},
onSubmit: async ({ value }) => {
await onSubmit(value.email, selectedDFNSOrganization);
},
});

return (
<VStack w={'100%'}>
<form
onSubmit={e => {
e.preventDefault();
e.stopPropagation();
void formAPI.handleSubmit();
}}
>
<VStack spacing={4} w={'100%'}>
<formAPI.Field
name="email"
validators={{
onChange: ({ value }) => validateEmail(value),
}}
children={field => (
<FormControl isInvalid={!!field.state.meta.errorMap.onChange}>
<FormLabel color={'white.01'} fontSize={'md'}>
E-Mail Address
</FormLabel>
<Input
type="email"
value={field.state.value}
onChange={e => field.handleChange(e.target.value)}
placeholder="[email protected]"
/>
<FormErrorMessage>{field.state.meta.errorMap.onChange}</FormErrorMessage>
</FormControl>
)}
/>
<formAPI.Subscribe
selector={state => [state.canSubmit]}
children={([canSubmit]) => (
<Button variant={'dfns'} type="submit" isDisabled={!canSubmit}>
Submit
</Button>
)}
/>
</VStack>
</form>
</VStack>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ReactNode } from 'react';

import {
Image,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalOverlay,
VStack,
} from '@chakra-ui/react';

interface DFNSModalLayoutProps {
logo: string;
isOpen: boolean;
onClose: () => void;
children: ReactNode;
}

export function DFNSModalLayout({
logo,
isOpen,
onClose,
children,
}: DFNSModalLayoutProps): React.JSX.Element {
return (
<Modal isOpen={isOpen} onClose={onClose} variant={'dfns'}>
<ModalOverlay />
<ModalContent>
<ModalHeader>
<Image src={logo} alt={'DFNS Logo'} boxSize={'100px'} objectFit={'contain'} />
</ModalHeader>
<ModalCloseButton />
<ModalBody>
<VStack minHeight={'425px'} spacing={'25px'}>
{children}
</VStack>
</ModalBody>
</ModalContent>
</Modal>
);
}
Loading
Loading