From 715a25e582507903f0988334f14c7ad2f1900928 Mon Sep 17 00:00:00 2001 From: IrohDW Date: Tue, 16 Jul 2024 18:15:30 -0600 Subject: [PATCH] Major updates to many files. --- index.d.ts | 2 +- index.ts | 12 +- package.json | 2 +- src/QortalRequest/Profile.ts | 51 +++++ src/QortalRequest/Qapps/Qfund.ts | 62 ++++++ src/QortalRequest/Search.ts | 28 +++ src/QortalRequest/SendCoin.ts | 38 +++- .../Utils/Interfaces/Responses.ts | 29 +++ src/QortalRequest/Utils/Types.ts | 22 ++- src/QortalRequest/general.ts | 57 +++++- src/QortalRequest/getFromAddress.ts | 4 +- src/QortalRequest/getFromName.ts | 8 + src/QortalRequest/getFromSelf.ts | 42 +++- src/QortalRequest/setFromSelf.ts | 12 -- .../Numbers/Colors.ts | 0 .../Numbers/NumberConversion.ts | 0 .../Numbers/Numbers.ts | 4 + .../Numbers/StringNumbers.ts | 0 src/Utils/PublishFormatter.ts | 184 ++++++++++++++++++ .../Strings/printFunctions.ts | 0 src/Utils/Strings/stringFunctions.ts | 13 ++ src/global.d.ts | 3 +- 22 files changed, 524 insertions(+), 49 deletions(-) create mode 100644 src/QortalRequest/Profile.ts create mode 100644 src/QortalRequest/Qapps/Qfund.ts create mode 100644 src/QortalRequest/Search.ts create mode 100644 src/QortalRequest/getFromName.ts rename src/{TypescriptUtils => Utils}/Numbers/Colors.ts (100%) rename src/{TypescriptUtils => Utils}/Numbers/NumberConversion.ts (100%) rename src/{TypescriptUtils => Utils}/Numbers/Numbers.ts (71%) rename src/{TypescriptUtils => Utils}/Numbers/StringNumbers.ts (100%) create mode 100644 src/Utils/PublishFormatter.ts rename src/{TypescriptUtils => Utils}/Strings/printFunctions.ts (100%) create mode 100644 src/Utils/Strings/stringFunctions.ts diff --git a/index.d.ts b/index.d.ts index a2b3683..54e2ae9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -10,7 +10,7 @@ export * from "./dist/src/QortalRequest/Utils/Types"; export * from "./dist/src/QortalRequest/getFromAddress"; export * from "./dist/src/QortalRequest/getFromSelf"; -export * from "./dist/src/QortalRequest/setFromSelf"; +export * from "./dist/src/QortalRequest/profile"; export * from "./dist/src/QortalRequest/SendCoin"; export * from "./dist/src/QortalRequest/Transactions"; export * from "./dist/src/QortalRequest/general" \ No newline at end of file diff --git a/index.ts b/index.ts index e5f0c02..21738aa 100644 --- a/index.ts +++ b/index.ts @@ -1,8 +1,8 @@ -export * from "./src/TypescriptUtils/Numbers/Colors"; -export * from "./src/TypescriptUtils/Numbers/NumberConversion"; -export * from "./src/TypescriptUtils/Numbers/Numbers"; -export * from "./src/TypescriptUtils/Numbers/StringNumbers"; -export * from "./src/TypescriptUtils/Strings/printFunctions"; +export * from "./src/Utils/Numbers/Colors"; +export * from "./src/Utils/Numbers/NumberConversion"; +export * from "./src/Utils/Numbers/Numbers"; +export * from "./src/Utils/Numbers/StringNumbers"; +export * from "./src/Utils/Strings/printFunctions"; export * from "./src/QortalRequest/Utils/Interfaces/Responses"; export * from "./src/QortalRequest/Utils/Interfaces/Parameters"; @@ -10,7 +10,7 @@ export * from "./src/QortalRequest/Utils/Types"; export * from "./src/QortalRequest/getFromAddress"; export * from "./src/QortalRequest/getFromSelf"; -export * from "./src/QortalRequest/setFromSelf"; +export * from "./src/QortalRequest/profile"; export * from "./src/QortalRequest/SendCoin"; export * from "./src/QortalRequest/Transactions"; export * from "./src/QortalRequest/general"; diff --git a/package.json b/package.json index f47eccc..30ce882 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "qortal-app-utils", - "version": "1.4.0", + "version": "1.5.0", "description": "A series of convenience functions that perform common tasks, especially those that interact with the Qortal blockchain", "keywords": [ "Qortal", diff --git a/src/QortalRequest/Profile.ts b/src/QortalRequest/Profile.ts new file mode 100644 index 0000000..6135a55 --- /dev/null +++ b/src/QortalRequest/Profile.ts @@ -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; +}; diff --git a/src/QortalRequest/Qapps/Qfund.ts b/src/QortalRequest/Qapps/Qfund.ts new file mode 100644 index 0000000..c2bdcf0 --- /dev/null +++ b/src/QortalRequest/Qapps/Qfund.ts @@ -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, + }); +}; \ No newline at end of file diff --git a/src/QortalRequest/Search.ts b/src/QortalRequest/Search.ts new file mode 100644 index 0000000..f9c7be4 --- /dev/null +++ b/src/QortalRequest/Search.ts @@ -0,0 +1,28 @@ +import { SearchResourcesResponse } from "./Utils/Interfaces/Responses.ts"; + +export const fetchResourcesByIdentifier = async ( + 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[] = []; + distinctNames.map(response => { + const resource: Promise = qortalRequest({ + action: "FETCH_QDN_RESOURCE", + name: response.name, + service, + identifier, + }); + promises.push(resource); + }); + return (await Promise.all(promises)) as T[]; +}; diff --git a/src/QortalRequest/SendCoin.ts b/src/QortalRequest/SendCoin.ts index 35e788f..fafbf35 100644 --- a/src/QortalRequest/SendCoin.ts +++ b/src/QortalRequest/SendCoin.ts @@ -1,22 +1,48 @@ import { CoinType } from "./Utils/Types"; +import { SendCoinResponse } from "./Utils/Interfaces/Responses.ts"; export const sendCoin = async ( address: string, amount: number, coin: CoinType ) => { - return qortalRequest({ - action: "SEND_COIN", - coin, - destinationAddress: address, - amount, - }); + try { + return (await qortalRequest({ + action: "SEND_COIN", + coin, + destinationAddress: address, + amount, + })) as SendCoinResponse; + } catch (e) { + console.log("sendCoin refused", e); + } }; export const sendQORT = async (address: string, amount: number) => { return await sendCoin(address, amount, "QORT"); }; +export interface NameData { + name: string; + reducedName: string; + owner: string; + data: string; + registered: number; + isForSale: boolean; +} +export const getNameData = async (name: string) => { + return qortalRequest({ + action: "GET_NAME_DATA", + name: name, + }) as Promise; +}; + +export const sendQORTtoName = async (name: string, amount: number) => { + const address = await getNameData(name); + if (address) return await sendQORT(address.owner, amount); + else throw Error("Name Not Found"); +}; + export const sendBitCoin = async (address: string, amount: number) => { return await sendCoin(address, amount, "BTC"); }; diff --git a/src/QortalRequest/Utils/Interfaces/Responses.ts b/src/QortalRequest/Utils/Interfaces/Responses.ts index 10219f1..f81e59e 100644 --- a/src/QortalRequest/Utils/Interfaces/Responses.ts +++ b/src/QortalRequest/Utils/Interfaces/Responses.ts @@ -33,3 +33,32 @@ export interface DaySummaryResponse { totalTransactionCount: number; transactionCountByType: SummaryTransactionCounts; } + +export interface MetaData { + title: string; + description: string; + tags: string[]; + mimeType: string; +} +export interface SearchResourcesResponse { + name: string; + service: string; + identifier: string; + metadata?: MetaData; + size: number; + created: number; + updated: number; +} + +export interface SendCoinResponse { + amount: number; + approvalStatus: string; + fee: string; + recipient: string; + reference: string; + senderPublicKey: string; + signature: string; + timestamp: number; + txGroupId: number; + type: string; +} diff --git a/src/QortalRequest/Utils/Types.ts b/src/QortalRequest/Utils/Types.ts index 13b0b11..76b6af4 100644 --- a/src/QortalRequest/Utils/Types.ts +++ b/src/QortalRequest/Utils/Types.ts @@ -42,12 +42,18 @@ export type TransactionType = | "TRANSFER_PRIVS" | "PRESENCE"; -export type CoinType = "QORT" | "BTC" | "LTC" | "DOGE" | "DGB" | "RVN" | "ARRR"; +export const Coins = ["QORT", "BTC", "LTC", "DOGE", "DGB", "RVN", "ARRR"]; +export type CoinType = (typeof Coins)[number]; -export type BlockchainType = - | "BITCOIN" - | "LITECOIN" - | "DODGECOIN" - | "DIGIBYTE" - | "RAVENCOIN" - | "PIRATECHAIN"; +export const ProfileCoins = ["btc", "ltc", "doge", "dgb", "rvn", "arrr"]; +export type ProfileCoinType = (typeof ProfileCoins)[number]; +export const Blockchains = [ + "BITCOIN", + "LITECOIN", + "DOGECOIN", + "DIGIBYTE", + "RAVENCOIN", + "PIRATECHAIN", +]; + +export type BlockchainType = (typeof Blockchains)[number]; diff --git a/src/QortalRequest/general.ts b/src/QortalRequest/general.ts index 958702a..27fef55 100644 --- a/src/QortalRequest/general.ts +++ b/src/QortalRequest/general.ts @@ -1,6 +1,8 @@ import { DaySummaryResponse } from "./Utils/Interfaces/Responses.ts"; -import { BlockchainType } from "./Utils/Types.ts"; -import { truncateNumber } from "../TypescriptUtils/Numbers/StringNumbers.ts"; +import { Blockchains, BlockchainType } from "./Utils/Types.ts"; +import { truncateNumber } from "../Utils/Numbers/StringNumbers.ts"; +import { getNameData } from "./SendCoin.ts"; +import { getUserAccountNames } from "./getFromSelf.ts"; export const getDaySummary = async () => { return (await qortalRequest({ @@ -32,16 +34,59 @@ export const getDurationFromBlocks = async (blocks: number) => { }); }; -export const getPrice = async ( +export const getPriceAsNumber = async ( blockchainName: BlockchainType, - tradesToInclude = 10, - isQortRatio = true + tradesToInclude = 10 ) => { const response = (await qortalRequest({ action: "GET_PRICE", blockchain: blockchainName, maxTrades: tradesToInclude, - inverse: isQortRatio, + inverse: true, })) as number; return response / 1e8; }; + +type BlockchainPrice = { name: BlockchainType; price: number }; + +const getPriceAsObject = async ( + chain: BlockchainType, + tradesToInclude: number +) => { + return { name: chain, price: await getPriceAsNumber(chain, tradesToInclude) }; +}; + +export const getPricesAsObject = async ( + chains: BlockchainType[], + tradesToInclude = 10 +) => { + return await Promise.all( + chains.map(async (chain: BlockchainType) => { + return getPriceAsObject(chain, tradesToInclude); + }) + ); +}; + +export const sendQchatDM = async ( + recipientName: string, + message: string, + allowSelfAsRecipient = false +) => { + if (!allowSelfAsRecipient) { + const userAccountNames = await getUserAccountNames(); + const userNames = userAccountNames.map(name => name.name); + if (userNames.includes(recipientName)) return; + } + + const address = await getNameData(recipientName); + try { + return await qortalRequest({ + action: "SEND_CHAT_MESSAGE", + destinationAddress: address.owner, + message, + }); + } catch (e) { + console.log(e); + return false; + } +}; diff --git a/src/QortalRequest/getFromAddress.ts b/src/QortalRequest/getFromAddress.ts index 96fda08..b211bd8 100644 --- a/src/QortalRequest/getFromAddress.ts +++ b/src/QortalRequest/getFromAddress.ts @@ -1,4 +1,4 @@ -import { stringIsEmpty } from "../TypescriptUtils/Numbers/StringNumbers"; +import { stringIsEmpty } from "../Utils/Numbers/StringNumbers"; import { GetRequestData } from "./Utils/Interfaces/Parameters.ts"; type AccountName = { name: string; owner: string }; @@ -8,7 +8,7 @@ export const getAccountNames = async ( ) => { const names = (await qortalRequest({ action: "GET_ACCOUNT_NAMES", - address, + address: address, ...params, })) as AccountName[]; diff --git a/src/QortalRequest/getFromName.ts b/src/QortalRequest/getFromName.ts new file mode 100644 index 0000000..71930e3 --- /dev/null +++ b/src/QortalRequest/getFromName.ts @@ -0,0 +1,8 @@ +export const getAvatarFromName = async (name: string) => { + return await qortalRequest({ + action: "GET_QDN_RESOURCE_URL", + name, + service: "THUMBNAIL", + identifier: "qortal_avatar", + }); +}; diff --git a/src/QortalRequest/getFromSelf.ts b/src/QortalRequest/getFromSelf.ts index d9c8fc3..cd03cff 100644 --- a/src/QortalRequest/getFromSelf.ts +++ b/src/QortalRequest/getFromSelf.ts @@ -1,5 +1,6 @@ import { getBalance } from "./getFromAddress"; import { CoinType } from "./Utils/Types"; +import { GetRequestData } from "./Utils/Interfaces/Parameters.ts"; export const getWalletBalance = async (coin: CoinType) => { return (await qortalRequest({ @@ -21,16 +22,45 @@ export const getForeignWallet = async (coin: CoinType) => { coin, })) as AccountInfo; }; + +export const stringIsEmpty = (value: string) => { + return value === ""; +}; + +export type AccountName = { name: string; owner: string }; +export const getAccountNames = async ( + address: string, + params?: GetRequestData +) => { + const names = (await qortalRequest({ + action: "GET_ACCOUNT_NAMES", + address: address, + ...params, + })) as AccountName[]; + + const namelessAddress = { name: "", owner: address }; + const emptyNamesFilled = names.map(({ name, owner }) => { + return stringIsEmpty(name) ? namelessAddress : { name, owner }; + }); + + const returnValue = + emptyNamesFilled.length > 0 ? emptyNamesFilled : [namelessAddress]; + return returnValue as AccountName[]; +}; + export const getUserAccount = async () => { return (await qortalRequest({ action: "GET_USER_ACCOUNT", })) as AccountInfo; }; -// returns {error: "Cannot find requested data"} if data isn't found -export const getProfileData = async (property: string) => { - return (await qortalRequest({ - action: "GET_PROFILE_DATA", - property, - })) as string | object; +export const getUserAccountNames = async () => { + const account = await getUserAccount(); + return await getAccountNames(account.address); +}; + +export const userHasName = async (name: string) => { + const userAccountNames = await getUserAccountNames(); + const userNames = userAccountNames.map(userName => userName.name); + return userNames.includes(name); }; diff --git a/src/QortalRequest/setFromSelf.ts b/src/QortalRequest/setFromSelf.ts index 5f40948..e69de29 100644 --- a/src/QortalRequest/setFromSelf.ts +++ b/src/QortalRequest/setFromSelf.ts @@ -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; -}; diff --git a/src/TypescriptUtils/Numbers/Colors.ts b/src/Utils/Numbers/Colors.ts similarity index 100% rename from src/TypescriptUtils/Numbers/Colors.ts rename to src/Utils/Numbers/Colors.ts diff --git a/src/TypescriptUtils/Numbers/NumberConversion.ts b/src/Utils/Numbers/NumberConversion.ts similarity index 100% rename from src/TypescriptUtils/Numbers/NumberConversion.ts rename to src/Utils/Numbers/NumberConversion.ts diff --git a/src/TypescriptUtils/Numbers/Numbers.ts b/src/Utils/Numbers/Numbers.ts similarity index 71% rename from src/TypescriptUtils/Numbers/Numbers.ts rename to src/Utils/Numbers/Numbers.ts index f8ef24d..d5106b0 100644 --- a/src/TypescriptUtils/Numbers/Numbers.ts +++ b/src/Utils/Numbers/Numbers.ts @@ -7,3 +7,7 @@ export const setNumberWithinBounds = ( if (num < minValue) return minValue; return num; }; + +export const numberToInt = (num: number) => { + return Math.floor(num); +}; diff --git a/src/TypescriptUtils/Numbers/StringNumbers.ts b/src/Utils/Numbers/StringNumbers.ts similarity index 100% rename from src/TypescriptUtils/Numbers/StringNumbers.ts rename to src/Utils/Numbers/StringNumbers.ts diff --git a/src/Utils/PublishFormatter.ts b/src/Utils/PublishFormatter.ts new file mode 100644 index 0000000..e6368ba --- /dev/null +++ b/src/Utils/PublishFormatter.ts @@ -0,0 +1,184 @@ +export const publishFormatter = ( + file: File +): Promise => + 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((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 { + return new Promise( + (resolve: (value: Uint8Array) => void, reject: (reason?: any) => void) => { + const reader = new FileReader(); + + reader.onload = function (event: ProgressEvent) { + const arrayBuffer = event.target?.result as ArrayBuffer; + const uint8Array = new Uint8Array(arrayBuffer); + resolve(uint8Array); + }; + + reader.onerror = function (error: ProgressEvent) { + reject(error); + }; + + reader.readAsArrayBuffer(file); + } + ); +} + +// export async function processFileInChunks(file: File, chunkSize = 1024 * 1024): Promise { +// 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; +// } diff --git a/src/TypescriptUtils/Strings/printFunctions.ts b/src/Utils/Strings/printFunctions.ts similarity index 100% rename from src/TypescriptUtils/Strings/printFunctions.ts rename to src/Utils/Strings/printFunctions.ts diff --git a/src/Utils/Strings/stringFunctions.ts b/src/Utils/Strings/stringFunctions.ts new file mode 100644 index 0000000..e18928c --- /dev/null +++ b/src/Utils/Strings/stringFunctions.ts @@ -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); +}; diff --git a/src/global.d.ts b/src/global.d.ts index eb598d5..680302b 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -99,6 +99,7 @@ interface QortalRequestOptions { maxTrades?: number; inverse?: boolean; property?: string; - data?: { customData: object }; + data?: { customData?: object }; + message?: string; } declare function qortalRequest(options: QortalRequestOptions): Promise;