mirror of https://github.com/Qortal/Q-Apps-Utils
22 changed files with 524 additions and 49 deletions
@ -0,0 +1,51 @@ |
|||||||
|
// returns {error: "Cannot find requested data"} if data isn't found
|
||||||
|
import { ProfileCoinType } from "./Utils/Types.ts"; |
||||||
|
|
||||||
|
export const getProfileData = async (property: string) => { |
||||||
|
return (await qortalRequest({ |
||||||
|
action: "GET_PROFILE_DATA", |
||||||
|
property, |
||||||
|
})) as string | object; |
||||||
|
}; |
||||||
|
|
||||||
|
export const setProfileData = async ( |
||||||
|
property: string, |
||||||
|
data: object, |
||||||
|
encrypt = false |
||||||
|
) => { |
||||||
|
if (encrypt) property += "-private"; |
||||||
|
return (await qortalRequest({ |
||||||
|
action: "SET_PROFILE_DATA", |
||||||
|
property, |
||||||
|
data: { customData: data }, |
||||||
|
})) as string; |
||||||
|
}; |
||||||
|
|
||||||
|
export const setDefaultProfileData = async ( |
||||||
|
property: string, |
||||||
|
data: object, |
||||||
|
encrypt = false |
||||||
|
) => { |
||||||
|
if (encrypt) property += "-private"; |
||||||
|
return (await qortalRequest({ |
||||||
|
action: "SET_PROFILE_DATA", |
||||||
|
property, |
||||||
|
data, |
||||||
|
})) as string; |
||||||
|
}; |
||||||
|
|
||||||
|
export const getProfileWallet = async (coin: ProfileCoinType) => { |
||||||
|
return await getProfileData("wallets")[coin]; |
||||||
|
}; |
||||||
|
|
||||||
|
export const setProfileWallet = async (wallet: object) => { |
||||||
|
return await setProfileData("wallets", wallet); |
||||||
|
}; |
||||||
|
|
||||||
|
export const summonProfileModal = async () => { |
||||||
|
return (await qortalRequest({ |
||||||
|
action: "SET_PROFILE_DATA", |
||||||
|
property: "wallets", |
||||||
|
data: {}, |
||||||
|
})) as string; |
||||||
|
}; |
@ -0,0 +1,62 @@ |
|||||||
|
export const hasQFundEnded = async (atAddress: string) => { |
||||||
|
try { |
||||||
|
const url = `/at/${atAddress}`; |
||||||
|
const response = await fetch(url, { |
||||||
|
method: "GET", |
||||||
|
headers: { |
||||||
|
"Content-Type": "application/json", |
||||||
|
}, |
||||||
|
}); |
||||||
|
if (response.status === 200) { |
||||||
|
const responseDataSearch = await response.json(); |
||||||
|
if ( |
||||||
|
Object.keys(responseDataSearch).length > 0 && |
||||||
|
responseDataSearch?.isFinished |
||||||
|
) { |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (error) { |
||||||
|
console.log(error); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export const getATAmount = async crowdfundLink => { |
||||||
|
const crowdfund = await getCrowdfund(crowdfundLink); |
||||||
|
const atAddress = crowdfund?.deployedAT?.aTAddress; |
||||||
|
if (!atAddress) return 0; |
||||||
|
try { |
||||||
|
const res = await qortalRequest({ |
||||||
|
action: "SEARCH_TRANSACTIONS", |
||||||
|
txType: ["PAYMENT"], |
||||||
|
confirmationStatus: "CONFIRMED", |
||||||
|
address: atAddress, |
||||||
|
limit: 0, |
||||||
|
reverse: true, |
||||||
|
}); |
||||||
|
if (res?.length > 0) { |
||||||
|
const totalAmount: number = res.reduce( |
||||||
|
(total: number, transaction) => total + parseFloat(transaction.amount), |
||||||
|
0 |
||||||
|
); |
||||||
|
return totalAmount; |
||||||
|
} |
||||||
|
} catch (e) { |
||||||
|
console.log(e); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export const getCrowdfund = async (crowdfundLink: string) => { |
||||||
|
const splitLink = crowdfundLink.split("/"); |
||||||
|
const name = splitLink[5]; |
||||||
|
const identifier = splitLink[6]; |
||||||
|
return await qortalRequest({ |
||||||
|
action: "FETCH_QDN_RESOURCE", |
||||||
|
service: "DOCUMENT", |
||||||
|
name, |
||||||
|
identifier, |
||||||
|
}); |
||||||
|
}; |
@ -0,0 +1,28 @@ |
|||||||
|
import { SearchResourcesResponse } from "./Utils/Interfaces/Responses.ts"; |
||||||
|
|
||||||
|
export const fetchResourcesByIdentifier = async <T>( |
||||||
|
service: string, |
||||||
|
identifier: string |
||||||
|
) => { |
||||||
|
const names: SearchResourcesResponse[] = await qortalRequest({ |
||||||
|
action: "SEARCH_QDN_RESOURCES", |
||||||
|
service, |
||||||
|
identifier, |
||||||
|
includeMetadata: false, |
||||||
|
}); |
||||||
|
const distinctNames = names.filter( |
||||||
|
(searchResponse, index) => names.indexOf(searchResponse) === index |
||||||
|
); |
||||||
|
|
||||||
|
const promises: Promise<T>[] = []; |
||||||
|
distinctNames.map(response => { |
||||||
|
const resource: Promise<T> = qortalRequest({ |
||||||
|
action: "FETCH_QDN_RESOURCE", |
||||||
|
name: response.name, |
||||||
|
service, |
||||||
|
identifier, |
||||||
|
}); |
||||||
|
promises.push(resource); |
||||||
|
}); |
||||||
|
return (await Promise.all(promises)) as T[]; |
||||||
|
}; |
@ -0,0 +1,8 @@ |
|||||||
|
export const getAvatarFromName = async (name: string) => { |
||||||
|
return await qortalRequest({ |
||||||
|
action: "GET_QDN_RESOURCE_URL", |
||||||
|
name, |
||||||
|
service: "THUMBNAIL", |
||||||
|
identifier: "qortal_avatar", |
||||||
|
}); |
||||||
|
}; |
@ -1,12 +0,0 @@ |
|||||||
export const setProfileData = async ( |
|
||||||
property: string, |
|
||||||
data: object, |
|
||||||
encrypt = false |
|
||||||
) => { |
|
||||||
if (encrypt) property += "-private"; |
|
||||||
return (await qortalRequest({ |
|
||||||
action: "SET_PROFILE_DATA", |
|
||||||
property, |
|
||||||
data: { customData: data }, |
|
||||||
})) as string; |
|
||||||
}; |
|
@ -0,0 +1,184 @@ |
|||||||
|
export const publishFormatter = ( |
||||||
|
file: File |
||||||
|
): Promise<string | ArrayBuffer | null> => |
||||||
|
new Promise((resolve, reject) => { |
||||||
|
const reader = new FileReader(); |
||||||
|
reader.readAsDataURL(file); |
||||||
|
|
||||||
|
reader.onload = () => { |
||||||
|
const result = reader.result; |
||||||
|
reader.onload = null; // remove onload handler
|
||||||
|
reader.onerror = null; // remove onerror handler
|
||||||
|
resolve(result); |
||||||
|
}; |
||||||
|
|
||||||
|
reader.onerror = error => { |
||||||
|
reader.onload = null; // remove onload handler
|
||||||
|
reader.onerror = null; // remove onerror handler
|
||||||
|
reject(error); |
||||||
|
}; |
||||||
|
}); |
||||||
|
|
||||||
|
export function objectToBase64(obj: any) { |
||||||
|
// Step 1: Convert the object to a JSON string
|
||||||
|
const jsonString = JSON.stringify(obj); |
||||||
|
|
||||||
|
// Step 2: Create a Blob from the JSON string
|
||||||
|
const blob = new Blob([jsonString], { type: "application/json" }); |
||||||
|
|
||||||
|
// Step 3: Create a FileReader to read the Blob as a base64-encoded string
|
||||||
|
return new Promise<string>((resolve, reject) => { |
||||||
|
const reader = new FileReader(); |
||||||
|
reader.onloadend = () => { |
||||||
|
if (typeof reader.result === "string") { |
||||||
|
// Remove 'data:application/json;base64,' prefix
|
||||||
|
const base64 = reader.result.replace( |
||||||
|
"data:application/json;base64,", |
||||||
|
"" |
||||||
|
); |
||||||
|
resolve(base64); |
||||||
|
} else { |
||||||
|
reject(new Error("Failed to read the Blob as a base64-encoded string")); |
||||||
|
} |
||||||
|
}; |
||||||
|
reader.onerror = () => { |
||||||
|
reject(reader.error); |
||||||
|
}; |
||||||
|
reader.readAsDataURL(blob); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
export function objectToFile(obj: any) { |
||||||
|
// Step 1: Convert the object to a JSON string
|
||||||
|
const jsonString = JSON.stringify(obj); |
||||||
|
|
||||||
|
// Step 2: Create a Blob from the JSON string
|
||||||
|
return new Blob([jsonString], { type: "application/json" }); |
||||||
|
} |
||||||
|
|
||||||
|
export function objectToUint8Array(obj: any) { |
||||||
|
// Convert the object to a JSON string
|
||||||
|
const jsonString = JSON.stringify(obj); |
||||||
|
|
||||||
|
// Encode the JSON string as a byte array using TextEncoder
|
||||||
|
const encoder = new TextEncoder(); |
||||||
|
const byteArray = encoder.encode(jsonString); |
||||||
|
|
||||||
|
// Create a new Uint8Array and set its content to the encoded byte array
|
||||||
|
const uint8Array = new Uint8Array(byteArray); |
||||||
|
|
||||||
|
return uint8Array; |
||||||
|
} |
||||||
|
|
||||||
|
export function uint8ArrayToBase64(uint8Array: Uint8Array): string { |
||||||
|
const length = uint8Array.length; |
||||||
|
let binaryString = ""; |
||||||
|
const chunkSize = 1024 * 1024; // Process 1MB at a time
|
||||||
|
|
||||||
|
for (let i = 0; i < length; i += chunkSize) { |
||||||
|
const chunkEnd = Math.min(i + chunkSize, length); |
||||||
|
const chunk = uint8Array.subarray(i, chunkEnd); |
||||||
|
binaryString += Array.from(chunk, byte => String.fromCharCode(byte)).join( |
||||||
|
"" |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
return btoa(binaryString); |
||||||
|
} |
||||||
|
|
||||||
|
export function objectToUint8ArrayFromResponse(obj: any) { |
||||||
|
const len = Object.keys(obj).length; |
||||||
|
const result = new Uint8Array(len); |
||||||
|
|
||||||
|
for (let i = 0; i < len; i++) { |
||||||
|
result[i] = obj[i]; |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
// export function uint8ArrayToBase64(arrayBuffer: Uint8Array): string {
|
||||||
|
// let binary = ''
|
||||||
|
// const bytes = new Uint8Array(arrayBuffer)
|
||||||
|
// const len = bytes.length
|
||||||
|
|
||||||
|
// for (let i = 0; i < len; i++) {
|
||||||
|
// binary += String.fromCharCode(bytes[i])
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return btoa(binary)
|
||||||
|
// }
|
||||||
|
|
||||||
|
export function base64ToUint8Array(base64: string) { |
||||||
|
const binaryString = atob(base64); |
||||||
|
const len = binaryString.length; |
||||||
|
const bytes = new Uint8Array(len); |
||||||
|
|
||||||
|
for (let i = 0; i < len; i++) { |
||||||
|
bytes[i] = binaryString.charCodeAt(i); |
||||||
|
} |
||||||
|
|
||||||
|
return bytes; |
||||||
|
} |
||||||
|
|
||||||
|
export function uint8ArrayToObject(uint8Array: Uint8Array) { |
||||||
|
// Decode the byte array using TextDecoder
|
||||||
|
const decoder = new TextDecoder(); |
||||||
|
const jsonString = decoder.decode(uint8Array); |
||||||
|
|
||||||
|
// Convert the JSON string back into an object
|
||||||
|
const obj = JSON.parse(jsonString); |
||||||
|
|
||||||
|
return obj; |
||||||
|
} |
||||||
|
|
||||||
|
export function processFileInChunks(file: File): Promise<Uint8Array> { |
||||||
|
return new Promise( |
||||||
|
(resolve: (value: Uint8Array) => void, reject: (reason?: any) => void) => { |
||||||
|
const reader = new FileReader(); |
||||||
|
|
||||||
|
reader.onload = function (event: ProgressEvent<FileReader>) { |
||||||
|
const arrayBuffer = event.target?.result as ArrayBuffer; |
||||||
|
const uint8Array = new Uint8Array(arrayBuffer); |
||||||
|
resolve(uint8Array); |
||||||
|
}; |
||||||
|
|
||||||
|
reader.onerror = function (error: ProgressEvent<FileReader>) { |
||||||
|
reject(error); |
||||||
|
}; |
||||||
|
|
||||||
|
reader.readAsArrayBuffer(file); |
||||||
|
} |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
// export async function processFileInChunks(file: File, chunkSize = 1024 * 1024): Promise<Uint8Array> {
|
||||||
|
// const fileStream = file.stream();
|
||||||
|
// const reader = fileStream.getReader();
|
||||||
|
// const totalLength = file.size;
|
||||||
|
|
||||||
|
// if (totalLength <= 0 || isNaN(totalLength)) {
|
||||||
|
// throw new Error('Invalid file size');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const combinedArray = new Uint8Array(totalLength);
|
||||||
|
// let offset = 0;
|
||||||
|
|
||||||
|
// while (offset < totalLength) {
|
||||||
|
// const { value, done } = await reader.read();
|
||||||
|
|
||||||
|
// if (done) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const chunk = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
||||||
|
|
||||||
|
// // Set elements one by one instead of using combinedArray.set(chunk, offset)
|
||||||
|
// for (let i = 0; i < chunk.length; i++) {
|
||||||
|
// combinedArray[offset + i] = chunk[i];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// offset += chunk.length;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return combinedArray;
|
||||||
|
// }
|
@ -0,0 +1,13 @@ |
|||||||
|
export const getFileExtensionIndex = (s: string) => { |
||||||
|
const lastIndex = s.lastIndexOf("."); |
||||||
|
return lastIndex > 0 ? lastIndex : s.length - 1; |
||||||
|
}; |
||||||
|
|
||||||
|
export const getFileName = (s: string) => { |
||||||
|
return s.substring(0, getFileExtensionIndex(s)); |
||||||
|
}; |
||||||
|
|
||||||
|
export const isNumber = (input: string) => { |
||||||
|
const num = Number(input); |
||||||
|
return !isNaN(num); |
||||||
|
}; |
Loading…
Reference in new issue