diff --git a/src/App.tsx b/src/App.tsx index bae4331..310dc21 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3189,6 +3189,24 @@ function App() { )} + {messageQortalRequestExtension?.appFee && ( + <> + + {"App Fee: "} + {messageQortalRequestExtension?.appFee} + {" QORT"} + + + + )} {messageQortalRequestExtension?.foreignFee && ( <> @@ -3212,7 +3230,6 @@ function App() { {"Manage your minting"} + setIsOpenMinting(false)} + aria-label="close" + > + + "; diff --git a/src/qortalRequests/get.ts b/src/qortalRequests/get.ts index b28bd13..21412f9 100644 --- a/src/qortalRequests/get.ts +++ b/src/qortalRequests/get.ts @@ -569,7 +569,7 @@ export const getUserAccount = async ({isFromExtension, appInfo}) => { }; export const encryptData = async (data, sender) => { - let data64 = data.data64; + let data64 = data.data64 || data.base64; let publicKeys = data.publicKeys || []; if (data.fileId) { data64 = await getFileFromContentScript(data.fileId, sender); @@ -818,24 +818,41 @@ export const publishQDNResource = async (data: any, sender, isFromExtension) => const errorMsg = `Missing fields: ${missingFieldsString}`; throw new Error(errorMsg); } - if (!data.fileId && !data.data64) { + if (!data.fileId && !data.data64 && !data.base64) { throw new Error("No data or file was submitted"); } // Use "default" if user hasn't specified an identifer const service = data.service; + + const appFee = data?.appFee ? +data.appFee : undefined + const appFeeRecipient = data?.appFeeRecipient + let hasAppFee = false + if(appFee && appFee > 0 && appFeeRecipient){ + hasAppFee = true + } const registeredName = await getNameInfo(); const name = registeredName; + if(!name){ + throw new Error('User has no Qortal name') + } let identifier = data.identifier; - let data64 = data.data64; + let data64 = data.data64 || data.base64; + const filename = data.filename; const title = data.title; const description = data.description; const category = data.category; - const tag1 = data.tag1; - const tag2 = data.tag2; - const tag3 = data.tag3; - const tag4 = data.tag4; - const tag5 = data.tag5; + const tags = data?.tags || []; +const result = {}; + +// Fill tags dynamically while maintaining backward compatibility +for (let i = 0; i < 5; i++) { + result[`tag${i + 1}`] = tags[i] || data[`tag${i + 1}`] || undefined; +} + +// Access tag1 to tag5 from result +const { tag1, tag2, tag3, tag4, tag5 } = result; + if (data.identifier == null) { identifier = "default"; } @@ -874,14 +891,30 @@ export const publishQDNResource = async (data: any, sender, isFromExtension) => const fee = await getFee("ARBITRARY"); + const handleDynamicValues = {} + if(hasAppFee){ + const feePayment = await getFee("PAYMENT"); + + handleDynamicValues['appFee'] = +appFee + +feePayment.fee, + handleDynamicValues['checkbox1'] = { + value: true, + label: "accept app fee", + } + } + if(!!data?.encrypt){ + handleDynamicValues['highlightedText'] = `isEncrypted: ${!!data.encrypt}` + } + const resPermission = await getUserPermission({ text1: "Do you give this application permission to publish to QDN?", text2: `service: ${service}`, text3: `identifier: ${identifier || null}`, - highlightedText: `isEncrypted: ${!!data.encrypt}`, fee: fee.fee, + ...handleDynamicValues }, isFromExtension); - const { accepted } = resPermission; + + const { accepted, checkbox1 = false } = resPermission; + if (accepted) { try { @@ -904,6 +937,12 @@ export const publishQDNResource = async (data: any, sender, isFromExtension) => apiVersion: 2, withFee: true, }); + if(resPublish?.signature && hasAppFee && checkbox1){ + sendCoinFunc({ + amount: appFee, + receiver: appFeeRecipient + }, true) + } return resPublish; } catch (error) { throw new Error(error?.message || "Upload failed"); @@ -969,16 +1008,48 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten if (resources.length === 0) { throw new Error("No resources to publish"); } - if ( - data.encrypt && - (!data.publicKeys || - (Array.isArray(data.publicKeys) && data.publicKeys.length === 0)) - ) { - throw new Error("Encrypting data requires public keys"); + + const encrypt = data?.encrypt + + for (const resource of resources) { + const resourceEncrypt = encrypt && resource?.disableEncrypt !== true + if (!resourceEncrypt && resource?.service.endsWith("_PRIVATE")) { + const errorMsg = "Only encrypted data can go into private services"; + throw new Error(errorMsg) + } else if(resourceEncrypt && !resource?.service.endsWith("_PRIVATE")){ + const errorMsg = "For an encrypted publish please use a service that ends with _PRIVATE"; + throw new Error(errorMsg) + } } + const fee = await getFee("ARBITRARY"); const registeredName = await getNameInfo(); const name = registeredName; + + if(!name){ + throw new Error('You need a Qortal name to publish.') + } + const appFee = data?.appFee ? +data.appFee : undefined + const appFeeRecipient = data?.appFeeRecipient + let hasAppFee = false + if(appFee && appFee > 0 && appFeeRecipient){ + hasAppFee = true + } + + const handleDynamicValues = {} + if(hasAppFee){ + const feePayment = await getFee("PAYMENT"); + + handleDynamicValues['appFee'] = +appFee + +feePayment.fee, + handleDynamicValues['checkbox1'] = { + value: true, + label: "accept app fee", + } + } + if(data?.encrypt){ + handleDynamicValues['highlightedText'] = `isEncrypted: ${!!data.encrypt}` + } + const resPermission = await getUserPermission({ text1: "Do you give this application permission to publish to QDN?", html: ` @@ -1028,7 +1099,7 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten
Service: ${ resource.service }
-
Name: ${resource.name}
+
Name: ${name}
Identifier: ${ resource.identifier }
@@ -1043,10 +1114,13 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten `, - highlightedText: `isEncrypted: ${!!data.encrypt}`, - fee: fee.fee * resources.length, + fee: +fee.fee * resources.length, + ...handleDynamicValues }, isFromExtension); - const { accepted } = resPermission; + + + const { accepted, checkbox1 = false } = resPermission; + if (!accepted) { throw new Error("User declined request"); } @@ -1069,7 +1143,7 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten }); continue; } - if (!resource.fileId && !resource.data64) { + if (!resource.fileId && !resource.data64 && !resource?.base64) { const errorMsg = "No data or file was submitted"; failedPublishesIdentifiers.push({ reason: errorMsg, @@ -1079,20 +1153,26 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten } const service = resource.service; let identifier = resource.identifier; - let data64 = resource.data64; + let data64 = resource?.data64 || resource?.base64; const filename = resource.filename; const title = resource.title; const description = resource.description; const category = resource.category; - const tag1 = resource.tag1; - const tag2 = resource.tag2; - const tag3 = resource.tag3; - const tag4 = resource.tag4; - const tag5 = resource.tag5; + const tags = resource?.tags || []; + const result = {}; + + // Fill tags dynamically while maintaining backward compatibility + for (let i = 0; i < 5; i++) { + result[`tag${i + 1}`] = tags[i] || resource[`tag${i + 1}`] || undefined; + } + + // Access tag1 to tag5 from result + const { tag1, tag2, tag3, tag4, tag5 } = result; + const resourceEncrypt = encrypt && resource?.disableEncrypt !== true if (resource.identifier == null) { identifier = "default"; } - if (!data.encrypt && service.endsWith("_PRIVATE")) { + if (!resourceEncrypt && service.endsWith("_PRIVATE")) { const errorMsg = "Only encrypted data can go into private services"; failedPublishesIdentifiers.push({ reason: errorMsg, @@ -1103,7 +1183,7 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten if (resource.fileId) { data64 = await getFileFromContentScript(resource.fileId, sender); } - if (data.encrypt) { + if (resourceEncrypt) { try { const resKeyPair = await getKeyPair() const parsedData = JSON.parse(resKeyPair) @@ -1155,7 +1235,7 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten }, 1000); }); } catch (error) { - const errorMsg = error.message || "Upload failed"; + const errorMsg = error?.message || "Upload failed"; failedPublishesIdentifiers.push({ reason: errorMsg, identifier: resource.identifier, @@ -1163,7 +1243,7 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten } } catch (error) { failedPublishesIdentifiers.push({ - reason: "Unknown error", + reason: error?.message || "Unknown error", identifier: resource.identifier, }); } @@ -1175,6 +1255,12 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten }; return obj; } + if(hasAppFee && checkbox1){ + sendCoinFunc({ + amount: appFee, + receiver: appFeeRecipient + }, true) + } return true; };