Skip to content

Commit 1ff6d1d

Browse files
feat(packages): pegin flow
1 parent f3d2ee5 commit 1ff6d1d

File tree

15 files changed

+795
-8
lines changed

15 files changed

+795
-8
lines changed

packages/babylon-core-ui/src/components/ActivityList/ActivityList.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,49 @@ import type { PropsWithChildren } from "react";
1717
export interface ActivityListProps {
1818
onNewItem?: () => void;
1919
className?: string;
20+
isEmpty?: boolean;
21+
isConnected?: boolean;
2022
}
2123

2224
export function ActivityList({
2325
onNewItem,
2426
className,
2527
children,
28+
isEmpty = false,
29+
isConnected = false,
2630
}: PropsWithChildren<ActivityListProps>) {
31+
// Show empty state when connected but no activities
32+
if (isEmpty && isConnected) {
33+
return (
34+
<Card className={className}>
35+
<div className="flex flex-col items-center justify-center gap-6 py-12 px-4">
36+
<img
37+
src="/mascot-smile-expression-full-body.png"
38+
alt="Babylon mascot"
39+
className="size-[200px]"
40+
/>
41+
<div className="text-center">
42+
<h3 className="text-xl font-semibold text-accent-primary mb-2">
43+
Supply Collateral BTC Trustlessly
44+
</h3>
45+
<p className="text-sm text-accent-secondary max-w-md">
46+
Enter the amount of BTC you want to deposit and select a provider to secure it.
47+
Your deposit will appear here once confirmed.
48+
</p>
49+
</div>
50+
<IconButton
51+
variant="outlined"
52+
size="large"
53+
onClick={onNewItem}
54+
aria-label="Create new item"
55+
>
56+
<PlusIcon />
57+
</IconButton>
58+
</div>
59+
</Card>
60+
);
61+
}
62+
2763
return (
2864
<Card className={className}>
2965
<div className="flex flex-col gap-4">
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* Vault Provider API
3+
*
4+
* This module handles fetching vault provider data.
5+
* Currently returns mock data, but structured to support GraphQL integration.
6+
*/
7+
8+
export interface VaultProvider {
9+
id: string;
10+
name: string;
11+
icon: string;
12+
apy?: number;
13+
tvl?: string;
14+
description?: string;
15+
}
16+
17+
export interface VaultProvidersResponse {
18+
providers: VaultProvider[];
19+
}
20+
21+
/**
22+
* Fetch vault providers from backend
23+
* TODO: Implement GraphQL query when backend is ready
24+
*
25+
* @returns Promise<VaultProvidersResponse>
26+
*/
27+
export async function getVaultProviders(): Promise<VaultProvidersResponse> {
28+
// TODO: Replace with actual GraphQL endpoint
29+
// Example GraphQL query:
30+
// query GetVaultProviders {
31+
// vaultProviders {
32+
// id
33+
// name
34+
// icon
35+
// apy
36+
// tvl
37+
// description
38+
// }
39+
// }
40+
41+
// Mock data - will be replaced by GraphQL query
42+
const mockProviders: VaultProvider[] = [
43+
{
44+
id: "ironclad",
45+
name: "Ironclad BTC",
46+
icon: "/icons/ironclad.svg",
47+
apy: 8.5,
48+
tvl: "1.2M",
49+
description: "Secure Bitcoin custody with institutional-grade security"
50+
},
51+
{
52+
id: "atlas",
53+
name: "Atlas Custody",
54+
icon: "/icons/atlas.svg",
55+
apy: 7.8,
56+
tvl: "2.5M",
57+
description: "Regulated custody solution for digital assets"
58+
},
59+
{
60+
id: "stonewall",
61+
name: "Stonewall Capital",
62+
icon: "/icons/stonewall.svg",
63+
apy: 9.2,
64+
tvl: "850K",
65+
description: "High-yield Bitcoin vault provider"
66+
},
67+
{
68+
id: "redwood",
69+
name: "Redwood BTC",
70+
icon: "/icons/redwood.svg",
71+
apy: 8.0,
72+
tvl: "1.8M",
73+
description: "Enterprise-grade Bitcoin vault infrastructure"
74+
},
75+
];
76+
77+
return {
78+
providers: mockProviders,
79+
};
80+
}

routes/vault/src/api/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* API Module
3+
*
4+
* Centralized exports for all API functions
5+
*/
6+
7+
export * from './getVaultProviders';

routes/vault/src/assets/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// Asset exports for vault application
22

3+
// Bitcoin icon as data URI - Orange bitcoin logo
4+
export const bitcoinIcon = "data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='%23FF7C2A' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M23.638 14.904c-1.602 6.43-8.113 10.34-14.542 8.736C2.67 22.05-1.244 15.525.362 9.105 1.962 2.67 8.475-1.243 14.9.358c6.43 1.605 10.342 8.115 8.738 14.548v-.002zm-6.35-4.613c.24-1.59-.974-2.45-2.64-3.03l.54-2.153-1.315-.33-.525 2.107c-.345-.087-.705-.167-1.064-.25l.526-2.127-1.32-.33-.54 2.165c-.285-.067-.565-.132-.84-.2l-1.815-.45-.35 1.407s.975.225.955.236c.535.136.63.486.615.766l-1.477 5.92c-.075.166-.24.406-.614.314.015.02-.96-.24-.96-.24l-.66 1.51 1.71.426.93.242-.54 2.19 1.32.327.54-2.17c.36.1.705.19 1.05.273l-.51 2.154 1.32.33.545-2.19c2.24.427 3.93.257 4.64-1.774.57-1.637-.03-2.58-1.217-3.196.854-.193 1.5-.76 1.68-1.93h.01zm-3.01 4.22c-.404 1.64-3.157.75-4.05.53l.72-2.9c.896.23 3.757.67 3.33 2.37zm.41-4.24c-.37 1.49-2.662.735-3.405.55l.654-2.64c.744.18 3.137.524 2.75 2.084v.006z'/%3E%3C/svg%3E";
5+
36
// USDC icon as data URI - Simple circle design with USDC branding
47
export const usdcIcon = 'data:image/svg+xml,%3Csvg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"%3E%3Ccircle cx="20" cy="20" r="20" fill="%232775CA"/%3E%3Cpath d="M24.0001 17.3999C24.0001 15.6399 22.8001 14.7999 20.4001 14.5999V12.3999H18.8001V14.5599C18.3601 14.5599 17.9201 14.5599 17.4801 14.5999V12.3999H15.8801V14.5999C15.5601 14.5999 15.2401 14.6399 14.9201 14.6399H13.2001V16.3599H14.4401C14.8801 16.3599 15.0801 16.5999 15.0801 16.9599V23.0399C15.0801 23.3999 14.8801 23.6399 14.4401 23.6399H13.2001V25.7599L14.8401 25.7999C15.1601 25.7999 15.4801 25.7999 15.8001 25.8399V28.0399H17.4001V25.8799C17.8401 25.8799 18.2801 25.9199 18.7201 25.9199V28.0799H20.3201V25.8799C23.2001 25.7199 24.8001 24.5199 24.8001 22.3599C24.8001 20.7999 24.0001 19.8799 22.5601 19.4799C23.5201 19.0799 24.0001 18.3599 24.0001 17.3999ZM18.7201 21.1999V23.5199C17.7201 23.4399 17.2001 23.3999 16.6801 23.3599V21.1999C17.2001 21.1599 17.7201 21.1199 18.7201 21.1999ZM20.3201 16.7199C21.2401 16.7999 21.7601 16.8399 22.3201 16.9199V19.0399C21.7601 18.9599 21.2401 18.9199 20.3201 18.8399V16.7199ZM20.3201 23.5599V21.1599C21.3201 21.2399 21.8401 21.2799 22.4001 21.3599C22.6001 22.3599 21.8401 23.1999 20.3201 23.5599Z" fill="white"/%3E%3C/svg%3E';
58

routes/vault/src/components/Activities/Activities.tsx

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ import {
77
ProviderItem,
88
} from "@babylonlabs-io/core-ui";
99
import { BorrowFlow } from "../BorrowFlow";
10+
import {
11+
PeginModal,
12+
PeginSignModal,
13+
PeginSuccessModal,
14+
} from "../modals";
1015
import { useActivitiesState } from "./useActivitiesState";
1116

1217
export function Activities() {
@@ -19,6 +24,18 @@ export function Activities() {
1924
handleBorrowFlowClose,
2025
isWalletConnected,
2126
refetchActivities,
27+
// Deposit flow
28+
peginModalOpen,
29+
peginSignModalOpen,
30+
peginSuccessModalOpen,
31+
peginAmount,
32+
selectedProviders,
33+
btcBalanceSat,
34+
handlePeginClick,
35+
handlePeginSignSuccess,
36+
handlePeginSuccessClose,
37+
setPeginModalOpen,
38+
setPeginSignModalOpen,
2239
} = useActivitiesState();
2340

2441
console.log('[Activities] activities:', activities);
@@ -110,7 +127,11 @@ export function Activities() {
110127
return (
111128
<>
112129
<div className="container mx-auto flex max-w-[760px] flex-1 flex-col px-4 py-8">
113-
<ActivityList onNewItem={handleNewBorrow}>
130+
<ActivityList
131+
onNewItem={handleNewBorrow}
132+
isEmpty={activities.length === 0}
133+
isConnected={isWalletConnected}
134+
>
114135
{activityCardData.map((data, index) => (
115136
<ActivityCard key={activities[index].id} data={data} />
116137
))}
@@ -123,6 +144,28 @@ export function Activities() {
123144
onClose={handleBorrowFlowClose}
124145
onBorrowSuccess={refetchActivities}
125146
/>
147+
148+
{/* Peg-in Modals */}
149+
<PeginModal
150+
open={peginModalOpen}
151+
onClose={() => setPeginModalOpen(false)}
152+
onPegIn={handlePeginClick}
153+
btcBalance={btcBalanceSat}
154+
/>
155+
156+
<PeginSignModal
157+
open={peginSignModalOpen}
158+
onClose={() => setPeginSignModalOpen(false)}
159+
onSuccess={handlePeginSignSuccess}
160+
amount={peginAmount}
161+
selectedProviders={selectedProviders}
162+
/>
163+
164+
<PeginSuccessModal
165+
open={peginSuccessModalOpen}
166+
onClose={handlePeginSuccessClose}
167+
amount={peginAmount}
168+
/>
126169
</>
127170
);
128171
}

routes/vault/src/components/Activities/useActivitiesState.ts

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useState, useMemo, useCallback } from "react";
22
import { useChainConnector } from "@babylonlabs-io/wallet-connector";
33
import type { Hex } from "viem";
44
import type { VaultActivity } from "../../mockData/vaultActivities";
5-
import { usePeginRequests } from "../../hooks/usePeginRequests";
5+
import { usePeginRequests } from "../../hooks";
66

77
export function useActivitiesState() {
88
const ethConnector = useChainConnector('ETH');
@@ -18,10 +18,20 @@ export function useActivitiesState() {
1818
return address;
1919
}, [ethConnector]);
2020

21+
// Hardcoded BTC balance (in satoshis) - TODO: Replace with real wallet balance
22+
const btcBalanceSat = 500000000; // 5 BTC
23+
2124
// Borrow flow state
2225
const [borrowFlowOpen, setBorrowFlowOpen] = useState(false);
2326
const [selectedActivity, setSelectedActivity] = useState<VaultActivity | null>(null);
2427

28+
// Peg-in flow state
29+
const [peginModalOpen, setPeginModalOpen] = useState(false);
30+
const [peginSignModalOpen, setPeginSignModalOpen] = useState(false);
31+
const [peginSuccessModalOpen, setPeginSuccessModalOpen] = useState(false);
32+
const [peginAmount, setPeginAmount] = useState(0);
33+
const [selectedProviders, setSelectedProviders] = useState<string[]>([]);
34+
2535
const handleActivityBorrow = useCallback((activity: VaultActivity) => {
2636
setSelectedActivity(activity);
2737
setBorrowFlowOpen(true);
@@ -36,17 +46,35 @@ export function useActivitiesState() {
3646
console.log('[useActivitiesState] activities from usePeginRequests:', activities);
3747

3848
const handleNewBorrow = useCallback(() => {
39-
if (activities.length > 0) {
40-
setSelectedActivity(activities[0]);
41-
setBorrowFlowOpen(true);
42-
}
43-
}, [activities]);
49+
// Open peg-in modal instead of borrow modal
50+
setPeginModalOpen(true);
51+
}, []);
4452

4553
const handleBorrowFlowClose = useCallback(() => {
4654
setBorrowFlowOpen(false);
4755
setSelectedActivity(null);
4856
}, []);
4957

58+
// Peg-in handlers
59+
const handlePeginClick = useCallback((amount: number, providers: string[]) => {
60+
console.log("Peg-in clicked:", { amount, providers });
61+
setPeginAmount(amount);
62+
setSelectedProviders(providers);
63+
setPeginModalOpen(false);
64+
setPeginSignModalOpen(true);
65+
}, []);
66+
67+
const handlePeginSignSuccess = useCallback(() => {
68+
setPeginSignModalOpen(false);
69+
setPeginSuccessModalOpen(true);
70+
}, []);
71+
72+
const handlePeginSuccessClose = useCallback(() => {
73+
setPeginSuccessModalOpen(false);
74+
setPeginAmount(0);
75+
setSelectedProviders([]);
76+
}, []);
77+
5078
return {
5179
activities,
5280
borrowFlowOpen,
@@ -56,5 +84,17 @@ export function useActivitiesState() {
5684
handleBorrowFlowClose,
5785
isWalletConnected: !!connectedAddress,
5886
refetchActivities: refetch,
87+
// Peg-in flow
88+
peginModalOpen,
89+
peginSignModalOpen,
90+
peginSuccessModalOpen,
91+
peginAmount,
92+
selectedProviders,
93+
btcBalanceSat,
94+
handlePeginClick,
95+
handlePeginSignSuccess,
96+
handlePeginSuccessClose,
97+
setPeginModalOpen,
98+
setPeginSignModalOpen,
5999
};
60100
}

0 commit comments

Comments
 (0)