diff --git a/img/dgb.png b/img/dgb.png
new file mode 100644
index 00000000..6950158b
Binary files /dev/null and b/img/dgb.png differ
diff --git a/img/dgb_transparent.png b/img/dgb_transparent.png
new file mode 100644
index 00000000..94e96ee1
Binary files /dev/null and b/img/dgb_transparent.png differ
diff --git a/img/qortdgb.png b/img/qortdgb.png
new file mode 100644
index 00000000..6e979807
Binary files /dev/null and b/img/qortdgb.png differ
diff --git a/qortal-ui-core/src/plugins/routes.js b/qortal-ui-core/src/plugins/routes.js
index 37e68f98..4310ad09 100644
--- a/qortal-ui-core/src/plugins/routes.js
+++ b/qortal-ui-core/src/plugins/routes.js
@@ -20,6 +20,7 @@ const cancelAllOffers = api.cancelAllOffers
const sendBtc = api.sendBtc
const sendLtc = api.sendLtc
const sendDoge = api.sendDoge
+const sendDgb = api.sendDgb
export const routes = {
hello: async (req) => {
@@ -333,4 +334,17 @@ export const routes = {
}
return response
},
+
+ sendDgb: async (req) => {
+ let response
+ try {
+ const res = await sendDgb(req.data)
+ response = res
+ } catch (e) {
+ console.error(e)
+ console.error(e.message)
+ response = e.message
+ }
+ return response
+ },
}
diff --git a/qortal-ui-crypto/api/PhraseWallet.js b/qortal-ui-crypto/api/PhraseWallet.js
index 86aaca35..00e6fd14 100644
--- a/qortal-ui-crypto/api/PhraseWallet.js
+++ b/qortal-ui-crypto/api/PhraseWallet.js
@@ -138,11 +138,27 @@ export default class PhraseWallet {
}
}).createWallet(new Uint8Array(dogeSeed), false, 'DOGE');
+ // Create Digibyte HD Wallet
+ const dgbSeed = [...addrSeed];
+ const dgbWallet = new AltcoinHDWallet({
+ mainnet: {
+ private: 0x0488ADE4,
+ public: 0x0488B21E,
+ prefix: 0x1E
+ },
+ testnet: {
+ private: 0x04358394,
+ public: 0x043587CF,
+ prefix: 0x7E
+ }
+ }).createWallet(new Uint8Array(dgbSeed), false, 'DGB');
+
this._addresses[nonce] = {
address,
btcWallet,
ltcWallet,
dogeWallet,
+ dgbWallet,
qoraAddress,
keyPair: {
publicKey: addrKeyPair.publicKey,
diff --git a/qortal-ui-crypto/api/api.js b/qortal-ui-crypto/api/api.js
index 3fc50db4..d9c469e1 100644
--- a/qortal-ui-crypto/api/api.js
+++ b/qortal-ui-crypto/api/api.js
@@ -4,6 +4,6 @@ export { transactionTypes as transactions } from './transactions/transactions.js
export { processTransaction, createTransaction, computeChatNonce, signChatTransaction, signArbitraryTransaction } from './createTransaction.js'
-export { tradeBotCreateRequest, tradeBotRespondRequest, signTradeBotTxn, deleteTradeOffer, sendBtc, sendLtc, sendDoge } from './tradeRequest.js'
+export { tradeBotCreateRequest, tradeBotRespondRequest, signTradeBotTxn, deleteTradeOffer, sendBtc, sendLtc, sendDoge, sendDgb } from './tradeRequest.js'
export { cancelAllOffers } from './transactions/trade-portal/tradeoffer/cancelAllOffers.js'
diff --git a/qortal-ui-crypto/api/tradeRequest.js b/qortal-ui-crypto/api/tradeRequest.js
index 8eab79a6..bef31a07 100644
--- a/qortal-ui-crypto/api/tradeRequest.js
+++ b/qortal-ui-crypto/api/tradeRequest.js
@@ -101,3 +101,17 @@ export const sendDoge = (requestObject) => {
body: JSON.stringify(requestObject)
})
}
+
+// Send DGB
+export const sendDgb = (requestObject) => {
+ const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
+
+ return request(`/crosschain/dgb/send?apiKey=${myNode.apiKey}`, {
+ method: 'POST',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(requestObject)
+ })
+}
diff --git a/qortal-ui-plugins/plugins/core/trade-portal/trade-portal.src.js b/qortal-ui-plugins/plugins/core/trade-portal/trade-portal.src.js
index 6dfe2ea1..c7560c1c 100644
--- a/qortal-ui-plugins/plugins/core/trade-portal/trade-portal.src.js
+++ b/qortal-ui-plugins/plugins/core/trade-portal/trade-portal.src.js
@@ -346,6 +346,10 @@ class TradePortal extends LitElement {
background-image: url('/img/qortdoge.png');
}
+ .dgb.coinName:before {
+ background-image: url('/img/qortdgb.png');
+ }
+
.coinName {
display: inline-block;
height: 26px;
@@ -444,10 +448,26 @@ class TradePortal extends LitElement {
coinAmount: this.amountString
}
+ let digibyte = {
+ name: "DIGIBYTE",
+ balance: "0",
+ coinCode: "DGB",
+ openOrders: [],
+ openFilteredOrders: [],
+ historicTrades: [],
+ myOrders: [],
+ myHistoricTrades: [],
+ myOfferingOrders: [],
+ openTradeOrders: null,
+ tradeOffersSocketCounter: 1,
+ coinAmount: this.amountString
+ }
+
this.listedCoins = new Map()
this.listedCoins.set("QORTAL", qortal)
this.listedCoins.set("LITECOIN", litecoin)
this.listedCoins.set("DOGECOIN", dogecoin)
+ this.listedCoins.set("DIGIBYTE", digibyte)
workers.set("QORTAL", {
tradesConnectedWorker: null,
@@ -464,6 +484,11 @@ class TradePortal extends LitElement {
handleStuckTradesConnectedWorker: null
})
+ workers.set("DIGIBYTE", {
+ tradesConnectedWorker: null,
+ handleStuckTradesConnectedWorker: null
+ })
+
this.selectedCoin = "LITECOIN"
this.selectedAddress = {}
this.config = {}
@@ -846,6 +871,7 @@ class TradePortal extends LitElement {
@@ -1008,6 +1034,10 @@ class TradePortal extends LitElement {
_url = `/crosschain/doge/walletbalance?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet.derivedMasterPublicKey
break
+ case 'DIGIBYTE':
+ _url = `/crosschain/dgb/walletbalance?apiKey=${this.getApiKey()}`
+ _body = window.parent.reduxStore.getState().app.selectedAddress.dgbWallet.derivedMasterPublicKey
+ break
default:
break
}
@@ -1385,6 +1415,49 @@ class TradePortal extends LitElement {
})
}
+ /**
+ * DigibyteACCTv1 TRADEBOT STATES
+ * - BOB_WAITING_FOR_AT_CONFIRM
+ * - BOB_WAITING_FOR_MESSAGE
+ * - BOB_WAITING_FOR_AT_REDEEM
+ * - BOB_DONE
+ * - BOB_REFUNDED
+ * - ALICE_WAITING_FOR_AT_LOCK
+ * - ALICE_DONE
+ * - ALICE_REFUNDING_A
+ * - ALICE_REFUNDED
+ *
+ * @param {[{}]} states
+ */
+
+ const DigibyteACCTv1 = (states) => {
+ // Reverse the states
+ states.reverse()
+ states.forEach((state) => {
+ if (state.creatorAddress === this.selectedAddress.address) {
+ if (state.tradeState == 'BOB_WAITING_FOR_AT_CONFIRM') {
+ this.changeTradeBotState(state, 'PENDING')
+ } else if (state.tradeState == 'BOB_WAITING_FOR_MESSAGE') {
+ this.changeTradeBotState(state, 'LISTED')
+ } else if (state.tradeState == 'BOB_WAITING_FOR_AT_REDEEM') {
+ this.changeTradeBotState(state, 'TRADING')
+ } else if (state.tradeState == 'BOB_DONE') {
+ this.handleCompletedState(state)
+ } else if (state.tradeState == 'BOB_REFUNDED') {
+ this.handleCompletedState(state)
+ } else if (state.tradeState == 'ALICE_WAITING_FOR_AT_LOCK') {
+ this.changeTradeBotState(state, 'BUYING')
+ } else if (state.tradeState == 'ALICE_DONE') {
+ this.handleCompletedState(state)
+ } else if (state.tradeState == 'ALICE_REFUNDING_A') {
+ this.changeTradeBotState(state, 'REFUNDING')
+ } else if (state.tradeState == 'ALICE_REFUNDED') {
+ this.handleCompletedState(state)
+ }
+ }
+ })
+ }
+
switch (this.selectedCoin) {
case 'BITCOIN':
BitcoinACCTv1(tradeStates)
@@ -1395,6 +1468,9 @@ class TradePortal extends LitElement {
case 'DOGECOIN':
DogecoinACCTv1(tradeStates)
break
+ case 'DIGIBYTE':
+ DigibyteACCTv1(tradeStates)
+ break
default:
break
}
@@ -1684,6 +1760,9 @@ class TradePortal extends LitElement {
case 'DOGECOIN':
_receivingAddress = this.selectedAddress.dogeWallet.address
break
+ case 'DIGIBYTE':
+ _receivingAddress = this.selectedAddress.dgbWallet.address
+ break
default:
break
}
@@ -1744,6 +1823,9 @@ class TradePortal extends LitElement {
case 'DOGECOIN':
_foreignKey = this.selectedAddress.dogeWallet.derivedMasterPrivateKey
break
+ case 'DIGIBYTE':
+ _foreignKey = this.selectedAddress.dgbWallet.derivedMasterPrivateKey
+ break
default:
break
}
diff --git a/qortal-ui-plugins/plugins/core/wallet/wallet-app.src.js b/qortal-ui-plugins/plugins/core/wallet/wallet-app.src.js
index 2b48c42d..05547151 100644
--- a/qortal-ui-plugins/plugins/core/wallet/wallet-app.src.js
+++ b/qortal-ui-plugins/plugins/core/wallet/wallet-app.src.js
@@ -25,7 +25,7 @@ import '@github/time-elements'
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
-const coinsNames = ['qort', 'btc', 'ltc', 'doge']
+const coinsNames = ['qort', 'btc', 'ltc', 'doge', 'dgb']
class MultiWallet extends LitElement {
static get properties() {
@@ -46,6 +46,8 @@ class MultiWallet extends LitElement {
ltcAmount: { type: Number },
dogeRecipient: { type: String },
dogeAmount: { type: Number },
+ dgbRecipient: { type: String },
+ dgbAmount: { type: Number },
errorMessage: { type: String },
successMessage: { type: String },
sendMoneyLoading: { type: Boolean },
@@ -55,6 +57,7 @@ class MultiWallet extends LitElement {
btcFeePerByte: { type: Number },
ltcFeePerByte: { type: Number },
dogeFeePerByte: { type: Number },
+ dgbFeePerByte: { type: Number },
balanceString: { type: String }
}
}
@@ -421,6 +424,10 @@ class MultiWallet extends LitElement {
background-image: url('/img/doge.png');
}
+ .dgb .currency-image {
+ background-image: url('/img/dgb.png');
+ }
+
.card-list {
margin-top: 20px;
}
@@ -553,6 +560,7 @@ class MultiWallet extends LitElement {
this.btcRecipient = ''
this.ltcRecipient = ''
this.dogeRecipient = ''
+ this.dgbRecipient = ''
this.errorMessage = ''
this.successMessage = ''
this.sendMoneyLoading = false
@@ -563,6 +571,7 @@ class MultiWallet extends LitElement {
this.btcAmount = 0
this.ltcAmount = 0
this.dogeAmount = 0
+ this.dgbAmount = 0
this.btcFeePerByte = 100
this.btcSatMinFee = 20
this.btcSatMaxFee = 150
@@ -572,6 +581,9 @@ class MultiWallet extends LitElement {
this.dogeFeePerByte = 1000
this.dogeSatMinFee = 100
this.dogeSatMaxFee = 10000
+ this.dgbFeePerByte = 100
+ this.dgbSatMinFee = 10
+ this.dgbSatMaxFee = 1000
this.wallets = new Map()
@@ -591,6 +603,7 @@ class MultiWallet extends LitElement {
this.wallets.get('btc').wallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet
this.wallets.get('ltc').wallet = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet
this.wallets.get('doge').wallet = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet
+ this.wallets.get('dgb').wallet = window.parent.reduxStore.getState().app.selectedAddress.dgbWallet
this._selectedWallet = 'qort'
@@ -603,6 +616,7 @@ class MultiWallet extends LitElement {
this.wallets.get('btc').wallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet
this.wallets.get('ltc').wallet = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet
this.wallets.get('doge').wallet = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet
+ this.wallets.get('dgb').wallet = window.parent.reduxStore.getState().app.selectedAddress.dgbWallet
})
parentEpml.subscribe('copy_menu_switch', async (value) => {
@@ -636,6 +650,10 @@ class MultiWallet extends LitElement {
Dogecoin
+
@@ -862,6 +880,56 @@ class MultiWallet extends LitElement {
+
+
+
${translate("walletpage.wchange5")}
+
+
+
+
${translate("walletpage.wchange6")}
+
+
+ ${translate("walletpage.wchange40")}
+ ${this.selectedTransaction.dgbTxnFlow === 'OUT' ? html`${translate("walletpage.wchange7")}` : html`${translate("walletpage.wchange8")}`}
+
+
${translate("walletpage.wchange9")}
+
+
+ ${this.selectedTransaction.dgbSender}
+
+
${translate("walletpage.wchange10")}
+
+
+ ${this.selectedTransaction.dgbReceiver}
+
+
${translate("walletpage.wchange12")}
+
+
+ ${(this.selectedTransaction.feeAmount / 1e8).toFixed(8)} DGB
+
+
${translate("walletpage.wchange37")}
+
+
+ ${(this.selectedTransaction.totalAmount / 1e8).toFixed(8)} DGB
+
+
${translate("walletpage.wchange14")}
+
+
${new Date(this.selectedTransaction.timestamp).toString()}
+
${translate("walletpage.wchange16")}
+
+
+ ${this.selectedTransaction.txHash}
+
+
+
+ ${translate("general.close")}
+
+
+
@@ -1148,6 +1216,82 @@ class MultiWallet extends LitElement {
${translate("general.close")}
+
+
+
+
+
![](/img/dgb.png)
+
${translate("walletpage.wchange17")} DGB
+
+
+
+ ${translate("walletpage.wchange18")}:
+ ${this.getSelectedWalletAddress()}
+
+
+ ${translate("walletpage.wchange19")}:
+ ${this.balanceString}
+
+
+ { this._checkAmount(e) }}"
+ id="dgbAmountInput"
+ label="${translate("walletpage.wchange11")} (DGB)"
+ type="number"
+ auto-validate="false"
+ value="${this.dgbAmount}"
+ >
+
+
+
+
+
+
+
+
+ ${translate("walletpage.wchange24")}: ${(this.dgbFeePerByte / 1e8).toFixed(8)} DGB
L${translate("walletpage.wchange25")}
+
+
(this.dgbFeePerByte = e.target.value)}"
+ id="dgbFeeSlider"
+ min="${this.dgbSatMinFee}"
+ max="${this.dgbSatMaxFee}"
+ value="${this.dgbFeePerByte}"
+ >
+
+
+
${this.errorMessage}
+
${this.successMessage}
+ ${this.sendMoneyLoading ? html`
` : ''}
+
+
+
+ ${translate("general.close")}
+
+
`
}
@@ -1389,6 +1533,52 @@ class MultiWallet extends LitElement {
}
checkSelectedTextAndShowMenu()
})
+
+ this.shadowRoot.getElementById('dgbAmountInput').addEventListener('contextmenu', (event) => {
+ const getSelectedText = () => {
+ var text = ''
+ if (typeof window.getSelection != 'undefined') {
+ text = window.getSelection().toString()
+ } else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
+ text = this.shadowRoot.selection.createRange().text
+ }
+ return text
+ }
+ const checkSelectedTextAndShowMenu = () => {
+ let selectedText = getSelectedText()
+ if (selectedText && typeof selectedText === 'string') {
+ } else {
+ this.pasteMenu(event, 'dgbAmountInput')
+ this.isPasteMenuOpen = true
+ event.preventDefault()
+ event.stopPropagation()
+ }
+ }
+ checkSelectedTextAndShowMenu()
+ })
+
+ this.shadowRoot.getElementById('dgbRecipient').addEventListener('contextmenu', (event) => {
+ const getSelectedText = () => {
+ var text = ''
+ if (typeof window.getSelection != 'undefined') {
+ text = window.getSelection().toString()
+ } else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
+ text = this.shadowRoot.selection.createRange().text
+ }
+ return text
+ }
+ const checkSelectedTextAndShowMenu = () => {
+ let selectedText = getSelectedText()
+ if (selectedText && typeof selectedText === 'string') {
+ } else {
+ this.pasteMenu(event, 'dgbRecipient')
+ this.isPasteMenuOpen = true
+ event.preventDefault()
+ event.stopPropagation()
+ }
+ }
+ checkSelectedTextAndShowMenu()
+ })
}
renderFetchText() {
@@ -1766,6 +1956,52 @@ class MultiWallet extends LitElement {
this.showWallet()
}
+ async sendDgb() {
+ const dgbAmount = this.shadowRoot.getElementById('dgbAmountInput').value
+ let dgbRecipient = this.shadowRoot.getElementById('dgbRecipient').value
+ const xprv58 = this.wallets.get(this._selectedWallet).wallet.derivedMasterPrivateKey
+
+ this.sendMoneyLoading = true
+ this.btnDisable = true
+
+ const makeRequest = async () => {
+ const opts = {
+ xprv58: xprv58,
+ receivingAddress: dgbRecipient,
+ digibyteAmount: dgbAmount,
+ feePerByte: (this.dgbFeePerByte / 1e8).toFixed(8),
+ }
+ const response = await parentEpml.request('sendDgb', opts)
+ return response
+ }
+
+ const manageResponse = (response) => {
+ if (response.length === 64) {
+ this.shadowRoot.getElementById('dgbAmountInput').value = 0
+ this.shadowRoot.getElementById('dgbRecipient').value = ''
+ this.errorMessage = ''
+ this.dgbRecipient = ''
+ this.dgbAmount = 0
+ this.successMessage = this.renderSuccessText()
+ this.sendMoneyLoading = false
+ this.btnDisable = false
+ } else if (response === false) {
+ this.errorMessage = this.renderFailText()
+ this.sendMoneyLoading = false
+ this.btnDisable = false
+ throw new Error(txnResponse)
+ } else {
+ this.errorMessage = response.message
+ this.sendMoneyLoading = false
+ this.btnDisable = false
+ throw new Error(response)
+ }
+ }
+ const res = await makeRequest()
+ manageResponse(res)
+ this.showWallet()
+ }
+
async showWallet() {
this.transactionsDOM.hidden = true
this.loading = true
@@ -1816,6 +2052,7 @@ class MultiWallet extends LitElement {
case 'btc':
case 'ltc':
case 'doge':
+ case 'dgb':
const walletName = `${coin}Wallet`
parentEpml.request('apiCall', {
url: `/crosschain/${coin}/walletbalance?apiKey=${this.getApiKey()}`,
@@ -1866,6 +2103,8 @@ class MultiWallet extends LitElement {
return html`
this.openSendLtc()}> ${translate("walletpage.wchange17")} LTC`
} else if ( this._selectedWallet === "doge" ) {
return html`
this.openSendDoge()}> ${translate("walletpage.wchange17")} DOGE`
+ } else if ( this._selectedWallet === "dgb" ) {
+ return html`
this.openSendDgb()}> ${translate("walletpage.wchange17")} DGB`
} else {
return html``
}
@@ -1887,6 +2126,10 @@ class MultiWallet extends LitElement {
this.shadowRoot.querySelector("#sendDogeDialog").show();
}
+ openSendDgb() {
+ this.shadowRoot.querySelector("#sendDgbDialog").show();
+ }
+
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
@@ -1952,6 +2195,15 @@ class MultiWallet extends LitElement {
},
{ passive: true }
)
+ } else if (coin === 'dgb') {
+ this.transactionsGrid.addEventListener(
+ 'click',
+ (e) => {
+ let dgbItem = this.transactionsGrid.getEventContext(e).item
+ this.showDgbTransactionDetails(dgbItem, this.wallets.get(this._selectedWallet).transactions)
+ },
+ { passive: true }
+ )
}
this.pagesControl = this.shadowRoot.querySelector('#pages')
@@ -1967,6 +2219,8 @@ class MultiWallet extends LitElement {
render(this.renderLtcTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)
} else if (this._selectedWallet === 'doge') {
render(this.renderDogeTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)
+ } else if (this._selectedWallet === 'dgb') {
+ render(this.renderDgbTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)
}
}
@@ -2222,6 +2476,71 @@ class MultiWallet extends LitElement {
`
}
+ renderDgbTransactions(transactions, coin) {
+ return html`
+
${translate("walletpage.wchange38")}
+
+ {
+ render(html`check`, root)
+ }}
+ >
+
+ {
+ render(html` ${translate("walletpage.wchange40")} ${data.item.inputs[0].address === this.wallets.get(this._selectedWallet).wallet.address ? html`${translate("walletpage.wchange7")}` : html`${translate("walletpage.wchange8")}`} `, root)
+ }}
+ >
+
+ {
+ render(html`${data.item.inputs[0].address}`, root)
+ }}
+ >
+
+ {
+ render(html`${data.item.outputs[0].address}`, root)
+ }}
+ >
+
+
+ {
+ const amount = (Number(data.item.totalAmount) / 1e8).toFixed(8)
+ render(html`${amount}`, root)
+ }}
+ >
+
+ {
+ const time = new Date(data.item.timestamp * 1000)
+ render(html` `, root)
+ }}
+ >
+
+
+
+ `
+ }
+
async updateItemsFromPage(page, changeWallet = false) {
if (page === undefined) {
return
@@ -2394,6 +2713,20 @@ class MultiWallet extends LitElement {
})
}
+ showDgbTransactionDetails(myTransaction, allTransactions) {
+ allTransactions.forEach((transaction) => {
+ if (myTransaction.txHash === transaction.txHash) {
+ let dgbTxnFlow = myTransaction.inputs[0].address === this.wallets.get(this._selectedWallet).wallet.address ? 'OUT' : 'IN'
+ let dgbSender = myTransaction.inputs[0].address
+ let dgbReceiver = myTransaction.outputs[0].address
+ this.selectedTransaction = { ...transaction, dgbTxnFlow, dgbSender, dgbReceiver }
+ if (this.selectedTransaction.txHash.length != 0) {
+ this.shadowRoot.querySelector('#showDgbTransactionDetailsDialog').show()
+ }
+ }
+ })
+ }
+
isEmptyArray(arr) {
if (!arr) {
return true