@pioneer-platform/pioneer-react 0.0.2 → 0.2.32
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/.eslintrc.js +24 -0
- package/.github/workflows/release.yml +22 -0
- package/.github/workflows/update-license.yml +11 -0
- package/.lintstagedrc.json +6 -0
- package/.prettierrc +7 -0
- package/.vscode/extensions.json +8 -0
- package/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +40 -0
- package/commitlint.config.js +3 -0
- package/dist/assets/404 Error-rafiki.svg +1 -0
- package/dist/assets/Building blocks-amico.svg +1 -0
- package/dist/assets/chakra-ui-logomark-colored.svg +10 -0
- package/dist/assets/favicon.svg +0 -0
- package/dist/assets/react-icon.svg +7 -0
- package/dist/assets/ts-logo-512.svg +1 -0
- package/dist/assets/vite-logo.svg +15 -0
- package/dist/index.js +384249 -0
- package/dist/index_3bde86fb.js +205 -0
- package/dist/index_49fce0b0.js +384033 -0
- package/dist/index_d01e819c.css +63 -0
- package/dist/manifest.json +12 -0
- package/dist/robots.txt +6 -0
- package/index.html +13 -0
- package/netlify.toml +10 -0
- package/package.json +70 -10
- package/public/assets/404 Error-rafiki.svg +1 -0
- package/public/assets/Building blocks-amico.svg +1 -0
- package/public/assets/chakra-ui-logomark-colored.svg +10 -0
- package/public/assets/favicon.svg +0 -0
- package/public/assets/react-icon.svg +7 -0
- package/public/assets/ts-logo-512.svg +1 -0
- package/public/assets/vite-logo.svg +15 -0
- package/public/manifest.json +12 -0
- package/public/robots.txt +6 -0
- package/renovate.json +11 -0
- package/src/App.tsx +21 -0
- package/src/index.tsx +41 -0
- package/src/lib/assets/Icons/KeepKeyIcon.tsx +13 -0
- package/src/lib/assets/Icons/KeplrIcon.tsx +140 -0
- package/src/lib/assets/Icons/MetaMaskIcon.tsx +126 -0
- package/src/lib/assets/Icons/TallyHoIcon.tsx +17 -0
- package/src/lib/assets/Icons/XDEFIIcon.tsx +32 -0
- package/src/lib/assets/favicon.ico +0 -0
- package/src/lib/assets/png/keepkey.png +0 -0
- package/src/lib/assets/png/keplr.png +0 -0
- package/src/lib/assets/png/metamask.png +0 -0
- package/src/lib/assets/png/pioneer.png +0 -0
- package/src/lib/components/AssetSelect/index.tsx +166 -0
- package/src/lib/components/BlockchainSelect/index.tsx +166 -0
- package/src/lib/components/MiddleEllipsis/index.tsx +27 -0
- package/src/lib/components/WalletSelect/index.tsx +112 -0
- package/src/lib/components/auth/RequireAuth.tsx +22 -0
- package/src/lib/components/modals/AssetModal.tsx +67 -0
- package/src/lib/components/modals/SettingsModal.tsx +76 -0
- package/src/lib/components/pioneer/Pioneer/Balances.tsx +266 -0
- package/src/lib/components/pioneer/Pioneer/MiddleEllipsis.tsx +27 -0
- package/src/lib/components/pioneer/Pioneer/Nodes.tsx +0 -0
- package/src/lib/components/pioneer/Pioneer/Paths.tsx +290 -0
- package/src/lib/components/pioneer/Pioneer/Pubkey.tsx +67 -0
- package/src/lib/components/pioneer/Pioneer/Pubkeys.tsx +265 -0
- package/src/lib/components/pioneer/Pioneer/Receive.tsx +26 -0
- package/src/lib/components/pioneer/Pioneer/Send.tsx +135 -0
- package/src/lib/components/pioneer/Pioneer/View.tsx +44 -0
- package/src/lib/components/pioneer/Pioneer/Wallets.tsx +166 -0
- package/src/lib/components/pioneer/index.tsx +525 -0
- package/src/lib/components/utils/index.tsx +47 -0
- package/src/lib/context/Pioneer/index.tsx +420 -0
- package/src/lib/layout/Footer.tsx +22 -0
- package/src/lib/layout/Header.tsx +38 -0
- package/src/lib/layout/Meta.tsx +25 -0
- package/src/lib/layout/Pioneer/Balances.tsx +290 -0
- package/src/lib/layout/Pioneer/MiddleEllipsis.tsx +27 -0
- package/src/lib/layout/Pioneer/Pubkey.tsx +67 -0
- package/src/lib/layout/Pioneer/Receive.tsx +26 -0
- package/src/lib/layout/Pioneer/Send.tsx +135 -0
- package/src/lib/layout/Pioneer/View.tsx +44 -0
- package/src/lib/layout/Pioneer/Wallets.tsx +166 -0
- package/src/lib/layout/ThemeToggle.tsx +16 -0
- package/src/lib/layout/index.tsx +29 -0
- package/src/lib/pages/404/index.tsx +36 -0
- package/src/lib/pages/home/components/CTASection.tsx +36 -0
- package/src/lib/pages/home/components/SomeImage.tsx +36 -0
- package/src/lib/pages/home/components/SomeText.tsx +16 -0
- package/src/lib/pages/home/index.tsx +87 -0
- package/src/lib/router/Routings.tsx +45 -0
- package/src/lib/router/routes.tsx +13 -0
- package/src/lib/styles/theme/config.ts +5 -0
- package/src/lib/styles/theme/index.ts +17 -0
- package/tsconfig.json +19 -9
- package/turbo.json +17 -0
- package/vercel.json +4 -0
- package/vite.config.ts +110 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { Search2Icon } from "@chakra-ui/icons";
|
|
2
|
+
import {
|
|
3
|
+
Avatar,
|
|
4
|
+
AvatarBadge,
|
|
5
|
+
Box,
|
|
6
|
+
Button,
|
|
7
|
+
HStack,
|
|
8
|
+
Stack,
|
|
9
|
+
Image,
|
|
10
|
+
Modal,
|
|
11
|
+
ModalOverlay,
|
|
12
|
+
ModalContent,
|
|
13
|
+
ModalHeader,
|
|
14
|
+
ModalCloseButton,
|
|
15
|
+
ModalBody,
|
|
16
|
+
ModalFooter,
|
|
17
|
+
useDisclosure,
|
|
18
|
+
InputGroup,
|
|
19
|
+
InputLeftElement,
|
|
20
|
+
Input,
|
|
21
|
+
} from "@chakra-ui/react";
|
|
22
|
+
import React, { useState, useEffect } from "react";
|
|
23
|
+
//@ts-ignore
|
|
24
|
+
import KEEPKEY_ICON from "lib/assets/png/keepkey.png";
|
|
25
|
+
//@ts-ignore
|
|
26
|
+
import METAMASK_ICON from "lib/assets/png/metamask.png";
|
|
27
|
+
//@ts-ignore
|
|
28
|
+
import PIONEER_ICON from "lib/assets/png/pioneer.png";
|
|
29
|
+
import { usePioneer } from "lib/context/Pioneer";
|
|
30
|
+
|
|
31
|
+
import Receive from "./Receive";
|
|
32
|
+
import Send from "./Send";
|
|
33
|
+
import View from "./View";
|
|
34
|
+
|
|
35
|
+
interface Path {
|
|
36
|
+
image?: string;
|
|
37
|
+
symbol: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
path?: any;
|
|
40
|
+
size?: string;
|
|
41
|
+
context?: string; // Added context field
|
|
42
|
+
note: string;
|
|
43
|
+
blockchain: string;
|
|
44
|
+
network: string;
|
|
45
|
+
script_type: string;
|
|
46
|
+
available_scripts_types: string[];
|
|
47
|
+
type: string;
|
|
48
|
+
addressNList: number[];
|
|
49
|
+
addressNListMaster: number[];
|
|
50
|
+
curve: string;
|
|
51
|
+
showDisplay: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const getWalletType = (user: { walletDescriptions: any[] }, context: any) => {
|
|
55
|
+
if (user && user.walletDescriptions) {
|
|
56
|
+
const wallet = user.walletDescriptions.find((w) => w.id === context);
|
|
57
|
+
return wallet ? wallet.type : null;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const getWalletBadgeContent = (walletType: string) => {
|
|
63
|
+
const icons: any = {
|
|
64
|
+
metamask: METAMASK_ICON,
|
|
65
|
+
keepkey: KEEPKEY_ICON,
|
|
66
|
+
native: PIONEER_ICON,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const icon = icons[walletType];
|
|
70
|
+
|
|
71
|
+
if (!icon) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<AvatarBadge boxSize="1.25em" bg="green.500">
|
|
77
|
+
<Image rounded="full" src={icon} />
|
|
78
|
+
</AvatarBadge>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export default function Paths({ paths }: { paths: any[] }) {
|
|
83
|
+
const { state, dispatch } = usePioneer();
|
|
84
|
+
const { api, app, user } = state;
|
|
85
|
+
const [selectedPath, setSelectedPath] = useState<Path | null>(null);
|
|
86
|
+
const [selectedAction, setSelectedAction] = useState<string | null>(null);
|
|
87
|
+
const { isOpen, onOpen, onClose } = useDisclosure();
|
|
88
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
89
|
+
|
|
90
|
+
const handleSelectClick = async (path: Path) => {
|
|
91
|
+
try {
|
|
92
|
+
//
|
|
93
|
+
//console.log("path: ", path);
|
|
94
|
+
|
|
95
|
+
//set Path
|
|
96
|
+
let assetFromPioneer = await api.GetAsset({ symbol: path.symbol });
|
|
97
|
+
assetFromPioneer = assetFromPioneer.data[0];
|
|
98
|
+
let blockchainFromPioneer = await api.GetBlockchain({
|
|
99
|
+
symbol: path.symbol,
|
|
100
|
+
});
|
|
101
|
+
blockchainFromPioneer = blockchainFromPioneer.data[0];
|
|
102
|
+
//console.log("assetFromPioneer: ", path);
|
|
103
|
+
//set Blockchain
|
|
104
|
+
await app.setBlockchainContext(blockchainFromPioneer);
|
|
105
|
+
await app.setAssetContext(assetFromPioneer);
|
|
106
|
+
//set pubkey
|
|
107
|
+
// await app.setPubkeyContext(path.context)
|
|
108
|
+
//console.log("app.assetContext: ", app.assetContext);
|
|
109
|
+
//console.log("app.blockchainContext: ", app.blockchainContext);
|
|
110
|
+
} catch (e) {
|
|
111
|
+
console.error(e);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const handleSendClick = (path: Path) => {
|
|
116
|
+
setSelectedPath(path);
|
|
117
|
+
setSelectedAction("send");
|
|
118
|
+
onOpen();
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const handleReceiveClick = (path: Path) => {
|
|
122
|
+
setSelectedPath(path);
|
|
123
|
+
setSelectedAction("receive");
|
|
124
|
+
onOpen();
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const handleViewClick = (path: Path) => {
|
|
128
|
+
setSelectedPath(path);
|
|
129
|
+
setSelectedAction("view");
|
|
130
|
+
onOpen();
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
const setUser = async () => {
|
|
135
|
+
try {
|
|
136
|
+
if (user && user.wallets) {
|
|
137
|
+
const { walletDescriptions, paths } = user;
|
|
138
|
+
const updatedPaths = paths.map((path: Path) => {
|
|
139
|
+
const walletType = getWalletType(user, path.context);
|
|
140
|
+
const badgeContent = getWalletBadgeContent(walletType);
|
|
141
|
+
return {
|
|
142
|
+
//@ts-ignore
|
|
143
|
+
...path,
|
|
144
|
+
context: {
|
|
145
|
+
//@ts-ignore
|
|
146
|
+
...path.context,
|
|
147
|
+
badge: badgeContent,
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
dispatch({ type: "SET_BALANCES", payload: updatedPaths });
|
|
152
|
+
}
|
|
153
|
+
} catch (e) {
|
|
154
|
+
console.error("Error: ", e);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
setUser();
|
|
159
|
+
}, [user]);
|
|
160
|
+
|
|
161
|
+
// Filter and sort paths based on search query
|
|
162
|
+
const filteredPaths = paths.filter((path: Path) => {
|
|
163
|
+
// Convert the search query and path symbol/name to lowercase for case-insensitive search
|
|
164
|
+
const query = searchQuery.toLowerCase();
|
|
165
|
+
const symbol = path.symbol.toLowerCase();
|
|
166
|
+
const name = path.name ? path.name.toLowerCase() : "";
|
|
167
|
+
|
|
168
|
+
// Check if the symbol or name contains the search query
|
|
169
|
+
return symbol.includes(query) || name.includes(query);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const sortedPaths = filteredPaths.sort((a: Path, b: Path) => b.path - a.path);
|
|
173
|
+
|
|
174
|
+
// CSS for the scrollable container
|
|
175
|
+
const scrollContainerStyles: React.CSSProperties = {
|
|
176
|
+
maxHeight: "15em", // This value may need to be adjusted according to your design
|
|
177
|
+
overflowY: "scroll",
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
<Stack spacing={4}>
|
|
182
|
+
<InputGroup>
|
|
183
|
+
<InputLeftElement pointerEvents="none">
|
|
184
|
+
<Search2Icon color="gray.300" />
|
|
185
|
+
</InputLeftElement>
|
|
186
|
+
<Input
|
|
187
|
+
placeholder="Bitcoin..."
|
|
188
|
+
type="text"
|
|
189
|
+
value={searchQuery}
|
|
190
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
191
|
+
/>
|
|
192
|
+
</InputGroup>
|
|
193
|
+
<Box style={scrollContainerStyles}>
|
|
194
|
+
{sortedPaths.map((path: Path, index: number) => (
|
|
195
|
+
<Box key={index}>
|
|
196
|
+
<HStack spacing={4} alignItems="center">
|
|
197
|
+
<Avatar src={path.image} />
|
|
198
|
+
<Box>
|
|
199
|
+
{path && (
|
|
200
|
+
<>
|
|
201
|
+
<div>
|
|
202
|
+
<strong>Note:</strong> {path.note}
|
|
203
|
+
</div>
|
|
204
|
+
<div>
|
|
205
|
+
<strong>Blockchain:</strong> {path.blockchain}
|
|
206
|
+
</div>
|
|
207
|
+
<div>
|
|
208
|
+
<strong>Symbol:</strong> {path.symbol}
|
|
209
|
+
</div>
|
|
210
|
+
<div>
|
|
211
|
+
<strong>Network:</strong> {path.network}
|
|
212
|
+
</div>
|
|
213
|
+
<div>
|
|
214
|
+
<strong>Script Type:</strong> {path.script_type}
|
|
215
|
+
</div>
|
|
216
|
+
<div>
|
|
217
|
+
<strong>Available Script Types:</strong>{" "}
|
|
218
|
+
{path.available_scripts_types?.join(", ")}
|
|
219
|
+
</div>
|
|
220
|
+
<div>
|
|
221
|
+
<strong>Type:</strong> {path.type}
|
|
222
|
+
</div>
|
|
223
|
+
<div>
|
|
224
|
+
<strong>Address N List:</strong>{" "}
|
|
225
|
+
{path.addressNList?.join(", ")}
|
|
226
|
+
</div>
|
|
227
|
+
<div>
|
|
228
|
+
<strong>Address N List Master:</strong>{" "}
|
|
229
|
+
{path.addressNListMaster?.join(", ")}
|
|
230
|
+
</div>
|
|
231
|
+
<div>
|
|
232
|
+
<strong>Curve:</strong> {path.curve}
|
|
233
|
+
</div>
|
|
234
|
+
<div>
|
|
235
|
+
<strong>Show Display:</strong>{" "}
|
|
236
|
+
{path.showDisplay ? "true" : "false"}
|
|
237
|
+
</div>
|
|
238
|
+
</>
|
|
239
|
+
)}
|
|
240
|
+
</Box>
|
|
241
|
+
</HStack>
|
|
242
|
+
<HStack mt={2} spacing={2}>
|
|
243
|
+
<Button
|
|
244
|
+
size="sm"
|
|
245
|
+
variant="outline"
|
|
246
|
+
onClick={() => handleSelectClick(path)}
|
|
247
|
+
>
|
|
248
|
+
Select
|
|
249
|
+
</Button>
|
|
250
|
+
</HStack>
|
|
251
|
+
</Box>
|
|
252
|
+
))}
|
|
253
|
+
</Box>
|
|
254
|
+
|
|
255
|
+
<Modal isOpen={isOpen} onClose={onClose} isCentered blockScrollOnMount>
|
|
256
|
+
<ModalOverlay />
|
|
257
|
+
<ModalContent>
|
|
258
|
+
<ModalHeader>{selectedAction}</ModalHeader>
|
|
259
|
+
<ModalCloseButton />
|
|
260
|
+
{selectedAction === "send" && (
|
|
261
|
+
<div>
|
|
262
|
+
<h3>Selected Action: Send</h3>
|
|
263
|
+
<p>Selected Asset: {selectedPath?.symbol}</p>
|
|
264
|
+
<Send asset={selectedPath} />
|
|
265
|
+
</div>
|
|
266
|
+
)}
|
|
267
|
+
{selectedAction === "receive" && (
|
|
268
|
+
<div>
|
|
269
|
+
<h3>Selected Action: Receive</h3>
|
|
270
|
+
<p>Selected Asset: {selectedPath?.symbol}</p>
|
|
271
|
+
<Receive />
|
|
272
|
+
</div>
|
|
273
|
+
)}
|
|
274
|
+
{selectedAction === "view" && (
|
|
275
|
+
<div>
|
|
276
|
+
<h3>Selected Action: View</h3>
|
|
277
|
+
<p>Selected Asset: {selectedPath?.symbol}</p>
|
|
278
|
+
<View />
|
|
279
|
+
</div>
|
|
280
|
+
)}
|
|
281
|
+
<ModalFooter>
|
|
282
|
+
<Button colorScheme="blue" onClick={onClose}>
|
|
283
|
+
Cancel
|
|
284
|
+
</Button>
|
|
285
|
+
</ModalFooter>
|
|
286
|
+
</ModalContent>
|
|
287
|
+
</Modal>
|
|
288
|
+
</Stack>
|
|
289
|
+
);
|
|
290
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
chakra,
|
|
3
|
+
Stack,
|
|
4
|
+
CircularProgress,
|
|
5
|
+
Drawer,
|
|
6
|
+
DrawerOverlay,
|
|
7
|
+
DrawerContent,
|
|
8
|
+
DrawerHeader,
|
|
9
|
+
DrawerBody,
|
|
10
|
+
Tabs,
|
|
11
|
+
TabList,
|
|
12
|
+
TabPanels,
|
|
13
|
+
Tab,
|
|
14
|
+
TabPanel,
|
|
15
|
+
Avatar,
|
|
16
|
+
AvatarBadge,
|
|
17
|
+
Box,
|
|
18
|
+
Button,
|
|
19
|
+
Flex,
|
|
20
|
+
HStack,
|
|
21
|
+
IconButton,
|
|
22
|
+
Link,
|
|
23
|
+
Menu,
|
|
24
|
+
Image,
|
|
25
|
+
MenuButton,
|
|
26
|
+
MenuDivider,
|
|
27
|
+
Icon,
|
|
28
|
+
MenuItem,
|
|
29
|
+
MenuList,
|
|
30
|
+
Spacer,
|
|
31
|
+
Text,
|
|
32
|
+
useDisclosure,
|
|
33
|
+
Accordion,
|
|
34
|
+
AccordionItem,
|
|
35
|
+
AccordionButton,
|
|
36
|
+
AccordionIcon,
|
|
37
|
+
AccordionPanel,
|
|
38
|
+
SimpleGrid,
|
|
39
|
+
Card,
|
|
40
|
+
CardHeader,
|
|
41
|
+
Heading,
|
|
42
|
+
CardBody,
|
|
43
|
+
CardFooter,
|
|
44
|
+
Modal,
|
|
45
|
+
ModalOverlay,
|
|
46
|
+
ModalContent,
|
|
47
|
+
ModalHeader,
|
|
48
|
+
ModalCloseButton,
|
|
49
|
+
ModalBody,
|
|
50
|
+
ModalFooter,
|
|
51
|
+
} from "@chakra-ui/react";
|
|
52
|
+
import React, { useState } from "react";
|
|
53
|
+
|
|
54
|
+
import MiddleEllipsis from "./MiddleEllipsis";
|
|
55
|
+
|
|
56
|
+
interface Balance {
|
|
57
|
+
rating: number;
|
|
58
|
+
setRating: (rating: number) => void;
|
|
59
|
+
count?: number;
|
|
60
|
+
size?: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default function Pubkey(Balance: any) {
|
|
64
|
+
const [hover, setHover] = useState<number | null>(null);
|
|
65
|
+
|
|
66
|
+
return <div>{JSON.stringify(Balance)}</div>;
|
|
67
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { Search2Icon } from "@chakra-ui/icons";
|
|
2
|
+
import {
|
|
3
|
+
Avatar,
|
|
4
|
+
AvatarBadge,
|
|
5
|
+
Box,
|
|
6
|
+
Button,
|
|
7
|
+
HStack,
|
|
8
|
+
Stack,
|
|
9
|
+
Image,
|
|
10
|
+
Modal,
|
|
11
|
+
ModalOverlay,
|
|
12
|
+
ModalContent,
|
|
13
|
+
ModalHeader,
|
|
14
|
+
ModalCloseButton,
|
|
15
|
+
ModalBody,
|
|
16
|
+
ModalFooter,
|
|
17
|
+
useDisclosure,
|
|
18
|
+
InputGroup,
|
|
19
|
+
InputLeftElement,
|
|
20
|
+
Input,
|
|
21
|
+
} from "@chakra-ui/react";
|
|
22
|
+
import React, { useState, useEffect } from "react";
|
|
23
|
+
//@ts-ignore
|
|
24
|
+
import KEEPKEY_ICON from "lib/assets/png/keepkey.png";
|
|
25
|
+
//@ts-ignore
|
|
26
|
+
import METAMASK_ICON from "lib/assets/png/metamask.png";
|
|
27
|
+
//@ts-ignore
|
|
28
|
+
import PIONEER_ICON from "lib/assets/png/pioneer.png";
|
|
29
|
+
import { usePioneer } from "lib/context/Pioneer";
|
|
30
|
+
|
|
31
|
+
import Receive from "./Receive";
|
|
32
|
+
import Send from "./Send";
|
|
33
|
+
import View from "./View";
|
|
34
|
+
|
|
35
|
+
interface Pubkey {
|
|
36
|
+
image?: string;
|
|
37
|
+
symbol: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
pubkey?: any;
|
|
40
|
+
size?: string;
|
|
41
|
+
context?: string; // Added context field
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const getWalletType = (user: { walletDescriptions: any[] }, context: any) => {
|
|
45
|
+
if (user && user.walletDescriptions) {
|
|
46
|
+
const wallet = user.walletDescriptions.find((w) => w.id === context);
|
|
47
|
+
return wallet ? wallet.type : null;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const getWalletBadgeContent = (walletType: string) => {
|
|
53
|
+
const icons: any = {
|
|
54
|
+
metamask: METAMASK_ICON,
|
|
55
|
+
keepkey: KEEPKEY_ICON,
|
|
56
|
+
native: PIONEER_ICON,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const icon = icons[walletType];
|
|
60
|
+
|
|
61
|
+
if (!icon) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<AvatarBadge boxSize="1.25em" bg="green.500">
|
|
67
|
+
<Image rounded="full" src={icon} />
|
|
68
|
+
</AvatarBadge>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default function Pubkeys({ pubkeys }: { pubkeys: Pubkey[] }) {
|
|
73
|
+
const { state, dispatch } = usePioneer();
|
|
74
|
+
const { api, app, user } = state;
|
|
75
|
+
const [selectedPubkey, setSelectedPubkey] = useState<Pubkey | null>(null);
|
|
76
|
+
const [selectedAction, setSelectedAction] = useState<string | null>(null);
|
|
77
|
+
const { isOpen, onOpen, onClose } = useDisclosure();
|
|
78
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
79
|
+
|
|
80
|
+
const handleSelectClick = async (pubkey: Pubkey) => {
|
|
81
|
+
try {
|
|
82
|
+
//
|
|
83
|
+
//console.log("pubkey: ", pubkey);
|
|
84
|
+
|
|
85
|
+
//set Pubkey
|
|
86
|
+
let assetFromPioneer = await api.GetAsset({ symbol: pubkey.symbol });
|
|
87
|
+
assetFromPioneer = assetFromPioneer.data[0];
|
|
88
|
+
let blockchainFromPioneer = await api.GetBlockchain({
|
|
89
|
+
symbol: pubkey.symbol,
|
|
90
|
+
});
|
|
91
|
+
blockchainFromPioneer = blockchainFromPioneer.data[0];
|
|
92
|
+
//console.log("assetFromPioneer: ", pubkey);
|
|
93
|
+
//set Blockchain
|
|
94
|
+
await app.setBlockchainContext(blockchainFromPioneer);
|
|
95
|
+
await app.setAssetContext(assetFromPioneer);
|
|
96
|
+
//set pubkey
|
|
97
|
+
// await app.setPubkeyContext(pubkey.context)
|
|
98
|
+
//console.log("app.assetContext: ", app.assetContext);
|
|
99
|
+
//console.log("app.blockchainContext: ", app.blockchainContext);
|
|
100
|
+
} catch (e) {
|
|
101
|
+
console.error(e);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const handleSendClick = (pubkey: Pubkey) => {
|
|
106
|
+
setSelectedPubkey(pubkey);
|
|
107
|
+
setSelectedAction("send");
|
|
108
|
+
onOpen();
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const handleReceiveClick = (pubkey: Pubkey) => {
|
|
112
|
+
setSelectedPubkey(pubkey);
|
|
113
|
+
setSelectedAction("receive");
|
|
114
|
+
onOpen();
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const handleViewClick = (pubkey: Pubkey) => {
|
|
118
|
+
setSelectedPubkey(pubkey);
|
|
119
|
+
setSelectedAction("view");
|
|
120
|
+
onOpen();
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
const setUser = async () => {
|
|
125
|
+
try {
|
|
126
|
+
if (user && user.wallets) {
|
|
127
|
+
const { walletDescriptions, pubkeys } = user;
|
|
128
|
+
const updatedPubkeys = pubkeys.map((pubkey: Pubkey) => {
|
|
129
|
+
const walletType = getWalletType(user, pubkey.context);
|
|
130
|
+
const badgeContent = getWalletBadgeContent(walletType);
|
|
131
|
+
return {
|
|
132
|
+
//@ts-ignore
|
|
133
|
+
...pubkey,
|
|
134
|
+
context: {
|
|
135
|
+
//@ts-ignore
|
|
136
|
+
...pubkey.context,
|
|
137
|
+
badge: badgeContent,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
dispatch({ type: "SET_BALANCES", payload: updatedPubkeys });
|
|
142
|
+
}
|
|
143
|
+
} catch (e) {
|
|
144
|
+
console.error("Error: ", e);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
setUser();
|
|
149
|
+
}, [user]);
|
|
150
|
+
|
|
151
|
+
// Filter and sort pubkeys based on search query
|
|
152
|
+
const filteredPubkeys = pubkeys.filter((pubkey: Pubkey) => {
|
|
153
|
+
// Convert the search query and pubkey symbol/name to lowercase for case-insensitive search
|
|
154
|
+
const query = searchQuery.toLowerCase();
|
|
155
|
+
const symbol = pubkey.symbol.toLowerCase();
|
|
156
|
+
const name = pubkey.name ? pubkey.name.toLowerCase() : "";
|
|
157
|
+
|
|
158
|
+
// Check if the symbol or name contains the search query
|
|
159
|
+
return symbol.includes(query) || name.includes(query);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const sortedPubkeys = filteredPubkeys.sort(
|
|
163
|
+
(a: Pubkey, b: Pubkey) => b.pubkey - a.pubkey
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
// CSS for the scrollable container
|
|
167
|
+
const scrollContainerStyles: React.CSSProperties = {
|
|
168
|
+
maxHeight: "15em", // This value may need to be adjusted according to your design
|
|
169
|
+
overflowY: "scroll",
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<Stack spacing={4}>
|
|
174
|
+
<InputGroup>
|
|
175
|
+
<InputLeftElement pointerEvents="none">
|
|
176
|
+
<Search2Icon color="gray.300" />
|
|
177
|
+
</InputLeftElement>
|
|
178
|
+
<Input
|
|
179
|
+
placeholder="Bitcoin..."
|
|
180
|
+
type="text"
|
|
181
|
+
value={searchQuery}
|
|
182
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
183
|
+
/>
|
|
184
|
+
</InputGroup>
|
|
185
|
+
<Box style={scrollContainerStyles}>
|
|
186
|
+
{sortedPubkeys.map((pubkey: Pubkey, index: number) => (
|
|
187
|
+
<Box key={index}>
|
|
188
|
+
<HStack spacing={4} alignItems="center">
|
|
189
|
+
<Avatar src={pubkey.image} />
|
|
190
|
+
<Box>
|
|
191
|
+
<small>asset: {pubkey.symbol}</small>
|
|
192
|
+
<br />
|
|
193
|
+
<small>pubkey: {pubkey.pubkey}</small>
|
|
194
|
+
</Box>
|
|
195
|
+
</HStack>
|
|
196
|
+
<HStack mt={2} spacing={2}>
|
|
197
|
+
<Button
|
|
198
|
+
size="sm"
|
|
199
|
+
variant="outline"
|
|
200
|
+
onClick={() => handleSelectClick(pubkey)}
|
|
201
|
+
>
|
|
202
|
+
Select
|
|
203
|
+
</Button>
|
|
204
|
+
{/*<Button*/}
|
|
205
|
+
{/* size="sm"*/}
|
|
206
|
+
{/* variant="outline"*/}
|
|
207
|
+
{/* onClick={() => handleSendClick(pubkey)}*/}
|
|
208
|
+
{/*>*/}
|
|
209
|
+
{/* Send*/}
|
|
210
|
+
{/*</Button>*/}
|
|
211
|
+
{/*<Button*/}
|
|
212
|
+
{/* size="sm"*/}
|
|
213
|
+
{/* variant="outline"*/}
|
|
214
|
+
{/* onClick={() => handleReceiveClick(pubkey)}*/}
|
|
215
|
+
{/*>*/}
|
|
216
|
+
{/* Receive*/}
|
|
217
|
+
{/*</Button>*/}
|
|
218
|
+
{/*<Button*/}
|
|
219
|
+
{/* size="sm"*/}
|
|
220
|
+
{/* variant="outline"*/}
|
|
221
|
+
{/* onClick={() => handleViewClick(pubkey)}*/}
|
|
222
|
+
{/*>*/}
|
|
223
|
+
{/* View*/}
|
|
224
|
+
{/*</Button>*/}
|
|
225
|
+
</HStack>
|
|
226
|
+
</Box>
|
|
227
|
+
))}
|
|
228
|
+
</Box>
|
|
229
|
+
|
|
230
|
+
<Modal isOpen={isOpen} onClose={onClose} isCentered blockScrollOnMount>
|
|
231
|
+
<ModalOverlay />
|
|
232
|
+
<ModalContent>
|
|
233
|
+
<ModalHeader>{selectedAction}</ModalHeader>
|
|
234
|
+
<ModalCloseButton />
|
|
235
|
+
{selectedAction === "send" && (
|
|
236
|
+
<div>
|
|
237
|
+
<h3>Selected Action: Send</h3>
|
|
238
|
+
<p>Selected Asset: {selectedPubkey?.symbol}</p>
|
|
239
|
+
<Send asset={selectedPubkey} />
|
|
240
|
+
</div>
|
|
241
|
+
)}
|
|
242
|
+
{selectedAction === "receive" && (
|
|
243
|
+
<div>
|
|
244
|
+
<h3>Selected Action: Receive</h3>
|
|
245
|
+
<p>Selected Asset: {selectedPubkey?.symbol}</p>
|
|
246
|
+
<Receive />
|
|
247
|
+
</div>
|
|
248
|
+
)}
|
|
249
|
+
{selectedAction === "view" && (
|
|
250
|
+
<div>
|
|
251
|
+
<h3>Selected Action: View</h3>
|
|
252
|
+
<p>Selected Asset: {selectedPubkey?.symbol}</p>
|
|
253
|
+
<View />
|
|
254
|
+
</div>
|
|
255
|
+
)}
|
|
256
|
+
<ModalFooter>
|
|
257
|
+
<Button colorScheme="blue" onClick={onClose}>
|
|
258
|
+
Cancel
|
|
259
|
+
</Button>
|
|
260
|
+
</ModalFooter>
|
|
261
|
+
</ModalContent>
|
|
262
|
+
</Modal>
|
|
263
|
+
</Stack>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { FormControl, FormLabel, Input, Text } from "@chakra-ui/react";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import QRCode from "react-qr-code";
|
|
4
|
+
|
|
5
|
+
const Receive = () => {
|
|
6
|
+
const [address, setAddress] = useState("");
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<>
|
|
10
|
+
<FormControl>
|
|
11
|
+
<FormLabel>Address:</FormLabel>
|
|
12
|
+
<Input value={address} onChange={(e) => setAddress(e.target.value)} />
|
|
13
|
+
</FormControl>
|
|
14
|
+
|
|
15
|
+
{address && (
|
|
16
|
+
<>
|
|
17
|
+
<Text mt={4}>QR Code:</Text>
|
|
18
|
+
<QRCode value={address} size={128} />
|
|
19
|
+
<Text mt={2}>{address}</Text>
|
|
20
|
+
</>
|
|
21
|
+
)}
|
|
22
|
+
</>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default Receive;
|