mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-04-23 19:37:52 +00:00
added trade qortalrequests
This commit is contained in:
parent
40e8e316a8
commit
7a6a07c6e5
@ -15,23 +15,23 @@ import { myCapacitorApp } from '.';
|
|||||||
|
|
||||||
|
|
||||||
const defaultDomains = [
|
const defaultDomains = [
|
||||||
|
'capacitor-electron://-',
|
||||||
'http://127.0.0.1:12391',
|
'http://127.0.0.1:12391',
|
||||||
'ws://127.0.0.1:12391',
|
'ws://127.0.0.1:12391',
|
||||||
'https://ext-node.qortal.link',
|
'https://ext-node.qortal.link',
|
||||||
'wss://ext-node.qortal.link',
|
'wss://ext-node.qortal.link',
|
||||||
'https://appnode.qortal.org',
|
'https://appnode.qortal.org',
|
||||||
'wss://appnode.qortal.org',
|
'wss://appnode.qortal.org',
|
||||||
"https://api.qortal.org",
|
"https://api.qortal.org",
|
||||||
"https://api2.qortal.org",
|
"https://api2.qortal.org",
|
||||||
"https://appnode.qortal.org",
|
"https://apinode.qortalnodes.live",
|
||||||
"https://apinode.qortalnodes.live",
|
|
||||||
"https://apinode1.qortalnodes.live",
|
"https://apinode1.qortalnodes.live",
|
||||||
"https://apinode2.qortalnodes.live",
|
"https://apinode2.qortalnodes.live",
|
||||||
"https://apinode3.qortalnodes.live",
|
"https://apinode3.qortalnodes.live",
|
||||||
"https://apinode4.qortalnodes.live",
|
"https://apinode4.qortalnodes.live",
|
||||||
"https://www.qort.trade"
|
"https://www.qort.trade"
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// let allowedDomains: string[] = [...defaultDomains]
|
// let allowedDomains: string[] = [...defaultDomains]
|
||||||
const domainHolder = {
|
const domainHolder = {
|
||||||
allowedDomains: [...defaultDomains],
|
allowedDomains: [...defaultDomains],
|
||||||
@ -144,9 +144,7 @@ export class ElectronCapacitorApp {
|
|||||||
contextIsolation: true,
|
contextIsolation: true,
|
||||||
// Use preload to inject the electron varriant overrides for capacitor plugins.
|
// Use preload to inject the electron varriant overrides for capacitor plugins.
|
||||||
// preload: join(app.getAppPath(), "node_modules", "@capacitor-community", "electron", "dist", "runtime", "electron-rt.js"),
|
// preload: join(app.getAppPath(), "node_modules", "@capacitor-community", "electron", "dist", "runtime", "electron-rt.js"),
|
||||||
preload: preloadPath,
|
preload: preloadPath },
|
||||||
webSecurity: false
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
this.mainWindowState.manage(this.MainWindow);
|
this.mainWindowState.manage(this.MainWindow);
|
||||||
|
|
||||||
@ -242,58 +240,100 @@ export class ElectronCapacitorApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a CSP up for our application based on the custom scheme
|
|
||||||
// export function setupContentSecurityPolicy(customScheme: string): void {
|
|
||||||
// session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
|
||||||
// callback({
|
|
||||||
// responseHeaders: {
|
|
||||||
// ...details.responseHeaders,
|
|
||||||
// 'Content-Security-Policy': [
|
|
||||||
// "script-src 'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval'; object-src 'self'; connect-src 'self' https://*:* http://*:* wss://*:* ws://*:*",
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
export function setupContentSecurityPolicy(customScheme: string): void {
|
export function setupContentSecurityPolicy(customScheme: string): void {
|
||||||
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
session.defaultSession.webRequest.onHeadersReceived((details: any, callback) => {
|
||||||
const allowedSources = ["'self'", ...domainHolder.allowedDomains].join(' ');
|
const allowedSources = ["'self'", customScheme, ...domainHolder.allowedDomains];
|
||||||
const csp = `
|
const connectSources = [...allowedSources];
|
||||||
script-src 'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' ${allowedSources};
|
const frameSources = [
|
||||||
object-src 'self';
|
"'self'",
|
||||||
connect-src ${allowedSources};
|
'http://localhost:*',
|
||||||
`.replace(/\s+/g, ' ').trim();
|
'https://localhost:*',
|
||||||
|
'http://127.0.0.1:*',
|
||||||
|
'https://127.0.0.1:*',
|
||||||
|
...allowedSources,
|
||||||
|
];
|
||||||
|
|
||||||
callback({
|
// Create the Content Security Policy (CSP) string
|
||||||
responseHeaders: {
|
const csp = `
|
||||||
...details.responseHeaders,
|
default-src 'self' ${allowedSources.join(' ')};
|
||||||
'Content-Security-Policy': [csp],
|
frame-src ${frameSources.join(' ')};
|
||||||
},
|
script-src 'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' ${allowedSources.join(' ')};
|
||||||
});
|
object-src 'self';
|
||||||
});
|
connect-src ${connectSources.join(' ')};
|
||||||
|
img-src 'self' data: blob: ${allowedSources.join(' ')};
|
||||||
|
style-src 'self' 'unsafe-inline';
|
||||||
|
font-src 'self' data:;
|
||||||
|
`.replace(/\s+/g, ' ').trim();
|
||||||
|
|
||||||
|
// Get the request URL and origin
|
||||||
|
const requestUrl = details.url;
|
||||||
|
const requestOrigin = details.origin || details.referrer || 'capacitor-electron://-';
|
||||||
|
|
||||||
|
// Parse the request URL to get its origin
|
||||||
|
let requestUrlOrigin: string;
|
||||||
|
try {
|
||||||
|
const parsedUrl = new URL(requestUrl);
|
||||||
|
requestUrlOrigin = parsedUrl.origin;
|
||||||
|
} catch (e) {
|
||||||
|
// Handle invalid URLs gracefully
|
||||||
|
requestUrlOrigin = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if the request is cross-origin
|
||||||
|
const isCrossOrigin = requestOrigin !== requestUrlOrigin;
|
||||||
|
|
||||||
|
// Check if the response already includes Access-Control-Allow-Origin
|
||||||
|
const hasAccessControlAllowOrigin = Object.keys(details.responseHeaders).some(
|
||||||
|
(header) => header.toLowerCase() === 'access-control-allow-origin'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Prepare response headers
|
||||||
|
const responseHeaders: Record<string, string | string[]> = {
|
||||||
|
...details.responseHeaders,
|
||||||
|
'Content-Security-Policy': [csp],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isCrossOrigin && !hasAccessControlAllowOrigin) {
|
||||||
|
// Handle CORS for cross-origin requests lacking CORS headers
|
||||||
|
// Optionally, check if the requestOrigin is allowed
|
||||||
|
responseHeaders['Access-Control-Allow-Origin'] = requestOrigin;
|
||||||
|
responseHeaders['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS, DELETE';
|
||||||
|
responseHeaders['Access-Control-Allow-Headers'] = 'Content-Type, Authorization, x-api-key';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback with modified headers
|
||||||
|
callback({ responseHeaders });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// IPC listener for updating allowed domains
|
// IPC listener for updating allowed domains
|
||||||
ipcMain.on('set-allowed-domains', (event, domains: string[]) => {
|
ipcMain.on('set-allowed-domains', (event, domains: string[]) => {
|
||||||
|
|
||||||
// Validate and transform user-provided domains
|
// Validate and transform user-provided domains
|
||||||
const validatedUserDomains = domains
|
const validatedUserDomains = domains
|
||||||
.flatMap((domain) => {
|
.flatMap((domain) => {
|
||||||
try {
|
try {
|
||||||
const url = new URL(domain);
|
const url = new URL(domain);
|
||||||
const protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
const protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||||
const socketUrl = `${protocol}//${url.hostname}${url.port ? ':' + url.port : ''}`;
|
const socketUrl = `${protocol}//${url.hostname}${url.port ? ':' + url.port : ''}`;
|
||||||
return [url.origin, socketUrl];
|
return [url.origin, socketUrl];
|
||||||
} catch {
|
} catch {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter(Boolean) as string[];
|
.filter(Boolean) as string[];
|
||||||
|
|
||||||
// Combine default and validated user domains
|
// Combine default and validated user domains
|
||||||
const newAllowedDomains = [...new Set([...defaultDomains, ...validatedUserDomains])];
|
const newAllowedDomains = [...new Set([...defaultDomains, ...validatedUserDomains])];
|
||||||
|
19
src/App.tsx
19
src/App.tsx
@ -2744,6 +2744,25 @@ await showInfo({
|
|||||||
<Spacer height="15px" />
|
<Spacer height="15px" />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{messageQortalRequestExtension?.foreignFee && (
|
||||||
|
<>
|
||||||
|
<Spacer height="15px" />
|
||||||
|
|
||||||
|
<TextP
|
||||||
|
sx={{
|
||||||
|
textAlign: "center",
|
||||||
|
lineHeight: 1.2,
|
||||||
|
fontSize: "16px",
|
||||||
|
fontWeight: "normal",
|
||||||
|
maxWidth: "90%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{"Foreign Fee: "}
|
||||||
|
{messageQortalRequestExtension?.foreignFee}
|
||||||
|
</TextP>
|
||||||
|
<Spacer height="15px" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
{messageQortalRequestExtension?.checkbox1 && (
|
{messageQortalRequestExtension?.checkbox1 && (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -107,6 +107,9 @@ export function getProtocol(url) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const gateways = ['ext-node.qortal.link']
|
||||||
|
|
||||||
|
|
||||||
let lastGroupNotification;
|
let lastGroupNotification;
|
||||||
export const groupApi = "https://ext-node.qortal.link";
|
export const groupApi = "https://ext-node.qortal.link";
|
||||||
export const groupApiSocket = "wss://ext-node.qortal.link";
|
export const groupApiSocket = "wss://ext-node.qortal.link";
|
||||||
@ -221,6 +224,19 @@ export const clearAllQueues = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getForeignKey = async (foreignBlockchain)=> {
|
||||||
|
const resKeyPair = await getKeyPair();
|
||||||
|
const parsedData = resKeyPair;
|
||||||
|
|
||||||
|
switch (foreignBlockchain) {
|
||||||
|
case "LITECOIN":
|
||||||
|
return parsedData.ltcPrivateKey
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const pauseAllQueues = () => controlAllQueues("pause");
|
export const pauseAllQueues = () => controlAllQueues("pause");
|
||||||
export const resumeAllQueues = () => controlAllQueues("resume");
|
export const resumeAllQueues = () => controlAllQueues("resume");
|
||||||
const checkDifference = (createdTimestamp) => {
|
const checkDifference = (createdTimestamp) => {
|
||||||
@ -1657,27 +1673,29 @@ export async function decryptDirectFunc({ messages, involvingAddress }) {
|
|||||||
return holdMessages;
|
return holdMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createBuyOrderTx({ crosschainAtInfo, useLocal }) {
|
export async function createBuyOrderTx({ crosschainAtInfo, isGateway, foreignBlockchain }) {
|
||||||
try {
|
try {
|
||||||
if (useLocal) {
|
|
||||||
|
if (!isGateway) {
|
||||||
const wallet = await getSaveWallet();
|
const wallet = await getSaveWallet();
|
||||||
|
|
||||||
const address = wallet.address0;
|
const address = wallet.address0;
|
||||||
|
|
||||||
const resKeyPair = await getKeyPair();
|
|
||||||
const parsedData = resKeyPair;
|
|
||||||
const message = {
|
const message = {
|
||||||
addresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
addresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
||||||
foreignKey: parsedData.ltcPrivateKey,
|
foreignKey: await getForeignKey(foreignBlockchain),
|
||||||
receivingAddress: address,
|
receivingAddress: address,
|
||||||
};
|
};
|
||||||
let responseVar;
|
let responseVar;
|
||||||
const txn = new TradeBotRespondMultipleRequest().createTransaction(
|
const txn = new TradeBotRespondMultipleRequest().createTransaction(
|
||||||
message
|
message
|
||||||
);
|
);
|
||||||
const apiKey = await getApiKeyFromStorage();
|
|
||||||
|
|
||||||
|
const url = await createEndpoint('/crosschain/tradebot/respondmultiple')
|
||||||
|
|
||||||
const responseFetch = await fetch(
|
const responseFetch = await fetch(
|
||||||
`http://127.0.0.1:12391/crosschain/tradebot/respondmultiple?apiKey=${apiKey?.apikey}`,
|
url,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@ -1706,7 +1724,7 @@ export async function createBuyOrderTx({ crosschainAtInfo, useLocal }) {
|
|||||||
message: "Transaction processed successfully!",
|
message: "Transaction processed successfully!",
|
||||||
atAddresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
atAddresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
||||||
senderAddress: address,
|
senderAddress: address,
|
||||||
node: 'http://127.0.0.1:12391'
|
node: url
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@ -1716,7 +1734,7 @@ export async function createBuyOrderTx({ crosschainAtInfo, useLocal }) {
|
|||||||
message: response,
|
message: response,
|
||||||
atAddresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
atAddresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
||||||
senderAddress: address,
|
senderAddress: address,
|
||||||
node: 'http://127.0.0.1:12391'
|
node: url
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1726,11 +1744,10 @@ export async function createBuyOrderTx({ crosschainAtInfo, useLocal }) {
|
|||||||
const wallet = await getSaveWallet();
|
const wallet = await getSaveWallet();
|
||||||
const address = wallet.address0;
|
const address = wallet.address0;
|
||||||
|
|
||||||
const resKeyPair = await getKeyPair();
|
|
||||||
const parsedData = resKeyPair;
|
|
||||||
const message = {
|
const message = {
|
||||||
addresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
addresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
||||||
foreignKey: parsedData.ltcPrivateKey,
|
foreignKey: await getForeignKey(foreignBlockchain),
|
||||||
receivingAddress: address,
|
receivingAddress: address,
|
||||||
};
|
};
|
||||||
const res = await sendChatForBuyOrder({
|
const res = await sendChatForBuyOrder({
|
||||||
@ -1742,16 +1759,15 @@ export async function createBuyOrderTx({ crosschainAtInfo, useLocal }) {
|
|||||||
|
|
||||||
|
|
||||||
if (res?.signature) {
|
if (res?.signature) {
|
||||||
let responseMessage;
|
|
||||||
|
|
||||||
if(res?.encryptedMessageToBase58){
|
|
||||||
const message = await listenForChatMessageForBuyOrder({
|
const message = await listenForChatMessageForBuyOrder({
|
||||||
nodeBaseUrl: buyTradeNodeBaseUrl,
|
nodeBaseUrl: buyTradeNodeBaseUrl,
|
||||||
senderAddress: proxyAccountAddress,
|
senderAddress: proxyAccountAddress,
|
||||||
senderPublicKey: proxyAccountPublicKey,
|
senderPublicKey: proxyAccountPublicKey,
|
||||||
signature: res?.signature,
|
signature: res?.signature,
|
||||||
});
|
});
|
||||||
responseMessage = {
|
|
||||||
|
const responseMessage = {
|
||||||
callResponse: message.callResponse,
|
callResponse: message.callResponse,
|
||||||
extra: {
|
extra: {
|
||||||
message: message?.extra?.message,
|
message: message?.extra?.message,
|
||||||
@ -1760,48 +1776,7 @@ export async function createBuyOrderTx({ crosschainAtInfo, useLocal }) {
|
|||||||
atAddresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
atAddresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
const message = await listenForChatMessageForBuyOrder({
|
|
||||||
nodeBaseUrl: buyTradeNodeBaseUrl,
|
|
||||||
senderAddress: proxyAccountAddress,
|
|
||||||
senderPublicKey: proxyAccountPublicKey,
|
|
||||||
signature: res?.signature,
|
|
||||||
});
|
|
||||||
|
|
||||||
responseMessage = {
|
|
||||||
callResponse: message.callResponse,
|
|
||||||
extra: {
|
|
||||||
message: message?.extra?.message,
|
|
||||||
senderAddress: address,
|
|
||||||
node: buyTradeNodeBaseUrl,
|
|
||||||
atAddresses: crosschainAtInfo.map((order)=> order.qortalAtAddress),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// const status = response.callResponse === true ? 'trade-ongoing' : 'trade-failed'
|
|
||||||
// if (res?.encryptedMessageToBase58) {
|
|
||||||
// return {
|
|
||||||
// atAddresses: crosschainAtInfo.map((order) => order.qortalAtAddress),
|
|
||||||
// encryptedMessageToBase58: res?.encryptedMessageToBase58,
|
|
||||||
// node: buyTradeNodeBaseUrl,
|
|
||||||
// qortAddress: address,
|
|
||||||
// chatSignature: res?.signature,
|
|
||||||
// senderPublicKey: parsedData.publicKey,
|
|
||||||
// sender: address,
|
|
||||||
// reference: res?.reference,
|
|
||||||
// response.callResponse
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// return {
|
|
||||||
// atAddresses: crosschainAtInfo.map((order) => order.qortalAtAddress),
|
|
||||||
// chatSignature: res?.signature,
|
|
||||||
// node: buyTradeNodeBaseUrl,
|
|
||||||
// qortAddress: address,
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
|
||||||
return responseMessage
|
return responseMessage
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Unable to send buy order message");
|
throw new Error("Unable to send buy order message");
|
||||||
|
@ -36,7 +36,7 @@ export const AppsDevModeHome = ({
|
|||||||
availableQapps,
|
availableQapps,
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const [domain, setDomain] = useState("");
|
const [domain, setDomain] = useState("127.0.0.1");
|
||||||
const [port, setPort] = useState("");
|
const [port, setPort] = useState("");
|
||||||
const { isShow, onCancel, onOk, show, message } = useModal();
|
const { isShow, onCancel, onOk, show, message } = useModal();
|
||||||
const {
|
const {
|
||||||
|
@ -183,7 +183,7 @@ const UIQortalRequests = [
|
|||||||
'GET_WALLET_BALANCE', 'GET_USER_WALLET_INFO', 'GET_CROSSCHAIN_SERVER_INFO',
|
'GET_WALLET_BALANCE', 'GET_USER_WALLET_INFO', 'GET_CROSSCHAIN_SERVER_INFO',
|
||||||
'GET_TX_ACTIVITY_SUMMARY', 'GET_FOREIGN_FEE', 'UPDATE_FOREIGN_FEE',
|
'GET_TX_ACTIVITY_SUMMARY', 'GET_FOREIGN_FEE', 'UPDATE_FOREIGN_FEE',
|
||||||
'GET_SERVER_CONNECTION_HISTORY', 'SET_CURRENT_FOREIGN_SERVER',
|
'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'
|
'ADD_FOREIGN_SERVER', 'REMOVE_FOREIGN_SERVER', 'GET_DAY_SUMMARY', 'CREATE_TRADE_BUY_ORDER', 'CREATE_TRADE_SELL_ORDER', 'CANCEL_TRADE_SELL_ORDER', 'IS_USING_GATEWAY'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
@ -437,7 +437,7 @@ isDOMContentLoaded: false
|
|||||||
if (event?.data?.requestedHandler !== 'UI') return;
|
if (event?.data?.requestedHandler !== 'UI') return;
|
||||||
|
|
||||||
const sendMessageToRuntime = (message, eventPort) => {
|
const sendMessageToRuntime = (message, eventPort) => {
|
||||||
window.sendMessage(message.action, message.payload, 60000, message.isExtension)
|
window.sendMessage(message.action, message.payload, 300000, message.isExtension)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
eventPort.postMessage({
|
eventPort.postMessage({
|
||||||
|
@ -83,9 +83,9 @@ export const Save = ({ isDesktop, disableWidth }) => {
|
|||||||
.sendMessage(
|
.sendMessage(
|
||||||
"ENCRYPT_DATA",
|
"ENCRYPT_DATA",
|
||||||
{
|
{
|
||||||
payload: {
|
|
||||||
data64,
|
data64,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
60000
|
60000
|
||||||
)
|
)
|
||||||
@ -101,6 +101,7 @@ export const Save = ({ isDesktop, disableWidth }) => {
|
|||||||
console.error("Failed qortalRequest", error);
|
console.error("Failed qortalRequest", error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
console.log('encryptData', encryptData)
|
||||||
if (encryptData && !encryptData?.error) {
|
if (encryptData && !encryptData?.error) {
|
||||||
const fee = await getFee("ARBITRARY");
|
const fee = await getFee("ARBITRARY");
|
||||||
|
|
||||||
@ -138,6 +139,7 @@ export const Save = ({ isDesktop, disableWidth }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log('errorsave', error)
|
||||||
setInfoSnack({
|
setInfoSnack({
|
||||||
type: "error",
|
type: "error",
|
||||||
message: error?.message || "Unable to save to QDN",
|
message: error?.message || "Unable to save to QDN",
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { addForeignServer, addListItems, createBuyOrder, createPoll, createSellOrder, decryptData, deleteListItems, deployAt, encryptData, getCrossChainServerInfo, getDaySummary, getForeignFee, getListItems, getServerConnectionHistory, getTxActivitySummary, getUserAccount, getUserWallet, getUserWalletInfo, getWalletBalance, joinGroup, publishMultipleQDNResources, publishQDNResource, removeForeignServer, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, updateForeignFee, voteOnPoll } from "./qortalRequests/get";
|
import { gateways, getApiKeyFromStorage } from "./background";
|
||||||
|
import { addForeignServer, addListItems, cancelSellOrder, createBuyOrder, createPoll, createSellOrder, decryptData, deleteListItems, deployAt, encryptData, getCrossChainServerInfo, getDaySummary, getForeignFee, getListItems, getServerConnectionHistory, getTxActivitySummary, getUserAccount, getUserWallet, getUserWalletInfo, getWalletBalance, joinGroup, publishMultipleQDNResources, publishQDNResource, removeForeignServer, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, updateForeignFee, voteOnPoll } from "./qortalRequests/get";
|
||||||
import { getData, storeData } from "./utils/chromeStorage";
|
import { getData, storeData } from "./utils/chromeStorage";
|
||||||
|
|
||||||
|
|
||||||
@ -17,6 +18,15 @@ function setLocalStorage(key, data) {
|
|||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
export const isRunningGateway = async ()=> {
|
||||||
|
let isGateway = true;
|
||||||
|
const apiKey = await getApiKeyFromStorage();
|
||||||
|
if (apiKey && (apiKey?.url && !gateways.some(gateway => apiKey?.url?.includes(gateway)))) {
|
||||||
|
isGateway = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isGateway
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function setPermission(key, value) {
|
export async function setPermission(key, value) {
|
||||||
@ -623,7 +633,47 @@ function setLocalStorage(key, data) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "CANCEL_TRADE_SELL_ORDER": {
|
||||||
|
try {
|
||||||
|
const res = await cancelSellOrder(request.payload, isFromExtension);
|
||||||
|
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 "IS_USING_GATEWAY": {
|
||||||
|
try {
|
||||||
|
console.log('isusing going')
|
||||||
|
let isGateway = await isRunningGateway()
|
||||||
|
console.log('isGateway', isGateway)
|
||||||
|
event.source.postMessage({
|
||||||
|
requestId: request.requestId,
|
||||||
|
action: request.action,
|
||||||
|
payload: {isGateway},
|
||||||
|
type: "backgroundMessageResponse",
|
||||||
|
}, event.origin);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('isusing going', error)
|
||||||
|
event.source.postMessage({
|
||||||
|
requestId: request.requestId,
|
||||||
|
action: request.action,
|
||||||
|
error: error?.message,
|
||||||
|
type: "backgroundMessageResponse",
|
||||||
|
}, event.origin);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -28,11 +28,19 @@ import {
|
|||||||
uint8ArrayToBase64,
|
uint8ArrayToBase64,
|
||||||
} from "../qdn/encryption/group-encryption";
|
} from "../qdn/encryption/group-encryption";
|
||||||
import { publishData } from "../qdn/publish/pubish";
|
import { publishData } from "../qdn/publish/pubish";
|
||||||
import { getPermission, setPermission } from "../qortalRequests";
|
import { getPermission, isRunningGateway, setPermission } from "../qortalRequests";
|
||||||
|
import TradeBotCreateRequest from "../transactions/TradeBotCreateRequest";
|
||||||
|
import DeleteTradeOffer from "../transactions/TradeBotDeleteRequest";
|
||||||
|
import signTradeBotTransaction from "../transactions/signTradeBotTransaction";
|
||||||
import { createTransaction } from "../transactions/transactions";
|
import { createTransaction } from "../transactions/transactions";
|
||||||
import { mimeToExtensionMap } from "../utils/memeTypes";
|
import { mimeToExtensionMap } from "../utils/memeTypes";
|
||||||
|
|
||||||
|
const sellerForeignFee = {
|
||||||
|
'LITECOIN': {
|
||||||
|
value: '~0.00005',
|
||||||
|
ticker: 'LTC'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const btcFeePerByte = 0.00000100
|
const btcFeePerByte = 0.00000100
|
||||||
const ltcFeePerByte = 0.00000030
|
const ltcFeePerByte = 0.00000030
|
||||||
@ -302,7 +310,6 @@ export const encryptData = async (data, sender) => {
|
|||||||
if (!data64) {
|
if (!data64) {
|
||||||
throw new Error("Please include data to encrypt");
|
throw new Error("Please include data to encrypt");
|
||||||
}
|
}
|
||||||
|
|
||||||
const resKeyPair = await getKeyPair();
|
const resKeyPair = await getKeyPair();
|
||||||
const parsedData = resKeyPair;
|
const parsedData = resKeyPair;
|
||||||
const privateKey = parsedData.privateKey;
|
const privateKey = parsedData.privateKey;
|
||||||
@ -1367,7 +1374,6 @@ export const getWalletBalance = async (data, bypassPermission?: boolean, isFromE
|
|||||||
}
|
}
|
||||||
|
|
||||||
const value = (await getPermission(`qAPPAutoWalletBalance-${data.coin}`)) || false;
|
const value = (await getPermission(`qAPPAutoWalletBalance-${data.coin}`)) || false;
|
||||||
console.log('value', value)
|
|
||||||
let skip = false;
|
let skip = false;
|
||||||
if (value) {
|
if (value) {
|
||||||
skip = true;
|
skip = true;
|
||||||
@ -1384,7 +1390,6 @@ export const getWalletBalance = async (data, bypassPermission?: boolean, isFromE
|
|||||||
},
|
},
|
||||||
}, isFromExtension);
|
}, isFromExtension);
|
||||||
}
|
}
|
||||||
console.log('resPermission', resPermission)
|
|
||||||
const { accepted = false, checkbox1 = false } = resPermission || {};
|
const { accepted = false, checkbox1 = false } = resPermission || {};
|
||||||
if(resPermission){
|
if(resPermission){
|
||||||
setPermission(`qAPPAutoWalletBalance-${data.coin}`, checkbox1);
|
setPermission(`qAPPAutoWalletBalance-${data.coin}`, checkbox1);
|
||||||
@ -1476,7 +1481,7 @@ export const getWalletBalance = async (data, bypassPermission?: boolean, isFromE
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUserWalletFunc = async (coin) => {
|
export const getUserWalletFunc = async (coin) => {
|
||||||
let userWallet = {};
|
let userWallet = {};
|
||||||
const wallet = await getSaveWallet();
|
const wallet = await getSaveWallet();
|
||||||
const address = wallet.address0;
|
const address = wallet.address0;
|
||||||
@ -2413,7 +2418,7 @@ export const createBuyOrder = async (data, isFromExtension) => {
|
|||||||
|
|
||||||
const requiredFields = [
|
const requiredFields = [
|
||||||
"crosschainAtInfo",
|
"crosschainAtInfo",
|
||||||
"processType"
|
"foreignBlockchain"
|
||||||
];
|
];
|
||||||
const missingFields: string[] = [];
|
const missingFields: string[] = [];
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
@ -2426,12 +2431,10 @@ export const createBuyOrder = async (data, isFromExtension) => {
|
|||||||
const errorMsg = `Missing fields: ${missingFieldsString}`;
|
const errorMsg = `Missing fields: ${missingFieldsString}`;
|
||||||
throw new Error(errorMsg);
|
throw new Error(errorMsg);
|
||||||
}
|
}
|
||||||
|
const isGateway = await isRunningGateway()
|
||||||
|
const foreignBlockchain = data.foreignBlockchain
|
||||||
const crosschainAtInfo = data.crosschainAtInfo;
|
const crosschainAtInfo = data.crosschainAtInfo;
|
||||||
const atAddresses = data.crosschainAtInfo?.map((order)=> order.qortalAtAddress);
|
const atAddresses = data.crosschainAtInfo?.map((order)=> order.qortalAtAddress);
|
||||||
const processType = data.processType;
|
|
||||||
if(processType !== 'local' && processType !== 'gateway'){
|
|
||||||
throw new Error('Process Type must be either local or gateway')
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resPermission = await getUserPermission({
|
const resPermission = await getUserPermission({
|
||||||
@ -2448,16 +2451,18 @@ export const createBuyOrder = async (data, isFromExtension) => {
|
|||||||
}, 0)
|
}, 0)
|
||||||
)}
|
)}
|
||||||
${` ${crosschainAtInfo?.[0]?.foreignBlockchain}`}`,
|
${` ${crosschainAtInfo?.[0]?.foreignBlockchain}`}`,
|
||||||
highlightedText: `Using ${processType}`,
|
highlightedText: `Is using gateway: ${isGateway}`,
|
||||||
fee: ''
|
fee: '',
|
||||||
|
foreignFee: `${sellerForeignFee[foreignBlockchain].value} ${sellerForeignFee[foreignBlockchain].ticker}`
|
||||||
}, isFromExtension);
|
}, isFromExtension);
|
||||||
const { accepted } = resPermission;
|
const { accepted } = resPermission;
|
||||||
if (accepted) {
|
if (accepted) {
|
||||||
const resBuyOrder = await createBuyOrderTx(
|
const resBuyOrder = await createBuyOrderTx(
|
||||||
{
|
{
|
||||||
crosschainAtInfo,
|
crosschainAtInfo,
|
||||||
useLocal: processType === 'local' ? true : false
|
isGateway,
|
||||||
}
|
foreignBlockchain
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return resBuyOrder;
|
return resBuyOrder;
|
||||||
} else {
|
} else {
|
||||||
@ -2468,11 +2473,142 @@ export const createBuyOrder = async (data, isFromExtension) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cancelTradeOfferTradeBot = async (body, keyPair) => {
|
||||||
|
const txn = new DeleteTradeOffer().createTransaction(body)
|
||||||
|
const url = await createEndpoint(`/crosschain/tradeoffer`);
|
||||||
|
const bodyToString = JSON.stringify(txn);
|
||||||
|
|
||||||
|
const deleteTradeBotResponse = await fetch(url, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: bodyToString,
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!deleteTradeBotResponse.ok) throw new Error('Unable to update tradebot')
|
||||||
|
const unsignedTxn = await deleteTradeBotResponse.text()
|
||||||
|
const signedTxnBytes = await signTradeBotTransaction(
|
||||||
|
unsignedTxn,
|
||||||
|
keyPair
|
||||||
|
)
|
||||||
|
const signedBytes = Base58.encode(signedTxnBytes);
|
||||||
|
|
||||||
|
let res
|
||||||
|
try {
|
||||||
|
res = await processTransactionVersion2(signedBytes)
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
error: "Failed to Cancel Sell Order. Try again!",
|
||||||
|
failedTradeBot: {
|
||||||
|
atAddress: body.atAddress,
|
||||||
|
creatorAddress: body.creatorAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(res?.error){
|
||||||
|
return {
|
||||||
|
error: "Failed to Cancel Sell Order. Try again!",
|
||||||
|
failedTradeBot: {
|
||||||
|
atAddress: body.atAddress,
|
||||||
|
creatorAddress: body.creatorAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res?.signature){
|
||||||
|
return res
|
||||||
|
} else {
|
||||||
|
throw new Error("Failed to Cancel Sell Order. Try again!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const findFailedTradebot = async (createBotCreationTimestamp, body)=> {
|
||||||
|
//wait 5 secs
|
||||||
|
const wallet = await getSaveWallet();
|
||||||
|
const address = wallet.address0;
|
||||||
|
await new Promise((res)=> {
|
||||||
|
setTimeout(() => {
|
||||||
|
res(null)
|
||||||
|
}, 5000);
|
||||||
|
})
|
||||||
|
const url = await createEndpoint(`/crosschain/tradebot?foreignBlockchain=LITECOIN`);
|
||||||
|
|
||||||
|
const tradeBotsReponse = await fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const data = await tradeBotsReponse.json()
|
||||||
|
const latestItem2 = data
|
||||||
|
.filter(
|
||||||
|
(item) =>
|
||||||
|
item.creatorAddress === address
|
||||||
|
).sort((a, b) => b.timestamp - a.timestamp)[0]
|
||||||
|
const latestItem = data
|
||||||
|
.filter(
|
||||||
|
(item) =>
|
||||||
|
item.creatorAddress === address &&
|
||||||
|
+item.foreignAmount === +body.foreignAmount
|
||||||
|
)
|
||||||
|
.sort((a, b) => b.timestamp - a.timestamp)[0];
|
||||||
|
if (
|
||||||
|
latestItem &&
|
||||||
|
createBotCreationTimestamp - latestItem.timestamp <= 5000 &&
|
||||||
|
createBotCreationTimestamp > latestItem.timestamp // Ensure latestItem's timestamp is before createBotCreationTimestamp
|
||||||
|
) {
|
||||||
|
|
||||||
|
return latestItem
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
const tradeBotCreateRequest = async (body, keyPair)=> {
|
||||||
|
const txn = new TradeBotCreateRequest().createTransaction(body)
|
||||||
|
const url = await createEndpoint(`/crosschain/tradebot/create`);
|
||||||
|
const bodyToString = JSON.stringify(txn);
|
||||||
|
|
||||||
|
const unsignedTxnResponse = await fetch(url, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: bodyToString,
|
||||||
|
});
|
||||||
|
if(!unsignedTxnResponse.ok) throw new Error('Unable to create tradebot')
|
||||||
|
const createBotCreationTimestamp = Date.now()
|
||||||
|
const unsignedTxn = await unsignedTxnResponse.text()
|
||||||
|
const signedTxnBytes = await signTradeBotTransaction(
|
||||||
|
unsignedTxn,
|
||||||
|
keyPair
|
||||||
|
)
|
||||||
|
const signedBytes = Base58.encode(signedTxnBytes);
|
||||||
|
|
||||||
|
let res
|
||||||
|
try {
|
||||||
|
res = await processTransactionVersion2(signedBytes)
|
||||||
|
} catch (error) {
|
||||||
|
const findFailedTradeBot = await findFailedTradebot(createBotCreationTimestamp, body)
|
||||||
|
return {
|
||||||
|
error: "Failed to Create Sell Order. Try again!",
|
||||||
|
failedTradeBot: findFailedTradeBot
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res?.signature){
|
||||||
|
return res
|
||||||
|
} else {
|
||||||
|
throw new Error("Failed to Create Sell Order. Try again!")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export const createSellOrder = async (data, isFromExtension) => {
|
export const createSellOrder = async (data, isFromExtension) => {
|
||||||
|
|
||||||
const requiredFields = [
|
const requiredFields = [
|
||||||
"crosschainAtInfo",
|
"qortAmount",
|
||||||
"processType"
|
"foreignBlockchain",
|
||||||
|
"foreignAmount"
|
||||||
];
|
];
|
||||||
const missingFields: string[] = [];
|
const missingFields: string[] = [];
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
@ -2485,44 +2621,99 @@ export const createSellOrder = async (data, isFromExtension) => {
|
|||||||
const errorMsg = `Missing fields: ${missingFieldsString}`;
|
const errorMsg = `Missing fields: ${missingFieldsString}`;
|
||||||
throw new Error(errorMsg);
|
throw new Error(errorMsg);
|
||||||
}
|
}
|
||||||
const crosschainAtInfo = data.crosschainAtInfo;
|
|
||||||
const atAddresses = data.crosschainAtInfo?.map((order)=> order.qortalAtAddress);
|
|
||||||
const processType = data.processType;
|
|
||||||
if(processType !== 'local' && processType !== 'gateway'){
|
|
||||||
throw new Error('Process Type must be either local or gateway')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const receivingAddress = await getUserWalletFunc('LTC')
|
||||||
try {
|
try {
|
||||||
const resPermission = await getUserPermission({
|
const resPermission = await getUserPermission({
|
||||||
text1: "Do you give this application permission to perform a buy order?",
|
text1: "Do you give this application permission to perform a sell order?",
|
||||||
text2: `${atAddresses?.length}${" "}
|
text2: `${data.qortAmount}${" "}
|
||||||
${`buy order${
|
${`QORT`}`,
|
||||||
atAddresses?.length === 1 ? "" : "s"
|
text3: `FOR ${data.foreignAmount} ${data.foreignBlockchain}`,
|
||||||
}`}`,
|
fee: '0.02'
|
||||||
text3: `${crosschainAtInfo?.reduce((latest, cur) => {
|
|
||||||
return latest + +cur?.qortAmount;
|
|
||||||
}, 0)} QORT FOR ${roundUpToDecimals(
|
|
||||||
crosschainAtInfo?.reduce((latest, cur) => {
|
|
||||||
return latest + +cur?.foreignAmount;
|
|
||||||
}, 0)
|
|
||||||
)}
|
|
||||||
${` ${crosschainAtInfo?.[0]?.foreignBlockchain}`}`,
|
|
||||||
highlightedText: `Using ${processType}`,
|
|
||||||
fee: ''
|
|
||||||
}, isFromExtension);
|
}, isFromExtension);
|
||||||
const { accepted } = resPermission;
|
const { accepted } = resPermission;
|
||||||
if (accepted) {
|
if (accepted) {
|
||||||
const resBuyOrder = await createBuyOrderTx(
|
const resKeyPair = await getKeyPair()
|
||||||
{
|
const parsedData = resKeyPair
|
||||||
crosschainAtInfo,
|
const userPublicKey = parsedData.publicKey
|
||||||
useLocal: processType === 'local' ? true : false
|
const uint8PrivateKey = Base58.decode(parsedData.privateKey);
|
||||||
}
|
const uint8PublicKey = Base58.decode(parsedData.publicKey);
|
||||||
);
|
const keyPair = {
|
||||||
return resBuyOrder;
|
privateKey: uint8PrivateKey,
|
||||||
|
publicKey: uint8PublicKey,
|
||||||
|
};
|
||||||
|
const response = await tradeBotCreateRequest({
|
||||||
|
creatorPublicKey: userPublicKey,
|
||||||
|
qortAmount: parseFloat(data.qortAmount),
|
||||||
|
fundingQortAmount: parseFloat(data.qortAmount) + 0.001,
|
||||||
|
foreignBlockchain: data.foreignBlockchain,
|
||||||
|
foreignAmount: parseFloat(data.foreignAmount),
|
||||||
|
tradeTimeout: 120,
|
||||||
|
receivingAddress: receivingAddress.address
|
||||||
|
}, keyPair)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error("User declined request");
|
throw new Error("User declined request");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error?.message || "Failed to submit trade order.");
|
throw new Error(error?.message || "Failed to submit sell order.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const cancelSellOrder = async (data, isFromExtension) => {
|
||||||
|
|
||||||
|
const requiredFields = [
|
||||||
|
"qortAmount",
|
||||||
|
"foreignBlockchain",
|
||||||
|
"foreignAmount",
|
||||||
|
"atAddress"
|
||||||
|
];
|
||||||
|
const missingFields: string[] = [];
|
||||||
|
requiredFields.forEach((field) => {
|
||||||
|
if (!data[field]) {
|
||||||
|
missingFields.push(field);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (missingFields.length > 0) {
|
||||||
|
const missingFieldsString = missingFields.join(", ");
|
||||||
|
const errorMsg = `Missing fields: ${missingFieldsString}`;
|
||||||
|
throw new Error(errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const fee = await getFee("MESSAGE");
|
||||||
|
|
||||||
|
const resPermission = await getUserPermission({
|
||||||
|
text1: "Do you give this application permission to perform cancel a sell order?",
|
||||||
|
text2: `${data.qortAmount}${" "}
|
||||||
|
${`QORT`}`,
|
||||||
|
text3: `FOR ${data.foreignAmount} ${data.foreignBlockchain}`,
|
||||||
|
fee: fee.fee
|
||||||
|
}, isFromExtension);
|
||||||
|
const { accepted } = resPermission;
|
||||||
|
if (accepted) {
|
||||||
|
const resKeyPair = await getKeyPair()
|
||||||
|
const parsedData = resKeyPair
|
||||||
|
const userPublicKey = parsedData.publicKey
|
||||||
|
const uint8PrivateKey = Base58.decode(parsedData.privateKey);
|
||||||
|
const uint8PublicKey = Base58.decode(parsedData.publicKey);
|
||||||
|
const keyPair = {
|
||||||
|
privateKey: uint8PrivateKey,
|
||||||
|
publicKey: uint8PublicKey,
|
||||||
|
};
|
||||||
|
const response = await cancelTradeOfferTradeBot({
|
||||||
|
creatorPublicKey: userPublicKey,
|
||||||
|
atAddress: data.atAddress
|
||||||
|
}, keyPair)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new Error("User declined request");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(error?.message || "Failed to submit sell order.");
|
||||||
}
|
}
|
||||||
};
|
};
|
65
src/transactions/TradeBotCreateRequest.ts
Normal file
65
src/transactions/TradeBotCreateRequest.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CrossChain - TradeBot Create Request (Sell Action)
|
||||||
|
*
|
||||||
|
* These are special types of transactions (JSON ENCODED)
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default class TradeBotCreateRequest {
|
||||||
|
constructor() {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
createTransaction(txnReq) {
|
||||||
|
this.creatorPublicKey(txnReq.creatorPublicKey)
|
||||||
|
this.qortAmount(txnReq.qortAmount)
|
||||||
|
this.fundingQortAmount(txnReq.fundingQortAmount)
|
||||||
|
this.foreignBlockchain(txnReq.foreignBlockchain)
|
||||||
|
this.foreignAmount(txnReq.foreignAmount)
|
||||||
|
this.tradeTimeout(txnReq.tradeTimeout)
|
||||||
|
this.receivingAddress(txnReq.receivingAddress)
|
||||||
|
|
||||||
|
return this.txnRequest()
|
||||||
|
}
|
||||||
|
|
||||||
|
creatorPublicKey(creatorPublicKey) {
|
||||||
|
this._creatorPublicKey = creatorPublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
qortAmount(qortAmount) {
|
||||||
|
this._qortAmount = qortAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
fundingQortAmount(fundingQortAmount) {
|
||||||
|
this._fundingQortAmount = fundingQortAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
foreignBlockchain(foreignBlockchain) {
|
||||||
|
this._foreignBlockchain = foreignBlockchain
|
||||||
|
}
|
||||||
|
|
||||||
|
foreignAmount(foreignAmount) {
|
||||||
|
this._foreignAmount = foreignAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
tradeTimeout(tradeTimeout) {
|
||||||
|
this._tradeTimeout = tradeTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
receivingAddress(receivingAddress) {
|
||||||
|
this._receivingAddress = receivingAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
txnRequest() {
|
||||||
|
return {
|
||||||
|
creatorPublicKey: this._creatorPublicKey,
|
||||||
|
qortAmount: this._qortAmount,
|
||||||
|
fundingQortAmount: this._fundingQortAmount,
|
||||||
|
foreignBlockchain: this._foreignBlockchain,
|
||||||
|
foreignAmount: this._foreignAmount,
|
||||||
|
tradeTimeout: this._tradeTimeout,
|
||||||
|
receivingAddress: this._receivingAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
src/transactions/TradeBotDeleteRequest.ts
Normal file
35
src/transactions/TradeBotDeleteRequest.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CrossChain - DELETE TradeOffer
|
||||||
|
*
|
||||||
|
* These are special types of transactions (JSON ENCODED)
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default class DeleteTradeOffer {
|
||||||
|
constructor() {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
createTransaction(txnReq) {
|
||||||
|
this.creatorPublicKey(txnReq.creatorPublicKey)
|
||||||
|
this.atAddress(txnReq.atAddress)
|
||||||
|
|
||||||
|
return this.txnRequest()
|
||||||
|
}
|
||||||
|
|
||||||
|
creatorPublicKey(creatorPublicKey) {
|
||||||
|
this._creatorPublicKey = creatorPublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
atAddress(atAddress) {
|
||||||
|
this._atAddress = atAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
txnRequest() {
|
||||||
|
return {
|
||||||
|
creatorPublicKey: this._creatorPublicKey,
|
||||||
|
atAddress: this._atAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
src/transactions/signTradeBotTransaction.ts
Normal file
31
src/transactions/signTradeBotTransaction.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
|
||||||
|
import nacl from '../deps/nacl-fast'
|
||||||
|
import Base58 from '../deps/Base58'
|
||||||
|
import utils from '../utils/utils'
|
||||||
|
|
||||||
|
const signTradeBotTransaction = async (unsignedTxn, keyPair) => {
|
||||||
|
console.log('keypair', unsignedTxn, keyPair)
|
||||||
|
if (!unsignedTxn) {
|
||||||
|
throw new Error('Unsigned Transaction Bytes not defined')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keyPair) {
|
||||||
|
throw new Error('keyPair not defined')
|
||||||
|
}
|
||||||
|
|
||||||
|
const txnBuffer = Base58.decode(unsignedTxn)
|
||||||
|
|
||||||
|
if (keyPair.privateKey.length === undefined) {
|
||||||
|
const _privateKey = Object.keys(keyPair.privateKey).map(function (key) { return keyPair.privateKey[key] })
|
||||||
|
const privateKey = new Uint8Array(_privateKey)
|
||||||
|
const signature = nacl.sign.detached(txnBuffer, privateKey)
|
||||||
|
return utils.appendBuffer(txnBuffer, signature)
|
||||||
|
} else {
|
||||||
|
const signature = nacl.sign.detached(txnBuffer, keyPair.privateKey)
|
||||||
|
return utils.appendBuffer(txnBuffer, signature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default signTradeBotTransaction
|
Loading…
x
Reference in New Issue
Block a user