Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 5 additions & 5 deletions e2e/fixtures/wallet_balance.selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
export const SPINNER_SELECTOR =
'[data-testid="staked-balance"] .bbn-loader, [data-testid="stakable-balance"] .bbn-loader, [data-testid="baby-balance"] .bbn-loader, [data-testid="baby-rewards"] .bbn-loader';
export const STAKED_BALANCE_ITEM_SELECTOR =
'.bbn-list-item:has-text("Staked Balance")';
'.bbn-list-item-legacy:has-text("Staked Balance")';
export const STAKED_BALANCE_VALUE_SELECTOR =
'.bbn-list-item:has-text("Staked Balance") .bbn-list-value';
'.bbn-list-item-legacy:has-text("Staked Balance") .bbn-list-value-legacy';
export const STAKABLE_BALANCE_VALUE_SELECTOR =
'.bbn-list-item:has-text("Stakable Balance") .bbn-list-value';
'.bbn-list-item-legacy:has-text("Stakable Balance") .bbn-list-value-legacy';
export const BABY_BALANCE_VALUE_SELECTOR =
'.bbn-list-item:has-text("BABY Balance") .bbn-list-value';
'.bbn-list-item-legacy:has-text("BABY Balance") .bbn-list-value-legacy';
export const BABY_REWARDS_VALUE_SELECTOR =
'.bbn-list-item:has-text("BABY Rewards") .bbn-list-value';
'.bbn-list-item-legacy:has-text("BABY Rewards") .bbn-list-value-legacy';
18 changes: 9 additions & 9 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
"dependencies": {
"@babylonlabs-io/babylon-proto-ts": "1.1.0",
"@babylonlabs-io/btc-staking-ts": "2.3.4",
"@babylonlabs-io/core-ui": "1.1.1",
"@babylonlabs-io/wallet-connector": "1.7.9",
"@babylonlabs-io/core-ui": "1.4.1",
"@babylonlabs-io/wallet-connector": "1.8.1",
"@bitcoin-js/tiny-secp256k1-asmjs": "2.2.3",
"@cosmjs/proto-signing": "^0.32.4",
"@cosmjs/stargate": "^0.32.4",
Expand Down
11 changes: 4 additions & 7 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { createRoot } from "react-dom/client";
import { ErrorBoundary } from "react-error-boundary";
import { BrowserRouter } from "react-router";

import GlobalError from "@/ui/legacy/global-error";
import Providers from "@/ui/legacy/providers";
import GlobalError from "@/ui/common/global-error";
import { Router } from "@/ui/router";

import "@/ui/globals.css";
Expand All @@ -13,11 +12,9 @@ import "../sentry.client.config";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<BrowserRouter>
<Providers>
<ErrorBoundary FallbackComponent={GlobalError}>
<Router />
</ErrorBoundary>
</Providers>
<ErrorBoundary FallbackComponent={GlobalError}>
<Router />
</ErrorBoundary>
</BrowserRouter>
</StrictMode>,
);
28 changes: 28 additions & 0 deletions src/ui/baby/components/AmountInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
interface AmountInputProps {
value: string;
onChange: (value: string) => void;
label: string;
placeholder: string;
}

export function AmountInput({
value,
onChange,
label,
placeholder,
}: AmountInputProps) {
return (
<div>
<label className="block text-sm font-medium text-accent-primary mb-1">
{label}
</label>
<input
type="text"
value={value}
onChange={(e) => onChange(e.target.value)}
className="w-full bg-secondary-highlight py-[14px] px-6 rounded border border-transparent text-accent-primary outline-none"
placeholder={placeholder}
/>
</div>
);
}
102 changes: 102 additions & 0 deletions src/ui/baby/components/DelegationsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { Button } from "@babylonlabs-io/core-ui";

import { ubbnToBaby } from "@/ui/legacy/utils/bbn";

interface Delegation {
delegation?: {
validatorAddress: string;
};
balance?: {
amount: string;
denom: string;
};
}

interface Validator {
operatorAddress: string;
description?: {
moniker: string;
};
}

interface DelegationsListProps {
delegations: Delegation[];
validators: Validator[];
getRewardsForValidator: (validatorAddress: string) => number;
onUnstakeAll: (validatorAddress: string, amount: string) => void;
onClaimRewards: (validatorAddress: string) => Promise<void>;
loading: boolean;
}

export function DelegationsList({
delegations,
validators,
getRewardsForValidator,
onUnstakeAll,
onClaimRewards,
loading,
}: DelegationsListProps) {
if (delegations.length === 0) {
return null;
}

return (
<div className="bg-secondary-highlight text-accent-primary p-6 rounded mb-6">
<h2 className="text-xl font-semibold mb-4">My Delegations</h2>
<div className="space-y-2">
{delegations.map((delegation, index) => {
const validatorAddress =
delegation.delegation?.validatorAddress || "";
const stakedAmount = ubbnToBaby(
parseFloat(delegation.balance?.amount || "0"),
);
const rewardsAmount = getRewardsForValidator(validatorAddress);

return (
<div
key={index}
className="flex justify-between items-center p-3 rounded bg-secondary-highlight text-accent-primary"
>
<div>
<p className="font-medium">
{validators.find(
(v) => v.operatorAddress === validatorAddress,
)?.description?.moniker || validatorAddress}
</p>
<p className="text-sm text-gray-600">
Staked: {stakedAmount.toLocaleString()} tBABY
</p>
{rewardsAmount > 0 && (
<p className="text-sm text-green-600">
Rewards: {rewardsAmount.toLocaleString()} tBABY
</p>
)}
</div>
<div className="flex gap-2">
<Button
variant="outlined"
size="small"
onClick={() =>
onUnstakeAll(validatorAddress, stakedAmount.toString())
}
>
Unstake All
</Button>
{rewardsAmount > 0 && (
<Button
variant="outlined"
size="small"
onClick={() => onClaimRewards(validatorAddress)}
disabled={loading}
>
{loading ? "Claiming..." : "Claim"}
</Button>
)}
</div>
</div>
);
})}
</div>
</div>
);
}
47 changes: 47 additions & 0 deletions src/ui/baby/components/RewardsForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Button } from "@babylonlabs-io/core-ui";

import { ValidatorSelector } from "./ValidatorSelector";

interface Validator {
operatorAddress: string;
description?: {
moniker: string;
};
}

interface RewardsFormProps {
validators: Validator[];
validatorAddress: string;
setValidatorAddress: (address: string) => void;
onClaimRewards: () => void;
loading: boolean;
}

export function RewardsForm({
validators,
validatorAddress,
setValidatorAddress,
onClaimRewards,
loading,
}: RewardsFormProps) {
return (
<div className="bg-secondary-highlight text-accent-primary p-6 rounded">
<h2 className="text-xl font-semibold mb-4">Rewards</h2>
<div className="space-y-4">
<ValidatorSelector
validators={validators}
value={validatorAddress}
onChange={setValidatorAddress}
label="Validator"
/>
<Button
fluid
onClick={onClaimRewards}
disabled={loading || !validatorAddress}
>
{loading ? "Claiming..." : "Claim Rewards"}
</Button>
</div>
</div>
);
}
58 changes: 58 additions & 0 deletions src/ui/baby/components/StakeForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Button } from "@babylonlabs-io/core-ui";

import { AmountInput } from "./AmountInput";
import { ValidatorSelector } from "./ValidatorSelector";

interface Validator {
operatorAddress: string;
description?: {
moniker: string;
};
}

interface StakeFormProps {
validators: Validator[];
validatorAddress: string;
setValidatorAddress: (address: string) => void;
stakeAmount: string;
setStakeAmount: (amount: string) => void;
onStake: () => void;
loading: boolean;
}

export function StakeForm({
validators,
validatorAddress,
setValidatorAddress,
stakeAmount,
setStakeAmount,
onStake,
loading,
}: StakeFormProps) {
return (
<div className="bg-secondary-highlight text-accent-primary p-6 rounded">
<h2 className="text-xl font-semibold mb-4">Stake</h2>
<div className="space-y-4">
<ValidatorSelector
validators={validators}
value={validatorAddress}
onChange={setValidatorAddress}
label="Validator"
/>
<AmountInput
value={stakeAmount}
onChange={setStakeAmount}
label="Amount (tBABY)"
placeholder="Enter tBABY amount to stake (e.g., 10)"
/>
<Button
fluid
onClick={onStake}
disabled={loading || !validatorAddress || !stakeAmount}
>
{loading ? "Staking..." : "Stake tBABY"}
</Button>
</div>
</div>
);
}
58 changes: 58 additions & 0 deletions src/ui/baby/components/UnstakeForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Button } from "@babylonlabs-io/core-ui";

import { AmountInput } from "./AmountInput";
import { ValidatorSelector } from "./ValidatorSelector";

interface Validator {
operatorAddress: string;
description?: {
moniker: string;
};
}

interface UnstakeFormProps {
validators: Validator[];
validatorAddress: string;
setValidatorAddress: (address: string) => void;
unstakeAmount: string;
setUnstakeAmount: (amount: string) => void;
onUnstake: () => void;
loading: boolean;
}

export function UnstakeForm({
validators,
validatorAddress,
setValidatorAddress,
unstakeAmount,
setUnstakeAmount,
onUnstake,
loading,
}: UnstakeFormProps) {
return (
<div className="bg-secondary-highlight text-accent-primary p-6 rounded">
<h2 className="text-xl font-semibold mb-4">Unstake</h2>
<div className="space-y-4">
<ValidatorSelector
validators={validators}
value={validatorAddress}
onChange={setValidatorAddress}
label="Validator"
/>
<AmountInput
value={unstakeAmount}
onChange={setUnstakeAmount}
label="Amount (tBABY)"
placeholder="Enter tBABY amount to unstake (e.g., 5)"
/>
<Button
fluid
onClick={onUnstake}
disabled={loading || !validatorAddress || !unstakeAmount}
>
{loading ? "Unstaking..." : "Unstake tBABY"}
</Button>
</div>
</div>
);
}
Loading