From afa1ca9627d90978c4631e5418ccd30cd1ef5b27 Mon Sep 17 00:00:00 2001 From: PhilReact Date: Thu, 6 Mar 2025 17:46:20 +0200 Subject: [PATCH] added qortalRequests and payment component --- src/App.tsx | 144 +-------------- .../Apps/useQortalMessageListener.tsx | 6 +- src/components/QortPayment.tsx | 169 ++++++++++++++++++ src/qortalRequests.ts | 143 +++++++++++---- src/qortalRequests/get.ts | 62 +++++++ 5 files changed, 349 insertions(+), 175 deletions(-) create mode 100644 src/components/QortPayment.tsx diff --git a/src/App.tsx b/src/App.tsx index e15a478..df12157 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -136,6 +136,7 @@ import { RegisterName } from "./components/RegisterName"; import { BuyQortInformation } from "./components/BuyQortInformation"; import { WalletIcon } from "./assets/Icons/WalletIcon"; import { useBlockedAddresses } from "./components/Chat/useBlockUsers"; +import { QortPayment } from "./components/QortPayment"; type extStates = | "not-authenticated" @@ -677,55 +678,7 @@ function App() { setLtcBalanceLoading(false); }); }; - const sendCoinFunc = async () => { - try { - setSendPaymentError(""); - setSendPaymentSuccess(""); - if (!paymentTo) { - setSendPaymentError("Please enter a recipient"); - return; - } - if (!paymentAmount) { - setSendPaymentError("Please enter an amount greater than 0"); - return; - } - if (!paymentPassword) { - setSendPaymentError("Please enter your wallet password"); - return; - } - const fee = await getFee('PAYMENT') - - await show({ - message: `Would you like to transfer ${Number(paymentAmount)} QORT?` , - paymentFee: fee.fee + ' QORT' - }) - setIsLoading(true); - chrome?.runtime?.sendMessage( - { - action: "sendCoin", - payload: { - amount: Number(paymentAmount), - receiver: paymentTo.trim(), - password: paymentPassword, - }, - }, - (response) => { - if (response?.error) { - setSendPaymentError(response.error); - } else { - setIsOpenSendQort(false); - setIsOpenSendQortSuccess(true); - // setExtstate("transfer-success-regular"); - // setSendPaymentSuccess("Payment successfully sent"); - } - setIsLoading(false); - } - ); - } catch (error) { - //error - } - - }; + const clearAllStates = () => { setRequestConnection(null); @@ -2173,95 +2126,14 @@ function App() { /> - - - Transfer QORT - - - - Balance: - - - {balance?.toFixed(2)} QORT - - - + - - To - - setPaymentTo(e.target.value)} - autoComplete="off" + { + setIsOpenSendQort(false); + setIsOpenSendQortSuccess(true); + }} + defaultPaymentTo={paymentTo} /> - - - Amount - - - setPaymentAmount(+e)} - /> - - - Confirm Wallet Password - - - setPaymentPassword(e.target.value)} - autoComplete="off" - - /> - - - {sendPaymentError} - {/* {sendPaymentSuccess} */} - - { - sendCoinFunc(); - }} - > - Send - )} diff --git a/src/components/Apps/useQortalMessageListener.tsx b/src/components/Apps/useQortalMessageListener.tsx index d688469..156cae1 100644 --- a/src/components/Apps/useQortalMessageListener.tsx +++ b/src/components/Apps/useQortalMessageListener.tsx @@ -6,6 +6,8 @@ import { navigationControllerAtom } from '../../atoms/global'; import { extractComponents } from '../Chat/MessageDisplay'; + + const missingFieldsFunc = (data, requiredFields)=> { const missingFields: string[] = []; requiredFields.forEach((field) => { @@ -234,6 +236,7 @@ async function handleGetFileFromIndexedDB(fileId, sendResponse) { + const UIQortalRequests = [ 'GET_USER_ACCOUNT', 'DECRYPT_DATA', 'SEND_COIN', 'GET_LIST_ITEMS', @@ -243,7 +246,8 @@ const UIQortalRequests = [ 'GET_TX_ACTIVITY_SUMMARY', 'GET_FOREIGN_FEE', 'UPDATE_FOREIGN_FEE', 'GET_SERVER_CONNECTION_HISTORY', 'SET_CURRENT_FOREIGN_SERVER', 'ADD_FOREIGN_SERVER', 'REMOVE_FOREIGN_SERVER', 'GET_DAY_SUMMARY', 'CREATE_TRADE_BUY_ORDER', - 'CREATE_TRADE_SELL_ORDER', 'CANCEL_TRADE_SELL_ORDER', 'IS_USING_PUBLIC_NODE', 'ADMIN_ACTION', 'SIGN_TRANSACTION', 'DECRYPT_QORTAL_GROUP_DATA', 'DELETE_HOSTED_DATA', 'GET_HOSTED_DATA', 'DECRYPT_DATA_WITH_SHARING_KEY', 'SHOW_ACTIONS', 'REGISTER_NAME', 'UPDATE_NAME', 'LEAVE_GROUP', 'INVITE_TO_GROUP', 'KICK_FROM_GROUP', 'BAN_FROM_GROUP', 'CANCEL_GROUP_BAN', 'ADD_GROUP_ADMIN','REMOVE_GROUP_ADMIN','DECRYPT_AESGCM', 'CANCEL_GROUP_INVITE', 'CREATE_GROUP', 'GET_USER_WALLET_TRANSACTIONS' + 'CREATE_TRADE_SELL_ORDER', 'CANCEL_TRADE_SELL_ORDER', 'IS_USING_PUBLIC_NODE', 'ADMIN_ACTION', 'SIGN_TRANSACTION', 'DECRYPT_QORTAL_GROUP_DATA', 'DELETE_HOSTED_DATA', 'GET_HOSTED_DATA', 'DECRYPT_DATA_WITH_SHARING_KEY', 'SHOW_ACTIONS', 'REGISTER_NAME', 'UPDATE_NAME', 'LEAVE_GROUP', 'INVITE_TO_GROUP', 'KICK_FROM_GROUP', 'BAN_FROM_GROUP', 'CANCEL_GROUP_BAN', 'ADD_GROUP_ADMIN','REMOVE_GROUP_ADMIN','DECRYPT_AESGCM', 'CANCEL_GROUP_INVITE', 'CREATE_GROUP', 'GET_USER_WALLET_TRANSACTIONS', 'GET_NODE_INFO', + 'GET_NODE_STATUS' ]; diff --git a/src/components/QortPayment.tsx b/src/components/QortPayment.tsx new file mode 100644 index 0000000..3b3d572 --- /dev/null +++ b/src/components/QortPayment.tsx @@ -0,0 +1,169 @@ +import { Box, CircularProgress } from '@mui/material'; +import React, { useEffect, useState } from 'react' +import { CustomButton, CustomInput, CustomLabel, TextP } from '../App-styles'; +import { Spacer } from '../common/Spacer'; +import BoundedNumericTextField from '../common/BoundedNumericTextField'; +import { PasswordField } from './PasswordField/PasswordField'; +import { ErrorText } from './ErrorText/ErrorText'; +import { getFee } from '../background'; + +export const QortPayment = ({balance, show, onSuccess, defaultPaymentTo}) => { + const [paymentTo, setPaymentTo] = useState(defaultPaymentTo); + const [paymentAmount, setPaymentAmount] = useState(0); + const [paymentPassword, setPaymentPassword] = useState(""); + const [sendPaymentError, setSendPaymentError] = useState(""); + const [sendPaymentSuccess, setSendPaymentSuccess] = useState(""); + const [isLoadingSendCoin, setIsLoadingSendCoin] = useState(false); + + const sendCoinFunc = async () => { + try { + setSendPaymentError(""); + setSendPaymentSuccess(""); + if (!paymentTo) { + setSendPaymentError("Please enter a recipient"); + return; + } + if (!paymentAmount) { + setSendPaymentError("Please enter an amount greater than 0"); + return; + } + if (!paymentPassword) { + setSendPaymentError("Please enter your wallet password"); + return; + } + const fee = await getFee('PAYMENT') + + await show({ + message: `Would you like to transfer ${Number(paymentAmount)} QORT?` , + paymentFee: fee.fee + ' QORT' + }) + setIsLoadingSendCoin(true); + chrome?.runtime?.sendMessage( + { + action: "sendCoin", + payload: { + amount: Number(paymentAmount), + receiver: paymentTo.trim(), + password: paymentPassword, + }, + }, + (response) => { + if (response?.error) { + setSendPaymentError(response.error); + } else { + onSuccess() + // setExtstate("transfer-success-regular"); + // setSendPaymentSuccess("Payment successfully sent"); + } + setIsLoadingSendCoin(false); + } + ); + } catch (error) { + //error + } + + }; + + + return ( + <> + + + Transfer QORT + + + + Balance: + + + {balance?.toFixed(2)} QORT + + + + + + To + + setPaymentTo(e.target.value)} + autoComplete="off" + /> + + + Amount + + + setPaymentAmount(+e)} + /> + + + Confirm Wallet Password + + + setPaymentPassword(e.target.value)} + autoComplete="off" + /> + + + {sendPaymentError} + {/* {sendPaymentSuccess} */} + + { + if(isLoadingSendCoin) return + sendCoinFunc(); + }} + > + {isLoadingSendCoin && ( + + )} + Send + + + ) +} diff --git a/src/qortalRequests.ts b/src/qortalRequests.ts index f29699f..c860914 100644 --- a/src/qortalRequests.ts +++ b/src/qortalRequests.ts @@ -1,43 +1,87 @@ import { banFromGroup, gateways, getApiKeyFromStorage } from "./background"; -import { addForeignServer, addGroupAdminRequest, addListItems, adminAction, banFromGroupRequest, cancelGroupBanRequest, cancelGroupInviteRequest, cancelSellOrder, createBuyOrder, createGroupRequest, createPoll, createSellOrder, decryptAESGCMRequest, decryptData, decryptDataWithSharingKey, decryptQortalGroupData, deleteHostedData, deleteListItems, deployAt, encryptData, encryptDataWithSharingKey, encryptQortalGroupData, getCrossChainServerInfo, getDaySummary, getForeignFee, getHostedData, getListItems, getServerConnectionHistory, getTxActivitySummary, getUserAccount, getUserWallet, getUserWalletInfo, getUserWalletTransactions, getWalletBalance, inviteToGroupRequest, joinGroup, kickFromGroupRequest, leaveGroupRequest, publishMultipleQDNResources, publishQDNResource, registerNameRequest, removeForeignServer, removeGroupAdminRequest, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, signTransaction, updateForeignFee, updateNameRequest, voteOnPoll } from "./qortalRequests/get"; +import { addForeignServer, addGroupAdminRequest, addListItems, adminAction, banFromGroupRequest, cancelGroupBanRequest, cancelGroupInviteRequest, cancelSellOrder, createBuyOrder, createGroupRequest, createPoll, createSellOrder, decryptAESGCMRequest, decryptData, decryptDataWithSharingKey, decryptQortalGroupData, deleteHostedData, deleteListItems, deployAt, encryptData, encryptDataWithSharingKey, encryptQortalGroupData, getCrossChainServerInfo, getDaySummary, getForeignFee, getHostedData, getListItems, getNodeInfo, getNodeStatus, getServerConnectionHistory, getTxActivitySummary, getUserAccount, getUserWallet, getUserWalletInfo, getUserWalletTransactions, getWalletBalance, inviteToGroupRequest, joinGroup, kickFromGroupRequest, leaveGroupRequest, publishMultipleQDNResources, publishQDNResource, registerNameRequest, removeForeignServer, removeGroupAdminRequest, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, signTransaction, updateForeignFee, updateNameRequest, voteOnPoll } from "./qortalRequests/get"; - const listOfAllQortalRequests = [ - 'GET_USER_ACCOUNT', 'DECRYPT_DATA', 'SEND_COIN', 'GET_LIST_ITEMS', - 'ADD_LIST_ITEMS', 'DELETE_LIST_ITEM', 'VOTE_ON_POLL', 'CREATE_POLL', - 'SEND_CHAT_MESSAGE', 'JOIN_GROUP', 'DEPLOY_AT', 'GET_USER_WALLET', - 'GET_WALLET_BALANCE', 'GET_USER_WALLET_INFO', 'GET_CROSSCHAIN_SERVER_INFO', - 'GET_TX_ACTIVITY_SUMMARY', 'GET_FOREIGN_FEE', 'UPDATE_FOREIGN_FEE', - 'GET_SERVER_CONNECTION_HISTORY', 'SET_CURRENT_FOREIGN_SERVER', - 'ADD_FOREIGN_SERVER', 'REMOVE_FOREIGN_SERVER', 'GET_DAY_SUMMARY', 'CREATE_TRADE_BUY_ORDER', 'CREATE_TRADE_SELL_ORDER', 'CANCEL_TRADE_SELL_ORDER', 'IS_USING_PUBLIC_NODE', 'ADMIN_ACTION', 'SIGN_TRANSACTION', 'OPEN_NEW_TAB', 'CREATE_AND_COPY_EMBED_LINK', 'DECRYPT_QORTAL_GROUP_DATA', 'DECRYPT_DATA_WITH_SHARING_KEY', 'DELETE_HOSTED_DATA', 'GET_HOSTED_DATA', 'PUBLISH_MULTIPLE_QDN_RESOURCES', - 'PUBLISH_QDN_RESOURCE', - 'ENCRYPT_DATA', - 'ENCRYPT_DATA_WITH_SHARING_KEY', - 'ENCRYPT_QORTAL_GROUP_DATA', - 'SAVE_FILE', - 'GET_ACCOUNT_DATA', - 'GET_ACCOUNT_NAMES', - 'SEARCH_NAMES', - 'GET_NAME_DATA', - 'GET_QDN_RESOURCE_URL', - 'LINK_TO_QDN_RESOURCE', - 'LIST_QDN_RESOURCES', - 'SEARCH_QDN_RESOURCES', - 'FETCH_QDN_RESOURCE', - 'GET_QDN_RESOURCE_STATUS', - 'GET_QDN_RESOURCE_PROPERTIES', - 'GET_QDN_RESOURCE_METADATA', - 'SEARCH_CHAT_MESSAGES', - 'LIST_GROUPS', - 'GET_BALANCE', - 'GET_AT', - 'GET_AT_DATA', - 'LIST_ATS', - 'FETCH_BLOCK', - 'FETCH_BLOCK_RANGE', - 'SEARCH_TRANSACTIONS', - 'GET_PRICE', - 'SHOW_ACTIONS' -] + export const listOfAllQortalRequests = [ + 'GET_USER_ACCOUNT', + 'DECRYPT_DATA', + 'SEND_COIN', + 'GET_LIST_ITEMS', + 'ADD_LIST_ITEMS', + 'DELETE_LIST_ITEM', + 'VOTE_ON_POLL', + 'CREATE_POLL', + 'SEND_CHAT_MESSAGE', + 'JOIN_GROUP', + 'DEPLOY_AT', + 'GET_USER_WALLET', + 'GET_WALLET_BALANCE', + 'GET_USER_WALLET_INFO', + 'GET_CROSSCHAIN_SERVER_INFO', + 'GET_TX_ACTIVITY_SUMMARY', + 'GET_FOREIGN_FEE', + 'UPDATE_FOREIGN_FEE', + 'GET_SERVER_CONNECTION_HISTORY', + 'SET_CURRENT_FOREIGN_SERVER', + 'ADD_FOREIGN_SERVER', + 'REMOVE_FOREIGN_SERVER', + 'GET_DAY_SUMMARY', + 'CREATE_TRADE_BUY_ORDER', + 'CREATE_TRADE_SELL_ORDER', + 'CANCEL_TRADE_SELL_ORDER', + 'IS_USING_PUBLIC_NODE', + 'ADMIN_ACTION', + 'SIGN_TRANSACTION', + 'OPEN_NEW_TAB', + 'CREATE_AND_COPY_EMBED_LINK', + 'DECRYPT_QORTAL_GROUP_DATA', + 'DECRYPT_DATA_WITH_SHARING_KEY', + 'DELETE_HOSTED_DATA', + 'GET_HOSTED_DATA', + 'PUBLISH_MULTIPLE_QDN_RESOURCES', + 'PUBLISH_QDN_RESOURCE', + 'ENCRYPT_DATA', + 'ENCRYPT_DATA_WITH_SHARING_KEY', + 'ENCRYPT_QORTAL_GROUP_DATA', + 'SAVE_FILE', + 'GET_ACCOUNT_DATA', + 'GET_ACCOUNT_NAMES', + 'SEARCH_NAMES', + 'GET_NAME_DATA', + 'GET_QDN_RESOURCE_URL', + 'LINK_TO_QDN_RESOURCE', + 'LIST_QDN_RESOURCES', + 'SEARCH_QDN_RESOURCES', + 'FETCH_QDN_RESOURCE', + 'GET_QDN_RESOURCE_STATUS', + 'GET_QDN_RESOURCE_PROPERTIES', + 'GET_QDN_RESOURCE_METADATA', + 'SEARCH_CHAT_MESSAGES', + 'LIST_GROUPS', + 'GET_BALANCE', + 'GET_AT', + 'GET_AT_DATA', + 'LIST_ATS', + 'FETCH_BLOCK', + 'FETCH_BLOCK_RANGE', + 'SEARCH_TRANSACTIONS', + 'GET_PRICE', + 'SHOW_ACTIONS', + 'REGISTER_NAME', + 'UPDATE_NAME', + 'LEAVE_GROUP', + 'INVITE_TO_GROUP', + 'KICK_FROM_GROUP', + 'BAN_FROM_GROUP', + 'CANCEL_GROUP_BAN', + 'ADD_GROUP_ADMIN', + 'REMOVE_GROUP_ADMIN', + 'DECRYPT_AESGCM', + 'CANCEL_GROUP_INVITE', + 'CREATE_GROUP', + 'GET_USER_WALLET_TRANSACTIONS', + 'GET_NODE_INFO', + 'GET_NODE_STATUS' + ] // Promisify chrome.storage.local.get function getLocalStorage(key) { @@ -770,6 +814,29 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { break; } + case "GET_NODE_INFO" : { + + getNodeInfo() + .then((res) => { + sendResponse(res); + }) + .catch((error) => { + sendResponse({ error: error.message }); + }); + break; + } + case "GET_NODE_STATUS" : { + + getNodeStatus() + .then((res) => { + sendResponse(res); + }) + .catch((error) => { + sendResponse({ error: error.message }); + }); + break; + } + } } return true; diff --git a/src/qortalRequests/get.ts b/src/qortalRequests/get.ts index 17667bb..07d1fa4 100644 --- a/src/qortalRequests/get.ts +++ b/src/qortalRequests/get.ts @@ -4473,4 +4473,66 @@ if (resPermission) { } else { throw new Error("User declined request"); } +}; + +export const getNodeInfo = async () => { + const url = `/admin/info`; // Simplified endpoint URL + + try { + const endpoint = await createEndpoint(url); // Assuming createEndpoint is available for constructing the full URL + const response = await fetch(endpoint, { + method: "GET", + headers: { + Accept: "*/*", + }, + }); + + if (!response.ok) throw new Error("Failed to retrieve node info"); + + let res; + try { + res = await response.clone().json(); + } catch (e) { + res = await response.text(); + } + + if (res?.error && res?.message) { + throw new Error(res.message); + } + + return res; // Return the full response + } catch (error) { + throw new Error(error?.message || "Error in retrieving node info"); + } +}; + +export const getNodeStatus = async () => { + const url = `/admin/status`; // Simplified endpoint URL + + try { + const endpoint = await createEndpoint(url); // Assuming createEndpoint is available for constructing the full URL + const response = await fetch(endpoint, { + method: "GET", + headers: { + Accept: "*/*", + }, + }); + + if (!response.ok) throw new Error("Failed to retrieve node status"); + + let res; + try { + res = await response.clone().json(); + } catch (e) { + res = await response.text(); + } + + if (res?.error && res?.message) { + throw new Error(res.message); + } + + return res; // Return the full response + } catch (error) { + throw new Error(error?.message || "Error in retrieving node status"); + } }; \ No newline at end of file