From 3edea9fe8ce68575ea6b1705077c2fc5bbdcfbbb Mon Sep 17 00:00:00 2001 From: kennycud Date: Mon, 29 Jul 2024 13:59:58 -0700 Subject: [PATCH 1/4] Support for responding to multiple crosschain sell offers. --- core/src/plugins/routes.js | 16 +++++++ core/src/tradebot/trade-bot-routes.js | 16 +++++++ crypto/api/api.js | 2 +- crypto/api/tradeRequest.js | 16 +++++++ .../TradeBotRespondMultipleRequest.js | 39 +++++++++++++++++ .../core/trade-portal/trade-portal.src.js | 43 +++++++++++++------ 6 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 crypto/api/transactions/trade-portal/tradebot/TradeBotRespondMultipleRequest.js diff --git a/core/src/plugins/routes.js b/core/src/plugins/routes.js index d50c95b25..6dd953fd9 100644 --- a/core/src/plugins/routes.js +++ b/core/src/plugins/routes.js @@ -24,6 +24,7 @@ const signArbitraryTransaction = api.signArbitraryTransaction const signArbitraryWithFeeTransaction = api.signArbitraryWithFeeTransaction const tradeBotCreateRequest = api.tradeBotCreateRequest const tradeBotRespondRequest = api.tradeBotRespondRequest +const tradeBotRespondMultipleRequest = api.tradeBotRespondMultipleRequest const signTradeBotTxn = api.signTradeBotTxn const deleteTradeOffer = api.deleteTradeOffer const cancelAllOffers = api.cancelAllOffers @@ -396,6 +397,21 @@ export const routes = { return response }, + tradeBotRespondMultipleRequest: async (req) => { + let response + + try { + response = await tradeBotRespondMultipleRequest(req.data) + } catch (e) { + console.error(e) + console.error(e.message) + + response = e.message + } + + return response + }, + deleteTradeOffer: async (req) => { let response diff --git a/core/src/tradebot/trade-bot-routes.js b/core/src/tradebot/trade-bot-routes.js index de0a47f24..cb0c1d587 100644 --- a/core/src/tradebot/trade-bot-routes.js +++ b/core/src/tradebot/trade-bot-routes.js @@ -6,6 +6,7 @@ const createTransaction = api.createTransaction const processTransaction = api.processTransaction const tradeBotCreateRequest = api.tradeBotCreateRequest const tradeBotRespondRequest = api.tradeBotRespondRequest +const tradeBotRespondMultipleRequest = api.tradeBotRespondMultipleRequest const signTradeBotTxn = api.signTradeBotTxn const deleteTradeOffer = api.deleteTradeOffer const cancelAllOffers = api.cancelAllOffers @@ -163,6 +164,21 @@ export const routes = { return response }, + tradeBotRespondMultipleRequest: async (req) => { + let response + + try { + response = await tradeBotRespondMultipleRequest(req.data) + } catch (e) { + console.error(e) + console.error(e.message) + + response = e.message + } + + return response + }, + deleteTradeOffer: async (req) => { let response diff --git a/crypto/api/api.js b/crypto/api/api.js index 3c240b2eb..f264bc853 100644 --- a/crypto/api/api.js +++ b/crypto/api/api.js @@ -1,5 +1,5 @@ export { request } from './fetch-request' export { transactionTypes as transactions } from './transactions/transactions' export { processTransaction, processTransactionVersion2, createTransaction, computeChatNonce, signChatTransaction, signArbitraryTransaction, signArbitraryWithFeeTransaction } from './createTransaction' -export { tradeBotCreateRequest, tradeBotRespondRequest, signTradeBotTxn, deleteTradeOffer, sendBtc, sendLtc, sendDoge, sendDgb, sendRvn, sendArrr } from './tradeRequest' +export { tradeBotCreateRequest, tradeBotRespondRequest, tradeBotRespondMultipleRequest, signTradeBotTxn, deleteTradeOffer, sendBtc, sendLtc, sendDoge, sendDgb, sendRvn, sendArrr } from './tradeRequest' export { cancelAllOffers } from './transactions/trade-portal/tradeoffer/cancelAllOffers' diff --git a/crypto/api/tradeRequest.js b/crypto/api/tradeRequest.js index f95380b75..69420c383 100644 --- a/crypto/api/tradeRequest.js +++ b/crypto/api/tradeRequest.js @@ -4,6 +4,7 @@ import TradeBotRespondRequest from './transactions/trade-portal/tradebot/TradeBo import signTradeBotTransaction from './transactions/trade-portal/tradebot/signTradeBotTransaction' import DeleteTradeOffer from './transactions/trade-portal/tradeoffer/DeleteTradeOffer' import { request } from './fetch-request' +import TradeBotRespondMultipleRequest from "./transactions/trade-portal/tradebot/TradeBotRespondMultipleRequest"; // TradeBotCreateRequest export const tradeBotCreateRequest = (requestObject) => { @@ -35,6 +36,21 @@ export const tradeBotRespondRequest = (requestObject) => { }) } +// TradeBotRespondRequest +export const tradeBotRespondMultipleRequest = (requestObject) => { + const txn = new TradeBotRespondMultipleRequest().createTransaction(requestObject) + const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] + + return request(`/crosschain/tradebot/respondmultiple?apiKey=${myNode.apiKey}`, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify(txn) + }) +} + // Sign Trade Transactions export const signTradeBotTxn = (unsignedTxn, keyPair) => { return signTradeBotTransaction(unsignedTxn, keyPair) diff --git a/crypto/api/transactions/trade-portal/tradebot/TradeBotRespondMultipleRequest.js b/crypto/api/transactions/trade-portal/tradebot/TradeBotRespondMultipleRequest.js new file mode 100644 index 000000000..5dcc2e402 --- /dev/null +++ b/crypto/api/transactions/trade-portal/tradebot/TradeBotRespondMultipleRequest.js @@ -0,0 +1,39 @@ +/** + * CrossChain - TradeBot Respond Multiple Request (Buy Action) + * + * These are special types of transactions (JSON ENCODED) + */ + +export default class TradeBotRespondMultipleRequest { + constructor() { + // ... + } + + createTransaction(txnReq) { + this.addresses(txnReq.addresses) + this.foreignKey(txnReq.foreignKey) + this.receivingAddress(txnReq.receivingAddress) + + return this.txnRequest() + } + + addresses(addresses) { + this._addresses = addresses + } + + foreignKey(foreignKey) { + this._foreignKey = foreignKey + } + + receivingAddress(receivingAddress) { + this._receivingAddress = receivingAddress + } + + txnRequest() { + return { + addresses: this._addresses, + foreignKey: this._foreignKey, + receivingAddress: this._receivingAddress + } + } +} diff --git a/plugins/plugins/core/trade-portal/trade-portal.src.js b/plugins/plugins/core/trade-portal/trade-portal.src.js index d122b0df6..69607315f 100644 --- a/plugins/plugins/core/trade-portal/trade-portal.src.js +++ b/plugins/plugins/core/trade-portal/trade-portal.src.js @@ -30,6 +30,7 @@ import '@polymer/paper-spinner/paper-spinner-lite.js' import '@vaadin/grid' import '@vaadin/grid/vaadin-grid-sorter' import '@vaadin/password-field' +import '@vaadin/grid/vaadin-grid-selection-column.js' // Multi language support import { get, registerTranslateConfig, translate, use } from '../../../../core/translate' @@ -498,6 +499,10 @@ class TradePortal extends LitElement { this._openOrdersGrid = this.shadowRoot.getElementById('openOrdersGrid') + this._openOrdersGrid.addEventListener("selected-items-changed", function(event){ + _this.fillBuyForm(event.detail.value); + }); + this._openOrdersGrid.querySelector('#priceColumn').headerRenderer = function (root) { const priceString = get("tradepage.tchange9") root.innerHTML = '' + priceString + ' (' + _this.listedCoins.get(_this.selectedCoin).coinCode + ')' @@ -751,13 +756,14 @@ class TradePortal extends LitElement { aria-label="Open Orders" .items="${this.listedCoins.get(this.selectedCoin).openFilteredOrders}" > + { - render(html`${this.round(data.item.qortAmount)}`, root) + render(html`${this.round(data.item.qortAmount)}`, root) }} > @@ -767,7 +773,7 @@ class TradePortal extends LitElement { header="${translate("tradepage.tchange9")} (${this.listedCoins.get(this.selectedCoin).coinCode})" id="priceColumn" .renderer=${(root, column, data) => { - render(html`${this.round(data.item.price)}`, root) + render(html`${this.round(data.item.price)}`, root) }} > @@ -777,7 +783,7 @@ class TradePortal extends LitElement { header="${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})" id="foreignAmountColumn" .renderer=${(root, column, data) => { - render(html`${data.item.foreignAmount}`, root) + render(html`${data.item.foreignAmount}`, root) }} > @@ -1552,13 +1558,25 @@ class TradePortal extends LitElement { this.isLoadingMyOpenOrders = false } - fillBuyForm(sellerRequest) { - this.shadowRoot.getElementById('buyAmountInput').value = parseFloat(sellerRequest.item.qortAmount) - this.shadowRoot.getElementById('buyPriceInput').value = this.round(parseFloat(sellerRequest.item.foreignAmount) / parseFloat(sellerRequest.item.qortAmount)) - this.shadowRoot.getElementById('buyTotalInput').value = parseFloat(sellerRequest.item.foreignAmount) - this.shadowRoot.getElementById('qortalAtAddress').value = sellerRequest.item.qortalAtAddress - const buyFunds = this.round(parseFloat(sellerRequest.item.foreignAmount)) + fillBuyForm(sellerRequests) { + let qortalATAddresses = []; + let qortAmount = 0; + let foreignAmount = 0; + + sellerRequests.forEach((item, index) => { + qortalATAddresses.push(item.qortalAtAddress); + qortAmount += parseFloat(item.qortAmount); + foreignAmount += parseFloat(item.foreignAmount); + }) + + this.shadowRoot.getElementById('buyAmountInput').value = qortAmount + this.shadowRoot.getElementById('buyPriceInput').value = qortAmount > 0 ? this.round(foreignAmount / qortAmount) : 0 + this.shadowRoot.getElementById('buyTotalInput').value = foreignAmount + this.shadowRoot.getElementById('qortalAtAddress').value = qortalATAddresses + + const buyFunds = this.round(foreignAmount) const haveFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) + if (Number(haveFunds) > Number(buyFunds)) { this.buyBtnDisable = false this.autoBuyWarning = false @@ -1568,7 +1586,6 @@ class TradePortal extends LitElement { this.autoBuyWarning = true this.displayTabContent('buy') } - } processOfferingTrade(offer) { @@ -2330,8 +2347,8 @@ class TradePortal extends LitElement { } const makeRequest = async () => { - return await parentEpml.request('tradeBotRespondRequest', { - atAddress: qortalAtAddress, + return await parentEpml.request('tradeBotRespondMultipleRequest', { + addresses: qortalAtAddress.split(','), foreignKey: _foreignKey, receivingAddress: this.selectedAddress.address }) @@ -2836,4 +2853,4 @@ class TradePortal extends LitElement { } } -window.customElements.define('trade-portal', TradePortal) \ No newline at end of file +window.customElements.define('trade-portal', TradePortal) From b5a9be475ef7b972ca3895c2cd993ca44614d9fd Mon Sep 17 00:00:00 2001 From: kennycud Date: Mon, 29 Jul 2024 19:29:19 -0700 Subject: [PATCH 2/4] Removed a click handler that I missed when removing all the click handlers on the last commit. --- plugins/plugins/core/trade-portal/trade-portal.src.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins/core/trade-portal/trade-portal.src.js b/plugins/plugins/core/trade-portal/trade-portal.src.js index 69607315f..bd86cdf0f 100644 --- a/plugins/plugins/core/trade-portal/trade-portal.src.js +++ b/plugins/plugins/core/trade-portal/trade-portal.src.js @@ -793,7 +793,7 @@ class TradePortal extends LitElement { header="${translate("tradepage.tchange13")}" id="qortalCreatorColumn" .renderer=${(root, column, data) => { - render(html`${data.item.qortalCreator}`, root) + render(html`${data.item.qortalCreator}`, root) }} > From 3b378c6e56242442aec45b360a59556cc440ba80 Mon Sep 17 00:00:00 2001 From: kennycud Date: Tue, 30 Jul 2024 16:18:38 -0700 Subject: [PATCH 3/4] reselecting open orders after the open orders are rerendered --- plugins/plugins/core/trade-portal/trade-portal.src.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/plugins/core/trade-portal/trade-portal.src.js b/plugins/plugins/core/trade-portal/trade-portal.src.js index bd86cdf0f..4c2182dae 100644 --- a/plugins/plugins/core/trade-portal/trade-portal.src.js +++ b/plugins/plugins/core/trade-portal/trade-portal.src.js @@ -1552,6 +1552,14 @@ class TradePortal extends LitElement { this.isLoadingOpenTrades = false } + reSelectOpenOrders() { + const qortalATAddressesString = this.shadowRoot.getElementById('qortalAtAddress').value; + const qortalATAddresses = qortalATAddressesString.split(','); + const itemsToSelect = this.tradesPresenceCleaned.filter((order) => qortalATAddresses.includes(order.qortalAtAddress)); + this._openOrdersGrid.selectedItems = [...itemsToSelect]; + this.fillBuyForm(itemsToSelect); + } + async reRenderMyOpenOrders() { this.requestUpdate() await this.updateComplete @@ -2665,6 +2673,7 @@ class TradePortal extends LitElement { filterPresenceList() this.listedCoins.get(message.data.relatedCoin).openFilteredOrders = this.tradesPresenceCleaned this.reRenderOpenFilteredOrders() + this.reSelectOpenOrders() return null default: break From 3fc028165502a51677419ff04dbcd925519d5681 Mon Sep 17 00:00:00 2001 From: kennycud Date: Thu, 5 Sep 2024 17:41:27 -0700 Subject: [PATCH 4/4] block Pirate Chain from multi trade --- .../core/trade-portal/trade-portal.src.js | 72 +++++++++++++++---- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/plugins/plugins/core/trade-portal/trade-portal.src.js b/plugins/plugins/core/trade-portal/trade-portal.src.js index 4c2182dae..f42d3ab33 100644 --- a/plugins/plugins/core/trade-portal/trade-portal.src.js +++ b/plugins/plugins/core/trade-portal/trade-portal.src.js @@ -500,7 +500,7 @@ class TradePortal extends LitElement { this._openOrdersGrid = this.shadowRoot.getElementById('openOrdersGrid') this._openOrdersGrid.addEventListener("selected-items-changed", function(event){ - _this.fillBuyForm(event.detail.value); + _this.fillBuyFormMultiple(event.detail.value); }); this._openOrdersGrid.querySelector('#priceColumn').headerRenderer = function (root) { @@ -738,6 +738,25 @@ class TradePortal extends LitElement { ` } + coinGridSelection() { + + if(this.selectedCoin == 'PIRATECHAIN') { + return html`` + } + else { + return html` + + ` + } + } + + clickHandler(data) { + + if(this.selectedCoin == 'PIRATECHAIN') { + this.fillBuyFormSingle(data) + } + } + openTradesTemplate() { return html`
@@ -756,14 +775,14 @@ class TradePortal extends LitElement { aria-label="Open Orders" .items="${this.listedCoins.get(this.selectedCoin).openFilteredOrders}" > - + ${this.coinGridSelection()} { - render(html`${this.round(data.item.qortAmount)}`, root) + render(html`${this.round(data.item.qortAmount)}`, root) }} > @@ -773,7 +792,7 @@ class TradePortal extends LitElement { header="${translate("tradepage.tchange9")} (${this.listedCoins.get(this.selectedCoin).coinCode})" id="priceColumn" .renderer=${(root, column, data) => { - render(html`${this.round(data.item.price)}`, root) + render(html`${this.round(data.item.price)}`, root) }} > @@ -783,7 +802,7 @@ class TradePortal extends LitElement { header="${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})" id="foreignAmountColumn" .renderer=${(root, column, data) => { - render(html`${data.item.foreignAmount}`, root) + render(html`${data.item.foreignAmount}`, root) }} > @@ -793,7 +812,7 @@ class TradePortal extends LitElement { header="${translate("tradepage.tchange13")}" id="qortalCreatorColumn" .renderer=${(root, column, data) => { - render(html`${data.item.qortalCreator}`, root) + render(html`${data.item.qortalCreator}`, root) }} > @@ -1557,7 +1576,7 @@ class TradePortal extends LitElement { const qortalATAddresses = qortalATAddressesString.split(','); const itemsToSelect = this.tradesPresenceCleaned.filter((order) => qortalATAddresses.includes(order.qortalAtAddress)); this._openOrdersGrid.selectedItems = [...itemsToSelect]; - this.fillBuyForm(itemsToSelect); + this.fillBuyFormMultiple(itemsToSelect); } async reRenderMyOpenOrders() { @@ -1566,7 +1585,16 @@ class TradePortal extends LitElement { this.isLoadingMyOpenOrders = false } - fillBuyForm(sellerRequests) { + fillBuyFormSingle(sellerRequest) { + this.shadowRoot.getElementById('buyAmountInput').value = parseFloat(sellerRequest.item.qortAmount) + this.shadowRoot.getElementById('buyPriceInput').value = this.round(parseFloat(sellerRequest.item.foreignAmount) / parseFloat(sellerRequest.item.qortAmount)) + this.shadowRoot.getElementById('buyTotalInput').value = parseFloat(sellerRequest.item.foreignAmount) + this.shadowRoot.getElementById('qortalAtAddress').value = sellerRequest.item.qortalAtAddress + const buyFunds = this.round(parseFloat(sellerRequest.item.foreignAmount)) + this.fillBuyForm(buyFunds) + } + + fillBuyFormMultiple(sellerRequests) { let qortalATAddresses = []; let qortAmount = 0; let foreignAmount = 0; @@ -1583,6 +1611,10 @@ class TradePortal extends LitElement { this.shadowRoot.getElementById('qortalAtAddress').value = qortalATAddresses const buyFunds = this.round(foreignAmount) + this.fillBuyForm(buyFunds) + } + + fillBuyForm(buyFunds) { const haveFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) if (Number(haveFunds) > Number(buyFunds)) { @@ -2355,11 +2387,21 @@ class TradePortal extends LitElement { } const makeRequest = async () => { - return await parentEpml.request('tradeBotRespondMultipleRequest', { - addresses: qortalAtAddress.split(','), - foreignKey: _foreignKey, - receivingAddress: this.selectedAddress.address - }) + + if( this.selectedCoin == 'PIRATECHAIN') { + return await parentEpml.request('tradeBotRespondRequest', { + atAddress: qortalAtAddress, + foreignKey: _foreignKey, + receivingAddress: this.selectedAddress.address + }) + } + else { + return await parentEpml.request('tradeBotRespondMultipleRequest', { + addresses: qortalAtAddress.split(','), + foreignKey: _foreignKey, + receivingAddress: this.selectedAddress.address + }) + } } const manageResponse = (response) => { @@ -2673,7 +2715,9 @@ class TradePortal extends LitElement { filterPresenceList() this.listedCoins.get(message.data.relatedCoin).openFilteredOrders = this.tradesPresenceCleaned this.reRenderOpenFilteredOrders() - this.reSelectOpenOrders() + if( this.selectedCoin != 'PIRATECHAIN') { + this.reSelectOpenOrders() + } return null default: break