Skip to content
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
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
6 changes: 4 additions & 2 deletions src/bonsai/rest/lib/nobleTransactionStoreEffect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,16 @@ const selectNobleTxAuthorizedAccount = createAppSelector(
return undefined;
}

const localNobleWallet = localWalletManager.getLocalNobleWallet(localWalletNonce);
const localNobleWallet = localWalletManager.getCachedLocalNobleWallet(localWalletNonce);

const nobleAddress = convertBech32Address({
address: parentSubaccountInfo.wallet,
bech32Prefix: NOBLE_BECH32_PREFIX,
});

const isCorrectWallet = localNobleWallet?.address === nobleAddress;

if (!isCorrectWallet || localNobleWallet == null) return undefined;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant check since isCorrectWallet already checks

if (!isCorrectWallet) return undefined;

return {
localNobleWallet,
Expand Down
10 changes: 1 addition & 9 deletions src/constants/account.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { DydxAddress, EvmAddress } from './wallets';
import type { DydxAddress } from './wallets';
import { SolAddress } from './wallets';

export enum OnboardingSteps {
Expand Down Expand Up @@ -36,14 +36,6 @@ export enum EvmDerivedAccountStatus {
Derived,
}

export type EvmDerivedAddresses = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deprecated

version?: string;
[EvmAddress: EvmAddress]: {
encryptedSignature?: string;
dydxAddress?: DydxAddress;
};
};

export type SolDerivedAddresses = {
version?: string;
} & Record<
Expand Down
93 changes: 38 additions & 55 deletions src/hooks/Onboarding/useGenerateKeys.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { useEffect, useState } from 'react';

import { log } from 'console';
import { AES } from 'crypto-js';

import { EvmDerivedAccountStatus } from '@/constants/account';
import { AnalyticsEvents, AnalyticsUserProperties } from '@/constants/analytics';
import { DydxAddress } from '@/constants/wallets';

import { useAppDispatch } from '@/state/appTypes';
import { setSavedEncryptedSignature } from '@/state/wallet';

import { identify, track } from '@/lib/analytics/analytics';
import { onboardingManager } from '@/lib/onboarding/OnboardingSupervisor';
import { parseWalletError } from '@/lib/wallet';

import { useAccounts } from '../useAccounts';
Expand All @@ -28,9 +25,8 @@ type GenerateKeysProps = {

export function useGenerateKeys(generateKeysProps?: GenerateKeysProps) {
const stringGetter = useStringGetter();
const dispatch = useAppDispatch();
const { status, setStatus, onKeysDerived } = generateKeysProps ?? {};
const { sourceAccount, setWalletFromSignature } = useAccounts();
const { sourceAccount } = useAccounts();
const [derivationStatus, setDerivationStatus] = useState(
status ?? EvmDerivedAccountStatus.NotDerived
);
Expand Down Expand Up @@ -79,9 +75,9 @@ export function useGenerateKeys(generateKeysProps?: GenerateKeysProps) {
if (networkSwitched) await deriveKeys().then(onKeysDerived);
};

// 2. Derive keys from EVM account
// 2. Derive keys from EVM account using OnboardingSupervisor
const { getWalletFromSignature } = useDydxClient();
const { getSubaccounts } = useAccounts();
const { getSubaccounts, setLocalDydxWallet, setHdKey } = useAccounts();

const isDeriving = ![
EvmDerivedAccountStatus.NotDerived,
Expand All @@ -90,74 +86,61 @@ export function useGenerateKeys(generateKeysProps?: GenerateKeysProps) {

const signMessageAsync = useSignForWalletDerivation(sourceAccount.walletInfo);

const staticEncryptionKey = import.meta.env.VITE_PK_ENCRYPTION_KEY;

const deriveKeys = async () => {
setError(undefined);

try {
// 1. First signature
setDerivationStatus(EvmDerivedAccountStatus.Deriving);

const signature = await signMessageAsync();
track(
AnalyticsEvents.OnboardingDeriveKeysSignatureReceived({
signatureNumber: 1,
})
);
const { wallet: dydxWallet } = await getWalletFromSignature({ signature });
// Track first signature request
const wrappedSignMessage = async (requestNumber: 1 | 2) => {
if (requestNumber === 2) {
setDerivationStatus(EvmDerivedAccountStatus.EnsuringDeterminism);
}

// 2. Ensure signature is deterministic
// Check if subaccounts exist
const dydxAddress = dydxWallet.address as DydxAddress;
let hasPreviousTransactions = false;
const sig = await signMessageAsync();

try {
track(
AnalyticsEvents.OnboardingDeriveKeysSignatureReceived({ signatureNumber: requestNumber })
);

return sig;
};

// Check for previous transactions
const checkPreviousTransactions = async (dydxAddress: DydxAddress) => {
const subaccounts = await getSubaccounts({ dydxAddress });
hasPreviousTransactions = subaccounts.length > 0;
const hasPreviousTransactions = subaccounts.length > 0;

track(AnalyticsEvents.OnboardingAccountDerived({ hasPreviousTransactions }));
identify(AnalyticsUserProperties.IsNewUser(!hasPreviousTransactions));

if (!hasPreviousTransactions) {
identify(AnalyticsUserProperties.IsNewUser(true));
setDerivationStatus(EvmDerivedAccountStatus.EnsuringDeterminism);
return hasPreviousTransactions;
};

// Second signature
const additionalSignature = await signMessageAsync();
track(
AnalyticsEvents.OnboardingDeriveKeysSignatureReceived({
signatureNumber: 2,
})
);

if (signature !== additionalSignature) {
throw new Error(
'Your wallet does not support deterministic signing. Please switch to a different wallet provider.'
);
}
} else {
identify(AnalyticsUserProperties.IsNewUser(false));
}
} catch (err) {
// Derive with determinism check
const result = await onboardingManager.deriveKeysWithDeterminismCheck({
signMessageAsync: wrappedSignMessage,
getWalletFromSignature,
checkPreviousTransactions,
});

if (!result.success) {
setDerivationStatus(EvmDerivedAccountStatus.NotDerived);
const { message } = parseWalletError({ error: err, stringGetter });

if (message) {
if (result.isDeterminismError) {
track(AnalyticsEvents.OnboardingWalletIsNonDeterministic());
setError(message);
}

setError(result.error);
return;
}

await setWalletFromSignature(signature);

// 3: Remember me (encrypt and store signature)
if (staticEncryptionKey) {
const encryptedSignature = AES.encrypt(signature, staticEncryptionKey).toString();
dispatch(setSavedEncryptedSignature(encryptedSignature));
}
// Set wallet in useAccounts state
setLocalDydxWallet(result.wallet);
setHdKey(result.hdKey);

// 4. Done
// Done - wallet is already persisted to SecureStorage by OnboardingSupervisor
setDerivationStatus(EvmDerivedAccountStatus.Derived);
} catch (err) {
setDerivationStatus(EvmDerivedAccountStatus.NotDerived);
Expand Down
Loading
Loading