diff --git a/src/App.tsx b/src/App.tsx index 0f92b54..8dc9387 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -148,6 +148,7 @@ import { UserLookup } from "./components/UserLookup.tsx/UserLookup"; import { RegisterName } from "./components/RegisterName"; import { BuyQortInformation } from "./components/BuyQortInformation"; import { InstallPWA } from "./components/InstallPWA"; +import { QortPayment } from "./components/QortPayment"; type extStates = @@ -860,53 +861,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); - window - .sendMessage("sendCoin", { - amount: Number(paymentAmount), - receiver: paymentTo.trim(), - password: paymentPassword, - }) - .then((response) => { - if (response?.error) { - setSendPaymentError(response.error); - } else { - setIsOpenSendQort(false); - setIsOpenSendQortSuccess(true); - } - setIsLoading(false); - }) - .catch((error) => { - console.error("Failed to send coin:", error); - setIsLoading(false); - }); - } catch (error) { - //error - } - - }; + const clearAllStates = () => { setRequestConnection(null); @@ -1971,95 +1926,12 @@ function App() { src={Return} /> - - - - 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 d1d5ea3..249ccec 100644 --- a/src/components/Apps/useQortalMessageListener.tsx +++ b/src/components/Apps/useQortalMessageListener.tsx @@ -175,41 +175,85 @@ export function openIndexedDB() { } 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', + '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' + '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' ] @@ -222,7 +266,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', 'SIGN_TRANSACTION', 'ADMIN_ACTION', 'OPEN_NEW_TAB', 'CREATE_AND_COPY_EMBED_LINK', 'DECRYPT_QORTAL_GROUP_DATA', 'DECRYPT_DATA_WITH_SHARING_KEY', 'DELETE_HOSTED_DATA', 'GET_HOSTED_DATA', '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', 'SIGN_TRANSACTION', 'ADMIN_ACTION', 'OPEN_NEW_TAB', 'CREATE_AND_COPY_EMBED_LINK', 'DECRYPT_QORTAL_GROUP_DATA', 'DECRYPT_DATA_WITH_SHARING_KEY', 'DELETE_HOSTED_DATA', 'GET_HOSTED_DATA', '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..6add9b2 --- /dev/null +++ b/src/components/QortPayment.tsx @@ -0,0 +1,167 @@ +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); + window + .sendMessage("sendCoin", { + amount: Number(paymentAmount), + receiver: paymentTo.trim(), + password: paymentPassword, + }) + .then((response) => { + if (response?.error) { + setSendPaymentError(response.error); + } else { + onSuccess() + + } + setIsLoadingSendCoin(false); + }) + .catch((error) => { + console.error("Failed to send coin:", error); + 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 556f2de..116a50a 100644 --- a/src/qortalRequests.ts +++ b/src/qortalRequests.ts @@ -1,6 +1,6 @@ import { gateways, getApiKeyFromStorage } from "./background"; import { listOfAllQortalRequests } from "./components/Apps/useQortalMessageListener"; -import { addForeignServer, addGroupAdminRequest, addListItems, adminAction, banFromGroupRequest, cancelGroupBanRequest, cancelGroupInviteRequest, cancelSellOrder, createAndCopyEmbedLink, createBuyOrder, createGroupRequest, createPoll, 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, openNewTab, 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, createAndCopyEmbedLink, createBuyOrder, createGroupRequest, createPoll, 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, openNewTab, publishMultipleQDNResources, publishQDNResource, registerNameRequest, removeForeignServer, removeGroupAdminRequest, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, signTransaction, updateForeignFee, updateNameRequest, voteOnPoll } from "./qortalRequests/get"; import { getData, storeData } from "./utils/chromeStorage"; @@ -1122,6 +1122,45 @@ export const isRunningGateway = async ()=> { } break; } + case "GET_NODE_INFO": { + try { + const res = await getNodeInfo(); + event.source.postMessage({ + requestId: request.requestId, + action: request.action, + payload: res, + type: "backgroundMessageResponse", + }, event.origin); + } catch (error) { + event.source.postMessage({ + requestId: request.requestId, + action: request.action, + error: error.message, + type: "backgroundMessageResponse", + }, event.origin); + } + break; + } + + case "GET_NODE_STATUS": { + try { + const res = await getNodeStatus(); + event.source.postMessage({ + requestId: request.requestId, + action: request.action, + payload: res, + type: "backgroundMessageResponse", + }, event.origin); + } catch (error) { + event.source.postMessage({ + requestId: request.requestId, + action: request.action, + error: error.message, + type: "backgroundMessageResponse", + }, event.origin); + } + break; + } default: break; } diff --git a/src/qortalRequests/get.ts b/src/qortalRequests/get.ts index 351eabf..c7e4cf7 100644 --- a/src/qortalRequests/get.ts +++ b/src/qortalRequests/get.ts @@ -4416,4 +4416,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