Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c047836
add helper classes
jaredvu Nov 17, 2025
bdc1f52
onboarding orchestrator
jaredvu Nov 17, 2025
db04e33
Merge branch 'main' into jv/onboarding-refactor
jaredvu Nov 17, 2025
f81a3bb
Merge branch 'main' into jv/onboarding-refactor
jaredvu Nov 17, 2025
a4506f0
add cosmos wallet derivation helper
jaredvu Nov 17, 2025
b30d18b
replace local wallet useStates w/ derived approach
jaredvu Nov 17, 2025
61aca40
replace main side-effect in useAccounts
jaredvu Nov 18, 2025
64ad340
migration
jaredvu Nov 18, 2025
947f0ba
clean
jaredvu Nov 18, 2025
63348fd
add restoration logic
jaredvu Nov 18, 2025
ed94486
remove debug log
jaredvu Nov 18, 2025
cac211c
remove async import
jaredvu Nov 18, 2025
0326f4b
update useGenerateKeys
jaredvu Nov 19, 2025
d36bf84
Merge branch 'main' into jv/onboarding-refactor
jaredvu Nov 22, 2025
ac6ba75
Merge branch 'main' into jv/onboarding-refactor
jaredvu Nov 24, 2025
c333e34
fix
jaredvu Nov 25, 2025
a4deb13
cosmos wallet derivation fix
jaredvu Nov 25, 2025
6a91d95
fix
jaredvu Nov 25, 2025
8364cf6
requestNumber type
jaredvu Nov 25, 2025
5daae23
clean up
jaredvu Nov 25, 2025
c0c5f23
cleanup turnkey flow
jaredvu Nov 26, 2025
72e215b
restore state version of localNobleWallet
jaredvu Nov 26, 2025
c7d15b0
i mixed up chainId and bech32 prefix
jaredvu Nov 26, 2025
0c1c467
Merge branch 'main' into jv/onboarding-refactor
jaredvu Jan 6, 2026
36834a0
consolidate determinism check
jaredvu Jan 7, 2026
7ab4d52
Merge branch 'main' into jv/onboarding-refactor
jaredvu Jan 7, 2026
c6896dd
fix
jaredvu Jan 7, 2026
581cc7d
fix solana wallet derivation
jaredvu Jan 8, 2026
b2938ad
Merge branch 'main' into jv/onboarding-refactor
jaredvu Jan 8, 2026
cb34ef9
Merge branch 'main' into jv/onboarding-refactor
jaredvu Jan 9, 2026
bf726f4
feat: private key import (#1997)
jaredvu Jan 12, 2026
e04d7d8
Merge branch 'main' into jv/onboarding-refactor
jaredvu Jan 12, 2026
3cda631
Merge branch 'main' into jv/onboarding-refactor
jaredvu Jan 22, 2026
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
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
"@visx/tooltip": "^3.1.2",
"@visx/xychart": "^3.1.2",
"@wagmi/core": "^2.16.3",
"@yudiel/react-qr-scanner": "^2.5.0",
"bignumber.js": "^9.1.1",
"bs58": "^6.0.0",
"cmdk": "^0.2.0",
Expand All @@ -126,6 +127,7 @@
"fast-json-stable-stringify": "^2.1.0",
"graz": "^0.1.19",
"immer": "^10.1.1",
"input-otp": "^1.4.2",
"jsdom": "^24.1.0",
"jwt-decode": "^4.0.0",
"lodash": "^4.17.21",
Expand Down
74 changes: 74 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion src/bonsai/lifecycles/usdcRebalanceLifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ export function setUpUsdcRebalanceLifecycle(store: RootStore) {
const { localDydxWallet, parentSubaccountInfo, sourceAccount, rebalanceAction } = data!;

// context: Cosmos wallets do not support our lifecycle methods and are instead handled within useNotificationTypes
if (rebalanceAction == null || sourceAccount.chain === WalletNetworkType.Cosmos) {
if (
rebalanceAction == null ||
sourceAccount.chain === WalletNetworkType.Cosmos ||
sourceAccount.chain == null
) {
return;
}

Expand Down
4 changes: 3 additions & 1 deletion src/bonsai/rest/lib/nobleTransactionStoreEffect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ const selectNobleTxAuthorizedAccount = createAppSelector(
}

const localNobleWallet = localWalletManager.getLocalNobleWallet(localWalletNonce);

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

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

if (!isCorrectWallet || localNobleWallet == null) return undefined;
Copy link
Collaborator 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
126 changes: 126 additions & 0 deletions src/components/InputOtp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import * as React from 'react';

import { OTPInput, OTPInputContext, REGEXP_ONLY_DIGITS } from 'input-otp';
import styled, { createGlobalStyle } from 'styled-components';

const InputOTP = ({
className,
...props
}: React.ComponentProps<typeof OTPInput> & {
containerClassName?: string;
}) => {
return (
<React.Fragment>
<InputOtpContainerStyle />
<OTPInput
data-slot="input-otp"
containerClassName="input-otp-container"
tw="disabled:cursor-not-allowed"
className={className}
pattern={REGEXP_ONLY_DIGITS}
{...props}
/>
</React.Fragment>
);
};

const InputOTPGroup = ({ className, ...props }: React.ComponentProps<'div'>) => {
return (
<div data-slot="input-otp-group" tw="flex items-center" className={className} {...props} />
);
};

const InputOTPSlot = ({
index,
className,
...props
}: React.ComponentProps<'div'> & {
index: number;
}) => {
const inputOTPContext = React.useContext(OTPInputContext);
const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
return (
<$InputOTPSlot
data-slot="input-otp-slot"
data-active={isActive}
className={className}
{...props}
>
{char}
{hasFakeCaret && (
<div tw="pointer-events-none absolute inset-0 flex items-center justify-center">
<div tw="h-0.5 w-px duration-1000" />
</div>
)}
</$InputOTPSlot>
);
};

const InputOTPSeparator = ({ ...props }: React.ComponentProps<'div'>) => {
return (
<div data-slot="input-otp-separator" role="separator" {...props}>
<span>-</span>
</div>
);
};

/**
* This is necessary to access containerClassName.
* Our twin.macro tailwind classes do not work in this case so we fall back on good ole CSS.
*/
const InputOtpContainerStyle = createGlobalStyle`
.input-otp-container {
display: flex;
align-items: center;
gap: 0.5rem;
margin-left: auto;
margin-right: auto;

&:has(input:disabled) {
opacity: 0.5;
}
}
`;

const $InputOTPSlot = styled.div`
position: relative;
display: flex;
height: 3rem;
width: 2.625rem;
align-items: center;
justify-content: center;
font-size: 0.875rem;
line-height: 1.25rem;
border: var(--default-border-width) solid var(--input-otp-slot-border-color, var(--color-border));
outline: none;
transition: all 0.15s ease-in-out;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);

&:first-child {
border-left: 1px solid var(--input-otp-slot-border-color, var(--color-border));
border-top-left-radius: var(--input-otp-slot-border-radius, 0.75rem);
border-bottom-left-radius: var(--input-otp-slot-border-radius, 0.75rem);
}

&:last-child {
border-top-right-radius: var(--input-otp-slot-border-radius, 0.75rem);
border-bottom-right-radius: var(--input-otp-slot-border-radius, 0.75rem);
}

&[data-active='true'] {
border-color: var(--color-accent);
box-shadow: 0 0 0 3px rgba(var(--color-accent-rgb), 0.1);
z-index: 10;
}

&[aria-invalid='true'] {
border-color: var(--color-error);
}

&[data-active='true'][aria-invalid='true'] {
border-color: var(--color-error);
box-shadow: 0 0 0 3px var(--color-error);
}
`;

export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot };
22 changes: 0 additions & 22 deletions src/constants/account.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import type { DydxAddress, EvmAddress } from './wallets';
import { SolAddress } from './wallets';

export enum OnboardingSteps {
SignIn = 'SignIn',
ChooseWallet = 'ChooseWallet',
KeyDerivation = 'KeyDerivation',
}

Expand Down Expand Up @@ -48,24 +44,6 @@ export enum SpotWalletStatus {
Connected = 'Connected',
}

export type EvmDerivedAddresses = {
version?: string;
[EvmAddress: EvmAddress]: {
encryptedSignature?: string;
dydxAddress?: DydxAddress;
};
};

export type SolDerivedAddresses = {
version?: string;
} & Record<
SolAddress,
{
encryptedSignature?: string;
dydxAddress?: DydxAddress;
}
>;

export type Hdkey = {
mnemonic: string;
privateKey: Uint8Array | null;
Expand Down
5 changes: 3 additions & 2 deletions src/constants/localStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ export enum LocalStorageKey {
DydxAddress = 'dydx.DydxAddress',
OnboardingSelectedWallet = 'dydx.OnboardingSelectedWallet',
OnboardingHasAcknowledgedTerms = 'dydx.OnboardingHasAcknowledgedTerms',
EvmDerivedAddresses = 'dydx.EvmDerivedAddresses', // Deprecated
KeplrCompliance = 'dydx.KeplrCompliance',
SolDerivedAddresses = 'dydx.SolDerivedAddresses',

EvmDerivedAddresses = 'dydx.EvmDerivedAddresses', // Deprecated
SolDerivedAddresses = 'dydx.SolDerivedAddresses', // Deprecated

// Gas
SelectedGasDenom = 'dydx.SelectedGasDenom',
Expand Down
3 changes: 3 additions & 0 deletions src/constants/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,14 @@ export enum ConnectorType {
Privy = 'privy',
PhantomSolana = 'phantomSolana',
Turnkey = 'turnkey',
Import = 'import',
}

export enum WalletNetworkType {
Evm = 'evm',
Cosmos = 'cosmos',
Solana = 'solana',
Dydx = 'dydx',
}

// This is the type stored in localstorage, so it must consist of only serializable fields
Expand Down Expand Up @@ -112,6 +114,7 @@ export type WalletInfo =
name: CosmosWalletType;
}
| { connectorType: ConnectorType.Test; name: WalletType.TestWallet }
| { connectorType: ConnectorType.Import; name: 'Import' }
| { connectorType: ConnectorType.DownloadWallet; name: string; downloadLink: string };

type WalletConfig = {
Expand Down
Loading
Loading