Skip to content

Commit 758427b

Browse files
committed
Merge remote-tracking branch 'remotes/nonuwa-oss/chore/update-wallet-connect-impl' into feat/withdraw
# Conflicts: # apps/hub/src/app/_components/vaults/vaults-table.tsx
2 parents f91ab3b + 3512dec commit 758427b

File tree

34 files changed

+2531
-2966
lines changed

34 files changed

+2531
-2966
lines changed

.changeset/famous-deers-sell.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@status-im/status-network': patch
3+
'hub': patch
4+
---
5+
6+
add wallet connect

apps/api/package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,23 @@
1717
"dependencies": {
1818
"@status-im/wallet": "workspace:*",
1919
"@trpc/client": "10.45.2",
20-
"@trpc/server": "10.45.2",
2120
"@trpc/next": "10.45.2",
21+
"@trpc/server": "10.45.2",
22+
"next": "15.3.0",
2223
"react": "^19.0.0",
2324
"react-dom": "^19.0.0",
24-
"next": "15.3.0",
2525
"zod": "^3.23.8"
2626
},
2727
"devDependencies": {
28-
"typescript": "^5",
28+
"@eslint/eslintrc": "^3.1.0",
29+
"@next/eslint-plugin-next": "15.3.0",
2930
"@types/node": "^20",
3031
"@types/react": "^19",
3132
"@types/react-dom": "^19",
3233
"eslint": "^9",
3334
"eslint-config-next": "15.3.0",
34-
"@eslint/eslintrc": "^3",
35-
"globals": "^15.12.0"
35+
"globals": "^15.12.0",
36+
"typescript": "^5.6.2"
3637
},
3738
"engines": {
3839
"node": "20.x"

apps/hub/package.json

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,41 @@
1616
"dependencies": {
1717
"@hookform/devtools": "^4.3.1",
1818
"@hookform/resolvers": "^3.1.1",
19+
"@radix-ui/react-dialog": "^1.1.1",
1920
"@status-im/colors": "workspace:*",
2021
"@status-im/components": "workspace:*",
2122
"@status-im/icons": "workspace:*",
2223
"@status-im/status-network": "workspace:*",
24+
"@status-im/wallet": "workspace:*",
25+
"@tanstack/react-query": "5.66.0",
2326
"@tanstack/react-table": "^8.21.3",
2427
"@vercel/analytics": "^1.5.0",
28+
"connectkit": "^1.9.0",
29+
"connectkit-next-siwe": "^0.3.0",
30+
"cookie": "^1.0.2",
2531
"cva": "1.0.0-beta.1",
2632
"framer-motion": "^12.0.6",
27-
"next": "15.1.6",
33+
"iron-session": "^8.0.4",
34+
"next": "15.3.0",
2835
"next-mdx-remote": "^5.0.0",
29-
"react": "^19.0.0",
30-
"react-dom": "^19.0.0",
36+
"pino-pretty": "^13.1.1",
37+
"react": "19.1.0",
38+
"react-dom": "19.1.0",
3139
"react-hook-form": "^7.45.1",
3240
"rehype-slug": "^6.0.0",
3341
"siwe": "^2.3.2",
3442
"ts-pattern": "^5.6.2",
3543
"viem": "^2.21.1",
44+
"wagmi": "2.15.2",
3645
"zod": "^3.21.4"
3746
},
3847
"devDependencies": {
3948
"@ianvs/prettier-plugin-sort-imports": "^4.3.1",
4049
"@next/eslint-plugin-next": "15.3.0",
4150
"@status-im/eslint-config": "workspace:*",
4251
"@types/node": "^20",
43-
"@types/react": "^19",
44-
"@types/react-dom": "^19",
52+
"@types/react": "19.1.0",
53+
"@types/react-dom": "19.1.0",
4554
"eslint-config-next": "15.1.6",
4655
"eslint-plugin-tailwindcss": "^3.17.4",
4756
"lint-staged": "^15.4.3",

apps/hub/postcss.config.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ const config = {
33
plugins: {
44
tailwindcss: {},
55
},
6-
};
6+
}
77

8-
export default config;
8+
export default config
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use client'
2+
3+
import { Button, ShortenAddress } from '@status-im/status-network/components'
4+
import { ConnectKitButton } from 'connectkit'
5+
6+
import type { ComponentProps } from 'react'
7+
8+
type Props = {
9+
size?: ComponentProps<typeof Button>['size']
10+
label?: string
11+
className?: string
12+
/** If true, shows the label instead of the shortened address when connected */
13+
alwaysShowLabel?: boolean
14+
}
15+
16+
const ConnectButton = (props: Props) => {
17+
const {
18+
size = '32',
19+
label = 'Connect wallet',
20+
className,
21+
alwaysShowLabel = false,
22+
} = props
23+
24+
return (
25+
<ConnectKitButton.Custom>
26+
{({ show, isConnected, address }) => {
27+
return (
28+
<Button
29+
onClick={show}
30+
variant={isConnected ? 'secondary' : 'primary'}
31+
size={size}
32+
className={className}
33+
>
34+
{address && isConnected && !alwaysShowLabel ? (
35+
<ShortenAddress address={address} />
36+
) : (
37+
label
38+
)}
39+
</Button>
40+
)
41+
}}
42+
</ConnectKitButton.Custom>
43+
)
44+
}
45+
46+
export { ConnectButton }
47+
export type { Props as ConnectButtonProps }

apps/hub/src/app/_components/top-bar.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
import { Button, IconButton, Tag } from '@status-im/components'
44
import { SettingsIcon } from '@status-im/icons/20'
5-
import {
6-
Button as ButtonPrimary,
7-
Link,
8-
} from '@status-im/status-network/components'
5+
import { Link } from '@status-im/status-network/components'
96
import Image from 'next/image'
107

8+
import { ConnectButton } from './connect-button'
9+
1110
interface TopBarProps {
1211
onMenuToggle: () => void
1312
}
@@ -64,7 +63,7 @@ export function TopBar({ onMenuToggle }: TopBarProps) {
6463
</div>
6564

6665
{/* Connect Wallet Button */}
67-
<ButtonPrimary size="32">Connect Wallet</ButtonPrimary>
66+
<ConnectButton />
6867

6968
{/* Settings Button */}
7069
<IconButton variant="ghost" icon={<SettingsIcon />} />

apps/hub/src/app/_components/vaults/table-columns.tsx

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@ import { SNT_TOKEN } from '~constants/index'
88
import { type StakingVault } from '~hooks/useStakingVaults'
99
import { shortenAddress } from '~utils/address'
1010
import { formatSNT } from '~utils/currency'
11-
import {
12-
calculateDaysUntilUnlock,
13-
calculateVaultBoost,
14-
isVaultLocked,
15-
} from '~utils/vault'
11+
import { calculateDaysUntilUnlock, isVaultLocked } from '~utils/vault'
1612

1713
import { LockVaultModal } from './modals/lock-vault-modal'
1814
import { WithdrawVaultModal } from './modals/withdraw-vault-modal'
@@ -25,21 +21,56 @@ interface TableColumnsProps {
2521
// isConnected: boolean
2622
}
2723

24+
// Calculate total staked across all vaults
25+
const calculateTotalStaked = (vaults: StakingVault[]): bigint => {
26+
return vaults.reduce(
27+
(acc, vault) => acc + (vault.data?.stakedBalance || 0n),
28+
BigInt(0)
29+
)
30+
}
31+
32+
// Calculate total karma across all vaults
33+
const calculateTotalKarma = (vaults: StakingVault[]): bigint => {
34+
return vaults.reduce(
35+
(acc, vault) => acc + (vault.data?.rewardsAccrued || 0n),
36+
BigInt(0)
37+
)
38+
}
39+
40+
// Cache current time to avoid calling Date.now() on every cell render
41+
const getCurrentTimestamp = (): bigint => {
42+
return BigInt(Math.floor(Date.now() / 1000))
43+
}
44+
45+
// Validation function for lock time - extracted to avoid recreating on every render
46+
const validateLockTime = (_: string, days: string): string | null => {
47+
const totalDays = parseInt(days || '0')
48+
// TODO: read this from the contract
49+
return totalDays > 1460 ? 'Maximum lock time is 4 years' : null
50+
}
51+
52+
// Modal action configurations - static, never change
53+
const EXTEND_LOCK_ACTIONS = [
54+
{ label: 'Cancel' },
55+
{ label: 'Extend lock' },
56+
] as const
57+
58+
const LOCK_VAULT_ACTIONS = [{ label: "Don't lock" }, { label: 'Lock' }] as const
59+
60+
const LOCK_INFO_MESSAGE =
61+
'Boost the rate at which you receive Karma. The longer you lock your vault, the higher your boost, and the faster you accumulate Karma. You can add more SNT at any time, but withdrawing your SNT is only possible once the vault unlocks.' as const
62+
2863
export const createVaultTableColumns = ({
2964
vaults = [],
3065
openModalVaultId,
3166
setOpenModalVaultId,
3267
emergencyModeEnabled,
3368
// isConnected,
3469
}: TableColumnsProps) => {
35-
const totalStaked = vaults.reduce(
36-
(acc, vault) => acc + (vault.data?.stakedBalance || 0n),
37-
BigInt(0)
38-
)
39-
const totalKarma = vaults.reduce(
40-
(acc, vault) => acc + (vault.data?.rewardsAccrued || 0n),
41-
BigInt(0)
42-
)
70+
// Calculate totals and current time once per column creation
71+
const totalStaked = calculateTotalStaked(vaults)
72+
const totalKarma = calculateTotalKarma(vaults)
73+
const currentTimestamp = getCurrentTimestamp()
4374
const columnHelper = createColumnHelper<StakingVault>()
4475

4576
return [
@@ -140,10 +171,19 @@ export const createVaultTableColumns = ({
140171
? (maxMP - mpAccrued) / stakedBalance
141172
: undefined
142173

174+
// Calculate boost directly instead of recalculating for all vaults
175+
// Boost = (mpAccrued / stakedBalance) + 1 (base multiplier)
176+
const currentBoost =
177+
stakedBalance > 0n
178+
? Number(formatUnits(mpAccrued, SNT_TOKEN.decimals)) /
179+
Number(formatUnits(stakedBalance, SNT_TOKEN.decimals)) +
180+
1
181+
: 1
182+
143183
return (
144184
<div className="flex items-center gap-3">
145185
<span className="text-[13px] font-medium leading-[1.4] tracking-[-0.039px] text-neutral-100">
146-
x{calculateVaultBoost(vaults, row.original.address)}
186+
x{currentBoost.toFixed(2)}
147187
</span>
148188
{potentialBoost && (
149189
<span className="text-[13px] font-medium leading-[1.4] tracking-[-0.039px] text-[#7140fd]">
@@ -218,8 +258,9 @@ export const createVaultTableColumns = ({
218258
const isWithdrawModalOpen = openModalVaultId === withdrawModalId
219259
const isLockModalOpen = openModalVaultId === lockModalId
220260

261+
// Use cached timestamp instead of calling Date.now() on every render
221262
const isLocked = row.original?.data?.lockUntil
222-
? row.original.data.lockUntil > BigInt(Math.floor(Date.now() / 1000))
263+
? row.original.data.lockUntil > currentTimestamp
223264
: false
224265

225266
return (
@@ -255,16 +296,9 @@ export const createVaultTableColumns = ({
255296
initialYears="2"
256297
initialDays="732"
257298
description="Extending lock time increasing Karma boost"
258-
actions={[
259-
{
260-
label: 'Cancel',
261-
},
262-
{
263-
label: 'Extend lock',
264-
},
265-
]}
299+
actions={EXTEND_LOCK_ACTIONS}
266300
onClose={() => setOpenModalVaultId(null)}
267-
infoMessage="Boost the rate at which you receive Karma. The longer you lock your vault, the higher your boost, and the faster you accumulate Karma. You can add more SNT at any time, but withdrawing your SNT is only possible once the vault unlocks."
301+
infoMessage={LOCK_INFO_MESSAGE}
268302
>
269303
<Button variant="primary" size="24" iconBefore={<TimeIcon />}>
270304
Extend lock time
@@ -280,23 +314,10 @@ export const createVaultTableColumns = ({
280314
vaultAddress={row.original.address}
281315
title="Do you want to lock the vault?"
282316
description="Lock this vault to receive more Karma"
283-
actions={[
284-
{
285-
label: "Don't lock",
286-
},
287-
{
288-
label: 'Lock',
289-
},
290-
]}
317+
actions={LOCK_VAULT_ACTIONS}
291318
onClose={() => setOpenModalVaultId(null)}
292-
infoMessage="Boost the rate at which you receive Karma. The longer you lock your vault, the higher your boost, and the faster you accumulate Karma. You can add more SNT at any time, but withdrawing your SNT is only possible once the vault unlocks."
293-
onValidate={(_, days) => {
294-
const totalDays = parseInt(days || '0')
295-
// TODO: read this from the contract
296-
return totalDays > 1460
297-
? 'Maximum lock time is 4 years'
298-
: null
299-
}}
319+
infoMessage={LOCK_INFO_MESSAGE}
320+
onValidate={validateLockTime}
300321
>
301322
<Button
302323
variant="primary"

0 commit comments

Comments
 (0)