Skip to content

Commit 69d8d3d

Browse files
authored
Merge pull request #31 from HORNET-Storage/feat-ui/unconfirmed-transactions
Feat UI/unconfirmed transactions
2 parents b7f79d2 + d0a1d87 commit 69d8d3d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2475
-1028
lines changed

.env.development

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
REACT_APP_BASE_URL=http://localhost:9002
2-
# REACT_APP_BASE_URL=https://11561ba2d27f.ngrok.app
2+
REACT_APP_WALLET_BASE_URL=http://localhost:9003 # New wallet base URL
33
REACT_APP_ASSETS_BUCKET=http://localhost
4-
REACT_APP_DEMO_MODE=true
4+
REACT_APP_DEMO_MODE=false
55

6-
# more info https://create-react-app.dev/docs/advanced-configuration
6+
# More info https://create-react-app.dev/docs/advanced-configuration
77
ESLINT_NO_DEV_ERRORS=true
88
TSC_COMPILE_ON_ERROR=true

src/api/activity.api.ts

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11

22
// eslint-disable-next-line @typescript-eslint/no-unused-vars
33
import { ActivityStatusType } from '@app/interfaces/interfaces';
4+
import { readToken } from '@app/services/localStorage.service';
45
import config from '@app/config/config';
6+
import { message } from 'antd';
57

68
export interface WalletTransaction {
79
id: number;
@@ -11,33 +13,46 @@ export interface WalletTransaction {
1113
value: string;
1214
}
1315

14-
export const getUserActivities = (): Promise<WalletTransaction[]> => {
15-
return fetch(`${config.baseURL}/transactions/latest`)
16-
.then((response) => {
17-
if (!response.ok) {
18-
throw new Error('Network response was not ok');
19-
}
20-
return response.json();
21-
})
22-
.then((data) => {
23-
if (Array.isArray(data) && data.length === 0) {
24-
// Handle the case where the response is an empty array
25-
return [];
26-
}
27-
// Assuming your backend response matches the WalletTransaction interface
28-
// eslint-disable-next-line
29-
return data.map((item: any) => ({
30-
id: item.ID,
31-
witness_tx_id: item.WitnessTxId,
32-
date: new Date(item.Date).getTime(),
33-
output: item.Output,
34-
value: item.Value,
35-
}));
36-
})
37-
.catch((error) => {
38-
console.error('Error fetching user activities:', error);
16+
export const getUserActivities = (handleLogout: () => void): Promise<WalletTransaction[]> => {
17+
const token = readToken(); // Read the JWT token from local storage
18+
19+
if (!token) {
20+
handleLogout(); // Call handleLogout if no token
21+
return Promise.reject('No token found');
22+
}
23+
24+
return fetch(`${config.baseURL}/api/transactions/latest`, {
25+
method: 'GET',
26+
headers: {
27+
'Authorization': `Bearer ${token}`,
28+
'Content-Type': 'application/json',
29+
},
30+
})
31+
.then((response) => {
32+
if (!response.ok) {
33+
throw new Error('Network response was not ok');
34+
}
35+
return response.json();
36+
})
37+
.then((data) => {
38+
if (Array.isArray(data) && data.length === 0) {
39+
// Handle the case where the response is an empty array
3940
return [];
40-
});
41+
}
42+
// Assuming your backend response matches the WalletTransaction interface
43+
// eslint-disable-next-line
44+
return data.map((item: any) => ({
45+
id: item.ID,
46+
witness_tx_id: item.WitnessTxId,
47+
date: new Date(item.Date).getTime(),
48+
output: item.Output,
49+
value: item.Value,
50+
}));
51+
})
52+
.catch((error) => {
53+
console.error('Error fetching user activities:', error);
54+
return [];
55+
});
4156
};
4257

4358
export interface Activity {

src/api/earnings.api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export const getTotalEarning = (id: number, currency: CurrencyTypeEnum): Promise
7575

7676
export const getBitcoinRatesForLast30Days = (): Promise<Earning[]> => {
7777
console.log('Fetching bitcoin rate data.');
78-
return fetch('http://localhost:5000/bitcoin-rates/last-30-days')
78+
return fetch('http://localhost:5000/api/bitcoin-rates/last-30-days')
7979
.then((response) => response.json())
8080
.then((data) => {
8181
console.log('Received data:', data); // Add log statement to see the data

src/components/auth/LoginForm/LoginForm.tsx

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ export const LoginForm: React.FC = () => {
4545
const dispatch = useDispatch();
4646

4747
const [form] = Form.useForm();
48-
const [event, setEvent] = useState<any>(null);
4948

5049
useEffect(() => {
5150
const fetchPublicKey = async () => {
@@ -60,37 +59,44 @@ export const LoginForm: React.FC = () => {
6059
console.error('Failed to get public key:', error);
6160
}
6261
};
63-
64-
fetchPublicKey();
65-
66-
const isFirstLoad = localStorage.getItem('isFirstLoad');
67-
if (!isFirstLoad) {
68-
window.location.reload();
69-
localStorage.setItem('isFirstLoad', 'true');
70-
}
62+
63+
const intervalId = setInterval(() => {
64+
if (window.nostr) {
65+
fetchPublicKey();
66+
clearInterval(intervalId);
67+
}
68+
}, 1000); // Retry every 1 second
69+
70+
return () => clearInterval(intervalId); // Clear the interval on component unmount
7171
}, [form]);
72+
73+
74+
const [event, setEvent] = useState<any>(null);
7275

7376
const handleSubmit = async (values: LoginFormData) => {
7477
try {
78+
if (!window.nostr) {
79+
notificationController.error({ message: 'Nostr extension is not available' });
80+
return;
81+
}
82+
7583
const { success, event } = await login(values);
7684
if (success && event) {
7785
setEvent(event);
78-
// Automatically proceed to verification
7986
const signedEvent = await window.nostr.signEvent(event);
8087
console.log('Signed event:', signedEvent);
81-
88+
8289
const response = await verifyChallenge({
8390
challenge: signedEvent.content,
8491
signature: signedEvent.sig,
8592
messageHash: signedEvent.id,
8693
event: signedEvent,
8794
});
88-
95+
8996
if (response.success) {
9097
if (response.token && response.user) {
9198
persistToken(response.token);
9299
dispatch(setUser(response.user));
93-
// Set the token in the API instance
94100
notificationController.success({
95101
message: 'Login successful',
96102
description: 'You have successfully logged in!',
@@ -105,6 +111,7 @@ export const LoginForm: React.FC = () => {
105111
notificationController.error({ message: error.message });
106112
}
107113
};
114+
108115

109116
return (
110117
<Auth.FormWrapper>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React, { useState } from 'react';
2+
import { CopyOutlined } from '@ant-design/icons';
3+
import CopyToClipboard from 'react-copy-to-clipboard';
4+
import { Button, message } from 'antd';
5+
interface CopyToClipboardProps {
6+
textToCopy: string;
7+
}
8+
9+
const ClipboardCopy: React.FC<CopyToClipboardProps> = ({ textToCopy }) => {
10+
const copied = () => {
11+
message.success('Copied to clipboard');
12+
};
13+
const onCopy = () => {
14+
//display Copied to clipboard
15+
copied();
16+
};
17+
return (
18+
<CopyToClipboard text={textToCopy}>
19+
<Button onClick={onCopy} icon={<CopyOutlined />} size="small" />
20+
</CopyToClipboard>
21+
);
22+
};
23+
24+
export default ClipboardCopy;

src/components/layouts/main/MainHeader/MainHeader.styles.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const Header = styled(BaseLayout.Header)<Header>`
1212
line-height: 1.5;
1313
z-index: 105;
1414
15-
@media only screen and ${media.xs} {
15+
@media only screen and ${media.xxs} {
1616
${(props) =>
1717
props.$isSiderOpened &&
1818
css`

src/components/relay-dashboard/Balance/components/SendForm/SendForm.styles.ts

Lines changed: 16 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,6 @@ export const TextRow = styled.div`
1313
gap: 1rem;
1414
`;
1515

16-
export const SubCard = styled(BaseCard)<{ $isMobile?: boolean }>`
17-
width: 30%;
18-
${(props) =>
19-
props.$isMobile &&
20-
css`
21-
width: 100%;
22-
`}
23-
background-color: var(--additional-background-color);
24-
cursor: pointer;
25-
box-shadow: 0px 0px 10px 0px var(--shadow-color);
26-
.ant-card-body {
27-
padding: 1rem 2rem;
28-
}
29-
`;
3016
export const SendBody = styled(BaseRow)`
3117
padding-bottom: 1rem;
3218
`;
@@ -45,28 +31,16 @@ export const FormHeader = styled.span`
4531
padding-bottom: 1rem;
4632
`;
4733

48-
export const SubCardHeader = styled.span`
49-
font-size: 1.5rem;
50-
`;
51-
5234
export const InputHeader = styled.span`
5335
font-size: 1.5rem;
5436
`;
5537

56-
export const SubCardAmount = styled.span`
57-
font-size: 1.5rem;
58-
`;
59-
export const SubCardContent = styled.div`
60-
font-size: 1.3rem;
61-
height: 100%;
38+
export const RBFWrapper = styled.div`
6239
display: flex;
63-
justify-content: space-around;
64-
flex-direction: column;
40+
flex-direction: row;
41+
gap: 1rem;
6542
align-items: center;
66-
text-align: center;
67-
gap: 3rem;
68-
padding-top: 1rem;
69-
padding-bottom: 1rem;
43+
justify-content: center;
7044
`;
7145

7246
export const InputWrapper = styled.div`
@@ -75,38 +49,21 @@ export const InputWrapper = styled.div`
7549
flex-direction: column;
7650
gap: 0.5rem;
7751
`;
78-
export const TiersRow = styled.div`
52+
53+
export const InputHeaderWrapper = styled.div`
7954
display: flex;
8055
flex-direction: row;
8156
gap: 1rem;
82-
justify-content: space-around;
8357
`;
84-
85-
export const TiersCol = styled.div`
58+
export const TiersContainer = styled.div`
8659
display: flex;
8760
flex-direction: column;
8861
gap: 1rem;
89-
justify-content: space-around;
9062
`;
9163
export const SendFormButton = styled(BaseButton)`
9264
width: 100%;
9365
`;
94-
export const TiersContainer = styled.div`
95-
display: flex;
96-
flex-direction: column;
97-
gap: 1rem;
98-
transition: all 0.5s ease;
99-
padding: 1rem;
100-
.tier-hover:hover {
101-
background-color: var(--primary-color);
102-
}
103-
.selected {
104-
border: 1px solid var(--primary-color);
105-
}
106-
.invalidAmount {
107-
border: 1px solid var(--error-color);
108-
}
109-
`;
66+
11067
export const BalanceInfo = styled.small`
11168
color: var(--subtext-color);
11269
`;
@@ -118,26 +75,24 @@ export const Recipient = styled.span`
11875
export const ErrorText = styled.small`
11976
color: var(--error-color);
12077
display: flex;
78+
op
12179
flex-direction: row;
12280
align-items: center;
12381
`;
12482
export const AddressText = styled.span`
12583
text-decoration: underline;
12684
color: var(--text-main-color);
12785
`;
128-
129-
export const RateValueWrapper = styled.div`
86+
export const TiersRow = styled.div`
13087
display: flex;
131-
flex-direction: column;
88+
flex-direction: row;
13289
gap: 1rem;
90+
justify-content: space-around;
13391
`;
134-
export const RateValue = styled.span`
135-
color: green;
136-
`;
137-
export const RBFWrapper = styled.div`
92+
93+
export const TiersCol = styled.div`
13894
display: flex;
139-
flex-direction: row;
95+
flex-direction: column;
14096
gap: 1rem;
141-
align-items: center;
142-
justify-content: center;
97+
justify-content: space-around;
14398
`;

0 commit comments

Comments
 (0)