keynesol-shared 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -0
- package/dist/components/Common/ErrorBoundary.d.ts +23 -0
- package/dist/components/Common/ErrorBoundary.d.ts.map +1 -0
- package/dist/components/Common/ErrorBoundary.js +93 -0
- package/dist/components/Common/ErrorBoundary.jsx +103 -0
- package/dist/components/Common/ErrorMessage.d.ts +8 -0
- package/dist/components/Common/ErrorMessage.d.ts.map +1 -0
- package/dist/components/Common/ErrorMessage.js +36 -0
- package/dist/components/Common/ErrorMessage.jsx +40 -0
- package/dist/components/Common/Loading.d.ts +8 -0
- package/dist/components/Common/Loading.d.ts.map +1 -0
- package/dist/components/Common/Loading.js +41 -0
- package/dist/components/Common/Loading.jsx +44 -0
- package/dist/components/Common/LoadingIndicator.d.ts +17 -0
- package/dist/components/Common/LoadingIndicator.d.ts.map +1 -0
- package/dist/components/Common/LoadingIndicator.js +95 -0
- package/dist/components/Common/LoadingIndicator.jsx +108 -0
- package/dist/components/Common/ProgramStatus.d.ts +3 -0
- package/dist/components/Common/ProgramStatus.d.ts.map +1 -0
- package/dist/components/Common/ProgramStatus.js +26 -0
- package/dist/components/Common/ProgramStatus.jsx +27 -0
- package/dist/components/Common/Skeleton.d.ts +39 -0
- package/dist/components/Common/Skeleton.d.ts.map +1 -0
- package/dist/components/Common/Skeleton.js +53 -0
- package/dist/components/Common/Skeleton.jsx +67 -0
- package/dist/components/Common/SkeletonScreen.d.ts +18 -0
- package/dist/components/Common/SkeletonScreen.d.ts.map +1 -0
- package/dist/components/Common/SkeletonScreen.js +98 -0
- package/dist/components/Common/SkeletonScreen.jsx +108 -0
- package/dist/components/Common/index.d.ts +11 -0
- package/dist/components/Common/index.d.ts.map +1 -0
- package/dist/components/Common/index.js +10 -0
- package/dist/components/Wallet/TransactionStatus.d.ts +11 -0
- package/dist/components/Wallet/TransactionStatus.d.ts.map +1 -0
- package/dist/components/Wallet/TransactionStatus.js +97 -0
- package/dist/components/Wallet/TransactionStatus.jsx +106 -0
- package/dist/components/Wallet/WalletBalance.d.ts +4 -0
- package/dist/components/Wallet/WalletBalance.d.ts.map +1 -0
- package/dist/components/Wallet/WalletBalance.js +82 -0
- package/dist/components/Wallet/WalletBalance.jsx +86 -0
- package/dist/components/Wallet/WalletButton.d.ts +3 -0
- package/dist/components/Wallet/WalletButton.d.ts.map +1 -0
- package/dist/components/Wallet/WalletButton.js +51 -0
- package/dist/components/Wallet/WalletButton.jsx +53 -0
- package/dist/components/Wallet/WalletConnectionModal.d.ts +8 -0
- package/dist/components/Wallet/WalletConnectionModal.d.ts.map +1 -0
- package/dist/components/Wallet/WalletConnectionModal.js +150 -0
- package/dist/components/Wallet/WalletConnectionModal.jsx +170 -0
- package/dist/components/Wallet/WalletProvider.d.ts +9 -0
- package/dist/components/Wallet/WalletProvider.d.ts.map +1 -0
- package/dist/components/Wallet/WalletProvider.js +70 -0
- package/dist/components/Wallet/WalletProvider.jsx +75 -0
- package/dist/components/Wallet/index.d.ts +9 -0
- package/dist/components/Wallet/index.d.ts.map +1 -0
- package/dist/components/Wallet/index.js +8 -0
- package/dist/components/index.d.ts +7 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +6 -0
- package/dist/hooks/index.d.ts +10 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +9 -0
- package/dist/hooks/useCache.d.ts +16 -0
- package/dist/hooks/useCache.d.ts.map +1 -0
- package/dist/hooks/useCache.js +67 -0
- package/dist/hooks/usePolling.d.ts +16 -0
- package/dist/hooks/usePolling.d.ts.map +1 -0
- package/dist/hooks/usePolling.js +79 -0
- package/dist/hooks/useProgram.d.ts +14 -0
- package/dist/hooks/useProgram.d.ts.map +1 -0
- package/dist/hooks/useProgram.js +88 -0
- package/dist/hooks/useTokenBalance.d.ts +16 -0
- package/dist/hooks/useTokenBalance.d.ts.map +1 -0
- package/dist/hooks/useTokenBalance.js +100 -0
- package/dist/hooks/useVaults.d.ts +23 -0
- package/dist/hooks/useVaults.d.ts.map +1 -0
- package/dist/hooks/useVaults.js +98 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/services/index.d.ts +7 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +6 -0
- package/dist/services/reconciliationService.d.ts +76 -0
- package/dist/services/reconciliationService.d.ts.map +1 -0
- package/dist/services/reconciliationService.js +216 -0
- package/dist/services/syncService.d.ts +51 -0
- package/dist/services/syncService.d.ts.map +1 -0
- package/dist/services/syncService.js +218 -0
- package/dist/types/index.d.ts +201 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/cacheManager.d.ts +73 -0
- package/dist/utils/cacheManager.d.ts.map +1 -0
- package/dist/utils/cacheManager.js +232 -0
- package/dist/utils/errorHandler.d.ts +76 -0
- package/dist/utils/errorHandler.d.ts.map +1 -0
- package/dist/utils/errorHandler.js +267 -0
- package/dist/utils/index.d.ts +12 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +11 -0
- package/dist/utils/performanceMonitor.d.ts +75 -0
- package/dist/utils/performanceMonitor.d.ts.map +1 -0
- package/dist/utils/performanceMonitor.js +197 -0
- package/dist/utils/rpcRetry.d.ts +12 -0
- package/dist/utils/rpcRetry.d.ts.map +1 -0
- package/dist/utils/rpcRetry.js +47 -0
- package/dist/utils/supabase.d.ts +198 -0
- package/dist/utils/supabase.d.ts.map +1 -0
- package/dist/utils/supabase.js +50 -0
- package/dist/utils/toastService.d.ts +52 -0
- package/dist/utils/toastService.d.ts.map +1 -0
- package/dist/utils/toastService.js +139 -0
- package/dist/utils/tokenUtils.d.ts +33 -0
- package/dist/utils/tokenUtils.d.ts.map +1 -0
- package/dist/utils/tokenUtils.js +66 -0
- package/dist/utils/validation.d.ts +35 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +83 -0
- package/package.json +45 -0
- package/src/components/Common/ErrorBoundary.tsx +135 -0
- package/src/components/Common/ErrorMessage.tsx +52 -0
- package/src/components/Common/Loading.tsx +56 -0
- package/src/components/Common/LoadingIndicator.tsx +143 -0
- package/src/components/Common/ProgramStatus.tsx +37 -0
- package/src/components/Common/Skeleton.tsx +83 -0
- package/src/components/Common/SkeletonScreen.tsx +166 -0
- package/src/components/Common/index.ts +10 -0
- package/src/components/Wallet/TransactionStatus.tsx +138 -0
- package/src/components/Wallet/WalletBalance.tsx +94 -0
- package/src/components/Wallet/WalletButton.tsx +65 -0
- package/src/components/Wallet/WalletConnectionModal.tsx +193 -0
- package/src/components/Wallet/WalletProvider.tsx +104 -0
- package/src/components/Wallet/index.ts +8 -0
- package/src/components/index.ts +6 -0
- package/src/hooks/index.ts +10 -0
- package/src/hooks/useCache.ts +87 -0
- package/src/hooks/usePolling.ts +98 -0
- package/src/hooks/useProgram.ts +93 -0
- package/src/hooks/useTokenBalance.ts +113 -0
- package/src/hooks/useVaults.ts +122 -0
- package/src/index.ts +23 -0
- package/src/services/index.ts +6 -0
- package/src/services/reconciliationService.ts +246 -0
- package/src/services/syncService.ts +238 -0
- package/src/types/index.ts +233 -0
- package/src/utils/cacheManager.ts +286 -0
- package/src/utils/errorHandler.ts +336 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/performanceMonitor.ts +222 -0
- package/src/utils/rpcRetry.ts +55 -0
- package/src/utils/supabase.ts +253 -0
- package/src/utils/toastService.ts +166 -0
- package/src/utils/tokenUtils.ts +75 -0
- package/src/utils/validation.ts +107 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
const StatusContainer = styled.div `
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: 0.75rem;
|
|
7
|
+
padding: 1rem;
|
|
8
|
+
background: var(--color-surface, #f9fafb);
|
|
9
|
+
border: 1px solid ${props => {
|
|
10
|
+
switch (props.status) {
|
|
11
|
+
case 'confirmed': return 'var(--color-success, #10b981)';
|
|
12
|
+
case 'failed': return 'var(--color-error, #dc3545)';
|
|
13
|
+
default: return 'var(--color-primary, #6a8102)';
|
|
14
|
+
}
|
|
15
|
+
}};
|
|
16
|
+
border-radius: 0.5rem;
|
|
17
|
+
animation: slideIn 0.3s ease-out;
|
|
18
|
+
|
|
19
|
+
@keyframes slideIn {
|
|
20
|
+
from {
|
|
21
|
+
transform: translateX(100%);
|
|
22
|
+
opacity: 0;
|
|
23
|
+
}
|
|
24
|
+
to {
|
|
25
|
+
transform: translateX(0);
|
|
26
|
+
opacity: 1;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
const StatusIcon = styled.div `
|
|
31
|
+
width: 24px;
|
|
32
|
+
height: 24px;
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
justify-content: center;
|
|
36
|
+
font-size: 1.25rem;
|
|
37
|
+
|
|
38
|
+
${props => props.status === 'pending' && `
|
|
39
|
+
animation: spin 1s linear infinite;
|
|
40
|
+
@keyframes spin {
|
|
41
|
+
to { transform: rotate(360deg); }
|
|
42
|
+
}
|
|
43
|
+
`}
|
|
44
|
+
`;
|
|
45
|
+
const StatusContent = styled.div `
|
|
46
|
+
flex: 1;
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: column;
|
|
49
|
+
gap: 0.25rem;
|
|
50
|
+
`;
|
|
51
|
+
const StatusTitle = styled.span `
|
|
52
|
+
font-weight: 600;
|
|
53
|
+
color: var(--color-text, #1a1a1a);
|
|
54
|
+
font-size: 0.875rem;
|
|
55
|
+
`;
|
|
56
|
+
const StatusMessage = styled.span `
|
|
57
|
+
font-size: 0.75rem;
|
|
58
|
+
color: var(--color-text-secondary, #6b7280);
|
|
59
|
+
`;
|
|
60
|
+
const SignatureLink = styled.a `
|
|
61
|
+
font-size: 0.75rem;
|
|
62
|
+
color: var(--color-primary, #6a8102);
|
|
63
|
+
text-decoration: none;
|
|
64
|
+
font-family: monospace;
|
|
65
|
+
|
|
66
|
+
&:hover {
|
|
67
|
+
text-decoration: underline;
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
const TransactionStatus = ({ status, message, signature, explorerUrl = 'https://explorer.solana.com/tx', network }) => {
|
|
71
|
+
var _a;
|
|
72
|
+
const getIcon = () => {
|
|
73
|
+
switch (status) {
|
|
74
|
+
case 'confirmed':
|
|
75
|
+
return '✓';
|
|
76
|
+
case 'failed':
|
|
77
|
+
return '✗';
|
|
78
|
+
default:
|
|
79
|
+
return '⟳';
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const getTitle = () => {
|
|
83
|
+
switch (status) {
|
|
84
|
+
case 'confirmed':
|
|
85
|
+
return 'Transaction Confirmed';
|
|
86
|
+
case 'failed':
|
|
87
|
+
return 'Transaction Failed';
|
|
88
|
+
default:
|
|
89
|
+
return 'Transaction Pending';
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const networkParam = network ||
|
|
93
|
+
(typeof process !== 'undefined' && ((_a = process.env) === null || _a === void 0 ? void 0 : _a.NEXT_PUBLIC_SOLANA_NETWORK)) ||
|
|
94
|
+
'devnet';
|
|
95
|
+
return (_jsxs(StatusContainer, { status: status, children: [_jsx(StatusIcon, { status: status, children: getIcon() }), _jsxs(StatusContent, { children: [_jsx(StatusTitle, { children: getTitle() }), _jsx(StatusMessage, { children: message }), signature && status === 'confirmed' && (_jsx(SignatureLink, { href: `${explorerUrl}/${signature}?cluster=${networkParam}`, target: "_blank", rel: "noopener noreferrer", children: "View on Explorer \u2192" }))] })] }));
|
|
96
|
+
};
|
|
97
|
+
export default TransactionStatus;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
const StatusContainer = styled.div `
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: 0.75rem;
|
|
7
|
+
padding: 1rem;
|
|
8
|
+
background: var(--color-surface, #f9fafb);
|
|
9
|
+
border: 1px solid ${props => {
|
|
10
|
+
switch (props.status) {
|
|
11
|
+
case 'confirmed': return 'var(--color-success, #10b981)';
|
|
12
|
+
case 'failed': return 'var(--color-error, #dc3545)';
|
|
13
|
+
default: return 'var(--color-primary, #6a8102)';
|
|
14
|
+
}
|
|
15
|
+
}};
|
|
16
|
+
border-radius: 0.5rem;
|
|
17
|
+
animation: slideIn 0.3s ease-out;
|
|
18
|
+
|
|
19
|
+
@keyframes slideIn {
|
|
20
|
+
from {
|
|
21
|
+
transform: translateX(100%);
|
|
22
|
+
opacity: 0;
|
|
23
|
+
}
|
|
24
|
+
to {
|
|
25
|
+
transform: translateX(0);
|
|
26
|
+
opacity: 1;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
const StatusIcon = styled.div `
|
|
31
|
+
width: 24px;
|
|
32
|
+
height: 24px;
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
justify-content: center;
|
|
36
|
+
font-size: 1.25rem;
|
|
37
|
+
|
|
38
|
+
${props => props.status === 'pending' && `
|
|
39
|
+
animation: spin 1s linear infinite;
|
|
40
|
+
@keyframes spin {
|
|
41
|
+
to { transform: rotate(360deg); }
|
|
42
|
+
}
|
|
43
|
+
`}
|
|
44
|
+
`;
|
|
45
|
+
const StatusContent = styled.div `
|
|
46
|
+
flex: 1;
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: column;
|
|
49
|
+
gap: 0.25rem;
|
|
50
|
+
`;
|
|
51
|
+
const StatusTitle = styled.span `
|
|
52
|
+
font-weight: 600;
|
|
53
|
+
color: var(--color-text, #1a1a1a);
|
|
54
|
+
font-size: 0.875rem;
|
|
55
|
+
`;
|
|
56
|
+
const StatusMessage = styled.span `
|
|
57
|
+
font-size: 0.75rem;
|
|
58
|
+
color: var(--color-text-secondary, #6b7280);
|
|
59
|
+
`;
|
|
60
|
+
const SignatureLink = styled.a `
|
|
61
|
+
font-size: 0.75rem;
|
|
62
|
+
color: var(--color-primary, #6a8102);
|
|
63
|
+
text-decoration: none;
|
|
64
|
+
font-family: monospace;
|
|
65
|
+
|
|
66
|
+
&:hover {
|
|
67
|
+
text-decoration: underline;
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
const TransactionStatus = ({ status, message, signature, explorerUrl = 'https://explorer.solana.com/tx', network }) => {
|
|
71
|
+
var _a;
|
|
72
|
+
const getIcon = () => {
|
|
73
|
+
switch (status) {
|
|
74
|
+
case 'confirmed':
|
|
75
|
+
return '✓';
|
|
76
|
+
case 'failed':
|
|
77
|
+
return '✗';
|
|
78
|
+
default:
|
|
79
|
+
return '⟳';
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const getTitle = () => {
|
|
83
|
+
switch (status) {
|
|
84
|
+
case 'confirmed':
|
|
85
|
+
return 'Transaction Confirmed';
|
|
86
|
+
case 'failed':
|
|
87
|
+
return 'Transaction Failed';
|
|
88
|
+
default:
|
|
89
|
+
return 'Transaction Pending';
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const networkParam = network ||
|
|
93
|
+
(typeof process !== 'undefined' && ((_a = process.env) === null || _a === void 0 ? void 0 : _a.NEXT_PUBLIC_SOLANA_NETWORK)) ||
|
|
94
|
+
'devnet';
|
|
95
|
+
return (<StatusContainer status={status}>
|
|
96
|
+
<StatusIcon status={status}>{getIcon()}</StatusIcon>
|
|
97
|
+
<StatusContent>
|
|
98
|
+
<StatusTitle>{getTitle()}</StatusTitle>
|
|
99
|
+
<StatusMessage>{message}</StatusMessage>
|
|
100
|
+
{signature && status === 'confirmed' && (<SignatureLink href={`${explorerUrl}/${signature}?cluster=${networkParam}`} target="_blank" rel="noopener noreferrer">
|
|
101
|
+
View on Explorer →
|
|
102
|
+
</SignatureLink>)}
|
|
103
|
+
</StatusContent>
|
|
104
|
+
</StatusContainer>);
|
|
105
|
+
};
|
|
106
|
+
export default TransactionStatus;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WalletBalance.d.ts","sourceRoot":"","sources":["../../../src/components/Wallet/WalletBalance.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AA0CnD,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAiD1B,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { useEffect, useState } from 'react';
|
|
12
|
+
import styled from 'styled-components';
|
|
13
|
+
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
|
|
14
|
+
import { LAMPORTS_PER_SOL } from '@solana/web3.js';
|
|
15
|
+
const BalanceContainer = styled.div `
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
gap: 0.5rem;
|
|
19
|
+
padding: 1rem;
|
|
20
|
+
background: var(--color-surface, #f9fafb);
|
|
21
|
+
border: 1px solid var(--color-primary, #6a8102);
|
|
22
|
+
border-radius: 0.5rem;
|
|
23
|
+
`;
|
|
24
|
+
const BalanceLabel = styled.span `
|
|
25
|
+
font-size: 0.75rem;
|
|
26
|
+
color: var(--color-text-secondary, #6b7280);
|
|
27
|
+
text-transform: uppercase;
|
|
28
|
+
letter-spacing: 0.05em;
|
|
29
|
+
`;
|
|
30
|
+
const BalanceValue = styled.span `
|
|
31
|
+
font-size: 1.25rem;
|
|
32
|
+
font-weight: 700;
|
|
33
|
+
color: var(--color-primary, #6a8102);
|
|
34
|
+
font-family: monospace;
|
|
35
|
+
`;
|
|
36
|
+
const LoadingSpinner = styled.div `
|
|
37
|
+
width: 16px;
|
|
38
|
+
height: 16px;
|
|
39
|
+
border: 2px solid var(--color-primary, #6a8102);
|
|
40
|
+
border-top-color: transparent;
|
|
41
|
+
border-radius: 50%;
|
|
42
|
+
animation: spin 1s linear infinite;
|
|
43
|
+
|
|
44
|
+
@keyframes spin {
|
|
45
|
+
to { transform: rotate(360deg); }
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
const WalletBalance = () => {
|
|
49
|
+
const { publicKey, connected } = useWallet();
|
|
50
|
+
const { connection } = useConnection();
|
|
51
|
+
const [balance, setBalance] = useState(null);
|
|
52
|
+
const [loading, setLoading] = useState(false);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (!connected || !publicKey) {
|
|
55
|
+
setBalance(null);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const fetchBalance = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
|
+
try {
|
|
60
|
+
setLoading(true);
|
|
61
|
+
const lamports = yield connection.getBalance(publicKey);
|
|
62
|
+
setBalance(lamports / LAMPORTS_PER_SOL);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.error('Failed to fetch balance:', error);
|
|
66
|
+
setBalance(null);
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
setLoading(false);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
fetchBalance();
|
|
73
|
+
// Poll for balance updates every 10 seconds
|
|
74
|
+
const interval = setInterval(fetchBalance, 10000);
|
|
75
|
+
return () => clearInterval(interval);
|
|
76
|
+
}, [connected, publicKey, connection]);
|
|
77
|
+
if (!connected) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
return (_jsxs(BalanceContainer, { children: [_jsx(BalanceLabel, { children: "Wallet Balance" }), loading ? (_jsx(LoadingSpinner, {})) : (_jsx(BalanceValue, { children: balance !== null ? `${balance.toFixed(4)} SOL` : '—' }))] }));
|
|
81
|
+
};
|
|
82
|
+
export default WalletBalance;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import React, { useEffect, useState } from 'react';
|
|
11
|
+
import styled from 'styled-components';
|
|
12
|
+
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
|
|
13
|
+
import { LAMPORTS_PER_SOL } from '@solana/web3.js';
|
|
14
|
+
const BalanceContainer = styled.div `
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
gap: 0.5rem;
|
|
18
|
+
padding: 1rem;
|
|
19
|
+
background: var(--color-surface, #f9fafb);
|
|
20
|
+
border: 1px solid var(--color-primary, #6a8102);
|
|
21
|
+
border-radius: 0.5rem;
|
|
22
|
+
`;
|
|
23
|
+
const BalanceLabel = styled.span `
|
|
24
|
+
font-size: 0.75rem;
|
|
25
|
+
color: var(--color-text-secondary, #6b7280);
|
|
26
|
+
text-transform: uppercase;
|
|
27
|
+
letter-spacing: 0.05em;
|
|
28
|
+
`;
|
|
29
|
+
const BalanceValue = styled.span `
|
|
30
|
+
font-size: 1.25rem;
|
|
31
|
+
font-weight: 700;
|
|
32
|
+
color: var(--color-primary, #6a8102);
|
|
33
|
+
font-family: monospace;
|
|
34
|
+
`;
|
|
35
|
+
const LoadingSpinner = styled.div `
|
|
36
|
+
width: 16px;
|
|
37
|
+
height: 16px;
|
|
38
|
+
border: 2px solid var(--color-primary, #6a8102);
|
|
39
|
+
border-top-color: transparent;
|
|
40
|
+
border-radius: 50%;
|
|
41
|
+
animation: spin 1s linear infinite;
|
|
42
|
+
|
|
43
|
+
@keyframes spin {
|
|
44
|
+
to { transform: rotate(360deg); }
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
const WalletBalance = () => {
|
|
48
|
+
const { publicKey, connected } = useWallet();
|
|
49
|
+
const { connection } = useConnection();
|
|
50
|
+
const [balance, setBalance] = useState(null);
|
|
51
|
+
const [loading, setLoading] = useState(false);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (!connected || !publicKey) {
|
|
54
|
+
setBalance(null);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const fetchBalance = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
|
+
try {
|
|
59
|
+
setLoading(true);
|
|
60
|
+
const lamports = yield connection.getBalance(publicKey);
|
|
61
|
+
setBalance(lamports / LAMPORTS_PER_SOL);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
console.error('Failed to fetch balance:', error);
|
|
65
|
+
setBalance(null);
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
setLoading(false);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
fetchBalance();
|
|
72
|
+
// Poll for balance updates every 10 seconds
|
|
73
|
+
const interval = setInterval(fetchBalance, 10000);
|
|
74
|
+
return () => clearInterval(interval);
|
|
75
|
+
}, [connected, publicKey, connection]);
|
|
76
|
+
if (!connected) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return (<BalanceContainer>
|
|
80
|
+
<BalanceLabel>Wallet Balance</BalanceLabel>
|
|
81
|
+
{loading ? (<LoadingSpinner />) : (<BalanceValue>
|
|
82
|
+
{balance !== null ? `${balance.toFixed(4)} SOL` : '—'}
|
|
83
|
+
</BalanceValue>)}
|
|
84
|
+
</BalanceContainer>);
|
|
85
|
+
};
|
|
86
|
+
export default WalletBalance;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WalletButton.d.ts","sourceRoot":"","sources":["../../../src/components/Wallet/WalletButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAqBhC,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useWallet } from '@solana/wallet-adapter-react';
|
|
3
|
+
import { useWalletModal } from '@solana/wallet-adapter-react-ui';
|
|
4
|
+
import styled from 'styled-components';
|
|
5
|
+
export const WalletButton = () => {
|
|
6
|
+
const { publicKey, disconnect, connected } = useWallet();
|
|
7
|
+
const { setVisible } = useWalletModal();
|
|
8
|
+
const handleClick = () => {
|
|
9
|
+
if (connected) {
|
|
10
|
+
disconnect();
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
setVisible(true);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const formatAddress = (address) => {
|
|
17
|
+
return `${address.slice(0, 4)}...${address.slice(-4)}`;
|
|
18
|
+
};
|
|
19
|
+
return (_jsx(Button, { onClick: handleClick, connected: connected, children: connected && publicKey ? formatAddress(publicKey.toBase58()) : 'Connect Wallet' }));
|
|
20
|
+
};
|
|
21
|
+
const Button = styled.button `
|
|
22
|
+
background: ${props => props.connected
|
|
23
|
+
? 'var(--color-surface, #f9fafb)'
|
|
24
|
+
: 'linear-gradient(135deg, var(--color-primary, #6a8102), var(--color-secondary, #ffc107))'};
|
|
25
|
+
color: ${props => props.connected ? 'var(--color-text, #1a1a1a)' : 'var(--color-background, #ffffff)'};
|
|
26
|
+
border: ${props => props.connected ? '1px solid var(--color-primary, #6a8102)' : 'none'};
|
|
27
|
+
padding: var(--spacing-sm, 0.5rem) var(--spacing-lg, 1.5rem);
|
|
28
|
+
border-radius: var(--border-radius-md, 0.375rem);
|
|
29
|
+
font-weight: 600;
|
|
30
|
+
transition: all 0.3s ease;
|
|
31
|
+
box-shadow: ${props => props.connected
|
|
32
|
+
? '0 2px 8px rgba(106, 129, 2, 0.2)'
|
|
33
|
+
: '0 4px 12px rgba(106, 129, 2, 0.3)'};
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
|
|
36
|
+
&:hover {
|
|
37
|
+
transform: translateY(-2px);
|
|
38
|
+
box-shadow: ${props => props.connected
|
|
39
|
+
? '0 4px 12px rgba(106, 129, 2, 0.3)'
|
|
40
|
+
: '0 6px 16px rgba(106, 129, 2, 0.4)'};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&:active {
|
|
44
|
+
transform: translateY(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@media (max-width: 768px) {
|
|
48
|
+
padding: var(--spacing-xs, 0.25rem) var(--spacing-md, 1rem);
|
|
49
|
+
font-size: 0.875rem;
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useWallet } from '@solana/wallet-adapter-react';
|
|
3
|
+
import { useWalletModal } from '@solana/wallet-adapter-react-ui';
|
|
4
|
+
import styled from 'styled-components';
|
|
5
|
+
export const WalletButton = () => {
|
|
6
|
+
const { publicKey, disconnect, connected } = useWallet();
|
|
7
|
+
const { setVisible } = useWalletModal();
|
|
8
|
+
const handleClick = () => {
|
|
9
|
+
if (connected) {
|
|
10
|
+
disconnect();
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
setVisible(true);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const formatAddress = (address) => {
|
|
17
|
+
return `${address.slice(0, 4)}...${address.slice(-4)}`;
|
|
18
|
+
};
|
|
19
|
+
return (<Button onClick={handleClick} connected={connected}>
|
|
20
|
+
{connected && publicKey ? formatAddress(publicKey.toBase58()) : 'Connect Wallet'}
|
|
21
|
+
</Button>);
|
|
22
|
+
};
|
|
23
|
+
const Button = styled.button `
|
|
24
|
+
background: ${props => props.connected
|
|
25
|
+
? 'var(--color-surface, #f9fafb)'
|
|
26
|
+
: 'linear-gradient(135deg, var(--color-primary, #6a8102), var(--color-secondary, #ffc107))'};
|
|
27
|
+
color: ${props => props.connected ? 'var(--color-text, #1a1a1a)' : 'var(--color-background, #ffffff)'};
|
|
28
|
+
border: ${props => props.connected ? '1px solid var(--color-primary, #6a8102)' : 'none'};
|
|
29
|
+
padding: var(--spacing-sm, 0.5rem) var(--spacing-lg, 1.5rem);
|
|
30
|
+
border-radius: var(--border-radius-md, 0.375rem);
|
|
31
|
+
font-weight: 600;
|
|
32
|
+
transition: all 0.3s ease;
|
|
33
|
+
box-shadow: ${props => props.connected
|
|
34
|
+
? '0 2px 8px rgba(106, 129, 2, 0.2)'
|
|
35
|
+
: '0 4px 12px rgba(106, 129, 2, 0.3)'};
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
|
|
38
|
+
&:hover {
|
|
39
|
+
transform: translateY(-2px);
|
|
40
|
+
box-shadow: ${props => props.connected
|
|
41
|
+
? '0 4px 12px rgba(106, 129, 2, 0.3)'
|
|
42
|
+
: '0 6px 16px rgba(106, 129, 2, 0.4)'};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&:active {
|
|
46
|
+
transform: translateY(0);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@media (max-width: 768px) {
|
|
50
|
+
padding: var(--spacing-xs, 0.25rem) var(--spacing-md, 1rem);
|
|
51
|
+
font-size: 0.875rem;
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface WalletConnectionModalProps {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
}
|
|
6
|
+
declare const WalletConnectionModal: React.FC<WalletConnectionModalProps>;
|
|
7
|
+
export default WalletConnectionModal;
|
|
8
|
+
//# sourceMappingURL=WalletConnectionModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WalletConnectionModal.d.ts","sourceRoot":"","sources":["../../../src/components/Wallet/WalletConnectionModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAsI1B,UAAU,0BAA0B;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAmD/D,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import styled from 'styled-components';
|
|
12
|
+
import { useWallet } from '@solana/wallet-adapter-react';
|
|
13
|
+
const ModalOverlay = styled.div `
|
|
14
|
+
display: ${props => props.isOpen ? 'flex' : 'none'};
|
|
15
|
+
position: fixed;
|
|
16
|
+
top: 0;
|
|
17
|
+
left: 0;
|
|
18
|
+
right: 0;
|
|
19
|
+
bottom: 0;
|
|
20
|
+
background: rgba(0, 0, 0, 0.8);
|
|
21
|
+
backdrop-filter: blur(4px);
|
|
22
|
+
z-index: 1000;
|
|
23
|
+
align-items: center;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
animation: fadeIn 0.2s ease-in-out;
|
|
26
|
+
|
|
27
|
+
@keyframes fadeIn {
|
|
28
|
+
from { opacity: 0; }
|
|
29
|
+
to { opacity: 1; }
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
const ModalContent = styled.div `
|
|
33
|
+
background: var(--color-surface, #f9fafb);
|
|
34
|
+
border: 1px solid var(--color-primary, #6a8102);
|
|
35
|
+
border-radius: 1rem;
|
|
36
|
+
padding: 2rem;
|
|
37
|
+
max-width: 400px;
|
|
38
|
+
width: 90%;
|
|
39
|
+
animation: slideUp 0.3s ease-out;
|
|
40
|
+
|
|
41
|
+
@keyframes slideUp {
|
|
42
|
+
from {
|
|
43
|
+
transform: translateY(20px);
|
|
44
|
+
opacity: 0;
|
|
45
|
+
}
|
|
46
|
+
to {
|
|
47
|
+
transform: translateY(0);
|
|
48
|
+
opacity: 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
const ModalHeader = styled.div `
|
|
53
|
+
display: flex;
|
|
54
|
+
justify-content: space-between;
|
|
55
|
+
align-items: center;
|
|
56
|
+
margin-bottom: 1.5rem;
|
|
57
|
+
`;
|
|
58
|
+
const ModalTitle = styled.h2 `
|
|
59
|
+
font-size: 1.5rem;
|
|
60
|
+
color: var(--color-text, #1a1a1a);
|
|
61
|
+
margin: 0;
|
|
62
|
+
`;
|
|
63
|
+
const CloseButton = styled.button `
|
|
64
|
+
background: none;
|
|
65
|
+
border: none;
|
|
66
|
+
color: var(--color-text-secondary, #6b7280);
|
|
67
|
+
font-size: 1.5rem;
|
|
68
|
+
cursor: pointer;
|
|
69
|
+
padding: 0;
|
|
70
|
+
width: 32px;
|
|
71
|
+
height: 32px;
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
justify-content: center;
|
|
75
|
+
border-radius: 0.5rem;
|
|
76
|
+
transition: all 0.2s;
|
|
77
|
+
|
|
78
|
+
&:hover {
|
|
79
|
+
background: var(--color-background, #ffffff);
|
|
80
|
+
color: var(--color-text, #1a1a1a);
|
|
81
|
+
}
|
|
82
|
+
`;
|
|
83
|
+
const WalletList = styled.div `
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-direction: column;
|
|
86
|
+
gap: 0.75rem;
|
|
87
|
+
`;
|
|
88
|
+
const WalletButton = styled.button `
|
|
89
|
+
display: flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
gap: 1rem;
|
|
92
|
+
padding: 1rem;
|
|
93
|
+
background: var(--color-background, #ffffff);
|
|
94
|
+
border: 1px solid var(--color-primary, #6a8102);
|
|
95
|
+
border-radius: 0.5rem;
|
|
96
|
+
color: var(--color-text, #1a1a1a);
|
|
97
|
+
font-size: 1rem;
|
|
98
|
+
font-weight: 500;
|
|
99
|
+
cursor: pointer;
|
|
100
|
+
transition: all 0.2s;
|
|
101
|
+
|
|
102
|
+
&:hover {
|
|
103
|
+
background: var(--color-primary, #6a8102);
|
|
104
|
+
color: var(--color-background, #ffffff);
|
|
105
|
+
transform: translateX(4px);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&:disabled {
|
|
109
|
+
opacity: 0.5;
|
|
110
|
+
cursor: not-allowed;
|
|
111
|
+
transform: none;
|
|
112
|
+
}
|
|
113
|
+
`;
|
|
114
|
+
const WalletIcon = styled.div `
|
|
115
|
+
width: 32px;
|
|
116
|
+
height: 32px;
|
|
117
|
+
display: flex;
|
|
118
|
+
align-items: center;
|
|
119
|
+
justify-content: center;
|
|
120
|
+
font-size: 1.5rem;
|
|
121
|
+
`;
|
|
122
|
+
const WalletName = styled.span `
|
|
123
|
+
flex: 1;
|
|
124
|
+
text-align: left;
|
|
125
|
+
`;
|
|
126
|
+
const Description = styled.p `
|
|
127
|
+
color: var(--color-text-secondary, #6b7280);
|
|
128
|
+
font-size: 0.875rem;
|
|
129
|
+
margin-bottom: 1.5rem;
|
|
130
|
+
line-height: 1.5;
|
|
131
|
+
`;
|
|
132
|
+
const WalletConnectionModal = ({ isOpen, onClose }) => {
|
|
133
|
+
const { wallets, select, connecting } = useWallet();
|
|
134
|
+
const handleWalletSelect = (walletName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
135
|
+
try {
|
|
136
|
+
select(walletName);
|
|
137
|
+
onClose();
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error('Failed to select wallet:', error);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
const handleOverlayClick = (e) => {
|
|
144
|
+
if (e.target === e.currentTarget) {
|
|
145
|
+
onClose();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
return (_jsx(ModalOverlay, { isOpen: isOpen, onClick: handleOverlayClick, children: _jsxs(ModalContent, { children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: "Connect Wallet" }), _jsx(CloseButton, { onClick: onClose, children: "\u00D7" })] }), _jsx(Description, { children: "Select a wallet to connect to the Web3 Prediction Platform and start staking." }), _jsx(WalletList, { children: wallets.map((wallet) => (_jsxs(WalletButton, { onClick: () => handleWalletSelect(wallet.adapter.name), disabled: connecting, children: [_jsx(WalletIcon, { children: wallet.adapter.icon ? (_jsx("img", { src: wallet.adapter.icon, alt: wallet.adapter.name, width: 32, height: 32 })) : ('👛') }), _jsx(WalletName, { children: wallet.adapter.name })] }, wallet.adapter.name))) })] }) }));
|
|
149
|
+
};
|
|
150
|
+
export default WalletConnectionModal;
|