added deploy_at, join_group, publish qdn

This commit is contained in:
Phillip 2023-02-23 23:20:15 +00:00
parent ed1eeac37e
commit 6568d7600d
4 changed files with 467 additions and 148 deletions

View File

@ -0,0 +1,91 @@
'use strict'
import TransactionBase from './TransactionBase.js'
export default class DeployAtTransaction extends TransactionBase {
constructor() {
super()
this.type = 16
}
render(html) {
return html`
${this._groupdialog5}
<div style="background: #eee; padding: 8px; margin: 8px 0; border-radius: 5px;">
<div>${this._atDeployDialog1}: <span style="color: #000;">${this._rName}</span></div>
<br>
<div>${this.atDeployDialog2}: <span style="color: #000;">${this._rDescription}</span></div>
<br>
</div>
</div>
${this._groupdialog6}
`
}
set atDeployDialog1(atDeployDialog1) {
this._atDeployDialog1 = atDeployDialog1
}
set atDeployDialog2(atDeployDialog2) {
this._atDeployDialog2 = atDeployDialog2
}
set fee(fee) {
this._fee = fee
this._feeBytes = this.constructor.utils.int64ToBytes(this._fee)
}
set rAmount(rAmount) {
this._rAmount = rAmount
this._rAmountBytes = this.constructor.utils.int64ToBytes(this._rAmount)
}
set rName(rName) {
this._rName = rName
this._rNameBytes = this.constructor.utils.stringtoUTF8Array(this._rName.toLocaleLowerCase())
this._rNameLength = this.constructor.utils.int32ToBytes(this._rNameBytes.length)
}
set rDescription(rDescription) {
this._rDescription = rDescription
this._rDescriptionBytes = this.constructor.utils.stringtoUTF8Array(this._rDescription.toLocaleLowerCase())
this._rDescriptionLength = this.constructor.utils.int32ToBytes(this._rDescriptionBytes.length)
}
set atType(atType) {
this._atType = atType
this._atTypeBytes = this.constructor.utils.stringtoUTF8Array(this._atType)
this._atTypeLength = this.constructor.utils.int32ToBytes(this._atTypeBytes.length)
}
set rTags(rTags) {
this._rTags = rTags
this._rTagsBytes = this.constructor.utils.stringtoUTF8Array(this._rTags.toLocaleLowerCase())
this._rTagsLength = this.constructor.utils.int32ToBytes(this._rTagsBytes.length)
}
set rCreationBytes(rCreationBytes) {
const decode = this.constructor.Base58.decode(rCreationBytes)
console.log({decode})
this._rCreationBytes = this.constructor.utils.stringtoUTF8Array(decode)
this._rCreationBytesLength = this.constructor.utils.int32ToBytes(this._rCreationBytes.length)
}
set rAssetId(rAssetId) {
this._rAssetId = this.constructor.utils.int64ToBytes(rAssetId)
}
get params() {
const params = super.params
params.push(
this._rNameLength,
this._rNameBytes,
this._rDescriptionLength,
this._rDescriptionBytes,
this._atTypeLength,
this._atTypeBytes,
this._rTagsLength,
this._rTagsBytes,
this._rCreationBytesLength,
this._rCreationBytes,
this._rAmountBytes,
this._rAssetId,
this._feeBytes
)
return params
}
}

View File

@ -22,6 +22,7 @@ import LeaveGroupTransaction from './groups/LeaveGroupTransaction.js'
import RewardShareTransaction from './reward-share/RewardShareTransaction.js'
import RemoveRewardShareTransaction from './reward-share/RemoveRewardShareTransaction.js'
import TransferPrivsTransaction from './TransferPrivsTransaction.js'
import DeployAtTransaction from './DeployAtTransaction.js'
export const transactionTypes = {
2: PaymentTransaction,
@ -30,6 +31,7 @@ export const transactionTypes = {
5: SellNameTransacion,
6: CancelSellNameTransacion,
7: BuyNameTransacion,
16: DeployAtTransaction,
17: MessageTransaction,
18: ChatTransaction,
181: GroupChatTransaction,

View File

@ -170,18 +170,15 @@ class WebBrowser extends LitElement {
];
const nodeUrl =
myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
this.url = `${nodeUrl}/render/${this.service}/${this.name}${
this.path != null ? this.path : ''
}?theme=${this.theme}&identifier=${
this.identifier != null ? this.identifier : ''
this.url = `${nodeUrl}/render/${this.service}/${this.name}${this.path != null ? this.path : ''
}?theme=${this.theme}&identifier=${this.identifier != null ? this.identifier : ''
}`;
};
const authorizeAndRender = () => {
parentEpml
.request('apiCall', {
url: `/render/authorize/${
this.name
url: `/render/authorize/${this.name
}?apiKey=${this.getApiKey()}`,
method: 'POST',
})
@ -231,7 +228,6 @@ class WebBrowser extends LitElement {
}
render() {
console.log(2, 'browser page here');
return html`
<div id="websitesWrapper" style="width:auto; padding:10px; background: var(--white);">
<div class="layout horizontal center">
@ -248,8 +244,7 @@ class WebBrowser extends LitElement {
<mwc-button @click=${() => this.goBackToList()} title="${translate(
'browserpage.bchange3'
)}" class="address-bar-button"><mwc-icon>home</mwc-icon></mwc-button>
<input disabled style="width: 550px; color: var(--black);" id="address" type="text" value="${
this.displayUrl
<input disabled style="width: 550px; color: var(--black);" id="address" type="text" value="${this.displayUrl
}"></input>
<mwc-button @click=${() => this.delete()} title="${translate(
'browserpage.bchange4'
@ -260,8 +255,7 @@ class WebBrowser extends LitElement {
${this.renderFollowUnfollowButton()}
</div>
<div class="iframe-container">
<iframe id="browser-iframe" src="${
this.url
<iframe id="browser-iframe" src="${this.url
}" sandbox="allow-scripts allow-forms allow-downloads">
<span style="color: var(--black);">${translate(
'browserpage.bchange6'
@ -273,6 +267,142 @@ class WebBrowser extends LitElement {
`;
}
async unitJoinFee() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
const url = `${nodeUrl}/transactions/unitfee?txType=JOIN_GROUP`
const response = await fetch(url)
if (!response.ok) {
throw new Error('Error when fetching join fee');
}
const data = await response.json()
const joinFee = (Number(data) / 1e8).toFixed(8)
return joinFee
}
async deployAtFee() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
const url = `${nodeUrl}/transactions/unitfee?txType=DEPLOY_AT`
const response = await fetch(url)
if (!response.ok) {
throw new Error('Error when fetching join fee');
}
const data = await response.json()
const joinFee = data
return joinFee
}
async _joinGroup(groupId, groupName) {
const joinFeeInput = await this.unitJoinFee()
const getLastRef = async () => {
let myRef = await parentEpml.request('apiCall', {
type: 'api',
url: `/addresses/lastreference/${this.selectedAddress.address}`
})
return myRef
};
const validateReceiver = async () => {
let lastRef = await getLastRef();
let myTransaction = await makeTransactionRequest(lastRef)
const res = getTxnRequestResponse(myTransaction)
return res
}
const makeTransactionRequest = async (lastRef) => {
let groupdialog1 = get("transactions.groupdialog1")
let groupdialog2 = get("transactions.groupdialog2")
let myTxnrequest = await parentEpml.request('transaction', {
type: 31,
nonce: this.selectedAddress.nonce,
params: {
fee: joinFeeInput,
registrantAddress: this.selectedAddress.address,
rGroupName: groupName,
rGroupId: groupId,
lastReference: lastRef,
groupdialog1: groupdialog1,
groupdialog2: groupdialog2
}
})
return myTxnrequest
}
const getTxnRequestResponse = (txnResponse) => {
if (txnResponse.success === false && txnResponse.message) {
throw new Error(txnResponse.message)
} else if (txnResponse.success === true && !txnResponse.data.error) {
return txnResponse.data
} else if (txnResponse.data && txnResponse.data.message) {
throw new Error(txnResponse.data.message)
} else {
throw new Error('Server error. Could not perform action.')
}
}
const groupRes = await validateReceiver()
return groupRes
}
async _deployAt(name, description, tags, creationBytes, amount, assetId, fee, atType) {
const deployAtFee = await this.deployAtFee()
const getLastRef = async () => {
let myRef = await parentEpml.request('apiCall', {
type: 'api',
url: `/addresses/lastreference/${this.selectedAddress.address}`
})
return myRef
};
const validateReceiver = async () => {
let lastRef = await getLastRef();
let myTransaction = await makeTransactionRequest(lastRef)
const res = getTxnRequestResponse(myTransaction)
return res
}
const makeTransactionRequest = async (lastRef) => {
let groupdialog1 = get("transactions.groupdialog1")
let groupdialog2 = get("transactions.groupdialog2")
let myTxnrequest = await parentEpml.request('transaction', {
type: 16,
nonce: this.selectedAddress.nonce,
params: {
fee: fee || deployAtFee,
rName: name,
rDescription: description,
rTags: tags,
rAmount: amount,
rAssetId: assetId,
rCreationBytes: creationBytes,
atType: atType,
lastReference: lastRef,
atDeployDialog1: groupdialog1,
atDeployDialog2: groupdialog2
}
})
return myTxnrequest
}
const getTxnRequestResponse = (txnResponse) => {
if (txnResponse.success === false && txnResponse.message) {
throw new Error(txnResponse.message)
} else if (txnResponse.success === true && !txnResponse.data.error) {
return txnResponse.data
} else if (txnResponse.data && txnResponse.data.message) {
throw new Error(txnResponse.data.message)
} else {
throw new Error('Server error. Could not perform action.')
}
}
const groupRes = await validateReceiver()
return groupRes
}
firstUpdated() {
this.changeTheme();
this.changeLanguage();
@ -338,7 +468,7 @@ class WebBrowser extends LitElement {
const errorMsg = get('browserpage.bchange17');
data['error'] = errorMsg;
response = JSON.stringify(data);
return;
break;
}
case 'LINK_TO_QDN_RESOURCE':
case actions.QDN_RESOURCE_DISPLAYED:
@ -363,16 +493,29 @@ class WebBrowser extends LitElement {
this.displayUrl = url;
return;
case actions.PUBLISH_QDN_RESOURCE:
case actions.PUBLISH_QDN_RESOURCE: {
const requiredFields = ['service', 'name', 'data64'];
const missingFields = [];
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field);
}
});
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ');
const errorMsg = `Missing fields: ${missingFieldsString}`
let data = {};
data['error'] = errorMsg;
response = JSON.stringify(data);
break
}
// Use "default" if user hasn't specified an identifer
const service = data.service;
const name = data.name;
let identifier = data.identifier;
const data64 = data.data64;
if (!service || !name || !data64) {
return;
}
if (data.identifier == null) {
identifier = 'default';
}
@ -394,16 +537,15 @@ class WebBrowser extends LitElement {
worker: worker,
isBase64: true,
});
let data = {};
data['data'] = resPublish;
response = JSON.stringify(data);
response = JSON.stringify(resPublish);
worker.terminate();
} catch (error) {
worker.terminate();
const data = {};
const obj = {};
const errorMsg = error.message || 'Upload failed';
data['error'] = errorMsg;
response = JSON.stringify(data);
obj['error'] = errorMsg;
response = JSON.stringify(obj);
console.error(error);
return;
} finally {
@ -417,6 +559,8 @@ class WebBrowser extends LitElement {
// then set the response string from the core to the `response` variable (defined above)
// If they decline, send back JSON that includes an `error` key, such as `{"error": "User declined request"}`
break;
}
case 'SEND_CHAT_MESSAGE':
// Params: data.groupId, data.destinationAddress, data.message
@ -425,11 +569,60 @@ class WebBrowser extends LitElement {
// If they decline, send back JSON that includes an `error` key, such as `{"error": "User declined request"}`
break;
case actions.JOIN_GROUP:
case actions.JOIN_GROUP: {
const requiredFields = ['groupId'];
const missingFields = [];
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field);
}
});
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ');
const errorMsg = `Missing fields: ${missingFieldsString}`
let data = {};
data['error'] = errorMsg;
response = JSON.stringify(data);
break
}
const groupId = data.groupId;
if (!groupId) {
return;
let groupInfo = null
try {
groupInfo = await parentEpml.request("apiCall", {
type: "api",
url: `/groups/${groupId}`,
});
} catch (error) {
const errorMsg = (error && error.message) || 'Group not found';
let obj = {};
obj['error'] = errorMsg;
response = JSON.stringify(obj);
break
}
if (!groupInfo || groupInfo.error) {
const errorMsg = (groupInfo && groupInfo.message) || 'Group not found';
let obj = {};
obj['error'] = errorMsg;
response = JSON.stringify(obj);
break
}
try {
this.loader.show();
const resJoinGroup = await this._joinGroup(groupId, groupInfo.groupName)
response = JSON.stringify(resJoinGroup);
} catch (error) {
const obj = {};
const errorMsg = error.message || 'Failed to join the group.';
obj['error'] = errorMsg;
response = JSON.stringify(obj);
} finally {
this.loader.hide();
}
// Params: data.groupId
@ -437,21 +630,55 @@ class WebBrowser extends LitElement {
// then set the response string from the core to the `response` variable (defined above)
// If they decline, send back JSON that includes an `error` key, such as `{"error": "User declined request"}`
break;
}
case 'DEPLOY_AT':
case 'DEPLOY_AT': {
const requiredFields = ['name', 'description', 'tags', 'creationBytes', 'amount', 'assetId', 'type'];
const missingFields = [];
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field);
}
});
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ');
const errorMsg = `Missing fields: ${missingFieldsString}`
let data = {};
data['error'] = errorMsg;
response = JSON.stringify(data);
break
}
try {
this.loader.show();
const fee = data.fee || undefined
const resJoinGroup = await this._deployAt(data.name, data.description, data.tags, data.creationBytes, data.amount, data.assetId, fee, data.type)
response = JSON.stringify(resJoinGroup);
} catch (error) {
const obj = {};
const errorMsg = error.message || 'Failed to join the group.';
obj['error'] = errorMsg;
response = JSON.stringify(obj);
} finally {
this.loader.hide();
}
// Params: data.creationBytes, data.name, data.description, data.type, data.tags, data.amount, data.assetId, data.fee
// TODO: prompt user to deploy an AT. If they confirm, sign+process a DEPLOY_AT transaction
// then set the response string from the core to the `response` variable (defined above)
// If they decline, send back JSON that includes an `error` key, such as `{"error": "User declined request"}`
break;
}
case 'GET_WALLET_BALANCE':
// Params: data.coin (QORT / LTC / DOGE / DGB / C / ARRR)
// TODO: prompt user to share wallet balance. If they confirm, call `GET /crosschain/:coin/walletbalance`, or for QORT, call `GET /addresses/balance/:address`
// then set the response string from the core to the `response` variable (defined above)
// If they decline, send back JSON that includes an `error` key, such as `{"error": "User declined request"}`
console.log('case passed here');
console.log(data.coin, "data coin here");
const res3 = await showModalAndWait(
actions.GET_WALLET_BALANCE
);
@ -464,7 +691,6 @@ class WebBrowser extends LitElement {
const QORTBalance = await parentEpml.request('apiCall', {
url: `/addresses/balance/${qortAddress}?apiKey=${this.getApiKey()}`,
})
console.log({QORTBalance})
return QORTBalance;
} catch (error) {
console.error(error);
@ -554,14 +780,16 @@ class WebBrowser extends LitElement {
// Not all responses will be JSON
responseObj = response;
}
console.log({ responseObj })
// Respond to app
if (responseObj.error != null) {
console.log('hello error')
event.ports[0].postMessage({
result: null,
error: responseObj,
});
} else {
console.log('hello success')
event.ports[0].postMessage({
result: responseObj,
error: null,
@ -658,10 +886,8 @@ class WebBrowser extends LitElement {
];
const nodeUrl =
myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
this.url = `${nodeUrl}/render/${this.service}/${this.name}${
this.path != null ? this.path : ''
}?theme=${this.theme}&identifier=${
this.identifier != null ? this.identifier : ''
this.url = `${nodeUrl}/render/${this.service}/${this.name}${this.path != null ? this.path : ''
}?theme=${this.theme}&identifier=${this.identifier != null ? this.identifier : ''
}`;
}
@ -811,8 +1037,7 @@ class WebBrowser extends LitElement {
this.identifier == null ? 'default' : resource.identifier;
let ret = await parentEpml.request('apiCall', {
url: `/arbitrary/resource/${this.service}/${
this.name
url: `/arbitrary/resource/${this.service}/${this.name
}/${identifier}?apiKey=${this.getApiKey()}`,
method: 'DELETE',
});

View File

@ -148,7 +148,8 @@ export const publishData = async ({
}
}
try {
await validate()
const validateRes = await validate()
return validateRes
} catch (error) {
throw new Error(error.message)
}