mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-05-25 19:07:03 +00:00
Merge remote-tracking branch 'upstream/develop' into feature/refine-i18n-italian
This commit is contained in:
commit
fdc3dfc1d1
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
Before Width: | Height: | Size: 1.5 KiB |
27
src/App.tsx
27
src/App.tsx
@ -35,7 +35,7 @@ import PersonSearchIcon from '@mui/icons-material/PersonSearch';
|
||||
import qortLogo from './assets/qort.png';
|
||||
import { Return } from './assets/Icons/Return.tsx';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import './utils/seedPhrase/RandomSentenceGenerator';
|
||||
import './utils/seedPhrase/randomSentenceGenerator.ts';
|
||||
import EngineeringIcon from '@mui/icons-material/Engineering';
|
||||
import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet';
|
||||
import PriorityHighIcon from '@mui/icons-material/PriorityHigh';
|
||||
@ -64,7 +64,7 @@ import { Loader } from './components/Loader';
|
||||
import { PasswordField, ErrorText } from './components';
|
||||
import { Group, requestQueueMemberNames } from './components/Group/Group';
|
||||
import { TaskManager } from './components/TaskManager/TaskManager.tsx';
|
||||
import { useModal } from './common/useModal';
|
||||
import { useModal } from './hooks/useModal.tsx';
|
||||
import { CustomizedSnackbars } from './components/Snackbar/Snackbar';
|
||||
import SettingsIcon from '@mui/icons-material/Settings';
|
||||
import LogoutIcon from '@mui/icons-material/Logout';
|
||||
@ -76,7 +76,7 @@ import {
|
||||
groupApi,
|
||||
groupApiSocket,
|
||||
storeWallets,
|
||||
} from './background';
|
||||
} from './background/background.ts';
|
||||
import {
|
||||
executeEvent,
|
||||
subscribeToEvent,
|
||||
@ -118,13 +118,13 @@ import {
|
||||
} from './atoms/global';
|
||||
import { NotAuthenticated } from './components/NotAuthenticated.tsx';
|
||||
import { handleGetFileFromIndexedDB } from './utils/indexedDB';
|
||||
import { Wallets } from './Wallets';
|
||||
import { useFetchResources } from './common/useFetchResources';
|
||||
import { Wallets } from './components/Wallets.tsx';
|
||||
import { useFetchResources } from './hooks/useFetchResources.tsx';
|
||||
import { Tutorials } from './components/Tutorials/Tutorials';
|
||||
import { useHandleTutorials } from './hooks/useHandleTutorials.tsx';
|
||||
import { useHandleUserInfo } from './hooks/useHandleUserInfo.tsx';
|
||||
import { Minting } from './components/Minting/Minting';
|
||||
import { isRunningGateway } from './qortalRequests';
|
||||
import { isRunningGateway } from './qortal/qortal-requests.ts';
|
||||
import { QMailStatus } from './components/QMailStatus';
|
||||
import { GlobalActions } from './components/GlobalActions/GlobalActions';
|
||||
import { useBlockedAddresses } from './hooks/useBlockUsers.tsx';
|
||||
@ -236,7 +236,8 @@ const defaultValuesGlobal = {
|
||||
setOpenTutorialModal: () => {},
|
||||
};
|
||||
|
||||
export const MyContext = createContext<MyContextInterface>(defaultValues);
|
||||
export const QORTAL_APP_CONTEXT =
|
||||
createContext<MyContextInterface>(defaultValues);
|
||||
|
||||
export let globalApiKey: string | null = null;
|
||||
|
||||
@ -307,7 +308,13 @@ function App() {
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [isLoadingSendCoin, setIsLoadingSendCoin] = useState<boolean>(false);
|
||||
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const theme = useTheme();
|
||||
|
||||
const [
|
||||
@ -2016,7 +2023,7 @@ function App() {
|
||||
>
|
||||
<PdfViewer />
|
||||
|
||||
<MyContext.Provider value={contextValue}>
|
||||
<QORTAL_APP_CONTEXT.Provider value={contextValue}>
|
||||
<Tutorials />
|
||||
{extState === 'not-authenticated' && (
|
||||
<NotAuthenticated
|
||||
@ -3858,7 +3865,7 @@ function App() {
|
||||
setInfoSnack={setInfoSnack}
|
||||
/>
|
||||
<BuyQortInformation balance={balance} />
|
||||
</MyContext.Provider>
|
||||
</QORTAL_APP_CONTEXT.Provider>
|
||||
|
||||
{extState === 'create-wallet' && walletToBeDownloaded && (
|
||||
<ButtonBase
|
||||
|
@ -11,7 +11,6 @@ import {
|
||||
checkLocalFunc,
|
||||
checkNewMessages,
|
||||
checkThreads,
|
||||
clearAllNotifications,
|
||||
createEndpoint,
|
||||
createGroup,
|
||||
decryptDirectFunc,
|
||||
@ -55,20 +54,20 @@ import {
|
||||
setGroupData,
|
||||
updateThreadActivity,
|
||||
walletVersion,
|
||||
} from './background';
|
||||
} from '../background/background.ts';
|
||||
import {
|
||||
decryptGroupEncryption,
|
||||
encryptAndPublishSymmetricKeyGroupChat,
|
||||
encryptAndPublishSymmetricKeyGroupChatForAdmins,
|
||||
publishGroupEncryptedResource,
|
||||
publishOnQDN,
|
||||
} from './backgroundFunctions/encryption';
|
||||
import { PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY } from './constants/constants';
|
||||
import Base58 from './deps/Base58';
|
||||
import { encryptSingle } from './qdn/encryption/group-encryption';
|
||||
import { _createPoll, _voteOnPoll } from './qortalRequests/get';
|
||||
import { createTransaction } from './transactions/transactions';
|
||||
import { getData, storeData } from './utils/chromeStorage';
|
||||
} from '../encryption/encryption.ts';
|
||||
import { PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY } from '../constants/constants';
|
||||
import Base58 from '../encryption/Base58.ts';
|
||||
import { encryptSingle } from '../qdn/encryption/group-encryption';
|
||||
import { _createPoll, _voteOnPoll } from '../qortal/get.ts';
|
||||
import { createTransaction } from '../transactions/transactions';
|
||||
import { getData, storeData } from '../utils/chromeStorage';
|
||||
|
||||
export function versionCase(request, event) {
|
||||
event.source.postMessage(
|
||||
@ -1142,32 +1141,6 @@ export async function getEnteredQmailTimestampCase(request, event) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function clearAllNotificationsCase(request, event) {
|
||||
try {
|
||||
await clearAllNotifications();
|
||||
|
||||
event.source.postMessage(
|
||||
{
|
||||
requestId: request.requestId,
|
||||
action: 'clearAllNotifications',
|
||||
payload: true,
|
||||
type: 'backgroundMessageResponse',
|
||||
},
|
||||
event.origin
|
||||
);
|
||||
} catch (error) {
|
||||
event.source.postMessage(
|
||||
{
|
||||
requestId: request.requestId,
|
||||
action: 'clearAllNotifications',
|
||||
error: error?.message,
|
||||
type: 'backgroundMessageResponse',
|
||||
},
|
||||
event.origin
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function setGroupDataCase(request, event) {
|
||||
try {
|
||||
const { groupId, secretKeyData, secretKeyResource, admins } =
|
@ -1,27 +1,27 @@
|
||||
// @ts-nocheck
|
||||
import './qortalRequests';
|
||||
import '../qortal/qortal-requests.ts';
|
||||
import { isArray } from 'lodash';
|
||||
import { uint8ArrayToObject } from './backgroundFunctions/encryption';
|
||||
import Base58 from './deps/Base58';
|
||||
import { uint8ArrayToObject } from '../encryption/encryption.ts';
|
||||
import Base58 from '../encryption/Base58';
|
||||
import axios from 'axios';
|
||||
import {
|
||||
base64ToUint8Array,
|
||||
decryptSingle,
|
||||
encryptSingle,
|
||||
objectToBase64,
|
||||
} from './qdn/encryption/group-encryption';
|
||||
import ChatComputePowWorker from './chatComputePow.worker.js?worker';
|
||||
import { reusableGet } from './qdn/publish/pubish';
|
||||
import { signChat } from './transactions/signChat';
|
||||
import { createTransaction } from './transactions/transactions';
|
||||
import { decryptChatMessage } from './utils/decryptChatMessage';
|
||||
import { decryptStoredWallet } from './utils/decryptWallet';
|
||||
import PhraseWallet from './utils/generateWallet/phrase-wallet';
|
||||
import { RequestQueueWithPromise } from './utils/queue/queue';
|
||||
import { validateAddress } from './utils/validateAddress';
|
||||
} from '../qdn/encryption/group-encryption';
|
||||
import ChatComputePowWorker from '../chatComputePow.worker.js?worker';
|
||||
import { reusableGet } from '../qdn/publish/publish.ts';
|
||||
import { signChat } from '../transactions/signChat';
|
||||
import { createTransaction } from '../transactions/transactions';
|
||||
import { decryptChatMessage } from '../utils/decryptChatMessage';
|
||||
import { decryptStoredWallet } from '../utils/decryptWallet';
|
||||
import PhraseWallet from '../utils/generateWallet/phrase-wallet';
|
||||
import { RequestQueueWithPromise } from '../utils/queue/queue';
|
||||
import { validateAddress } from '../utils/validateAddress';
|
||||
import { Sha256 } from 'asmcrypto.js';
|
||||
import { TradeBotRespondMultipleRequest } from './transactions/TradeBotRespondMultipleRequest';
|
||||
import { RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS } from './constants/constants';
|
||||
import { TradeBotRespondMultipleRequest } from '../transactions/TradeBotRespondMultipleRequest';
|
||||
import { RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS } from '../constants/constants';
|
||||
import {
|
||||
addDataPublishesCase,
|
||||
addEnteredQmailTimestampCase,
|
||||
@ -34,7 +34,6 @@ import {
|
||||
cancelBanCase,
|
||||
cancelInvitationToGroupCase,
|
||||
checkLocalCase,
|
||||
clearAllNotificationsCase,
|
||||
createGroupCase,
|
||||
createPollCase,
|
||||
createRewardShareCase,
|
||||
@ -68,7 +67,6 @@ import {
|
||||
ltcBalanceCase,
|
||||
makeAdminCase,
|
||||
nameCase,
|
||||
notificationCase,
|
||||
notifyAdminRegenerateSecretKeyCase,
|
||||
pauseAllQueuesCase,
|
||||
publishGroupEncryptedResourceCase,
|
||||
@ -90,9 +88,13 @@ import {
|
||||
validApiCase,
|
||||
versionCase,
|
||||
voteOnPollCase,
|
||||
} from './background-cases';
|
||||
import { getData, removeKeysAndLogout, storeData } from './utils/chromeStorage';
|
||||
import TradeBotRespondRequest from './transactions/TradeBotRespondRequest';
|
||||
} from '../background/background-cases';
|
||||
import {
|
||||
getData,
|
||||
removeKeysAndLogout,
|
||||
storeData,
|
||||
} from '../utils/chromeStorage';
|
||||
import TradeBotRespondRequest from '../transactions/TradeBotRespondRequest';
|
||||
|
||||
export let groupSecretkeys = {};
|
||||
|
||||
@ -300,6 +302,7 @@ export const createEndpoint = async (endpoint, customApi?: string) => {
|
||||
};
|
||||
|
||||
export const walletVersion = 2;
|
||||
|
||||
// List of your API endpoints
|
||||
const apiEndpoints = [
|
||||
'https://api.qortal.org',
|
||||
@ -433,10 +436,6 @@ export async function performPowTask(chatBytes, difficulty) {
|
||||
});
|
||||
}
|
||||
|
||||
function playNotificationSound() {
|
||||
// chrome.runtime.sendMessage({ action: "PLAY_NOTIFICATION_SOUND" });
|
||||
}
|
||||
|
||||
const handleNotificationDirect = async (directs) => {
|
||||
let isFocused;
|
||||
const wallet = await getSaveWallet();
|
||||
@ -600,7 +599,7 @@ export function updateThreadActivity({
|
||||
threads = JSON.parse(storedData);
|
||||
}
|
||||
|
||||
let lastResetTime = threads.lastResetTime || 0;
|
||||
const lastResetTime = threads.lastResetTime || 0;
|
||||
|
||||
// Check if a week has passed since the last reset
|
||||
if (currentTime - lastResetTime > ONE_WEEK_IN_MS) {
|
||||
@ -650,7 +649,7 @@ export function updateThreadActivity({
|
||||
const handleNotification = async (groups) => {
|
||||
const wallet = await getSaveWallet();
|
||||
const address = wallet.address0;
|
||||
let isDisableNotifications =
|
||||
const isDisableNotifications =
|
||||
(await getUserSettings({ key: 'disable-push-notifications' })) || false;
|
||||
|
||||
let mutedGroups = (await getUserSettings({ key: 'mutedGroups' })) || [];
|
||||
@ -675,7 +674,6 @@ const handleNotification = async (groups) => {
|
||||
const newActiveChats = data;
|
||||
const oldActiveChats = await getChatHeads();
|
||||
|
||||
let results = [];
|
||||
let newestLatestTimestamp = null;
|
||||
let oldestLatestTimestamp = null;
|
||||
// Find the latest timestamp from newActiveChats
|
||||
@ -875,13 +873,6 @@ export async function storeWallets(wallets) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function clearAllNotifications() {
|
||||
// const notifications = await chrome.notifications.getAll();
|
||||
// for (const notificationId of Object.keys(notifications)) {
|
||||
// await chrome.notifications.clear(notificationId);
|
||||
// }
|
||||
}
|
||||
|
||||
export async function getUserInfo() {
|
||||
const wallet = await getSaveWallet();
|
||||
const address = wallet.address0;
|
||||
@ -3230,9 +3221,6 @@ function setupMessageListener() {
|
||||
case 'addGroupNotificationTimestamp':
|
||||
addGroupNotificationTimestampCase(request, event);
|
||||
break;
|
||||
case 'clearAllNotifications':
|
||||
clearAllNotificationsCase(request, event);
|
||||
break;
|
||||
case 'setGroupData':
|
||||
setGroupDataCase(request, event);
|
||||
break;
|
@ -1,14 +0,0 @@
|
||||
export const CustomSvg = ({ src, color = 'black', size = 24 }) => {
|
||||
return (
|
||||
<svg
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
style={{ fill: color }}
|
||||
>
|
||||
{src}
|
||||
</svg>
|
||||
);
|
||||
};
|
@ -37,7 +37,13 @@ export const AppInfo = ({ app, myName }) => {
|
||||
);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const isSelectedAppPinned = !!sortablePinnedApps?.find(
|
||||
(item) => item?.name === app?.name && item?.service === app?.service
|
||||
|
@ -42,7 +42,13 @@ export const AppInfoSnippet = ({
|
||||
);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
return (
|
||||
<AppInfoSnippetContainer
|
||||
|
@ -16,13 +16,13 @@ import {
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { styled } from '@mui/system';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT, getBaseApiReact } from '../../App';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { executeEvent } from '../../utils/events';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar';
|
||||
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { fileToBase64 } from '../../utils/fileReading';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -65,9 +65,15 @@ export const AppPublish = ({ names, categories }) => {
|
||||
const [category, setCategory] = useState('');
|
||||
const [appType, setAppType] = useState('APP');
|
||||
const [file, setFile] = useState(null);
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [tag1, setTag1] = useState('');
|
||||
const [tag2, setTag2] = useState('');
|
||||
const [tag3, setTag3] = useState('');
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Box, Rating } from '@mui/material';
|
||||
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
||||
import { getFee } from '../../background';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { QORTAL_APP_CONTEXT, getBaseApiReact } from '../../App';
|
||||
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
||||
import { StarFilledIcon } from '../../assets/Icons/StarFilled';
|
||||
import { StarEmptyIcon } from '../../assets/Icons/StarEmpty';
|
||||
@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const AppRating = ({ app, myName, ratingCountPosition = 'right' }) => {
|
||||
const [value, setValue] = useState(0);
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const [hasPublishedRating, setHasPublishedRating] = useState<null | boolean>(
|
||||
null
|
||||
);
|
||||
@ -20,7 +20,13 @@ export const AppRating = ({ app, myName, ratingCountPosition = 'right' }) => {
|
||||
const [openSnack, setOpenSnack] = useState(false);
|
||||
const [infoSnack, setInfoSnack] = useState(null);
|
||||
const hasCalledRef = useRef(false);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const getRating = useCallback(async (name, service) => {
|
||||
try {
|
||||
|
@ -45,7 +45,13 @@ export const AppsCategoryDesktop = ({
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const virtuosoRef = useRef(null);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const categoryList = useMemo(() => {
|
||||
if (category?.id === 'all') return availableQapps;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { AppsHomeDesktop } from './AppsHomeDesktop';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT, getBaseApiReact } from '../../App';
|
||||
import { AppInfo } from './AppInfo';
|
||||
import {
|
||||
executeEvent,
|
||||
@ -48,9 +48,15 @@ export const AppsDesktop = ({
|
||||
const [categories, setCategories] = useState([]);
|
||||
const iframeRefs = useRef({});
|
||||
const [isEnabledDevMode, setIsEnabledDevMode] = useAtom(enabledDevModeAtom);
|
||||
const { showTutorial } = useContext(MyContext);
|
||||
const { showTutorial } = useContext(QORTAL_APP_CONTEXT);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const myApp = useMemo(() => {
|
||||
return availableQapps.find(
|
||||
|
@ -47,7 +47,13 @@ export const AppsDevMode = ({
|
||||
const [categories, setCategories] = useState([]);
|
||||
const iframeRefs = useRef({});
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
|
@ -19,11 +19,11 @@ import {
|
||||
Input,
|
||||
} from '@mui/material';
|
||||
import { Add } from '@mui/icons-material';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT, getBaseApiReact } from '../../App';
|
||||
import { executeEvent } from '../../utils/events';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { useModal } from '../../common/useModal';
|
||||
import { createEndpoint, isUsingLocal } from '../../background';
|
||||
import { useModal } from '../../hooks/useModal.tsx';
|
||||
import { createEndpoint, isUsingLocal } from '../../background/background.ts';
|
||||
import { Label } from '../Group/AddGroup';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
import swaggerSVG from '../../assets/svgs/swagger.svg';
|
||||
@ -41,14 +41,20 @@ export const AppsDevModeHome = ({
|
||||
const [domain, setDomain] = useState('127.0.0.1');
|
||||
const [port, setPort] = useState('');
|
||||
const [selectedPreviewFile, setSelectedPreviewFile] = useState(null);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const { isShow, onCancel, onOk, show, message } = useModal();
|
||||
const {
|
||||
openSnackGlobal,
|
||||
setOpenSnackGlobal,
|
||||
infoSnackCustom,
|
||||
setInfoSnackCustom,
|
||||
} = useContext(MyContext);
|
||||
} = useContext(QORTAL_APP_CONTEXT);
|
||||
|
||||
const handleSelectFile = async (existingFilePath) => {
|
||||
const filePath = existingFilePath || (await window.electron.selectFile());
|
||||
|
@ -27,7 +27,13 @@ export const AppsHomeDesktop = ({
|
||||
}) => {
|
||||
const [qortalUrl, setQortalUrl] = useState('');
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const openQortalUrl = () => {
|
||||
try {
|
||||
|
@ -105,7 +105,13 @@ export const AppsLibraryDesktop = ({
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const virtuosoRef = useRef(null);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const officialApps = useMemo(() => {
|
||||
return availableQapps.filter(
|
||||
|
@ -76,7 +76,13 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [isNewTabWindow, setIsNewTabWindow] = useState(false);
|
||||
const tabsRef = useRef(null);
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
@ -31,10 +31,10 @@ import {
|
||||
} from './Apps-styles';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import ImageUploader from '../../common/ImageUploader';
|
||||
import { MyContext } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT } from '../../App';
|
||||
import { fileToBase64 } from '../../utils/fileReading';
|
||||
import { objectToBase64 } from '../../qdn/encryption/group-encryption';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -59,11 +59,17 @@ export const AppsPrivate = ({ myName }) => {
|
||||
|
||||
const [isOpenPrivateModal, setIsOpenPrivateModal] = useState(false);
|
||||
const { show, setInfoSnackCustom, setOpenSnackGlobal } =
|
||||
useContext(MyContext);
|
||||
useContext(QORTAL_APP_CONTEXT);
|
||||
const [memberGroups] = useAtom(memberGroupsAtom);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const myGroupsPrivate = useMemo(() => {
|
||||
return memberGroups?.filter(
|
||||
|
@ -27,7 +27,13 @@ import { useTranslation } from 'react-i18next';
|
||||
export const BuyQortInformation = ({ balance }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const openBuyQortInfoFunc = useCallback(
|
||||
(e) => {
|
||||
|
@ -19,7 +19,13 @@ export const AdminSpace = ({
|
||||
isOwner,
|
||||
}) => {
|
||||
const [isMoved, setIsMoved] = useState(false);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (hide) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import {
|
||||
MyContext,
|
||||
QORTAL_APP_CONTEXT,
|
||||
getArbitraryEndpointReact,
|
||||
getBaseApiReact,
|
||||
} from '../../App';
|
||||
@ -10,9 +10,9 @@ import {
|
||||
getPublishesFromAdmins,
|
||||
validateSecretKey,
|
||||
} from '../Group/Group';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { base64ToUint8Array } from '../../qdn/encryption/group-encryption';
|
||||
import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
|
||||
import { uint8ArrayToObject } from '../../encryption/encryption.ts';
|
||||
import { formatTimestampForum } from '../../utils/time';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { GroupAvatar } from './GroupAvatar';
|
||||
@ -73,8 +73,14 @@ export const AdminSpaceInner = ({
|
||||
useState(null);
|
||||
const [isLoadingPublishKey, setIsLoadingPublishKey] = useState(false);
|
||||
const { show, setInfoSnackCustom, setOpenSnackGlobal } =
|
||||
useContext(MyContext);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
useContext(QORTAL_APP_CONTEXT);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const getAdminGroupSecretKey = useCallback(async () => {
|
||||
try {
|
||||
|
@ -8,7 +8,7 @@ import { Box, CircularProgress, useTheme } from '@mui/material';
|
||||
import { objectToBase64 } from '../../qdn/encryption/group-encryption';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import {
|
||||
decryptPublishes,
|
||||
getTempPublish,
|
||||
@ -40,7 +40,13 @@ export const AnnouncementDiscussion = ({
|
||||
isPrivate,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [isSending, setIsSending] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isFocusedParent, setIsFocusedParent] = useState(false);
|
||||
|
@ -18,7 +18,13 @@ export const AnnouncementItem = ({
|
||||
myName,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [commentLength, setCommentLength] = useState(0);
|
||||
|
||||
const getNumberOfComments = useCallback(async () => {
|
||||
|
@ -20,7 +20,13 @@ export const AnnouncementList = ({
|
||||
myName,
|
||||
}) => {
|
||||
const [messages, setMessages] = useState(initialMessages);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
cache.clearAll();
|
||||
|
@ -14,8 +14,8 @@ import {
|
||||
pauseAllQueues,
|
||||
resumeAllQueues,
|
||||
} from '../../App';
|
||||
import { getPublicKey } from '../../background';
|
||||
import { useMessageQueue } from '../../MessageQueueContext';
|
||||
import { getPublicKey } from '../../background/background.ts';
|
||||
import { useMessageQueue } from '../../messaging/MessageQueueContext.tsx';
|
||||
import {
|
||||
executeEvent,
|
||||
subscribeToEvent,
|
||||
@ -42,7 +42,13 @@ export const ChatDirect = ({
|
||||
setMobileViewModeKeepOpen,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const { queueChats, addToQueue, processWithNewMessages } = useMessageQueue();
|
||||
const [isFocusedParent, setIsFocusedParent] = useState(false);
|
||||
const [onEditMessage, setOnEditMessage] = useState(null);
|
||||
|
@ -19,13 +19,13 @@ import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar';
|
||||
import {
|
||||
getBaseApiReact,
|
||||
getBaseApiReactSocket,
|
||||
MyContext,
|
||||
QORTAL_APP_CONTEXT,
|
||||
pauseAllQueues,
|
||||
resumeAllQueues,
|
||||
} from '../../App';
|
||||
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
||||
import { PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY } from '../../constants/constants';
|
||||
import { useMessageQueue } from '../../MessageQueueContext';
|
||||
import { useMessageQueue } from '../../messaging/MessageQueueContext.tsx';
|
||||
import {
|
||||
executeEvent,
|
||||
subscribeToEvent,
|
||||
@ -44,7 +44,7 @@ import ShortUniqueId from 'short-unique-id';
|
||||
import { ReplyPreview } from './MessageItem';
|
||||
import { ExitIcon } from '../../assets/Icons/ExitIcon';
|
||||
import { RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS } from '../../constants/constants';
|
||||
import { getFee, isExtMsg } from '../../background';
|
||||
import { getFee, isExtMsg } from '../../background/background.ts';
|
||||
import AppViewerContainer from '../Apps/AppViewerContainer';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import { throttle } from 'lodash';
|
||||
@ -71,7 +71,7 @@ export const ChatGroup = ({
|
||||
hideView,
|
||||
isPrivate,
|
||||
}) => {
|
||||
const { isUserBlocked, show } = useContext(MyContext);
|
||||
const { isUserBlocked, show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const [messages, setMessages] = useState([]);
|
||||
const [chatReferences, setChatReferences] = useState({});
|
||||
const [isSending, setIsSending] = useState(false);
|
||||
@ -96,7 +96,13 @@ export const ChatGroup = ({
|
||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||
const lastReadTimestamp = useRef(null);
|
||||
const handleUpdateRef = useRef(null);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const getTimestampEnterChat = async (selectedGroup) => {
|
||||
try {
|
||||
|
@ -181,7 +181,13 @@ export const ChatList = ({
|
||||
}, []);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
|
@ -60,7 +60,13 @@ export const ChatOptions = ({
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const [selectedMember, setSelectedMember] = useState(0);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const parentRef = useRef(null);
|
||||
const parentRefMentions = useRef(null);
|
||||
const [lastMentionTimestamp, setLastMentionTimestamp] = useState(null);
|
||||
|
@ -3,19 +3,19 @@ import { Box, Button, Typography, useTheme } from '@mui/material';
|
||||
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import {
|
||||
MyContext,
|
||||
QORTAL_APP_CONTEXT,
|
||||
getArbitraryEndpointReact,
|
||||
getBaseApiReact,
|
||||
pauseAllQueues,
|
||||
} from '../../App';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import {
|
||||
decryptResource,
|
||||
getGroupAdmins,
|
||||
validateSecretKey,
|
||||
} from '../Group/Group';
|
||||
import { base64ToUint8Array } from '../../qdn/encryption/group-encryption';
|
||||
import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
|
||||
import { uint8ArrayToObject } from '../../encryption/encryption.ts';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { txListAtom } from '../../atoms/global';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -32,7 +32,7 @@ export const CreateCommonSecret = ({
|
||||
setIsForceShowCreationKeyPopup,
|
||||
isForceShowCreationKeyPopup,
|
||||
}) => {
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const setTxList = useSetAtom(txListAtom);
|
||||
|
||||
const [openSnack, setOpenSnack] = useState(false);
|
||||
@ -40,7 +40,13 @@ export const CreateCommonSecret = ({
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const getPublishesFromAdmins = async (admins: string[]) => {
|
||||
const queryString = admins.map((name) => `name=${name}`).join('&');
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
|
||||
import { uint8ArrayToObject } from '../../encryption/encryption.ts';
|
||||
import {
|
||||
base64ToUint8Array,
|
||||
objectToBase64,
|
||||
@ -15,7 +15,7 @@ import {
|
||||
import Tiptap from './TipTap';
|
||||
import { CustomButton } from '../../styles/App-styles';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar';
|
||||
import { Box, Typography, useTheme } from '@mui/material';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
@ -24,7 +24,7 @@ import { AnnouncementList } from './AnnouncementList';
|
||||
import CampaignIcon from '@mui/icons-material/Campaign';
|
||||
import { AnnouncementDiscussion } from './AnnouncementDiscussion';
|
||||
import {
|
||||
MyContext,
|
||||
QORTAL_APP_CONTEXT,
|
||||
getArbitraryEndpointReact,
|
||||
getBaseApiReact,
|
||||
pauseAllQueues,
|
||||
@ -142,7 +142,7 @@ export const GroupAnnouncements = ({
|
||||
const [selectedAnnouncement, setSelectedAnnouncement] = useState(null);
|
||||
const [isFocusedParent, setIsFocusedParent] = useState(false);
|
||||
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const [openSnack, setOpenSnack] = useState(false);
|
||||
const [infoSnack, setInfoSnack] = useState(null);
|
||||
const hasInitialized = useRef(false);
|
||||
@ -153,7 +153,13 @@ export const GroupAnnouncements = ({
|
||||
editorRef.current = editorInstance;
|
||||
};
|
||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const triggerRerender = () => {
|
||||
forceUpdate(); // Trigger re-render by updating the state
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import Logo2 from '../../assets/svgs/Logo2.svg';
|
||||
import {
|
||||
MyContext,
|
||||
QORTAL_APP_CONTEXT,
|
||||
getArbitraryEndpointReact,
|
||||
getBaseApiReact,
|
||||
} from '../../App';
|
||||
@ -16,7 +16,7 @@ import {
|
||||
} from '@mui/material';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import ImageUploader from '../../common/ImageUploader';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { fileToBase64 } from '../../utils/fileReading';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import ErrorIcon from '@mui/icons-material/Error';
|
||||
@ -32,8 +32,14 @@ export const GroupAvatar = ({
|
||||
const [hasAvatar, setHasAvatar] = useState(false);
|
||||
const [avatarFile, setAvatarFile] = useState(null);
|
||||
const [tempAvatar, setTempAvatar] = useState(null);
|
||||
const { show } = useContext(MyContext);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
// Handle child element click to open Popover
|
||||
@ -262,7 +268,13 @@ const PopoverComp = ({
|
||||
myName,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
|
@ -2,7 +2,13 @@ import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default forwardRef((props, ref) => {
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { formatTimestamp } from '../../utils/time';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT, getBaseApiReact } from '../../App';
|
||||
import { generateHTML } from '@tiptap/react';
|
||||
import Highlight from '@tiptap/extension-highlight';
|
||||
import Mention from '@tiptap/extension-mention';
|
||||
@ -113,7 +113,7 @@ export const MessageItem = memo(
|
||||
onEdit,
|
||||
isPrivate,
|
||||
}) => {
|
||||
const { getIndividualUserInfo } = useContext(MyContext);
|
||||
const { getIndividualUserInfo } = useContext(QORTAL_APP_CONTEXT);
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const [selectedReaction, setSelectedReaction] = useState(null);
|
||||
const [userInfo, setUserInfo] = useState(null);
|
||||
@ -170,7 +170,13 @@ export const MessageItem = memo(
|
||||
}, [message?.id]);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -612,7 +618,13 @@ export const MessageItem = memo(
|
||||
|
||||
export const ReplyPreview = ({ message, isEdit = false }) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
|
@ -54,7 +54,13 @@ const MenuBar = memo(
|
||||
const { editor } = useCurrentEditor();
|
||||
const fileInputRef = useRef(null);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editor && setEditorRef) {
|
||||
|
@ -13,7 +13,13 @@ export const CoreSyncStatus = () => {
|
||||
const [coreInfos, setCoreInfos] = useState({});
|
||||
const [isUsingGateway, setIsUsingGateway] = useState(false);
|
||||
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const theme = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -67,7 +67,13 @@ export const DesktopFooter = ({
|
||||
}) => {
|
||||
const [isEnabledDevMode, setIsEnabledDevMode] = useAtom(enabledDevModeAtom);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
if (hide) return;
|
||||
return (
|
||||
|
@ -84,7 +84,13 @@ export const DesktopHeader = ({
|
||||
}) => {
|
||||
const [value, setValue] = useState(0);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
|
@ -28,7 +28,13 @@ export const DesktopSideBar = ({
|
||||
const [isEnabledDevMode, setIsEnabledDevMode] = useAtom(enabledDevModeAtom);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useContext, useState } from 'react';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT, getBaseApiReact } from '../../App';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@ -36,9 +36,15 @@ export const AttachmentCard = ({
|
||||
selectedGroupId,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const { downloadResource } = useContext(MyContext);
|
||||
const { downloadResource } = useContext(QORTAL_APP_CONTEXT);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const saveToDisk = async () => {
|
||||
const { name, service, identifier } = resourceData;
|
||||
@ -226,8 +232,7 @@ export const AttachmentCard = ({
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
<CustomLoader />{' '}
|
||||
<CustomLoader />
|
||||
</Box>
|
||||
)}
|
||||
{errorMsg && (
|
||||
|
@ -63,7 +63,13 @@ export const Embed = ({ embedLink }) => {
|
||||
const [parsedData, setParsedData] = useState(null);
|
||||
const setBlobs = useSetAtom(blobControllerAtom);
|
||||
const [selectedGroupId] = useAtom(selectedGroupIdAtom);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const resourceData = useMemo(() => {
|
||||
const parsedDataOnTheFly = parseQortalLink(embedLink);
|
||||
if (
|
||||
|
@ -30,7 +30,13 @@ export const ImageCard = ({
|
||||
encryptionType,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const [height, setHeight] = useState('400px');
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { MyContext } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT } from '../../App';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@ -16,7 +16,7 @@ import {
|
||||
} from '@mui/material';
|
||||
import { getNameInfo } from '../Group/Group';
|
||||
import PollIcon from '@mui/icons-material/Poll';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||
@ -37,10 +37,16 @@ export const PollCard = ({
|
||||
const [ownerName, setOwnerName] = useState('');
|
||||
const [showResults, setShowResults] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { show, userInfo } = useContext(MyContext);
|
||||
const { show, userInfo } = useContext(QORTAL_APP_CONTEXT);
|
||||
const [isLoadingSubmit, setIsLoadingSubmit] = useState(false);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const handleVote = async () => {
|
||||
const fee = await getFee('VOTE_ON_POLL');
|
||||
@ -379,7 +385,13 @@ const PollResults = ({ votes }) => {
|
||||
...votes?.voteCounts?.map((option) => option.voteCount)
|
||||
);
|
||||
const options = votes?.voteCounts;
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
return (
|
||||
<Box sx={{ width: '100%', p: 2 }}>
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
} from '@mui/icons-material';
|
||||
import { styled } from '@mui/system';
|
||||
import { Refresh } from '@mui/icons-material';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT, getBaseApiReact } from '../../App';
|
||||
import { resourceKeySelector } from '../../atoms/global';
|
||||
|
||||
import { useAtomValue } from 'jotai';
|
||||
@ -88,7 +88,7 @@ export const VideoPlayer: FC<VideoPlayerProps> = ({
|
||||
}, [service, name, identifier]);
|
||||
|
||||
const download = useAtomValue(resourceKeySelector(keyIdentifier));
|
||||
const { downloadResource } = useContext(MyContext);
|
||||
const { downloadResource } = useContext(QORTAL_APP_CONTEXT);
|
||||
const videoRef = useRef<HTMLVideoElement | null>(null);
|
||||
const [playing, setPlaying] = useState(false);
|
||||
const [volume, setVolume] = useState(1);
|
||||
|
@ -32,7 +32,13 @@ export const GeneralNotifications = ({ address }) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
|
@ -11,8 +11,8 @@ import {
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { CustomButtonAccept } from '../../styles/App-styles';
|
||||
import { getBaseApiReact, MyContext } from '../../App';
|
||||
import { getFee } from '../../background';
|
||||
import { getBaseApiReact, QORTAL_APP_CONTEXT } from '../../App';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
||||
import { FidgetSpinner } from 'react-loader-spinner';
|
||||
import { useAtom, useSetAtom } from 'jotai';
|
||||
@ -20,7 +20,7 @@ import { memberGroupsAtom, txListAtom } from '../../atoms/global';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const JoinGroup = () => {
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const setTxList = useSetAtom(txListAtom);
|
||||
const [memberGroups] = useAtom(memberGroupsAtom);
|
||||
const [openSnack, setOpenSnack] = useState(false);
|
||||
@ -29,7 +29,13 @@ export const JoinGroup = () => {
|
||||
const [isLoadingInfo, setIsLoadingInfo] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [isLoadingJoinGroup, setIsLoadingJoinGroup] = useState(false);
|
||||
|
||||
const handleJoinGroup = async (e) => {
|
||||
|
@ -34,8 +34,8 @@ import {
|
||||
import { AddGroupList } from './AddGroupList';
|
||||
import { UserListOfInvites } from './UserListOfInvites';
|
||||
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
||||
import { getFee } from '../../background';
|
||||
import { MyContext } from '../../App';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { QORTAL_APP_CONTEXT } from '../../App';
|
||||
import { subscribeToEvent, unsubscribeFromEvent } from '../../utils/events';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSetAtom } from 'jotai';
|
||||
@ -59,7 +59,7 @@ const Transition = forwardRef(function Transition(
|
||||
});
|
||||
|
||||
export const AddGroup = ({ address, open, setOpen }) => {
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const setTxList = useSetAtom(txListAtom);
|
||||
|
||||
const [openAdvance, setOpenAdvance] = useState(false);
|
||||
@ -97,7 +97,13 @@ export const AddGroup = ({ address, open, setOpen }) => {
|
||||
setMaxBlock(event.target.value as string);
|
||||
};
|
||||
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const theme = useTheme();
|
||||
|
||||
const handleCreateGroup = async () => {
|
||||
|
@ -23,9 +23,9 @@ import {
|
||||
List,
|
||||
} from 'react-virtualized';
|
||||
import _ from 'lodash';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT, getBaseApiReact } from '../../App';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
@ -39,10 +39,16 @@ const cache = new CellMeasurerCache({
|
||||
});
|
||||
|
||||
export const AddGroupList = ({ setInfoSnack, setOpenSnack }) => {
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const [memberGroups] = useAtom(memberGroupsAtom);
|
||||
const setTxList = useSetAtom(txListAtom);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [groups, setGroups] = useState([]);
|
||||
const [popoverAnchor, setPopoverAnchor] = useState(null); // Track which list item the popover is anchored to
|
||||
const [openPopoverIndex, setOpenPopoverIndex] = useState(null); // Track which list item has the popover open
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { getBaseApiReact, MyContext } from '../../App';
|
||||
import { getBaseApiReact, QORTAL_APP_CONTEXT } from '../../App';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import {
|
||||
executeEvent,
|
||||
@ -20,7 +20,7 @@ import {
|
||||
} from '../../utils/events';
|
||||
import { validateAddress } from '../../utils/validateAddress';
|
||||
import { getNameInfo, requestQueueMemberNames } from './Group';
|
||||
import { useModal } from '../../common/useModal';
|
||||
import { useModal } from '../../hooks/useModal';
|
||||
import { isOpenBlockedModalAtom } from '../../atoms/global';
|
||||
import InfoIcon from '@mui/icons-material/Info';
|
||||
import { useAtom } from 'jotai';
|
||||
@ -28,7 +28,13 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const BlockedUsersModal = () => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [isOpenBlockedModal, setIsOpenBlockedModal] = useAtom(
|
||||
isOpenBlockedModalAtom
|
||||
);
|
||||
@ -42,7 +48,7 @@ export const BlockedUsersModal = () => {
|
||||
addToBlockList,
|
||||
setOpenSnackGlobal,
|
||||
setInfoSnackCustom,
|
||||
} = useContext(MyContext);
|
||||
} = useContext(QORTAL_APP_CONTEXT);
|
||||
|
||||
const [blockedUsers, setBlockedUsers] = useState({
|
||||
addresses: {},
|
||||
|
@ -73,7 +73,13 @@ export const GroupMail = ({
|
||||
const anchorElInstanceFilter = useRef<any>(null);
|
||||
const [tempPublishedList, setTempPublishedList] = useState([]);
|
||||
const dataPublishes = useRef({});
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const theme = useTheme();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const groupIdRef = useRef<any>(null);
|
||||
|
@ -17,8 +17,12 @@ import { ReusableModal } from './ReusableModal';
|
||||
import { Spacer } from '../../../common/Spacer';
|
||||
import { CreateThreadIcon } from '../../../assets/Icons/CreateThreadIcon';
|
||||
import { SendNewMessage } from '../../../assets/Icons/SendNewMessage';
|
||||
import { MyContext, pauseAllQueues, resumeAllQueues } from '../../../App';
|
||||
import { getFee } from '../../../background';
|
||||
import {
|
||||
QORTAL_APP_CONTEXT,
|
||||
pauseAllQueues,
|
||||
resumeAllQueues,
|
||||
} from '../../../App';
|
||||
import { getFee } from '../../../background/background';
|
||||
import TipTap from '../../Chat/TipTap';
|
||||
import { MessageDisplay } from '../../Chat/MessageDisplay';
|
||||
import { CustomizedSnackbars } from '../../Snackbar/Snackbar';
|
||||
@ -140,8 +144,14 @@ export const NewThread = ({
|
||||
setPostReply,
|
||||
isPrivate,
|
||||
}: NewMessageProps) => {
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { show } = useContext(MyContext);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
const [value, setValue] = useState('');
|
||||
const [isSending, setIsSending] = useState(false);
|
||||
|
@ -115,7 +115,13 @@ export const Thread = ({
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [postReply, setPostReply] = useState(null);
|
||||
const [hasLastPage, setHasLastPage] = useState(false);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const theme = useTheme();
|
||||
// Update: Use a new ref for the scrollable container
|
||||
const threadContainerRef = useRef(null);
|
||||
@ -931,6 +937,7 @@ export const Thread = ({
|
||||
}}
|
||||
>
|
||||
<CustomLoader />
|
||||
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '18px',
|
||||
|
@ -13,7 +13,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { ChatGroup } from '../Chat/ChatGroup';
|
||||
import { CreateCommonSecret } from '../Chat/CreateCommonSecret';
|
||||
import { base64ToUint8Array } from '../../qdn/encryption/group-encryption';
|
||||
import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
|
||||
import { uint8ArrayToObject } from '../../encryption/encryption';
|
||||
import { AddGroup } from './AddGroup';
|
||||
import CreateIcon from '@mui/icons-material/Create';
|
||||
import {
|
||||
@ -43,7 +43,7 @@ import {
|
||||
} from '../../utils/events';
|
||||
import { RequestQueueWithPromise } from '../../utils/queue/queue';
|
||||
import { WebSocketActive } from './WebsocketActive';
|
||||
import { useMessageQueue } from '../../MessageQueueContext';
|
||||
import { useMessageQueue } from '../../messaging/MessageQueueContext';
|
||||
import { HomeDesktop } from './HomeDesktop';
|
||||
import { IconWrapper } from '../Desktop/DesktopFooter';
|
||||
import { DesktopHeader } from '../Desktop/DesktopHeader';
|
||||
@ -444,7 +444,13 @@ export const Group = ({
|
||||
const [isForceShowCreationKeyPopup, setIsForceShowCreationKeyPopup] =
|
||||
useState(false);
|
||||
const groupsOwnerNamesRef = useRef({});
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const [groupsProperties, setGroupsProperties] = useAtom(groupsPropertiesAtom);
|
||||
const setGroupsOwnerNames = useSetAtom(groupsOwnerNamesAtom);
|
||||
|
@ -18,7 +18,13 @@ export const GroupInvites = ({ myAddress, setOpenAddGroup }) => {
|
||||
const [groupsWithJoinRequests, setGroupsWithJoinRequests] = useState([]);
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const theme = useTheme();
|
||||
|
||||
const getJoinRequests = async () => {
|
||||
|
@ -28,7 +28,13 @@ export const GroupJoinRequests = ({
|
||||
setDesktopViewMode,
|
||||
}) => {
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [groupsWithJoinRequests, setGroupsWithJoinRequests] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [txList] = useAtom(txListAtom);
|
||||
|
@ -49,7 +49,13 @@ export const GroupList = ({
|
||||
myAddress,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [isRunningPublicNode] = useAtom(isRunningPublicNodeAtom);
|
||||
|
||||
return (
|
||||
|
@ -31,7 +31,13 @@ export const HomeDesktop = ({
|
||||
const [checked1, setChecked1] = useState(false);
|
||||
const [checked2, setChecked2] = useState(false);
|
||||
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const theme = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -3,14 +3,20 @@ import { Box, Input, MenuItem, Select, SelectChangeEvent } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { Label } from './AddGroup';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const InviteMember = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
||||
const [value, setValue] = useState('');
|
||||
const [expiryTime, setExpiryTime] = useState<string>('259200');
|
||||
const [isLoadingInvite, setIsLoadingInvite] = useState(false);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const inviteMember = async () => {
|
||||
try {
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
List,
|
||||
} from 'react-virtualized';
|
||||
import { getNameInfo } from './Group';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { getBaseApiReact } from '../../App';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -56,7 +56,13 @@ export const ListOfBans = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
||||
const [openPopoverIndex, setOpenPopoverIndex] = useState(null); // Track which list item has the popover open
|
||||
const listRef = useRef(null);
|
||||
const [isLoadingUnban, setIsLoadingUnban] = useState(false);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const getInvites = async (groupId) => {
|
||||
try {
|
||||
|
@ -21,7 +21,7 @@ import { LoadingButton } from '@mui/lab';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
|
||||
import {
|
||||
MyContext,
|
||||
QORTAL_APP_CONTEXT,
|
||||
getArbitraryEndpointReact,
|
||||
getBaseApiReact,
|
||||
} from '../../App';
|
||||
@ -42,7 +42,7 @@ import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import ErrorBoundary from '../../common/ErrorBoundary';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { useAtom, useSetAtom } from 'jotai';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -88,10 +88,16 @@ export const ListOfGroupPromotions = () => {
|
||||
const [fee, setFee] = useState(null);
|
||||
const [isLoadingJoinGroup, setIsLoadingJoinGroup] = useState(false);
|
||||
const [isLoadingPublish, setIsLoadingPublish] = useState(false);
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const setTxList = useSetAtom(txListAtom);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const listRef = useRef(null);
|
||||
const rowVirtualizer = useVirtualizer({
|
||||
count: promotions.length,
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
List,
|
||||
} from 'react-virtualized';
|
||||
import { getNameInfo } from './Group';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { getBaseApiReact } from '../../App';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -60,7 +60,13 @@ export const ListOfInvites = ({
|
||||
const [popoverAnchor, setPopoverAnchor] = useState(null); // Track which list item the popover is anchored to
|
||||
const [openPopoverIndex, setOpenPopoverIndex] = useState(null); // Track which list item has the popover open
|
||||
const [isLoadingCancelInvite, setIsLoadingCancelInvite] = useState(false);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const listRef = useRef(null);
|
||||
|
||||
const getInvites = async (groupId) => {
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
List,
|
||||
} from 'react-virtualized';
|
||||
import { getNameInfo } from './Group';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { getBaseApiReact } from '../../App';
|
||||
import { txListAtom } from '../../atoms/global';
|
||||
@ -64,7 +64,13 @@ export const ListOfJoinRequests = ({
|
||||
const [openPopoverIndex, setOpenPopoverIndex] = useState(null); // Track which list item has the popover open
|
||||
const listRef = useRef(null);
|
||||
const [isLoadingAccept, setIsLoadingAccept] = useState(false);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const getInvites = async (groupId) => {
|
||||
try {
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
List,
|
||||
} from 'react-virtualized';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { getBaseApiReact } from '../../App';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -42,7 +42,13 @@ const ListOfMembers = ({
|
||||
const [isLoadingMakeAdmin, setIsLoadingMakeAdmin] = useState(false);
|
||||
const [isLoadingRemoveAdmin, setIsLoadingRemoveAdmin] = useState(false);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const listRef = useRef(null);
|
||||
|
||||
const handlePopoverOpen = (event, index) => {
|
||||
|
@ -14,7 +14,13 @@ import { useTranslation } from 'react-i18next';
|
||||
export const ListOfThreadPostsWatched = () => {
|
||||
const [posts, setPosts] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const getPosts = async () => {
|
||||
try {
|
||||
|
@ -25,10 +25,10 @@ import { ListOfBans } from './ListOfBans';
|
||||
import { ListOfJoinRequests } from './ListOfJoinRequests';
|
||||
import { Box, ButtonBase, Card, Tab, Tabs, useTheme } from '@mui/material';
|
||||
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT, getBaseApiReact } from '../../App';
|
||||
import { getGroupMembers, getNames } from './Group';
|
||||
import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { subscribeToEvent, unsubscribeFromEvent } from '../../utils/events';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
@ -71,8 +71,14 @@ export const ManageMembers = ({
|
||||
setValue(newValue);
|
||||
};
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { show } = useContext(MyContext);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const setTxList = useSetAtom(txListAtom);
|
||||
|
||||
const handleClose = () => {
|
||||
|
@ -54,7 +54,13 @@ export const QMailMessages = ({ userName, userAddress }) => {
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const getMails = useCallback(async () => {
|
||||
try {
|
||||
|
@ -36,9 +36,9 @@ import { useAtom } from 'jotai';
|
||||
import { decryptStoredWallet } from '../../utils/decryptWallet';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import PhraseWallet from '../../utils/generateWallet/phrase-wallet';
|
||||
import { walletVersion } from '../../background';
|
||||
import Base58 from '../../deps/Base58';
|
||||
import { MyContext } from '../../App';
|
||||
import { walletVersion } from '../../background/background.ts';
|
||||
import Base58 from '../../encryption/Base58.ts';
|
||||
import { QORTAL_APP_CONTEXT } from '../../App';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const LocalNodeSwitch = styled(Switch)(({ theme }) => ({
|
||||
@ -87,7 +87,13 @@ export const Settings = ({ open, setOpen, rawWallet }) => {
|
||||
const [checked, setChecked] = useState(false);
|
||||
const [isEnabledDevMode, setIsEnabledDevMode] = useAtom(enabledDevModeAtom);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
setChecked(event.target.checked);
|
||||
@ -233,8 +239,15 @@ const ExportPrivateKey = ({ rawWallet }) => {
|
||||
const [password, setPassword] = useState('');
|
||||
const [privateKey, setPrivateKey] = useState('');
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { setOpenSnackGlobal, setInfoSnackCustom } = useContext(MyContext);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { setOpenSnackGlobal, setInfoSnackCustom } =
|
||||
useContext(QORTAL_APP_CONTEXT);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const exportPrivateKeyFunc = async () => {
|
||||
try {
|
||||
|
@ -14,9 +14,9 @@ import {
|
||||
CellMeasurerCache,
|
||||
List,
|
||||
} from 'react-virtualized';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT, getBaseApiReact } from '../../App';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
@ -55,13 +55,19 @@ export const UserListOfInvites = ({
|
||||
setInfoSnack,
|
||||
setOpenSnack,
|
||||
}) => {
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const setTxList = useSetAtom(txListAtom);
|
||||
|
||||
const [invites, setInvites] = useState<any[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [popoverAnchor, setPopoverAnchor] = useState(null); // Track which list item the popover is anchored to
|
||||
const [openPopoverIndex, setOpenPopoverIndex] = useState(null); // Track which list item has the popover open
|
||||
const listRef = useRef(null);
|
||||
|
@ -15,7 +15,13 @@ import { useAtom } from 'jotai';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const WalletsAppWrapper = () => {
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const iframeRef = useRef(null);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [navigationController, setNavigationController] = useAtom(
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import Logo2 from '../assets/svgs/Logo2.svg';
|
||||
import { MyContext, getArbitraryEndpointReact, getBaseApiReact } from '../App';
|
||||
import {
|
||||
QORTAL_APP_CONTEXT,
|
||||
getArbitraryEndpointReact,
|
||||
getBaseApiReact,
|
||||
} from '../App';
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
@ -12,7 +16,7 @@ import {
|
||||
} from '@mui/material';
|
||||
import { Spacer } from '../common/Spacer';
|
||||
import ImageUploader from '../common/ImageUploader';
|
||||
import { getFee } from '../background';
|
||||
import { getFee } from '../background/background.ts';
|
||||
import { fileToBase64 } from '../utils/fileReading';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import ErrorIcon from '@mui/icons-material/Error';
|
||||
@ -22,7 +26,7 @@ export const MainAvatar = ({ myName, balance, setOpenSnack, setInfoSnack }) => {
|
||||
const [hasAvatar, setHasAvatar] = useState(false);
|
||||
const [avatarFile, setAvatarFile] = useState(null);
|
||||
const [tempAvatar, setTempAvatar] = useState(null);
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@ -41,7 +45,13 @@ export const MainAvatar = ({ myName, balance, setOpenSnack, setInfoSnack }) => {
|
||||
const open = Boolean(anchorEl);
|
||||
const id = open ? 'avatar-img' : undefined;
|
||||
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const checkIfAvatarExists = async () => {
|
||||
try {
|
||||
@ -253,7 +263,13 @@ const PopoverComp = ({
|
||||
myName,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
|
@ -21,10 +21,10 @@ import {
|
||||
subscribeToEvent,
|
||||
unsubscribeFromEvent,
|
||||
} from '../../utils/events';
|
||||
import { getFee } from '../../background';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { FidgetSpinner } from 'react-loader-spinner';
|
||||
import { useModal } from '../../common/useModal';
|
||||
import { useModal } from '../../hooks/useModal.tsx';
|
||||
import { useAtom, useSetAtom } from 'jotai';
|
||||
import { memberGroupsAtom, txListAtom } from '../../atoms/global';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -45,7 +45,13 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
|
||||
const { show: showKey, message } = useModal();
|
||||
const { isShow: isShowNext, onOk, show: showNext } = useModal();
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [info, setInfo] = useState(null);
|
||||
const [names, setNames] = useState({});
|
||||
const [accountInfos, setAccountInfos] = useState({});
|
||||
|
@ -3,7 +3,13 @@ import { Spacer } from '../common/Spacer';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const NewUsersCTA = ({ balance }) => {
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
if (balance === undefined || +balance > 0) return null;
|
||||
|
||||
|
@ -27,12 +27,12 @@ import {
|
||||
import Logo1Dark from '../assets/svgs/Logo1Dark.svg';
|
||||
import HelpIcon from '@mui/icons-material/Help';
|
||||
import { CustomizedSnackbars } from './Snackbar/Snackbar';
|
||||
import { cleanUrl, gateways } from '../background';
|
||||
import { cleanUrl, gateways } from '../background/background.ts';
|
||||
import Tooltip, { TooltipProps, tooltipClasses } from '@mui/material/Tooltip';
|
||||
import ThemeSelector from './Theme/ThemeSelector';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import LanguageSelector from './Language/LanguageSelector';
|
||||
import { MyContext } from '../App';
|
||||
import { QORTAL_APP_CONTEXT } from '../App';
|
||||
|
||||
export const manifestData = {
|
||||
version: '0.5.4',
|
||||
@ -81,7 +81,8 @@ export const NotAuthenticated = ({
|
||||
const [showSelectApiKey, setShowSelectApiKey] = useState(false);
|
||||
const [enteredApiKey, setEnteredApiKey] = useState('');
|
||||
const [customNodeToSaveIndex, setCustomNodeToSaveIndex] = useState(null);
|
||||
const { showTutorial, hasSeenGettingStarted } = useContext(MyContext);
|
||||
const { showTutorial, hasSeenGettingStarted } =
|
||||
useContext(QORTAL_APP_CONTEXT);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core']);
|
||||
|
||||
|
@ -8,7 +8,13 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
export const QMailStatus = () => {
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const theme = useTheme();
|
||||
|
||||
const [lastEnteredTimestamp, setLastEnteredTimestamp] = useAtom(
|
||||
|
@ -2,12 +2,18 @@ import { Box, useTheme } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import { TextP } from '../styles/App-styles';
|
||||
import { Spacer } from '../common/Spacer';
|
||||
import { getFee } from '../background';
|
||||
import { getFee } from '../background/background.ts';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const QortPayment = ({ balance, show, onSuccess, defaultPaymentTo }) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [paymentTo, setPaymentTo] = useState<string>(defaultPaymentTo);
|
||||
const [paymentAmount, setPaymentAmount] = useState<number>(0);
|
||||
const [paymentPassword, setPaymentPassword] = useState<string>('');
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
import { Label } from './Group/AddGroup';
|
||||
import { Spacer } from '../common/Spacer';
|
||||
import { getBaseApiReact } from '../App';
|
||||
import { getFee } from '../background';
|
||||
import { getFee } from '../background/background.ts';
|
||||
import RadioButtonCheckedIcon from '@mui/icons-material/RadioButtonChecked';
|
||||
import { subscribeToEvent, unsubscribeFromEvent } from '../utils/events';
|
||||
import { BarSpinner } from '../common/Spinners/BarSpinner/BarSpinner';
|
||||
@ -51,7 +51,13 @@ export const RegisterName = ({
|
||||
);
|
||||
const [nameFee, setNameFee] = useState(null);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const checkIfNameExisits = async (name) => {
|
||||
if (!name?.trim()) {
|
||||
setIsNameAvailable(Availability.NULL);
|
||||
|
@ -18,20 +18,20 @@ import {
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { objectToBase64 } from '../../qdn/encryption/group-encryption';
|
||||
import { MyContext } from '../../App';
|
||||
import { getFee } from '../../background';
|
||||
import { QORTAL_APP_CONTEXT } from '../../App';
|
||||
import { getFee } from '../../background/background.ts';
|
||||
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
||||
import { SaveIcon } from '../../assets/Icons/SaveIcon';
|
||||
import { IconWrapper } from '../Desktop/DesktopFooter';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { saveToLocalStorage } from '../Apps/AppsNavBarDesktop';
|
||||
import { decryptData, encryptData } from '../../qortalRequests/get';
|
||||
import { decryptData, encryptData } from '../../qortal/get.ts';
|
||||
import { saveFileToDiskGeneric } from '../../utils/generateWallet/generateWallet';
|
||||
import {
|
||||
base64ToUint8Array,
|
||||
uint8ArrayToObject,
|
||||
} from '../../backgroundFunctions/encryption';
|
||||
} from '../../encryption/encryption.ts';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAtom, useSetAtom } from 'jotai';
|
||||
|
||||
@ -82,9 +82,15 @@ export const Save = ({ isDesktop, disableWidth, myName }) => {
|
||||
const [oldPinnedApps, setOldPinnedApps] = useAtom(oldPinnedAppsAtom);
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(QORTAL_APP_CONTEXT);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const hasChanged = useMemo(() => {
|
||||
const newChanges = {
|
||||
|
@ -82,7 +82,13 @@ export default function ThemeManager() {
|
||||
});
|
||||
const [currentTab, setCurrentTab] = useState('light');
|
||||
const nameInputRef = useRef(null);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (openEditor && nameInputRef.current) {
|
||||
|
@ -5,7 +5,13 @@ import DarkModeIcon from '@mui/icons-material/DarkMode';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const ThemeSelector = () => {
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const { themeMode, toggleTheme } = useThemeContext();
|
||||
|
||||
return (
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useContext, useState } from 'react';
|
||||
import { MyContext } from '../../App';
|
||||
import { QORTAL_APP_CONTEXT } from '../../App';
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
@ -16,7 +16,8 @@ import { VideoPlayer } from '../Embeds/VideoPlayer';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const Tutorials = () => {
|
||||
const { openTutorialModal, setOpenTutorialModal } = useContext(MyContext);
|
||||
const { openTutorialModal, setOpenTutorialModal } =
|
||||
useContext(QORTAL_APP_CONTEXT);
|
||||
const [multiNumber, setMultiNumber] = useState(0);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['core', 'tutorial']);
|
||||
|
@ -19,7 +19,10 @@ import {
|
||||
useTheme,
|
||||
Autocomplete,
|
||||
} from '@mui/material';
|
||||
import { getAddressInfo, getNameOrAddress } from '../../background';
|
||||
import {
|
||||
getAddressInfo,
|
||||
getNameOrAddress,
|
||||
} from '../../background/background.ts';
|
||||
import { getBaseApiReact } from '../../App';
|
||||
import { getNameInfo } from '../Group/Group';
|
||||
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
||||
@ -46,7 +49,13 @@ function formatAddress(str) {
|
||||
|
||||
export const UserLookup = ({ isOpenDrawerLookup, setIsOpenDrawerLookup }) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [nameOrAddress, setNameOrAddress] = useState('');
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const { results, isLoading } = useNameSearch(inputValue);
|
||||
|
@ -18,20 +18,24 @@ import {
|
||||
Input,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { CustomButton } from './styles/App-styles';
|
||||
import { CustomButton } from '../styles/App-styles.ts';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import { Label } from './components/Group/AddGroup';
|
||||
import { Spacer } from './common/Spacer';
|
||||
import { getWallets, storeWallets, walletVersion } from './background';
|
||||
import { useModal } from './common/useModal';
|
||||
import PhraseWallet from './utils/generateWallet/phrase-wallet';
|
||||
import { decryptStoredWalletFromSeedPhrase } from './utils/decryptWallet';
|
||||
import { crypto } from './constants/decryptWallet';
|
||||
import { Label } from './Group/AddGroup.tsx';
|
||||
import { Spacer } from '../common/Spacer.tsx';
|
||||
import {
|
||||
getWallets,
|
||||
storeWallets,
|
||||
walletVersion,
|
||||
} from '../background/background.ts';
|
||||
import { useModal } from '../hooks/useModal.tsx';
|
||||
import PhraseWallet from '../utils/generateWallet/phrase-wallet.ts';
|
||||
import { decryptStoredWalletFromSeedPhrase } from '../utils/decryptWallet.ts';
|
||||
import { crypto } from '../constants/decryptWallet.ts';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { PasswordField } from './components';
|
||||
import { HtmlTooltip } from './components/NotAuthenticated';
|
||||
import { MyContext } from './App';
|
||||
import { PasswordField } from './index.ts';
|
||||
import { HtmlTooltip } from './NotAuthenticated.tsx';
|
||||
import { QORTAL_APP_CONTEXT } from '../App.tsx';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const parsefilenameQortal = (filename) => {
|
||||
@ -44,12 +48,18 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => {
|
||||
const [seedValue, setSeedValue] = useState('');
|
||||
const [seedName, setSeedName] = useState('');
|
||||
const [seedError, setSeedError] = useState('');
|
||||
const { hasSeenGettingStarted } = useContext(MyContext);
|
||||
const { hasSeenGettingStarted } = useContext(QORTAL_APP_CONTEXT);
|
||||
const [password, setPassword] = useState('');
|
||||
const [isOpenSeedModal, setIsOpenSeedModal] = useState(false);
|
||||
const [isLoadingEncryptSeed, setIsLoadingEncryptSeed] = useState(false);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const { isShow, onCancel, onOk, show } = useModal();
|
||||
|
||||
const { getRootProps, getInputProps } = useDropzone({
|
||||
@ -65,7 +75,7 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => {
|
||||
const fileContents = await new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onabort = () => reject('File reading was aborted');
|
||||
reader.onabort = () => reject('File reading was aborted'); // TODO translate
|
||||
reader.onerror = () => reject('File reading has failed');
|
||||
reader.onload = () => {
|
||||
// Resolve the promise with the reader result when reading completes
|
||||
@ -457,7 +467,13 @@ const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => {
|
||||
const [note, setNote] = useState('');
|
||||
const [isEdit, setIsEdit] = useState(false);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (wallet?.name) {
|
@ -7,14 +7,20 @@ import {
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { executeEvent } from '../utils/events';
|
||||
import { MyContext } from '../App';
|
||||
import { QORTAL_APP_CONTEXT } from '../App';
|
||||
import { useAtom } from 'jotai';
|
||||
import { isRunningPublicNodeAtom } from '../atoms/global';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const WrapperUserAction = ({ children, address, name, disabled }) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
const [isRunningPublicNode] = useAtom(isRunningPublicNodeAtom);
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
@ -175,9 +181,15 @@ const BlockUser = ({ address, name, handleClose }) => {
|
||||
const [isAlreadyBlocked, setIsAlreadyBlocked] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { isUserBlocked, addToBlockList, removeBlockFromList } =
|
||||
useContext(MyContext);
|
||||
useContext(QORTAL_APP_CONTEXT);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!address) return;
|
||||
|
@ -1,864 +0,0 @@
|
||||
// @ts-nocheck
|
||||
;
|
||||
import Base58 from '../deps/Base58.js'
|
||||
import {Sha256, Sha512} from 'asmcrypto.js'
|
||||
import jsSHA from 'jssha'
|
||||
import RIPEMD160 from '../deps/ripemd160.js'
|
||||
import utils from '../utils/utils'
|
||||
import {BigInteger, EllipticCurve} from './ecbn'
|
||||
import {Buffer} from 'buffer'
|
||||
|
||||
export default class AltcoinHDWallet {
|
||||
|
||||
constructor(addressParams) {
|
||||
|
||||
/**
|
||||
* Seed - 32 bytes
|
||||
*/
|
||||
|
||||
this.seed = new Uint8Array(32)
|
||||
|
||||
/**
|
||||
* Version Bytes - 4 byte
|
||||
*/
|
||||
|
||||
this.versionBytes = addressParams
|
||||
|
||||
/**
|
||||
* Depth - 1 byte
|
||||
*/
|
||||
|
||||
this.depth = 0
|
||||
|
||||
/**
|
||||
* Parent Fingerprint - 4 bytes
|
||||
*/
|
||||
|
||||
this.parentFingerprint = '0x00000000' // master key
|
||||
|
||||
/**
|
||||
* Child Index - 4 bytes
|
||||
*/
|
||||
|
||||
this.childIndex = '0x00000000' // master key
|
||||
|
||||
/**
|
||||
* Chain Code - 32 bytes
|
||||
*/
|
||||
|
||||
this.chainCode = new Uint8Array(32)
|
||||
|
||||
/**
|
||||
* Key Data - 33 bytes
|
||||
*/
|
||||
|
||||
this.keyData = new Uint8Array(33)
|
||||
|
||||
/**
|
||||
* Seed Hash - 64 bytes
|
||||
*/
|
||||
|
||||
this.seedHash = new Uint8Array(64)
|
||||
|
||||
/**
|
||||
* Private Key - 32 bytes
|
||||
*/
|
||||
|
||||
this.privateKey = new Uint8Array(32)
|
||||
|
||||
/**
|
||||
* Public Key - 33 bytes (compressed)
|
||||
*/
|
||||
|
||||
this.publicKey = new Uint8Array(33)
|
||||
|
||||
/**
|
||||
* Public Key Hash160 (used to derive the parent fingerprint for derived)
|
||||
*/
|
||||
|
||||
this.publicKeyHash = new Uint8Array(20)
|
||||
|
||||
/**
|
||||
* Master Private Key (Base58 encoded)
|
||||
*/
|
||||
|
||||
this.masterPrivateKey = ''
|
||||
|
||||
/**
|
||||
* Master Public Key (Base58 encoded)
|
||||
*/
|
||||
|
||||
this.masterPublicKey = ''
|
||||
|
||||
/**
|
||||
* Testnet Master Private Key (Base58 encoded) - THIS IS TESTNET
|
||||
*/
|
||||
|
||||
this._tMasterPrivateKey = ''
|
||||
|
||||
/**
|
||||
* Testnet Master Public Key (Base58 encoded) - THIS IS TESTNET
|
||||
*/
|
||||
|
||||
this._tmasterPublicKey = ''
|
||||
|
||||
/**
|
||||
* Child Keys Derivation from the Parent Keys
|
||||
*/
|
||||
|
||||
/**
|
||||
* Child Private Key - 32 bytes
|
||||
*/
|
||||
|
||||
this.childPrivateKey = new Uint8Array(32)
|
||||
|
||||
/**
|
||||
* Child Chain Code - 32 bytes
|
||||
*/
|
||||
|
||||
this.childChainCode = new Uint8Array(32)
|
||||
|
||||
/**
|
||||
* Child Public Key - 33 bytes (compressed)
|
||||
*/
|
||||
|
||||
this.childPublicKey = new Uint8Array(33)
|
||||
|
||||
/**
|
||||
* Child Public Key Hash160 (used to derive the parent fingerprint for derived)
|
||||
*/
|
||||
|
||||
this.childPublicKeyHash = new Uint8Array(20)
|
||||
|
||||
/**
|
||||
* Extended Private Child Key - Base58 encoded
|
||||
*/
|
||||
|
||||
this.xPrivateChildKey = ''
|
||||
|
||||
/**
|
||||
* Extended Public Child Key - Base58 encoded
|
||||
*/
|
||||
|
||||
this.xPublicChildKey = ''
|
||||
|
||||
/**
|
||||
* Grand Child Keys Derivation from the Child Keys
|
||||
*/
|
||||
|
||||
/**
|
||||
* Grand Child Private Key - 32 bytes
|
||||
*/
|
||||
|
||||
this.grandChildPrivateKey = new Uint8Array(32)
|
||||
|
||||
/**
|
||||
* Grand Child Chain Code - 32 bytes
|
||||
*/
|
||||
|
||||
this.grandChildChainCode = new Uint8Array(32)
|
||||
|
||||
/**
|
||||
* Grand Child Public Key - 33 bytes (compressed)
|
||||
*/
|
||||
|
||||
this.grandChildPublicKey = new Uint8Array(33)
|
||||
|
||||
/**
|
||||
* Grand Public Key Hash160 (used to derive the parent fingerprint for derived)
|
||||
*/
|
||||
|
||||
this.grandChildPublicKeyHash = new Uint8Array(20)
|
||||
|
||||
/**
|
||||
* Extended Private Grand Child Key - Base58 encoded
|
||||
*/
|
||||
|
||||
this.xPrivateGrandChildKey = ''
|
||||
|
||||
/**
|
||||
* Extended Public Grand Child Key - Base58 encoded
|
||||
*/
|
||||
|
||||
this.xPublicGrandChildKey = ''
|
||||
|
||||
/**
|
||||
* Litecoin Legacy Address - Derived from the Grand Child Public Key Hash
|
||||
*/
|
||||
|
||||
this.litecoinLegacyAddress = ''
|
||||
|
||||
/**
|
||||
* TESTNET Litecoin Legacy Address (Derived from the Grand Child Public Key Hash) - THIS IS TESTNET
|
||||
*/
|
||||
|
||||
this._tlitecoinLegacyAddress = ''
|
||||
|
||||
/**
|
||||
* Wallet - Wallet Object (keys...)
|
||||
*/
|
||||
|
||||
this.wallet = {}
|
||||
}
|
||||
|
||||
setSeed(seed) {
|
||||
this.seed = seed
|
||||
}
|
||||
|
||||
createWallet(seed, isBIP44, indicator = null) {
|
||||
|
||||
// Set Seeed
|
||||
this.setSeed(seed)
|
||||
|
||||
// Generate Seed Hash
|
||||
this.generateSeedHash(this.seed, isBIP44, indicator)
|
||||
|
||||
// Generate Private Key
|
||||
this.generatePrivateKey(this.seedHash)
|
||||
|
||||
// Generate Chain Code
|
||||
this.generateChainCode(this.seedHash)
|
||||
|
||||
// Generate Public Key from Private Key
|
||||
this.generatePublicKey(this.privateKey)
|
||||
|
||||
// Generate Mainnet Master Private Key
|
||||
this.generateMainnetMasterPrivateKey()
|
||||
|
||||
// Generate Mainnet Master Public Key
|
||||
this.generateMainnetMasterPublicKey()
|
||||
|
||||
// Generate Testnet Master Private Key
|
||||
this.generateTestnetMasterPrivateKey()
|
||||
|
||||
// Generate Testnet Master Public Key
|
||||
this.generateTestnetMasterPublicKey()
|
||||
|
||||
// Generate Child and Grand Child Keys
|
||||
this.generateDerivedChildKeys()
|
||||
|
||||
// Return Wallet Object Specification
|
||||
return this.returnWallet()
|
||||
}
|
||||
|
||||
|
||||
generateSeedHash(seed, isBIP44, indicator = null) {
|
||||
let buffer
|
||||
|
||||
if (isBIP44) {
|
||||
buffer = utils.appendBuffer(seed.reverse(), utils.int32ToBytes(indicator))
|
||||
} else {
|
||||
if(indicator !== null) {
|
||||
const indicatorString = utils.stringtoUTF8Array(indicator)
|
||||
buffer = utils.appendBuffer(seed.reverse(), indicatorString)
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = seed.reverse()
|
||||
}
|
||||
}
|
||||
|
||||
const _reverseSeedHash = new Sha256().process(buffer).finish().result
|
||||
this.seedHash = new Sha512().process(utils.appendBuffer(seed, _reverseSeedHash)).finish().result
|
||||
}
|
||||
|
||||
generatePrivateKey(seedHash) {
|
||||
const SECP256K1_CURVE_ORDER = new BigInteger("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141")
|
||||
|
||||
const privateKeyHash = seedHash.slice(0, 32)
|
||||
|
||||
this.seed58 = Base58.encode(privateKeyHash)
|
||||
|
||||
const _privateKeyHash = [...privateKeyHash]
|
||||
let privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKeyHash)
|
||||
|
||||
const privateKey = (privateKeyBigInt.mod(SECP256K1_CURVE_ORDER.subtract(BigInteger.ONE))).add(BigInteger.ONE)
|
||||
this.privateKey = privateKey.toByteArrayUnsigned()
|
||||
}
|
||||
|
||||
generateChainCode(seedHash) {
|
||||
this.chainCode = new Sha256().process(seedHash.slice(32, 64)).finish().result
|
||||
}
|
||||
|
||||
generatePublicKey(privateKey) {
|
||||
const _privateKey = [...privateKey]
|
||||
const privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKey)
|
||||
|
||||
const epCurve = EllipticCurve.getSECCurveByName("secp256k1")
|
||||
const curvePoints = epCurve.getG().multiply(privateKeyBigInt)
|
||||
|
||||
|
||||
const x = curvePoints.getX().toBigInteger()
|
||||
const y = curvePoints.getY().toBigInteger()
|
||||
|
||||
/**
|
||||
* Deriving Uncompressed Public Key (65 bytes)
|
||||
*
|
||||
* const publicKeyBytes = EllipticCurve.integerToBytes(x, 32)
|
||||
* this.publicKey = publicKeyBytes.concat(EllipticCurve.integerToBytes(y, 32))
|
||||
* this.publicKey.unshift(0x04) // append point indicator
|
||||
*/
|
||||
|
||||
// Compressed Public Key (33 bytes)
|
||||
this.publicKey = EllipticCurve.integerToBytes(x, 32)
|
||||
|
||||
|
||||
if (y.isEven()) {
|
||||
this.publicKey.unshift(0x02) // append point indicator
|
||||
} else {
|
||||
this.publicKey.unshift(0x03) // append point indicator
|
||||
}
|
||||
|
||||
// PublicKey Hash
|
||||
const publicKeySHA256 = new Sha256().process(new Uint8Array(this.publicKey)).finish().result
|
||||
const _publicKeyHash = new RIPEMD160().update(Buffer.from(publicKeySHA256)).digest('hex')
|
||||
this.publicKeyHash = _publicKeyHash
|
||||
}
|
||||
|
||||
generateMainnetMasterPrivateKey() {
|
||||
// Serialization Variable
|
||||
const s = []
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.private)))
|
||||
|
||||
// Append Depth
|
||||
s.push(this.depth)
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...(utils.int32ToBytes(this.parentFingerprint)))
|
||||
|
||||
// Append Child Number
|
||||
s.push(...(utils.int32ToBytes(this.childIndex)))
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.chainCode)
|
||||
|
||||
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
|
||||
s.push(0)
|
||||
|
||||
//if the private key length is less than 32 let's add leading zeros
|
||||
if(this.privateKey.length<32){
|
||||
for(let i=this.privateKey.length;i<32;i++){
|
||||
s.push(0)
|
||||
}
|
||||
}
|
||||
|
||||
// Append Private Key
|
||||
s.push(...this.privateKey)
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s)
|
||||
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
|
||||
const checkSum = _checkSum.slice(0, 4)
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum) // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Private Key as Base58 encoded
|
||||
this.masterPrivateKey = Base58.encode(s)
|
||||
}
|
||||
|
||||
generateMainnetMasterPublicKey() {
|
||||
// Serialization Variable
|
||||
const s = []
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.public)))
|
||||
|
||||
// Append Depth
|
||||
s.push(this.depth)
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...(utils.int32ToBytes(this.parentFingerprint)))
|
||||
|
||||
// Append Child Number
|
||||
s.push(...(utils.int32ToBytes(this.childIndex)))
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.chainCode)
|
||||
|
||||
// Append Public Key
|
||||
s.push(...this.publicKey)
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s)
|
||||
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
|
||||
const checkSum = _checkSum.slice(0, 4)
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum) // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Public Key as Base58 encoded
|
||||
this.masterPublicKey = Base58.encode(s)
|
||||
}
|
||||
|
||||
generateTestnetMasterPrivateKey() {
|
||||
|
||||
// To be Used ONLY in Testnet...
|
||||
|
||||
// Serialization Variable
|
||||
const s = []
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...(utils.int32ToBytes(this.versionBytes.testnet.private)))
|
||||
|
||||
// Append Depth
|
||||
s.push(this.depth)
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...(utils.int32ToBytes(this.parentFingerprint)))
|
||||
|
||||
// Append Child Number
|
||||
s.push(...(utils.int32ToBytes(this.childIndex)))
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.chainCode)
|
||||
|
||||
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
|
||||
s.push(0)
|
||||
|
||||
// Append Private Key
|
||||
s.push(...this.privateKey)
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s)
|
||||
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
|
||||
const checkSum = _checkSum.slice(0, 4)
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum) // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Private Key as Base58 encoded
|
||||
this._tMasterPrivateKey = Base58.encode(s)
|
||||
}
|
||||
|
||||
generateTestnetMasterPublicKey() {
|
||||
|
||||
// To be Used ONLY in Testnet...
|
||||
|
||||
// Serialization Variable
|
||||
const s = []
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...(utils.int32ToBytes(this.versionBytes.testnet.public)))
|
||||
|
||||
// Append Depth
|
||||
s.push(this.depth)
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...(utils.int32ToBytes(this.parentFingerprint)))
|
||||
|
||||
// Append Child Number
|
||||
s.push(...(utils.int32ToBytes(this.childIndex)))
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.chainCode)
|
||||
|
||||
// Append Private Key
|
||||
s.push(...this.publicKey)
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s)
|
||||
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
|
||||
const checkSum = _checkSum.slice(0, 4)
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum) // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Private Key as Base58 encoded
|
||||
this._tmasterPublicKey = Base58.encode(s)
|
||||
}
|
||||
|
||||
generateDerivedChildKeys() {
|
||||
|
||||
// SPEC INFO: https://en.bitcoin.it/wiki/BIP_0032#Child_key_derivation_.28CKD.29_functions
|
||||
// NOTE: will not be using some of derivations func as the value is known. (So I'd rather shove in the values and rewrite out the derivations later ?)
|
||||
|
||||
// NOTE: I "re-wrote" and "reduplicate" the code for child and grandChild keys derivations inorder to get the child and grandchild from the child
|
||||
// TODO: Make this more better in the future
|
||||
|
||||
const path = 'm/0/0'
|
||||
// let p = path.split('/')
|
||||
|
||||
// Get Public kEY
|
||||
const derivePublicChildKey = () => {
|
||||
|
||||
const _privateKey = [...this.childPrivateKey]
|
||||
const privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKey)
|
||||
|
||||
const epCurve = EllipticCurve.getSECCurveByName("secp256k1")
|
||||
const curvePoints = epCurve.getG().multiply(privateKeyBigInt)
|
||||
|
||||
const x = curvePoints.getX().toBigInteger()
|
||||
const y = curvePoints.getY().toBigInteger()
|
||||
|
||||
// Compressed Public Key (33 bytes)
|
||||
this.childPublicKey = EllipticCurve.integerToBytes(x, 32)
|
||||
|
||||
|
||||
if (y.isEven()) {
|
||||
|
||||
this.childPublicKey.unshift(0x02) // append point indicator
|
||||
} else {
|
||||
|
||||
this.childPublicKey.unshift(0x03) // append point indicator
|
||||
}
|
||||
|
||||
// PublicKey Hash
|
||||
const childPublicKeySHA256 = new Sha256().process(new Uint8Array(this.childPublicKey)).finish().result
|
||||
const _childPublicKeyHash = new RIPEMD160().update(Buffer.from(childPublicKeySHA256)).digest('hex')
|
||||
this.childPublicKeyHash = _childPublicKeyHash
|
||||
|
||||
|
||||
// Call deriveExtendedPublicChildKey // WIll be hardcoding the values...
|
||||
deriveExtendedPublicChildKey(1, 0)
|
||||
}
|
||||
|
||||
const derivePrivateChildKey = (cI) => {
|
||||
|
||||
let ib = []
|
||||
ib.push((cI >> 24) & 0xff)
|
||||
ib.push((cI >> 16) & 0xff)
|
||||
ib.push((cI >> 8) & 0xff)
|
||||
ib.push(cI & 0xff)
|
||||
|
||||
const s = [...this.publicKey].concat(ib)
|
||||
|
||||
const _hmacSha512 = new jsSHA("SHA-512", "UINT8ARRAY", { numRounds: 1, hmacKey: { value: this.chainCode, format: "UINT8ARRAY" } })
|
||||
_hmacSha512.update(new Uint8Array(s))
|
||||
|
||||
|
||||
const IL = BigInteger.fromByteArrayUnsigned([..._hmacSha512.getHMAC('UINT8ARRAY').slice(0, 32)])
|
||||
this.childChainCode = _hmacSha512.getHMAC('UINT8ARRAY').slice(32, 64) // IR according to the SPEC
|
||||
|
||||
|
||||
// SECP256k1 init
|
||||
const epCurve = EllipticCurve.getSECCurveByName("secp256k1")
|
||||
|
||||
|
||||
const ki = IL.add(BigInteger.fromByteArrayUnsigned(this.privateKey)).mod(epCurve.getN()) // parse256(IL) + kpar (mod n) ==> ki
|
||||
this.childPrivateKey = ki.toByteArrayUnsigned()
|
||||
|
||||
// Call deriveExtendedPrivateChildKey
|
||||
deriveExtendedPrivateChildKey(1, 0)
|
||||
}
|
||||
|
||||
|
||||
const deriveExtendedPrivateChildKey = (i, childIndex) => {
|
||||
|
||||
// Serialization Variable
|
||||
const s = []
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.private)))
|
||||
|
||||
// Append Depth (using the index as depth)
|
||||
i = parseInt(i)
|
||||
s.push(i)
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...(this.publicKeyHash.slice(0, 4)))
|
||||
|
||||
// Append Child Index
|
||||
s.push(childIndex >>> 24)
|
||||
s.push((childIndex >>> 16) & 0xff)
|
||||
s.push((childIndex >>> 8) & 0xff)
|
||||
s.push(childIndex & 0xff)
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.childChainCode)
|
||||
|
||||
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
|
||||
s.push(0)
|
||||
|
||||
// Append Private Key
|
||||
s.push(...this.childPrivateKey)
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s)
|
||||
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
|
||||
const checkSum = _checkSum.slice(0, 4)
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum) // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Private Key as Base58 encoded
|
||||
this.xPrivateChildKey = Base58.encode(s)
|
||||
}
|
||||
|
||||
const deriveExtendedPublicChildKey = (i, childIndex) => {
|
||||
|
||||
// Serialization Variable
|
||||
const s = []
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.public)))
|
||||
|
||||
// Append Depth
|
||||
i = parseInt(i)
|
||||
s.push(i)
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...(this.publicKeyHash.slice(0, 4)))
|
||||
|
||||
// Append Child Index
|
||||
s.push(childIndex >>> 24)
|
||||
s.push((childIndex >>> 16) & 0xff)
|
||||
s.push((childIndex >>> 8) & 0xff)
|
||||
s.push(childIndex & 0xff)
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.childChainCode)
|
||||
|
||||
// Append Public Key
|
||||
s.push(...this.childPublicKey)
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s)
|
||||
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
|
||||
const checkSum = _checkSum.slice(0, 4)
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum) // And this brings us to the end of the serialization...
|
||||
|
||||
|
||||
// Save to Public Key as Base58 encoded
|
||||
this.xPublicChildKey = Base58.encode(s)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* GRAND CHILD KEYS
|
||||
*
|
||||
* NOTE: I know this is not the best way to generate this (even though it works the way it ought)
|
||||
* Things to rewrite will be and not limited to deriving this through a for loop, removing hard code values, etc...
|
||||
*/
|
||||
|
||||
const derivePublicGrandChildKey = () => {
|
||||
|
||||
const _privateKey = [...this.grandChildPrivateKey]
|
||||
const privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKey)
|
||||
|
||||
|
||||
const epCurve = EllipticCurve.getSECCurveByName("secp256k1")
|
||||
const curvePoints = epCurve.getG().multiply(privateKeyBigInt)
|
||||
|
||||
const x = curvePoints.getX().toBigInteger()
|
||||
const y = curvePoints.getY().toBigInteger()
|
||||
|
||||
// Compressed Public Key (33 bytes)
|
||||
this.grandChildPublicKey = EllipticCurve.integerToBytes(x, 32)
|
||||
|
||||
|
||||
if (y.isEven()) {
|
||||
this.grandChildPublicKey.unshift(0x02) // append point indicator
|
||||
} else {
|
||||
this.grandChildPublicKey.unshift(0x03) // append point indicator
|
||||
}
|
||||
|
||||
|
||||
// PublicKey Hash
|
||||
const grandChildPublicKeySHA256 = new Sha256().process(new Uint8Array(this.grandChildPublicKey)).finish().result
|
||||
const _grandChildPublicKeyHash = new RIPEMD160().update(Buffer.from(grandChildPublicKeySHA256)).digest('hex')
|
||||
this.grandChildPublicKeyHash = _grandChildPublicKeyHash
|
||||
|
||||
|
||||
// Call deriveExtendedPublicChildKey // WIll be hardcoding the values...
|
||||
deriveExtendedPublicGrandChildKey(2, 0)
|
||||
|
||||
/**
|
||||
* Derive Litecoin Legacy Address
|
||||
*/
|
||||
|
||||
// Append Address Prefix
|
||||
let prefix = [this.versionBytes.mainnet.prefix]
|
||||
if (2 == this.versionBytes.mainnet.prefix.length) {
|
||||
prefix = [this.versionBytes.mainnet.prefix[0]]
|
||||
prefix.push([this.versionBytes.mainnet.prefix[1]])
|
||||
}
|
||||
|
||||
const k = prefix.concat(...this.grandChildPublicKeyHash)
|
||||
|
||||
// Derive Checksum
|
||||
const _addressCheckSum = new Sha256().process(new Sha256().process(new Uint8Array(k)).finish().result).finish().result
|
||||
const addressCheckSum = _addressCheckSum.slice(0, 4)
|
||||
|
||||
// Append CheckSum
|
||||
const _litecoinLegacyAddress = k.concat(...addressCheckSum)
|
||||
|
||||
// Convert to Base58
|
||||
this.litecoinLegacyAddress = Base58.encode(_litecoinLegacyAddress)
|
||||
|
||||
|
||||
/**
|
||||
* Derive TESTNET Litecoin Legacy Address
|
||||
*/
|
||||
|
||||
// Append Version Byte
|
||||
const tK = [this.versionBytes.testnet.prefix].concat(...this.grandChildPublicKeyHash)
|
||||
|
||||
// Derive Checksum
|
||||
const _tAddressCheckSum = new Sha256().process(new Sha256().process(new Uint8Array(tK)).finish().result).finish().result
|
||||
const tAddressCheckSum = _tAddressCheckSum.slice(0, 4)
|
||||
|
||||
// Append CheckSum
|
||||
const _tlitecoinLegacyAddress = tK.concat(...tAddressCheckSum)
|
||||
|
||||
// Convert to Base58
|
||||
this._tlitecoinLegacyAddress = Base58.encode(_tlitecoinLegacyAddress)
|
||||
}
|
||||
|
||||
const derivePrivateGrandChildKey = (cI, i) => {
|
||||
|
||||
let ib = []
|
||||
ib.push((cI >> 24) & 0xff)
|
||||
ib.push((cI >> 16) & 0xff)
|
||||
ib.push((cI >> 8) & 0xff)
|
||||
ib.push(cI & 0xff)
|
||||
|
||||
const s = [...this.childPublicKey].concat(ib)
|
||||
|
||||
|
||||
const _hmacSha512 = new jsSHA("SHA-512", "UINT8ARRAY", { numRounds: 1, hmacKey: { value: this.childChainCode, format: "UINT8ARRAY" } })
|
||||
_hmacSha512.update(new Uint8Array(s))
|
||||
|
||||
|
||||
const IL = BigInteger.fromByteArrayUnsigned([..._hmacSha512.getHMAC('UINT8ARRAY').slice(0, 32)])
|
||||
this.grandChildChainCode = _hmacSha512.getHMAC('UINT8ARRAY').slice(32, 64) // IR according to the SPEC
|
||||
|
||||
// SECP256k1 init
|
||||
const epCurve = EllipticCurve.getSECCurveByName("secp256k1")
|
||||
|
||||
|
||||
const ki = IL.add(BigInteger.fromByteArrayUnsigned(this.childPrivateKey)).mod(epCurve.getN()) // parse256(IL) + kpar (mod n) ==> ki
|
||||
this.grandChildPrivateKey = ki.toByteArrayUnsigned()
|
||||
|
||||
|
||||
// Call deriveExtendedPrivateChildKey
|
||||
deriveExtendedPrivateGrandChildKey(2, 0)
|
||||
}
|
||||
|
||||
|
||||
const deriveExtendedPrivateGrandChildKey = (i, childIndex) => {
|
||||
|
||||
// Serialization Variable
|
||||
const s = []
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.private)))
|
||||
|
||||
// Append Depth (using the index as depth)
|
||||
i = parseInt(i)
|
||||
s.push(i)
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...(this.childPublicKeyHash.slice(0, 4)))
|
||||
|
||||
// Append Child Index
|
||||
s.push(childIndex >>> 24)
|
||||
s.push((childIndex >>> 16) & 0xff)
|
||||
s.push((childIndex >>> 8) & 0xff)
|
||||
s.push(childIndex & 0xff)
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.grandChildChainCode)
|
||||
|
||||
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
|
||||
s.push(0)
|
||||
|
||||
// Append Private Key
|
||||
s.push(...this.grandChildPrivateKey)
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s)
|
||||
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
|
||||
const checkSum = _checkSum.slice(0, 4)
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum) // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Private Key as Base58 encoded
|
||||
this.xPrivateGrandChildKey = Base58.encode(s)
|
||||
}
|
||||
|
||||
const deriveExtendedPublicGrandChildKey = (i, childIndex) => {
|
||||
|
||||
// Serialization Variable
|
||||
const s = []
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.public)))
|
||||
|
||||
// Append Depth
|
||||
i = parseInt(i)
|
||||
s.push(i)
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...(this.childPublicKeyHash.slice(0, 4)))
|
||||
|
||||
// Append Child Index
|
||||
s.push(childIndex >>> 24)
|
||||
s.push((childIndex >>> 16) & 0xff)
|
||||
s.push((childIndex >>> 8) & 0xff)
|
||||
s.push(childIndex & 0xff)
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.grandChildChainCode)
|
||||
|
||||
// Append Public Key
|
||||
s.push(...this.grandChildPublicKey)
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s)
|
||||
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
|
||||
const checkSum = _checkSum.slice(0, 4)
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum) // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Public Key as Base58 encoded
|
||||
this.xPublicGrandChildKey = Base58.encode(s)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Hard Code value..
|
||||
let childIndex = 0
|
||||
|
||||
// Call derivePrivateChildKey //Hard code value
|
||||
derivePrivateChildKey(childIndex)
|
||||
|
||||
// Call derivePublicChildKey
|
||||
derivePublicChildKey()
|
||||
|
||||
|
||||
// Call derivePrivateGrandChildKey // Hard Code value...
|
||||
derivePrivateGrandChildKey(0, 2)
|
||||
|
||||
// Call derivePublicGrandChildKey
|
||||
derivePublicGrandChildKey()
|
||||
}
|
||||
|
||||
returnWallet() {
|
||||
|
||||
// Will be limiting the exported Wallet Object to just the Master keys and Legacy Addresses
|
||||
|
||||
const wallet = {
|
||||
derivedMasterPrivateKey: this.masterPrivateKey,
|
||||
derivedMasterPublicKey: this.masterPublicKey,
|
||||
_tDerivedMasterPrivateKey: this._tMasterPrivateKey,
|
||||
_tDerivedmasterPublicKey: this._tmasterPublicKey,
|
||||
seed58: this.seed58,
|
||||
// derivedPrivateChildKey: this.xPrivateChildKey,
|
||||
// derivedPublicChildKey: this.xPublicChildKey,
|
||||
// derivedPrivateGrandChildKey: this.xPrivateGrandChildKey,
|
||||
// derivedPublicGrandChildKey: this.xPublicGrandChildKey,
|
||||
address: this.litecoinLegacyAddress,
|
||||
_taddress: this._tlitecoinLegacyAddress
|
||||
}
|
||||
|
||||
this.wallet = wallet
|
||||
return wallet
|
||||
}
|
||||
}
|
881
src/encryption/AltcoinHDWallet.ts
Normal file
881
src/encryption/AltcoinHDWallet.ts
Normal file
@ -0,0 +1,881 @@
|
||||
// @ts-nocheck
|
||||
import Base58 from './Base58.js';
|
||||
import { Sha256, Sha512 } from 'asmcrypto.js';
|
||||
import jsSHA from 'jssha';
|
||||
import RIPEMD160 from './ripemd160.js';
|
||||
import utils from '../utils/utils.js';
|
||||
import { BigInteger, EllipticCurve } from './ecbn';
|
||||
import { Buffer } from 'buffer';
|
||||
|
||||
export default class AltcoinHDWallet {
|
||||
constructor(addressParams) {
|
||||
/**
|
||||
* Seed - 32 bytes
|
||||
*/
|
||||
|
||||
this.seed = new Uint8Array(32);
|
||||
|
||||
/**
|
||||
* Version Bytes - 4 byte
|
||||
*/
|
||||
|
||||
this.versionBytes = addressParams;
|
||||
|
||||
/**
|
||||
* Depth - 1 byte
|
||||
*/
|
||||
|
||||
this.depth = 0;
|
||||
|
||||
/**
|
||||
* Parent Fingerprint - 4 bytes
|
||||
*/
|
||||
|
||||
this.parentFingerprint = '0x00000000'; // master key
|
||||
|
||||
/**
|
||||
* Child Index - 4 bytes
|
||||
*/
|
||||
|
||||
this.childIndex = '0x00000000'; // master key
|
||||
|
||||
/**
|
||||
* Chain Code - 32 bytes
|
||||
*/
|
||||
|
||||
this.chainCode = new Uint8Array(32);
|
||||
|
||||
/**
|
||||
* Key Data - 33 bytes
|
||||
*/
|
||||
|
||||
this.keyData = new Uint8Array(33);
|
||||
|
||||
/**
|
||||
* Seed Hash - 64 bytes
|
||||
*/
|
||||
|
||||
this.seedHash = new Uint8Array(64);
|
||||
|
||||
/**
|
||||
* Private Key - 32 bytes
|
||||
*/
|
||||
|
||||
this.privateKey = new Uint8Array(32);
|
||||
|
||||
/**
|
||||
* Public Key - 33 bytes (compressed)
|
||||
*/
|
||||
|
||||
this.publicKey = new Uint8Array(33);
|
||||
|
||||
/**
|
||||
* Public Key Hash160 (used to derive the parent fingerprint for derived)
|
||||
*/
|
||||
|
||||
this.publicKeyHash = new Uint8Array(20);
|
||||
|
||||
/**
|
||||
* Master Private Key (Base58 encoded)
|
||||
*/
|
||||
|
||||
this.masterPrivateKey = '';
|
||||
|
||||
/**
|
||||
* Master Public Key (Base58 encoded)
|
||||
*/
|
||||
|
||||
this.masterPublicKey = '';
|
||||
|
||||
/**
|
||||
* Testnet Master Private Key (Base58 encoded) - THIS IS TESTNET
|
||||
*/
|
||||
|
||||
this._tMasterPrivateKey = '';
|
||||
|
||||
/**
|
||||
* Testnet Master Public Key (Base58 encoded) - THIS IS TESTNET
|
||||
*/
|
||||
|
||||
this._tmasterPublicKey = '';
|
||||
|
||||
/**
|
||||
* Child Keys Derivation from the Parent Keys
|
||||
*/
|
||||
|
||||
/**
|
||||
* Child Private Key - 32 bytes
|
||||
*/
|
||||
|
||||
this.childPrivateKey = new Uint8Array(32);
|
||||
|
||||
/**
|
||||
* Child Chain Code - 32 bytes
|
||||
*/
|
||||
|
||||
this.childChainCode = new Uint8Array(32);
|
||||
|
||||
/**
|
||||
* Child Public Key - 33 bytes (compressed)
|
||||
*/
|
||||
|
||||
this.childPublicKey = new Uint8Array(33);
|
||||
|
||||
/**
|
||||
* Child Public Key Hash160 (used to derive the parent fingerprint for derived)
|
||||
*/
|
||||
|
||||
this.childPublicKeyHash = new Uint8Array(20);
|
||||
|
||||
/**
|
||||
* Extended Private Child Key - Base58 encoded
|
||||
*/
|
||||
|
||||
this.xPrivateChildKey = '';
|
||||
|
||||
/**
|
||||
* Extended Public Child Key - Base58 encoded
|
||||
*/
|
||||
|
||||
this.xPublicChildKey = '';
|
||||
|
||||
/**
|
||||
* Grand Child Keys Derivation from the Child Keys
|
||||
*/
|
||||
|
||||
/**
|
||||
* Grand Child Private Key - 32 bytes
|
||||
*/
|
||||
|
||||
this.grandChildPrivateKey = new Uint8Array(32);
|
||||
|
||||
/**
|
||||
* Grand Child Chain Code - 32 bytes
|
||||
*/
|
||||
|
||||
this.grandChildChainCode = new Uint8Array(32);
|
||||
|
||||
/**
|
||||
* Grand Child Public Key - 33 bytes (compressed)
|
||||
*/
|
||||
|
||||
this.grandChildPublicKey = new Uint8Array(33);
|
||||
|
||||
/**
|
||||
* Grand Public Key Hash160 (used to derive the parent fingerprint for derived)
|
||||
*/
|
||||
|
||||
this.grandChildPublicKeyHash = new Uint8Array(20);
|
||||
|
||||
/**
|
||||
* Extended Private Grand Child Key - Base58 encoded
|
||||
*/
|
||||
|
||||
this.xPrivateGrandChildKey = '';
|
||||
|
||||
/**
|
||||
* Extended Public Grand Child Key - Base58 encoded
|
||||
*/
|
||||
|
||||
this.xPublicGrandChildKey = '';
|
||||
|
||||
/**
|
||||
* Litecoin Legacy Address - Derived from the Grand Child Public Key Hash
|
||||
*/
|
||||
|
||||
this.litecoinLegacyAddress = '';
|
||||
|
||||
/**
|
||||
* TESTNET Litecoin Legacy Address (Derived from the Grand Child Public Key Hash) - THIS IS TESTNET
|
||||
*/
|
||||
|
||||
this._tlitecoinLegacyAddress = '';
|
||||
|
||||
/**
|
||||
* Wallet - Wallet Object (keys...)
|
||||
*/
|
||||
|
||||
this.wallet = {};
|
||||
}
|
||||
|
||||
setSeed(seed) {
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
createWallet(seed, isBIP44, indicator = null) {
|
||||
// Set Seeed
|
||||
this.setSeed(seed);
|
||||
|
||||
// Generate Seed Hash
|
||||
this.generateSeedHash(this.seed, isBIP44, indicator);
|
||||
|
||||
// Generate Private Key
|
||||
this.generatePrivateKey(this.seedHash);
|
||||
|
||||
// Generate Chain Code
|
||||
this.generateChainCode(this.seedHash);
|
||||
|
||||
// Generate Public Key from Private Key
|
||||
this.generatePublicKey(this.privateKey);
|
||||
|
||||
// Generate Mainnet Master Private Key
|
||||
this.generateMainnetMasterPrivateKey();
|
||||
|
||||
// Generate Mainnet Master Public Key
|
||||
this.generateMainnetMasterPublicKey();
|
||||
|
||||
// Generate Testnet Master Private Key
|
||||
this.generateTestnetMasterPrivateKey();
|
||||
|
||||
// Generate Testnet Master Public Key
|
||||
this.generateTestnetMasterPublicKey();
|
||||
|
||||
// Generate Child and Grand Child Keys
|
||||
this.generateDerivedChildKeys();
|
||||
|
||||
// Return Wallet Object Specification
|
||||
return this.returnWallet();
|
||||
}
|
||||
|
||||
generateSeedHash(seed, isBIP44, indicator = null) {
|
||||
let buffer;
|
||||
|
||||
if (isBIP44) {
|
||||
buffer = utils.appendBuffer(
|
||||
seed.reverse(),
|
||||
utils.int32ToBytes(indicator)
|
||||
);
|
||||
} else {
|
||||
if (indicator !== null) {
|
||||
const indicatorString = utils.stringtoUTF8Array(indicator);
|
||||
buffer = utils.appendBuffer(seed.reverse(), indicatorString);
|
||||
} else {
|
||||
buffer = seed.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
const _reverseSeedHash = new Sha256().process(buffer).finish().result;
|
||||
this.seedHash = new Sha512()
|
||||
.process(utils.appendBuffer(seed, _reverseSeedHash))
|
||||
.finish().result;
|
||||
}
|
||||
|
||||
generatePrivateKey(seedHash) {
|
||||
const SECP256K1_CURVE_ORDER = new BigInteger(
|
||||
'0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'
|
||||
);
|
||||
|
||||
const privateKeyHash = seedHash.slice(0, 32);
|
||||
|
||||
this.seed58 = Base58.encode(privateKeyHash);
|
||||
|
||||
const _privateKeyHash = [...privateKeyHash];
|
||||
let privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKeyHash);
|
||||
|
||||
const privateKey = privateKeyBigInt
|
||||
.mod(SECP256K1_CURVE_ORDER.subtract(BigInteger.ONE))
|
||||
.add(BigInteger.ONE);
|
||||
this.privateKey = privateKey.toByteArrayUnsigned();
|
||||
}
|
||||
|
||||
generateChainCode(seedHash) {
|
||||
this.chainCode = new Sha256()
|
||||
.process(seedHash.slice(32, 64))
|
||||
.finish().result;
|
||||
}
|
||||
|
||||
generatePublicKey(privateKey) {
|
||||
const _privateKey = [...privateKey];
|
||||
const privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKey);
|
||||
|
||||
const epCurve = EllipticCurve.getSECCurveByName('secp256k1');
|
||||
const curvePoints = epCurve.getG().multiply(privateKeyBigInt);
|
||||
|
||||
const x = curvePoints.getX().toBigInteger();
|
||||
const y = curvePoints.getY().toBigInteger();
|
||||
|
||||
/**
|
||||
* Deriving Uncompressed Public Key (65 bytes)
|
||||
*
|
||||
* const publicKeyBytes = EllipticCurve.integerToBytes(x, 32)
|
||||
* this.publicKey = publicKeyBytes.concat(EllipticCurve.integerToBytes(y, 32))
|
||||
* this.publicKey.unshift(0x04) // append point indicator
|
||||
*/
|
||||
|
||||
// Compressed Public Key (33 bytes)
|
||||
this.publicKey = EllipticCurve.integerToBytes(x, 32);
|
||||
|
||||
if (y.isEven()) {
|
||||
this.publicKey.unshift(0x02); // append point indicator
|
||||
} else {
|
||||
this.publicKey.unshift(0x03); // append point indicator
|
||||
}
|
||||
|
||||
// PublicKey Hash
|
||||
const publicKeySHA256 = new Sha256()
|
||||
.process(new Uint8Array(this.publicKey))
|
||||
.finish().result;
|
||||
const _publicKeyHash = new RIPEMD160()
|
||||
.update(Buffer.from(publicKeySHA256))
|
||||
.digest('hex');
|
||||
this.publicKeyHash = _publicKeyHash;
|
||||
}
|
||||
|
||||
generateMainnetMasterPrivateKey() {
|
||||
// Serialization Variable
|
||||
const s = [];
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...utils.int32ToBytes(this.versionBytes.mainnet.private));
|
||||
|
||||
// Append Depth
|
||||
s.push(this.depth);
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...utils.int32ToBytes(this.parentFingerprint));
|
||||
|
||||
// Append Child Number
|
||||
s.push(...utils.int32ToBytes(this.childIndex));
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.chainCode);
|
||||
|
||||
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
|
||||
s.push(0);
|
||||
|
||||
//if the private key length is less than 32 let's add leading zeros
|
||||
if (this.privateKey.length < 32) {
|
||||
for (let i = this.privateKey.length; i < 32; i++) {
|
||||
s.push(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Append Private Key
|
||||
s.push(...this.privateKey);
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s);
|
||||
const _checkSum = new Sha256()
|
||||
.process(new Sha256().process(_s).finish().result)
|
||||
.finish().result;
|
||||
const checkSum = _checkSum.slice(0, 4);
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum); // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Private Key as Base58 encoded
|
||||
this.masterPrivateKey = Base58.encode(s);
|
||||
}
|
||||
|
||||
generateMainnetMasterPublicKey() {
|
||||
// Serialization Variable
|
||||
const s = [];
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...utils.int32ToBytes(this.versionBytes.mainnet.public));
|
||||
|
||||
// Append Depth
|
||||
s.push(this.depth);
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...utils.int32ToBytes(this.parentFingerprint));
|
||||
|
||||
// Append Child Number
|
||||
s.push(...utils.int32ToBytes(this.childIndex));
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.chainCode);
|
||||
|
||||
// Append Public Key
|
||||
s.push(...this.publicKey);
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s);
|
||||
const _checkSum = new Sha256()
|
||||
.process(new Sha256().process(_s).finish().result)
|
||||
.finish().result;
|
||||
const checkSum = _checkSum.slice(0, 4);
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum); // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Public Key as Base58 encoded
|
||||
this.masterPublicKey = Base58.encode(s);
|
||||
}
|
||||
|
||||
generateTestnetMasterPrivateKey() {
|
||||
// To be Used ONLY in Testnet...
|
||||
|
||||
// Serialization Variable
|
||||
const s = [];
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...utils.int32ToBytes(this.versionBytes.testnet.private));
|
||||
|
||||
// Append Depth
|
||||
s.push(this.depth);
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...utils.int32ToBytes(this.parentFingerprint));
|
||||
|
||||
// Append Child Number
|
||||
s.push(...utils.int32ToBytes(this.childIndex));
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.chainCode);
|
||||
|
||||
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
|
||||
s.push(0);
|
||||
|
||||
// Append Private Key
|
||||
s.push(...this.privateKey);
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s);
|
||||
const _checkSum = new Sha256()
|
||||
.process(new Sha256().process(_s).finish().result)
|
||||
.finish().result;
|
||||
const checkSum = _checkSum.slice(0, 4);
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum); // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Private Key as Base58 encoded
|
||||
this._tMasterPrivateKey = Base58.encode(s);
|
||||
}
|
||||
|
||||
generateTestnetMasterPublicKey() {
|
||||
// To be Used ONLY in Testnet...
|
||||
|
||||
// Serialization Variable
|
||||
const s = [];
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...utils.int32ToBytes(this.versionBytes.testnet.public));
|
||||
|
||||
// Append Depth
|
||||
s.push(this.depth);
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...utils.int32ToBytes(this.parentFingerprint));
|
||||
|
||||
// Append Child Number
|
||||
s.push(...utils.int32ToBytes(this.childIndex));
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.chainCode);
|
||||
|
||||
// Append Private Key
|
||||
s.push(...this.publicKey);
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s);
|
||||
const _checkSum = new Sha256()
|
||||
.process(new Sha256().process(_s).finish().result)
|
||||
.finish().result;
|
||||
const checkSum = _checkSum.slice(0, 4);
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum); // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Private Key as Base58 encoded
|
||||
this._tmasterPublicKey = Base58.encode(s);
|
||||
}
|
||||
|
||||
generateDerivedChildKeys() {
|
||||
// SPEC INFO: https://en.bitcoin.it/wiki/BIP_0032#Child_key_derivation_.28CKD.29_functions
|
||||
// NOTE: will not be using some of derivations func as the value is known. (So I'd rather shove in the values and rewrite out the derivations later ?)
|
||||
|
||||
// NOTE: I "re-wrote" and "reduplicate" the code for child and grandChild keys derivations inorder to get the child and grandchild from the child
|
||||
// TODO: Make this more better in the future
|
||||
|
||||
const path = 'm/0/0';
|
||||
// let p = path.split('/')
|
||||
|
||||
// Get Public kEY
|
||||
const derivePublicChildKey = () => {
|
||||
const _privateKey = [...this.childPrivateKey];
|
||||
const privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKey);
|
||||
|
||||
const epCurve = EllipticCurve.getSECCurveByName('secp256k1');
|
||||
const curvePoints = epCurve.getG().multiply(privateKeyBigInt);
|
||||
|
||||
const x = curvePoints.getX().toBigInteger();
|
||||
const y = curvePoints.getY().toBigInteger();
|
||||
|
||||
// Compressed Public Key (33 bytes)
|
||||
this.childPublicKey = EllipticCurve.integerToBytes(x, 32);
|
||||
|
||||
if (y.isEven()) {
|
||||
this.childPublicKey.unshift(0x02); // append point indicator
|
||||
} else {
|
||||
this.childPublicKey.unshift(0x03); // append point indicator
|
||||
}
|
||||
|
||||
// PublicKey Hash
|
||||
const childPublicKeySHA256 = new Sha256()
|
||||
.process(new Uint8Array(this.childPublicKey))
|
||||
.finish().result;
|
||||
const _childPublicKeyHash = new RIPEMD160()
|
||||
.update(Buffer.from(childPublicKeySHA256))
|
||||
.digest('hex');
|
||||
this.childPublicKeyHash = _childPublicKeyHash;
|
||||
|
||||
// Call deriveExtendedPublicChildKey // WIll be hardcoding the values...
|
||||
deriveExtendedPublicChildKey(1, 0);
|
||||
};
|
||||
|
||||
const derivePrivateChildKey = (cI) => {
|
||||
let ib = [];
|
||||
ib.push((cI >> 24) & 0xff);
|
||||
ib.push((cI >> 16) & 0xff);
|
||||
ib.push((cI >> 8) & 0xff);
|
||||
ib.push(cI & 0xff);
|
||||
|
||||
const s = [...this.publicKey].concat(ib);
|
||||
|
||||
const _hmacSha512 = new jsSHA('SHA-512', 'UINT8ARRAY', {
|
||||
numRounds: 1,
|
||||
hmacKey: { value: this.chainCode, format: 'UINT8ARRAY' },
|
||||
});
|
||||
_hmacSha512.update(new Uint8Array(s));
|
||||
|
||||
const IL = BigInteger.fromByteArrayUnsigned([
|
||||
..._hmacSha512.getHMAC('UINT8ARRAY').slice(0, 32),
|
||||
]);
|
||||
this.childChainCode = _hmacSha512.getHMAC('UINT8ARRAY').slice(32, 64); // IR according to the SPEC
|
||||
|
||||
// SECP256k1 init
|
||||
const epCurve = EllipticCurve.getSECCurveByName('secp256k1');
|
||||
|
||||
const ki = IL.add(BigInteger.fromByteArrayUnsigned(this.privateKey)).mod(
|
||||
epCurve.getN()
|
||||
); // parse256(IL) + kpar (mod n) ==> ki
|
||||
this.childPrivateKey = ki.toByteArrayUnsigned();
|
||||
|
||||
// Call deriveExtendedPrivateChildKey
|
||||
deriveExtendedPrivateChildKey(1, 0);
|
||||
};
|
||||
|
||||
const deriveExtendedPrivateChildKey = (i, childIndex) => {
|
||||
// Serialization Variable
|
||||
const s = [];
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...utils.int32ToBytes(this.versionBytes.mainnet.private));
|
||||
|
||||
// Append Depth (using the index as depth)
|
||||
i = parseInt(i);
|
||||
s.push(i);
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...this.publicKeyHash.slice(0, 4));
|
||||
|
||||
// Append Child Index
|
||||
s.push(childIndex >>> 24);
|
||||
s.push((childIndex >>> 16) & 0xff);
|
||||
s.push((childIndex >>> 8) & 0xff);
|
||||
s.push(childIndex & 0xff);
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.childChainCode);
|
||||
|
||||
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
|
||||
s.push(0);
|
||||
|
||||
// Append Private Key
|
||||
s.push(...this.childPrivateKey);
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s);
|
||||
const _checkSum = new Sha256()
|
||||
.process(new Sha256().process(_s).finish().result)
|
||||
.finish().result;
|
||||
const checkSum = _checkSum.slice(0, 4);
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum); // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Private Key as Base58 encoded
|
||||
this.xPrivateChildKey = Base58.encode(s);
|
||||
};
|
||||
|
||||
const deriveExtendedPublicChildKey = (i, childIndex) => {
|
||||
// Serialization Variable
|
||||
const s = [];
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...utils.int32ToBytes(this.versionBytes.mainnet.public));
|
||||
|
||||
// Append Depth
|
||||
i = parseInt(i);
|
||||
s.push(i);
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...this.publicKeyHash.slice(0, 4));
|
||||
|
||||
// Append Child Index
|
||||
s.push(childIndex >>> 24);
|
||||
s.push((childIndex >>> 16) & 0xff);
|
||||
s.push((childIndex >>> 8) & 0xff);
|
||||
s.push(childIndex & 0xff);
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.childChainCode);
|
||||
|
||||
// Append Public Key
|
||||
s.push(...this.childPublicKey);
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s);
|
||||
const _checkSum = new Sha256()
|
||||
.process(new Sha256().process(_s).finish().result)
|
||||
.finish().result;
|
||||
const checkSum = _checkSum.slice(0, 4);
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum); // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Public Key as Base58 encoded
|
||||
this.xPublicChildKey = Base58.encode(s);
|
||||
};
|
||||
|
||||
/**
|
||||
* GRAND CHILD KEYS
|
||||
*
|
||||
* NOTE: I know this is not the best way to generate this (even though it works the way it ought)
|
||||
* Things to rewrite will be and not limited to deriving this through a for loop, removing hard code values, etc...
|
||||
*/
|
||||
|
||||
const derivePublicGrandChildKey = () => {
|
||||
const _privateKey = [...this.grandChildPrivateKey];
|
||||
const privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKey);
|
||||
|
||||
const epCurve = EllipticCurve.getSECCurveByName('secp256k1');
|
||||
const curvePoints = epCurve.getG().multiply(privateKeyBigInt);
|
||||
|
||||
const x = curvePoints.getX().toBigInteger();
|
||||
const y = curvePoints.getY().toBigInteger();
|
||||
|
||||
// Compressed Public Key (33 bytes)
|
||||
this.grandChildPublicKey = EllipticCurve.integerToBytes(x, 32);
|
||||
|
||||
if (y.isEven()) {
|
||||
this.grandChildPublicKey.unshift(0x02); // append point indicator
|
||||
} else {
|
||||
this.grandChildPublicKey.unshift(0x03); // append point indicator
|
||||
}
|
||||
|
||||
// PublicKey Hash
|
||||
const grandChildPublicKeySHA256 = new Sha256()
|
||||
.process(new Uint8Array(this.grandChildPublicKey))
|
||||
.finish().result;
|
||||
const _grandChildPublicKeyHash = new RIPEMD160()
|
||||
.update(Buffer.from(grandChildPublicKeySHA256))
|
||||
.digest('hex');
|
||||
this.grandChildPublicKeyHash = _grandChildPublicKeyHash;
|
||||
|
||||
// Call deriveExtendedPublicChildKey // WIll be hardcoding the values...
|
||||
deriveExtendedPublicGrandChildKey(2, 0);
|
||||
|
||||
/**
|
||||
* Derive Litecoin Legacy Address
|
||||
*/
|
||||
|
||||
// Append Address Prefix
|
||||
let prefix = [this.versionBytes.mainnet.prefix];
|
||||
if (2 == this.versionBytes.mainnet.prefix.length) {
|
||||
prefix = [this.versionBytes.mainnet.prefix[0]];
|
||||
prefix.push([this.versionBytes.mainnet.prefix[1]]);
|
||||
}
|
||||
|
||||
const k = prefix.concat(...this.grandChildPublicKeyHash);
|
||||
|
||||
// Derive Checksum
|
||||
const _addressCheckSum = new Sha256()
|
||||
.process(new Sha256().process(new Uint8Array(k)).finish().result)
|
||||
.finish().result;
|
||||
const addressCheckSum = _addressCheckSum.slice(0, 4);
|
||||
|
||||
// Append CheckSum
|
||||
const _litecoinLegacyAddress = k.concat(...addressCheckSum);
|
||||
|
||||
// Convert to Base58
|
||||
this.litecoinLegacyAddress = Base58.encode(_litecoinLegacyAddress);
|
||||
|
||||
/**
|
||||
* Derive TESTNET Litecoin Legacy Address
|
||||
*/
|
||||
|
||||
// Append Version Byte
|
||||
const tK = [this.versionBytes.testnet.prefix].concat(
|
||||
...this.grandChildPublicKeyHash
|
||||
);
|
||||
|
||||
// Derive Checksum
|
||||
const _tAddressCheckSum = new Sha256()
|
||||
.process(new Sha256().process(new Uint8Array(tK)).finish().result)
|
||||
.finish().result;
|
||||
const tAddressCheckSum = _tAddressCheckSum.slice(0, 4);
|
||||
|
||||
// Append CheckSum
|
||||
const _tlitecoinLegacyAddress = tK.concat(...tAddressCheckSum);
|
||||
|
||||
// Convert to Base58
|
||||
this._tlitecoinLegacyAddress = Base58.encode(_tlitecoinLegacyAddress);
|
||||
};
|
||||
|
||||
const derivePrivateGrandChildKey = (cI, i) => {
|
||||
let ib = [];
|
||||
ib.push((cI >> 24) & 0xff);
|
||||
ib.push((cI >> 16) & 0xff);
|
||||
ib.push((cI >> 8) & 0xff);
|
||||
ib.push(cI & 0xff);
|
||||
|
||||
const s = [...this.childPublicKey].concat(ib);
|
||||
|
||||
const _hmacSha512 = new jsSHA('SHA-512', 'UINT8ARRAY', {
|
||||
numRounds: 1,
|
||||
hmacKey: { value: this.childChainCode, format: 'UINT8ARRAY' },
|
||||
});
|
||||
_hmacSha512.update(new Uint8Array(s));
|
||||
|
||||
const IL = BigInteger.fromByteArrayUnsigned([
|
||||
..._hmacSha512.getHMAC('UINT8ARRAY').slice(0, 32),
|
||||
]);
|
||||
this.grandChildChainCode = _hmacSha512
|
||||
.getHMAC('UINT8ARRAY')
|
||||
.slice(32, 64); // IR according to the SPEC
|
||||
|
||||
// SECP256k1 init
|
||||
const epCurve = EllipticCurve.getSECCurveByName('secp256k1');
|
||||
|
||||
const ki = IL.add(
|
||||
BigInteger.fromByteArrayUnsigned(this.childPrivateKey)
|
||||
).mod(epCurve.getN()); // parse256(IL) + kpar (mod n) ==> ki
|
||||
this.grandChildPrivateKey = ki.toByteArrayUnsigned();
|
||||
|
||||
// Call deriveExtendedPrivateChildKey
|
||||
deriveExtendedPrivateGrandChildKey(2, 0);
|
||||
};
|
||||
|
||||
const deriveExtendedPrivateGrandChildKey = (i, childIndex) => {
|
||||
// Serialization Variable
|
||||
const s = [];
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...utils.int32ToBytes(this.versionBytes.mainnet.private));
|
||||
|
||||
// Append Depth (using the index as depth)
|
||||
i = parseInt(i);
|
||||
s.push(i);
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...this.childPublicKeyHash.slice(0, 4));
|
||||
|
||||
// Append Child Index
|
||||
s.push(childIndex >>> 24);
|
||||
s.push((childIndex >>> 16) & 0xff);
|
||||
s.push((childIndex >>> 8) & 0xff);
|
||||
s.push(childIndex & 0xff);
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.grandChildChainCode);
|
||||
|
||||
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
|
||||
s.push(0);
|
||||
|
||||
// Append Private Key
|
||||
s.push(...this.grandChildPrivateKey);
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s);
|
||||
const _checkSum = new Sha256()
|
||||
.process(new Sha256().process(_s).finish().result)
|
||||
.finish().result;
|
||||
const checkSum = _checkSum.slice(0, 4);
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum); // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Private Key as Base58 encoded
|
||||
this.xPrivateGrandChildKey = Base58.encode(s);
|
||||
};
|
||||
|
||||
const deriveExtendedPublicGrandChildKey = (i, childIndex) => {
|
||||
// Serialization Variable
|
||||
const s = [];
|
||||
|
||||
// Append Version Byte
|
||||
s.push(...utils.int32ToBytes(this.versionBytes.mainnet.public));
|
||||
|
||||
// Append Depth
|
||||
i = parseInt(i);
|
||||
s.push(i);
|
||||
|
||||
// Append Parent Fingerprint
|
||||
s.push(...this.childPublicKeyHash.slice(0, 4));
|
||||
|
||||
// Append Child Index
|
||||
s.push(childIndex >>> 24);
|
||||
s.push((childIndex >>> 16) & 0xff);
|
||||
s.push((childIndex >>> 8) & 0xff);
|
||||
s.push(childIndex & 0xff);
|
||||
|
||||
// Append Chain Code
|
||||
s.push(...this.grandChildChainCode);
|
||||
|
||||
// Append Public Key
|
||||
s.push(...this.grandChildPublicKey);
|
||||
|
||||
// Generate CheckSum
|
||||
const _s = new Uint8Array(s);
|
||||
const _checkSum = new Sha256()
|
||||
.process(new Sha256().process(_s).finish().result)
|
||||
.finish().result;
|
||||
const checkSum = _checkSum.slice(0, 4);
|
||||
|
||||
// Append CheckSum
|
||||
s.push(...checkSum); // And this brings us to the end of the serialization...
|
||||
|
||||
// Save to Public Key as Base58 encoded
|
||||
this.xPublicGrandChildKey = Base58.encode(s);
|
||||
};
|
||||
|
||||
// Hard Code value..
|
||||
let childIndex = 0;
|
||||
|
||||
// Call derivePrivateChildKey //Hard code value
|
||||
derivePrivateChildKey(childIndex);
|
||||
|
||||
// Call derivePublicChildKey
|
||||
derivePublicChildKey();
|
||||
|
||||
// Call derivePrivateGrandChildKey // Hard Code value...
|
||||
derivePrivateGrandChildKey(0, 2);
|
||||
|
||||
// Call derivePublicGrandChildKey
|
||||
derivePublicGrandChildKey();
|
||||
}
|
||||
|
||||
returnWallet() {
|
||||
// Will be limiting the exported Wallet Object to just the Master keys and Legacy Addresses
|
||||
|
||||
const wallet = {
|
||||
derivedMasterPrivateKey: this.masterPrivateKey,
|
||||
derivedMasterPublicKey: this.masterPublicKey,
|
||||
_tDerivedMasterPrivateKey: this._tMasterPrivateKey,
|
||||
_tDerivedmasterPublicKey: this._tmasterPublicKey,
|
||||
seed58: this.seed58,
|
||||
// derivedPrivateChildKey: this.xPrivateChildKey,
|
||||
// derivedPublicChildKey: this.xPublicChildKey,
|
||||
// derivedPrivateGrandChildKey: this.xPrivateGrandChildKey,
|
||||
// derivedPublicGrandChildKey: this.xPublicGrandChildKey,
|
||||
address: this.litecoinLegacyAddress,
|
||||
_taddress: this._tlitecoinLegacyAddress,
|
||||
};
|
||||
|
||||
this.wallet = wallet;
|
||||
return wallet;
|
||||
}
|
||||
}
|
@ -1,60 +1,24 @@
|
||||
import { getBaseApi } from '../background';
|
||||
import i18n from '../i18n/i18n';
|
||||
import { getBaseApi } from '../background/background.ts';
|
||||
import i18n from '../i18n/i18n.ts';
|
||||
import {
|
||||
createSymmetricKeyAndNonce,
|
||||
decryptGroupData,
|
||||
encryptDataGroup,
|
||||
objectToBase64,
|
||||
} from '../qdn/encryption/group-encryption';
|
||||
import { publishData } from '../qdn/publish/pubish';
|
||||
import { getData } from '../utils/chromeStorage';
|
||||
import { RequestQueueWithPromise } from '../utils/queue/queue';
|
||||
} from '../qdn/encryption/group-encryption.ts';
|
||||
import { publishData } from '../qdn/publish/publish.ts';
|
||||
import { getData } from '../utils/chromeStorage.ts';
|
||||
import { RequestQueueWithPromise } from '../utils/queue/queue.ts';
|
||||
|
||||
export const requestQueueGetPublicKeys = new RequestQueueWithPromise(10);
|
||||
|
||||
const apiEndpoints = [
|
||||
'https://api.qortal.org',
|
||||
'https://api2.qortal.org',
|
||||
'https://appnode.qortal.org',
|
||||
'https://apinode.qortalnodes.live',
|
||||
'https://apinode1.qortalnodes.live',
|
||||
'https://apinode2.qortalnodes.live',
|
||||
'https://apinode3.qortalnodes.live',
|
||||
'https://apinode4.qortalnodes.live',
|
||||
];
|
||||
|
||||
async function findUsableApi() {
|
||||
for (const endpoint of apiEndpoints) {
|
||||
try {
|
||||
const response = await fetch(`${endpoint}/admin/status`);
|
||||
if (!response.ok) throw new Error('Failed to fetch');
|
||||
|
||||
const data = await response.json();
|
||||
if (data.isSynchronizing === false && data.syncPercent === 100) {
|
||||
console.log(`Usable API found: ${endpoint}`);
|
||||
return endpoint;
|
||||
} else {
|
||||
console.log(`API not ready: ${endpoint}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error checking API ${endpoint}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
i18n.t('question:message.error.no_api_found', {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
async function getSaveWallet() {
|
||||
const res = await getData<any>('walletInfo').catch(() => null);
|
||||
|
||||
if (res) {
|
||||
return res;
|
||||
} else {
|
||||
throw new Error('No wallet saved');
|
||||
throw new Error('No wallet saved'); // TODO translate
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { getBaseApiReact } from '../App';
|
||||
import { getData, storeData } from '../utils/chromeStorage';
|
||||
import { checkDifference, getNameInfoForOthers } from '../background';
|
||||
import {
|
||||
checkDifference,
|
||||
getNameInfoForOthers,
|
||||
} from '../background/background.ts';
|
||||
import { lastPaymentSeenTimestampAtom } from '../atoms/global';
|
||||
import { subscribeToEvent, unsubscribeFromEvent } from '../utils/events';
|
||||
import { useAtom } from 'jotai';
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { useContext, useState } from 'react';
|
||||
import { executeEvent } from '../utils/events';
|
||||
import { getBaseApiReact, MyContext } from '../App';
|
||||
import { createEndpoint } from '../background';
|
||||
import { getBaseApiReact, QORTAL_APP_CONTEXT } from '../App';
|
||||
import { createEndpoint } from '../background/background.ts';
|
||||
import {
|
||||
settingsLocalLastUpdatedAtom,
|
||||
sortablePinnedAppsAtom,
|
||||
} from '../atoms/global';
|
||||
import { saveToLocalStorage } from '../components/Apps/AppsNavBarDesktop';
|
||||
import { base64ToUint8Array } from '../qdn/encryption/group-encryption';
|
||||
import { uint8ArrayToObject } from '../backgroundFunctions/encryption';
|
||||
import { uint8ArrayToObject } from '../encryption/encryption.ts';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -19,10 +19,16 @@ export const useHandlePrivateApps = () => {
|
||||
setOpenSnackGlobal,
|
||||
infoSnackCustom,
|
||||
setInfoSnackCustom,
|
||||
} = useContext(MyContext);
|
||||
} = useContext(QORTAL_APP_CONTEXT);
|
||||
const setSortablePinnedApps = useSetAtom(sortablePinnedAppsAtom);
|
||||
const setSettingsLocalLastUpdated = useSetAtom(settingsLocalLastUpdatedAtom);
|
||||
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||
const { t } = useTranslation([
|
||||
'auth',
|
||||
'core',
|
||||
'group',
|
||||
'question',
|
||||
'tutorial',
|
||||
]);
|
||||
|
||||
const openApp = async (
|
||||
privateAppProperties,
|
||||
|
@ -12,7 +12,7 @@ import { decryptResource } from '../components/Group/Group';
|
||||
import {
|
||||
base64ToUint8Array,
|
||||
uint8ArrayToObject,
|
||||
} from '../backgroundFunctions/encryption';
|
||||
} from '../encryption/encryption';
|
||||
import { useAtom, useSetAtom } from 'jotai';
|
||||
|
||||
function fetchFromLocalStorage(key) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user