Merge pull request #93 from nbenaglia/feature/fixes-core-information

Improve core information
This commit is contained in:
nico.benaz 2025-06-25 08:59:54 +02:00 committed by GitHub
commit a265b62b84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 151 additions and 136 deletions

View File

@ -377,6 +377,7 @@ export const ChatList = ({
} }
> >
<MessageItem <MessageItem
key={message.signature}
handleReaction={handleReaction} handleReaction={handleReaction}
isLast={index === messages.length - 1} isLast={index === messages.length - 1}
isPrivate={isPrivate} isPrivate={isPrivate}

View File

@ -25,9 +25,7 @@ export const CoreSyncStatus = () => {
useEffect(() => { useEffect(() => {
const getNodeInfos = async () => { const getNodeInfos = async () => {
try { try {
setIsUsingGateway( setIsUsingGateway(getBaseApiReact()?.includes('ext-node.qortal.link'));
!!getBaseApiReact()?.includes('ext-node.qortal.link')
);
const url = `${getBaseApiReact()}/admin/status`; const url = `${getBaseApiReact()}/admin/status`;
const response = await fetch(url, { const response = await fetch(url, {
method: 'GET', method: 'GET',
@ -82,27 +80,27 @@ export const CoreSyncStatus = () => {
: ''; : '';
let imagePath = syncingImg; let imagePath = syncingImg;
let message = t('core:minting.status.synchronizing', { let message: string = '';
postProcess: 'capitalizeFirstChar',
});
if (isMintingPossible && !isUsingGateway) { if (isUsingGateway) {
imagePath = syncingImg;
message = `${t('core:minting.status.no_status')}`;
} else if (isMintingPossible) {
if (isSynchronizing) {
imagePath = syncingImg;
message = `${t(`core:minting.status.synchronizing`, { percent: syncPercent, postProcess: 'capitalizeFirstChar' })} ${t('core:minting.status.minting')}`;
} else {
imagePath = syncedMintingImg; imagePath = syncedMintingImg;
message = `${t(`core:minting.status.${isSynchronizing ? 'synchronizing' : 'synchronized'}`, { postProcess: 'capitalizeFirstChar' })} ${t('core:minting.status.minting')}`; message = `${t(`core:minting.status.synchronized`, { percent: syncPercent, postProcess: 'capitalizeFirstChar' })} ${t('core:minting.status.minting')}`;
} else if (isSynchronizing === true && syncPercent === 99) { }
imagePath = syncingImg; } else if (!isMintingPossible) {
} else if (isSynchronizing && !isMintingPossible && syncPercent === 100) { if (syncPercent == 100) {
imagePath = syncingImg;
message = `${t('core:minting.status.synchronizing', { postProcess: 'capitalizeFirstChar' })} ${!isUsingGateway ? t('core:minting.status.not_minting') : ''}`;
} else if (!isSynchronizing && !isMintingPossible && syncPercent === 100) {
imagePath = syncedImg; imagePath = syncedImg;
message = `${t('core:minting.status.synchronized', { postProcess: 'capitalizeFirstChar' })} ${!isUsingGateway ? t('core:minting.status.not_minting') : ''}`; message = `${t(`core:minting.status.synchronized`, { percent: syncPercent, postProcess: 'capitalizeFirstChar' })} ${t('core:minting.status.not_minting')}`;
} else if (isSynchronizing && isMintingPossible && syncPercent === 100) { } else {
imagePath = syncingImg; imagePath = syncingImg;
message = `${t('core:minting.status.synchronizing', { postProcess: 'capitalizeFirstChar' })} ${!isUsingGateway ? t('core:minting.status.minting') : ''}`; message = `${t(`core:minting.status.synchronizing`, { percent: syncPercent, postProcess: 'capitalizeFirstChar' })} ${t('core:minting.status.not_minting')}`;
} else if (!isSynchronizing && isMintingPossible && syncPercent === 100) { }
imagePath = syncedMintingImg;
message = `${t('core:minting.status.synchronized', { postProcess: 'capitalizeFirstChar' })} ${!isUsingGateway ? t('core:minting.status.minting') : ''}`;
} }
return ( return (

View File

@ -96,6 +96,7 @@ interface ReadOnlySlateProps {
content: any; content: any;
mode?: string; mode?: string;
} }
const ReadOnlySlate: FC<ReadOnlySlateProps> = ({ content, mode }) => { const ReadOnlySlate: FC<ReadOnlySlateProps> = ({ content, mode }) => {
const [load, setLoad] = useState(false); const [load, setLoad] = useState(false);
const editor = useMemo(() => withReact(createEditor()), []); const editor = useMemo(() => withReact(createEditor()), []);
@ -103,11 +104,15 @@ const ReadOnlySlate: FC<ReadOnlySlateProps> = ({ content, mode }) => {
const performUpdate = useCallback(async () => { const performUpdate = useCallback(async () => {
setLoad(true); setLoad(true);
try {
await new Promise<void>((res) => { await new Promise<void>((res) => {
setTimeout(() => { setTimeout(() => {
res(); res();
}, 250); }, 250);
}); });
} catch (error) {
console.log(error);
}
setLoad(false); setLoad(false);
}, []); }, []);
useEffect(() => { useEffect(() => {

View File

@ -698,10 +698,14 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
label={t('core:minting.average_blocktime', { label={t('core:minting.average_blocktime', {
postProcess: 'capitalizeEachFirstChar', postProcess: 'capitalizeEachFirstChar',
})} })}
value={averageBlockTime( value={t('core:time.second', {
adminInfo, count: parseFloat(
nodeHeightBlock averageBlockTime(adminInfo, nodeHeightBlock).toFixed(
).toFixed(2)} 2
)
),
postProcess: 'capitalizeEachFirstChar',
})}
/> />
<StatCard <StatCard

View File

@ -299,7 +299,7 @@ export const countRewardDay = (
); );
return countRewardDay34; return countRewardDay34;
} else if (level === 5 || level === 6) { } else if (level === 5 || level === 6) {
if (this.tier4Online < 30) { if (tier4Online < 30) {
const countRewardDay56 = parseFloat( const countRewardDay56 = parseFloat(
( (
(((blockReward(nodeStatus) / 100) * (((blockReward(nodeStatus) / 100) *
@ -324,7 +324,7 @@ export const countRewardDay = (
return countRewardDay56; return countRewardDay56;
} }
} else if (level === 7 || level === 8) { } else if (level === 7 || level === 8) {
if (this.tier4Online < 30) { if (tier4Online < 30) {
const countRewardDay78 = parseFloat( const countRewardDay78 = parseFloat(
( (
(((blockReward(nodeStatus) / 100) * (((blockReward(nodeStatus) / 100) *
@ -368,7 +368,6 @@ export const mintingStatus = (nodeStatus): string => {
nodeStatus.isMintingPossible === true && nodeStatus.isMintingPossible === true &&
nodeStatus.isSynchronizing === true nodeStatus.isSynchronizing === true
) { ) {
// this.cssMinting = 'blue';
return i18n.t('core:minting.status.minting', { return i18n.t('core:minting.status.minting', {
postProcess: 'capitalizeFirstChar', postProcess: 'capitalizeFirstChar',
}); });
@ -376,7 +375,6 @@ export const mintingStatus = (nodeStatus): string => {
nodeStatus.isMintingPossible === true && nodeStatus.isMintingPossible === true &&
nodeStatus.isSynchronizing === false nodeStatus.isSynchronizing === false
) { ) {
// this.cssMinting = 'blue';
return i18n.t('core:minting.status.minting', { return i18n.t('core:minting.status.minting', {
postProcess: 'capitalizeFirstChar', postProcess: 'capitalizeFirstChar',
}); });
@ -384,7 +382,6 @@ export const mintingStatus = (nodeStatus): string => {
nodeStatus.isMintingPossible === false && nodeStatus.isMintingPossible === false &&
nodeStatus.isSynchronizing === true nodeStatus.isSynchronizing === true
) { ) {
// this.cssMinting = 'red';
return i18n.t('core:minting.status.synchronizing', { return i18n.t('core:minting.status.synchronizing', {
postProcess: 'capitalizeFirstChar', postProcess: 'capitalizeFirstChar',
}) + }) +
@ -396,7 +393,6 @@ export const mintingStatus = (nodeStatus): string => {
nodeStatus.isMintingPossible === false && nodeStatus.isMintingPossible === false &&
nodeStatus.isSynchronizing === false nodeStatus.isSynchronizing === false
) { ) {
// this.cssMinting = 'red';
return i18n.t('core:minting.status.not_minting', { return i18n.t('core:minting.status.not_minting', {
postProcess: 'capitalizeFirstChar', postProcess: 'capitalizeFirstChar',
}); });

View File

@ -1,26 +1,24 @@
// @ts-nocheck // @ts-nocheck
import {bytes_to_base64 as bytesToBase64, Sha512} from 'asmcrypto.js' import { bytes_to_base64 as bytesToBase64, Sha512 } from 'asmcrypto.js';
import utils from '../utils/utils' import utils from '../utils/utils';
import { crypto as crypto2 } from '../constants/decryptWallet' import { crypto as crypto2 } from '../constants/decryptWallet';
import BcryptWorker from './bcryptworker.worker.js?worker'; import BcryptWorker from './bcryptworker.worker.js?worker';
const stringtoUTF8Array = (message) => { const stringtoUTF8Array = (message) => {
if (typeof message === 'string') { if (typeof message === 'string') {
var s = unescape(encodeURIComponent(message)) // UTF-8 var s = unescape(encodeURIComponent(message)); // UTF-8
message = new Uint8Array(s.length) message = new Uint8Array(s.length);
for (var i = 0; i < s.length; i++) { for (var i = 0; i < s.length; i++) {
message[i] = s.charCodeAt(i) & 0xff message[i] = s.charCodeAt(i) & 0xff;
} }
} }
return message return message;
} };
const bcryptInWorker = (hashBase64, salt) => { const bcryptInWorker = (hashBase64, salt) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const worker = new BcryptWorker() const worker = new BcryptWorker();
worker.onmessage = (e) => { worker.onmessage = (e) => {
const { result, error } = e.data; const { result, error } = e.data;
if (error) { if (error) {
@ -38,63 +36,75 @@ const bcryptInWorker = (hashBase64, salt) => {
}); });
}; };
const stringToUTF8Array = (message) => { const stringToUTF8Array = (message) => {
if (typeof message !== 'string') return message; // Assuming you still want to pass through non-string inputs unchanged if (typeof message !== 'string') return message; // Assuming you still want to pass through non-string inputs unchanged
const encoder = new TextEncoder(); // TextEncoder defaults to UTF-8 const encoder = new TextEncoder(); // TextEncoder defaults to UTF-8
return encoder.encode(message); return encoder.encode(message);
} };
const computekdf = async (req) => { const computekdf = async (req) => {
const { salt, key, nonce, staticSalt, staticBcryptSalt } = req const { salt, key, nonce, staticSalt, staticBcryptSalt } = req;
const combinedBytes = utils.appendBuffer(new Uint8Array([]), stringToUTF8Array(`${staticSalt}${key}${nonce}`)) const combinedBytes = utils.appendBuffer(
new Uint8Array([]),
stringToUTF8Array(`${staticSalt}${key}${nonce}`)
);
const sha512Hash = new Sha512().process(combinedBytes).finish().result const sha512Hash = new Sha512().process(combinedBytes).finish().result;
const sha512HashBase64 = bytesToBase64(sha512Hash) const sha512HashBase64 = bytesToBase64(sha512Hash);
const result = await bcryptInWorker(sha512HashBase64.substring(0, 72), staticBcryptSalt); const result = await bcryptInWorker(
return { key, nonce, result } sha512HashBase64.substring(0, 72),
} staticBcryptSalt
);
return { key, nonce, result };
};
export const doInitWorkers = (numberOfWorkers) => { export const doInitWorkers = (numberOfWorkers) => {
const workers = [] const workers = [];
try { try {
for (let i = 0; i < numberOfWorkers; i++) { for (let i = 0; i < numberOfWorkers; i++) {
workers.push({}) workers.push({});
} }
} catch (e) {}
} catch (e) { return workers;
} };
return workers
}
export const kdf = async (seed, salt, threads) => { export const kdf = async (seed, salt, threads) => {
const workers = threads const workers = threads;
const salt2 = new Uint8Array(salt) const salt2 = new Uint8Array(salt);
salt = new Uint8Array(salt) salt = new Uint8Array(salt);
const seedParts = await Promise.all(workers.map((worker, index) => { const seedParts = await Promise.all(
const nonce = index workers.map((worker, index) => {
const nonce = index;
return computekdf({ return computekdf({
key: seed, key: seed,
salt, salt,
nonce, nonce,
staticSalt: crypto2.staticSalt, staticSalt: crypto2.staticSalt,
staticBcryptSalt: crypto2.staticBcryptSalt staticBcryptSalt: crypto2.staticBcryptSalt,
}).then(data => { }).then((data) => {
let jsonData let jsonData;
try { try {
jsonData = JSON.parse(data) jsonData = JSON.parse(data);
data = jsonData data = jsonData;
} catch (e) { } catch (e) {
// ... // ...
} }
// if (seed !== data.key) throw new Error(kst3 + seed + ' !== ' + data.key) // if (seed !== data.key) throw new Error(kst3 + seed + ' !== ' + data.key)
// if (nonce !== data.nonce) throw new Error(kst4) // if (nonce !== data.nonce) throw new Error(kst4)
return data.result return data.result;
});
}) })
})) );
const result = new Sha512().process(stringtoUTF8Array(crypto2.staticSalt + seedParts.reduce((a, c) => a + c))).finish().result
return result const result = new Sha512()
} .process(
stringtoUTF8Array(crypto2.staticSalt + seedParts.reduce((a, c) => a + c))
)
.finish().result;
return result;
};

View File

@ -334,8 +334,8 @@
"minting": "(Prägung)", "minting": "(Prägung)",
"not_minting": "(nicht punktieren)", "not_minting": "(nicht punktieren)",
"no_status": "kein Status", "no_status": "kein Status",
"synchronized": "synchronisiert", "synchronized": "synchronisiert ({{ percent }}%)",
"synchronizing": "Synchronisierung..." "synchronizing": "Synchronisierung ({{ percent }}%)..."
}, },
"status_title": "Münzstatus", "status_title": "Münzstatus",
"tier_share_per_block": "Stufenanteil pro Block", "tier_share_per_block": "Stufenanteil pro Block",

View File

@ -336,8 +336,8 @@
"minting": "(minting)", "minting": "(minting)",
"not_minting": "(not minting)", "not_minting": "(not minting)",
"no_status": "no status", "no_status": "no status",
"synchronized": "synchronized", "synchronized": "synchronized ({{ percent }}%)",
"synchronizing": "synchronizing..." "synchronizing": "synchronizing ({{ percent }}%)..."
}, },
"status_title": "minting status", "status_title": "minting status",
"tier_share_per_block": "tier share per block", "tier_share_per_block": "tier share per block",
@ -399,6 +399,8 @@
"hour_other": "{{count}} hours", "hour_other": "{{count}} hours",
"minute_one": "{{count}} minute", "minute_one": "{{count}} minute",
"minute_other": "{{count}} minutes", "minute_other": "{{count}} minutes",
"second_one": "{{count}} second",
"second_other": "{{count}} seconds",
"time": "time" "time": "time"
}, },
"title": "title", "title": "title",

View File

@ -335,8 +335,8 @@
"minting": "(acuñado)", "minting": "(acuñado)",
"not_minting": "(no acuñar)", "not_minting": "(no acuñar)",
"no_status": "sin estado", "no_status": "sin estado",
"synchronized": "sincronizado", "synchronized": "sincronizado ({{ percent }}%)",
"synchronizing": "sincronización..." "synchronizing": "sincronización ({{ percent }}%)..."
}, },
"status_title": "estado de acuñación", "status_title": "estado de acuñación",
"tier_share_per_block": "porción del nivel por bloque", "tier_share_per_block": "porción del nivel por bloque",

View File

@ -335,8 +335,8 @@
"minting": "(Frappe)", "minting": "(Frappe)",
"not_minting": "(pas de la frappe)", "not_minting": "(pas de la frappe)",
"no_status": "pas de statut", "no_status": "pas de statut",
"synchronized": "synchronisé", "synchronized": "synchronisé ({{ percent }}%)",
"synchronizing": "synchronisation..." "synchronizing": "synchronisation ({{ percent }}%)..."
}, },
"status_title": "statut de frappe", "status_title": "statut de frappe",
"tier_share_per_block": "part du niveau par bloc", "tier_share_per_block": "part du niveau par bloc",

View File

@ -334,8 +334,8 @@
"minting": "(minting)", "minting": "(minting)",
"not_minting": "(non minting)", "not_minting": "(non minting)",
"no_status": "nessun stato", "no_status": "nessun stato",
"synchronized": "sincronizzato", "synchronized": "sincronizzato ({{ percent }}%)",
"synchronizing": "sincronizzazione..." "synchronizing": "sincronizzazione ({{ percent }}%)..."
}, },
"status_title": "stato minting", "status_title": "stato minting",
"tier_share_per_block": "quota della fascia per blocco", "tier_share_per_block": "quota della fascia per blocco",

View File

@ -335,8 +335,8 @@
"minting": "(鋳造)", "minting": "(鋳造)",
"not_minting": "(造りではありません)", "not_minting": "(造りではありません)",
"no_status": "ステータスなし", "no_status": "ステータスなし",
"synchronized": "同期", "synchronized": "同期 ({{ percent }}%)",
"synchronizing": "同期..." "synchronizing": "同期 ({{ percent }}%)..."
}, },
"status_title": "ミントステータス", "status_title": "ミントステータス",
"tier_share_per_block": "ブロックごとのティアシェア", "tier_share_per_block": "ブロックごとのティアシェア",

View File

@ -335,8 +335,8 @@
"minting": "(добыча)", "minting": "(добыча)",
"not_minting": "(не шахта)", "not_minting": "(не шахта)",
"no_status": "нет статуса", "no_status": "нет статуса",
"synchronized": "синхронизированный", "synchronized": "синхронизированный ({{ percent }}%)",
"synchronizing": "синхронизация..." "synchronizing": "синхронизация ({{ percent }}%)..."
}, },
"status_title": "Статус майтинга", "status_title": "Статус майтинга",
"tier_share_per_block": "доля уровня за блок", "tier_share_per_block": "доля уровня за блок",

View File

@ -335,8 +335,8 @@
"minting": "(铸造)", "minting": "(铸造)",
"not_minting": "(不是铸造)", "not_minting": "(不是铸造)",
"no_status": "没有状态", "no_status": "没有状态",
"synchronized": "同步", "synchronized": "同步 ({{ percent }}%)",
"synchronizing": "同步..." "synchronizing": "同步 ({{ percent }}%)..."
}, },
"status_title": "铸造状态", "status_title": "铸造状态",
"tier_share_per_block": "每个区块的等级份额", "tier_share_per_block": "每个区块的等级份额",

View File

@ -71,7 +71,7 @@ async function uploadChunkWithRetry(endpoint, formData, index, maxRetries = 3) {
if (attempt >= maxRetries) { if (attempt >= maxRetries) {
throw new Error(`Chunk ${index} failed after ${maxRetries} attempts`); throw new Error(`Chunk ${index} failed after ${maxRetries} attempts`);
} }
// Wait 10 seconds before next retry // Wait 25 seconds before next retry
await new Promise((res) => setTimeout(res, 25_000)); await new Promise((res) => setTimeout(res, 25_000));
} }
} }

View File

@ -1546,7 +1546,6 @@ function setupMessageListenerQortalRequest() {
request.payload, request.payload,
isFromExtension isFromExtension
); );
event.source.postMessage( event.source.postMessage(
{ {
requestId: request.requestId, requestId: request.requestId,

View File

@ -19,7 +19,7 @@ export const decryptStoredWallet = async (password, wallet) => {
.process(encryptedSeedBytes) .process(encryptedSeedBytes)
.finish().result; .finish().result;
if (Base58.encode(mac) !== wallet.mac) { if (Base58.encode(mac) !== wallet.mac) {
throw new Error(i18n.t('auth:message.error.incorrect_password')); // TODO: i18n non-react integration throw new Error(i18n.t('auth:message.error.incorrect_password'));
} }
const decryptedBytes = AES_CBC.decrypt( const decryptedBytes = AES_CBC.decrypt(
encryptedSeedBytes, encryptedSeedBytes,