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/op users fusion #324

Merged
merged 46 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
23c7d20
chore: add top user modal
slavastartsev Nov 14, 2024
6d64514
chore: cast to string[]
slavastartsev Nov 14, 2024
fc41a85
chore: refetch lottery draw time every hour
slavastartsev Nov 14, 2024
474d67f
chore: improve color scheme for modal
slavastartsev Nov 18, 2024
2b08c55
chore: off color scheme
slavastartsev Nov 18, 2024
f342457
chore: set update time to minute
slavastartsev Nov 20, 2024
93f894b
chore: send gtm event on iframe events
slavastartsev Nov 20, 2024
79c9b78
chore: extract messages
slavastartsev Nov 20, 2024
5d299be
chore: localize format distance to now
slavastartsev Nov 20, 2024
aa3df81
chore: add missing locale
slavastartsev Nov 26, 2024
5d7a5c8
chore: add switch to hide modal forever
slavastartsev Nov 28, 2024
a3dd91b
chore: extract messages
slavastartsev Nov 28, 2024
50e0d9c
chore: capitalize `book a call`
slavastartsev Nov 28, 2024
ee2b85d
chore: place toggle at the very bottom
slavastartsev Nov 28, 2024
18b0261
Merge branch 'main' of https://github.com/bob-collective/ui into feat…
slavastartsev Nov 28, 2024
3b847fb
chore: add book a meeting button
slavastartsev Nov 28, 2024
354ba6b
Merge branch 'main' of https://github.com/bob-collective/ui into feat…
slavastartsev Nov 28, 2024
2895bfd
chore: add copy line for button
slavastartsev Nov 29, 2024
8e94b30
fix: keys for user query
slavastartsev Nov 29, 2024
078f241
feat: wip
danielsimao Nov 29, 2024
ebb8606
feat: some ideas
danielsimao Nov 29, 2024
0bd3bf3
Merge branch 'main' of https://github.com/bob-collective/ui into feat…
slavastartsev Dec 2, 2024
baed6c1
chore: wagmi ssr connect
slavastartsev Dec 2, 2024
5931a60
Merge branch 'feat/top-100-spice-users' of https://github.com/bob-col…
slavastartsev Dec 2, 2024
e039f52
chore: remove reconnect
slavastartsev Dec 2, 2024
20d13fc
chore: finish adjustments for op superuser
slavastartsev Dec 3, 2024
769192e
Merge branch 'main' of https://github.com/bob-collective/ui into feat…
slavastartsev Dec 5, 2024
9adce9f
chore: op text copies adjustments
slavastartsev Dec 5, 2024
014dfac
Merge branch 'main' of https://github.com/bob-collective/ui into feat…
slavastartsev Dec 5, 2024
3b1a182
chore: reorder parapgraphs
slavastartsev Dec 6, 2024
64b7859
chore: swap superchain logo
slavastartsev Dec 6, 2024
28522d9
chore: move top spice user bit to heading
slavastartsev Dec 6, 2024
aa687eb
chore: hide top 100 spice users with feature flag
slavastartsev Dec 6, 2024
0d46059
chore: hide op superuser features with flag
slavastartsev Dec 6, 2024
3341228
chore: fix failing tests
slavastartsev Dec 6, 2024
0d0685e
chore: update tests
slavastartsev Dec 7, 2024
a40788f
Merge branch 'main' of https://github.com/bob-collective/ui into feat…
slavastartsev Dec 7, 2024
b4f6df4
chore: update superchain banner
slavastartsev Dec 9, 2024
04dccb0
chore: update superchain logo styles, add top user img
slavastartsev Dec 9, 2024
7fa617c
chore: update translations
slavastartsev Dec 9, 2024
95968da
chore: add zh translations
slavastartsev Dec 9, 2024
64f9f89
chore: feature flag fusion popover
slavastartsev Dec 9, 2024
82af901
chore: add missing check
slavastartsev Dec 9, 2024
730d479
chore: update banner title translation
slavastartsev Dec 9, 2024
bfb8ee3
chore: update toggle top value
slavastartsev Dec 9, 2024
184d0d0
chore: update switch height multiplier
slavastartsev Dec 9, 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
11 changes: 7 additions & 4 deletions apps/evm/lingui.config.js → apps/bob-pay/lingui.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @type {import('@lingui/conf').LinguiConfig} */
module.exports = {
locales: ['en', 'zh'],
import { LinguiConfig } from '@lingui/conf';

const config = {
locales: ['en', 'zh'] as const,
sourceLocale: 'en',
fallbackLocales: {
default: 'en'
Expand All @@ -11,4 +12,6 @@ module.exports = {
include: ['src/']
}
]
};
} as const satisfies LinguiConfig;

export default config;
5 changes: 3 additions & 2 deletions apps/evm/.env.test
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ NEXT_PUBLIC_L1_CHAIN="11155111"
NEXT_PUBLIC_L2_CHAIN="808813"
NEXT_COINGECKO_API_KEY=
NEXT_PUBLIC_GEOBLOCK_ENABLED=false
NEXT_PUBLIC_FEATURE_FLAG_WALLET=enabled
NEXT_PUBLIC_INDEXER_URL=
NEXT_PUBLIC_SENTRY_AUTH_TOKEN=
NEXT_PUBLIC_SENTRY_URL=
SENTRY_AUTH_TOKEN=
KV_REST_API_URL=
KV_REST_API_TOKEN=
KV_REST_API_TOKEN=
NEXT_PUBLIC_FEATURE_FLAG_TOP_100_SPICE_USERS=enabled
NEXT_PUBLIC_FEATURE_FLAG_OP_SUPERUSER=enabled
9 changes: 6 additions & 3 deletions apps/bob-pay/lingui.config.js → apps/evm/lingui.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/** @type {import('@lingui/conf').LinguiConfig} */
module.exports = {
import { LinguiConfig } from '@lingui/conf';

const config = {
locales: ['en', 'zh'],
sourceLocale: 'en',
fallbackLocales: {
Expand All @@ -11,4 +12,6 @@ module.exports = {
include: ['src/']
}
]
};
} as const satisfies LinguiConfig;

export default config;
3 changes: 3 additions & 0 deletions apps/evm/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { withSentryConfig } from '@sentry/nextjs';

/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
domains: ['raw.githubusercontent.com'] // Add the allowed hostname here
},
compiler: {
styledComponents: true
},
Expand Down
1 change: 1 addition & 0 deletions apps/evm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"date-fns": "catalog:",
"graphql-request": "catalog:",
"lottie-react": "^2.4.0",
"react-calendly": "^4.3.1",
"negotiator": "catalog:",
"next": "catalog:",
"react": "catalog:",
Expand Down
Binary file added apps/evm/public/assets/optimism-city.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/evm/public/assets/top-100-spice.webp
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
import { Trans } from '@lingui/macro';
import { formatDistanceToNow, isFuture } from 'date-fns';
import { ReactNode, useMemo } from 'react';
import { useParams } from 'next/navigation';

import { BridgeTransaction } from '../../hooks';

import { StyledTimePill } from './BridgeStatus.style';
import { BridgeStep } from './BridgeStep';

import { BridgeSteps } from '@/types';
import { getLocale } from '@/utils';

const TimeLabel = ({ label }: { label: ReactNode }) => (
<StyledTimePill size='xs'>
Expand All @@ -28,6 +30,8 @@
type TimeStepProps = Props & InheritAttrs;

const TimeStep = ({ step, data, currentStep }: TimeStepProps): JSX.Element => {
const { lang } = useParams();

const timeLabel = useMemo(() => {
// should only show step if it is not a complete step
const showTime =
Expand All @@ -44,8 +48,13 @@
return step === 'challenge-period' ? <Trans>7 days</Trans> : <Trans>2 hours</Trans>;
}

return <Trans>{formatDistanceToNow(data.statusEndDate)} remaining</Trans>;
return (
<Trans>
{formatDistanceToNow(data.statusEndDate, { locale: getLocale(lang as Parameters<typeof getLocale>[0]) })}{' '}
slavastartsev marked this conversation as resolved.
Show resolved Hide resolved
remaining
</Trans>
);
}, [step, currentStep, data.statusEndDate]);

Check warning on line 57 in apps/evm/src/app/[lang]/(bridge)/components/BridgeStatus/TimeStep.tsx

View workflow job for this annotation

GitHub Actions / ESLint

React Hook useMemo has a missing dependency: 'lang'. Either include it or remove the dependency array

return (
<Flex alignItems='center' flex={1} justifyContent='space-between'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { Currency, CurrencyAmount } from '@gobob/currency';
import { ArrowLongRight, Flex, FlexProps, P, UnstyledButton } from '@gobob/ui';
import { Trans } from '@lingui/macro';
import { formatDistanceToNow } from 'date-fns';
import { useParams } from 'next/navigation';

import { StyledDetailsButton, StyledExpandIcon } from './TransactionList.style';

import { Chain } from '@/components';
import { TransactionDirection } from '@/types';
import { getLocale } from '@/utils';

type Props = {
direction: TransactionDirection;
Expand Down Expand Up @@ -35,6 +37,7 @@ const TransactionDetails = ({
onExpand,
...props
}: TransactionDetailsProps): JSX.Element => {
const { lang } = useParams();
const directionLabel = direction === TransactionDirection.L1_TO_L2 ? <Trans>Deposit</Trans> : <Trans>Withdraw</Trans>;

const isExpandable = !!onExpand;
Expand All @@ -46,7 +49,7 @@ const TransactionDetails = ({
{directionLabel}
</P>
<P color='grey-50' size='xs' weight='semibold'>
<Trans>{formatDistanceToNow(date)} ago</Trans>
<Trans>{formatDistanceToNow(date, { locale: getLocale(lang as Parameters<typeof getLocale>[0]) })} ago</Trans>
</P>
</Flex>
<StyledDetailsButton elementType={onExpand ? UnstyledButton : undefined} {...{ onPress: onExpand }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,70 @@ const mockSegmentStrategy: GatewayStrategyContract = {
}
} as const;

const mockPellUniBTCStrategy: GatewayStrategyContract = {
id: 'pell-unibtc',
type: 'deposit',
address: '0xf5f2f90d3edc557b7ff0a285169a0b194df7b6f2',
method: '',
chain: {
id: '',
chainId: 60808,
slug: 'bob',
name: 'bob',
logo: '',
type: 'evm',
singleChainSwap: true,
singleChainStaking: true
},
integration: {
type: 'staking',
slug: 'pell-unibtc',
name: 'Pell (uniBTC)',
logo: '',
monetization: false
},
inputToken: {
symbol: 'WBTC',
address: '0x03c7054bcb39f7b2e5b2c7acb37583e32d70cfa3',
logo: 'https://ethereum-optimism.github.io/data/WBTC/logo.svg',
decimals: 8,
chain: 'bob'
},
outputToken: null
} as const;

const seTokensContractDataMock = {
seSOLVBTCBBN: [200420547971521033526791436n, 90941658309n, '0xCC0966D8418d412c599A6421b760a847eB169A8c'],
seTBTC: [207537267655402594884495418n, 8255486068n, '0xBBa2eF945D523C4e2608C9E1214C2Cc64D4fc2e2'],
seUNIBTC: [20020877878162857n, 8875128907n, '0x236f8c0a61dA474dB21B693fB2ea7AAB0c803894'],
seWBTC: [20083839753286961n, 63216624241n, '0x03C7054BCB39f7b2e5B2c7AcB37583e32D70Cfa3']
} as const;

const seTokensUnderlyingContractDataMock = {
seSOLVBTCBBN: 18,
seTBTC: 18,
seUNIBTC: 8,
seWBTC: 8
} as const;

const tokensContractDataMock = {
'SolvBTC.BBN': [1669199681543807681873n, 18],
uniBTC: [42320720383n, 8]
} as const;

const noOuputTokenContractDataMock = {
'0xdf3aa56f2626e253b5db7703ac7241e835140566': 8587056375410955041n,
'0xf5f2f90d3edc557b7ff0a285169a0b194df7b6f2': 20351418531n
} as const;

const noOuputTokenContractSharesToUnderlyingDataMock = {
'0xdf3aa56f2626e253b5db7703ac7241e835140566': 8587056375410955041n,
'0xf5f2f90d3edc557b7ff0a285169a0b194df7b6f2': 20351418531n
} as const;

describe('useGetStakingStrategies', () => {
afterEach(vi.clearAllMocks);

const mockExchangeRateStored = 207520794671396869399540716n;
const mockTotalSupply = 9036849246n;
const mockUnderlying = '0xabc';

const underlyingDecimals = 18;
const decimals = 8;

Expand All @@ -131,13 +188,19 @@ describe('useGetStakingStrategies', () => {
beforeEach(() => {
(useReadContracts as Mock)
.mockReturnValueOnce({
data: [mockExchangeRateStored, mockTotalSupply, mockUnderlying]
data: seTokensContractDataMock
})
.mockReturnValueOnce({
data: seTokensUnderlyingContractDataMock
})
.mockReturnValueOnce({
data: [underlyingDecimals]
data: tokensContractDataMock
})
.mockReturnValueOnce({
data: [mockTotalSupply, decimals]
data: noOuputTokenContractDataMock
})
.mockReturnValueOnce({
data: noOuputTokenContractSharesToUnderlyingDataMock
});

(usePrices as Mock).mockReturnValue({
Expand All @@ -148,13 +211,19 @@ describe('useGetStakingStrategies', () => {
it('should return strategy data', async () => {
(useReadContracts as Mock)
.mockReturnValueOnce({
data: [mockExchangeRateStored, mockTotalSupply, mockUnderlying]
data: seTokensContractDataMock
})
.mockReturnValueOnce({
data: [underlyingDecimals]
data: seTokensUnderlyingContractDataMock
})
.mockReturnValueOnce({
data: [mockTotalSupply, decimals]
data: tokensContractDataMock
})
.mockReturnValueOnce({
data: noOuputTokenContractDataMock
})
.mockReturnValueOnce({
data: noOuputTokenContractSharesToUnderlyingDataMock
});

(gatewaySDK.getStrategies as Mock).mockReturnValue([mockStrategy]);
Expand All @@ -177,7 +246,9 @@ describe('useGetStakingStrategies', () => {
mockStrategy.outputToken.symbol
)
: undefined,
tvl: new Big(mockTotalSupply.toString())
tvl: new Big(
tokensContractDataMock[mockStrategy.outputToken?.symbol as keyof typeof tokensContractDataMock][0].toString()
)
.mul(mockPrice)
.div(10 ** decimals)
.toNumber()
Expand All @@ -187,23 +258,25 @@ describe('useGetStakingStrategies', () => {
expect(result.current.data).toEqual([expectedData]);
});

it('should return undefined currency when outputToken is missing', async () => {
it('should return tvl value if output token is se* token', async () => {
(useReadContracts as Mock)
.mockReturnValueOnce({
data: [mockExchangeRateStored, mockTotalSupply, mockUnderlying]
data: seTokensContractDataMock
})
.mockReturnValueOnce({
data: seTokensUnderlyingContractDataMock
})
.mockReturnValueOnce({
data: tokensContractDataMock
})
.mockReturnValueOnce({
data: [underlyingDecimals]
data: noOuputTokenContractDataMock
})
.mockReturnValueOnce({
data: [mockTotalSupply, decimals]
data: noOuputTokenContractSharesToUnderlyingDataMock
});

const mockStrategyWithoutToken = {
outputToken: undefined
};

(gatewaySDK.getStrategies as Mock).mockReturnValue([mockStrategyWithoutToken]);
(gatewaySDK.getStrategies as Mock).mockReturnValue([mockSegmentStrategy]);

const { result, waitForValueToChange } = renderHook<PropsWithChildren, ReturnType<typeof useGetStakingStrategies>>(
() => useGetStakingStrategies(),
Expand All @@ -213,27 +286,52 @@ describe('useGetStakingStrategies', () => {
await waitForValueToChange(() => result.current.data);

const expectedData = {
raw: mockStrategyWithoutToken,
currency: undefined,
tvl: null
raw: mockSegmentStrategy,
currency: mockSegmentStrategy.outputToken
? new Token(
ChainId.BOB,
mockSegmentStrategy.outputToken.address as Address,
mockSegmentStrategy.outputToken.decimals,
mockSegmentStrategy.outputToken.symbol,
mockSegmentStrategy.outputToken.symbol
)
: undefined,
tvl: new Big(
(
seTokensContractDataMock[
mockSegmentStrategy.outputToken?.symbol as keyof typeof seTokensContractDataMock
][0] *
seTokensContractDataMock[mockSegmentStrategy.outputToken?.symbol as keyof typeof seTokensContractDataMock][1]
).toString()
)
.mul(mockPrice)
.div(1e18)
.div(10 ** underlyingDecimals)
.toNumber()
};

expect(result.current.data).toEqual([expectedData]);
});

it('should return tvl value if output token is se* token', async () => {
it('should return tvl value if no output', async () => {
(useReadContracts as Mock)
.mockReturnValueOnce({
data: [mockExchangeRateStored, mockTotalSupply, mockUnderlying]
data: seTokensContractDataMock
})
.mockReturnValueOnce({
data: [underlyingDecimals]
data: seTokensUnderlyingContractDataMock
})
.mockReturnValueOnce({
data: [mockTotalSupply, decimals]
data: tokensContractDataMock
})
.mockReturnValueOnce({
data: noOuputTokenContractDataMock
})
.mockReturnValueOnce({
data: noOuputTokenContractSharesToUnderlyingDataMock
});

(gatewaySDK.getStrategies as Mock).mockReturnValue([mockSegmentStrategy]);
(gatewaySDK.getStrategies as Mock).mockReturnValue([mockPellUniBTCStrategy]);

const { result, waitForValueToChange } = renderHook<PropsWithChildren, ReturnType<typeof useGetStakingStrategies>>(
() => useGetStakingStrategies(),
Expand All @@ -243,20 +341,15 @@ describe('useGetStakingStrategies', () => {
await waitForValueToChange(() => result.current.data);

const expectedData = {
raw: mockSegmentStrategy,
currency: mockSegmentStrategy.outputToken
? new Token(
ChainId.BOB,
mockSegmentStrategy.outputToken.address as Address,
mockSegmentStrategy.outputToken.decimals,
mockSegmentStrategy.outputToken.symbol,
mockSegmentStrategy.outputToken.symbol
)
: undefined,
tvl: new Big((mockExchangeRateStored * mockTotalSupply).toString())
raw: mockPellUniBTCStrategy,
currency: undefined,
tvl: new Big(
noOuputTokenContractSharesToUnderlyingDataMock[
mockPellUniBTCStrategy.address as keyof typeof noOuputTokenContractSharesToUnderlyingDataMock
].toString()
)
.mul(mockPrice)
.div(1e18)
.div(10 ** underlyingDecimals)
.div(10 ** (tokensContractDataMock.uniBTC[1]! as number))
.toNumber()
};

Expand Down
Loading
Loading