EMERGENCY UPDATE 1.06b

This commit is contained in:
crowetic 2025-01-31 16:37:16 -08:00
parent ae8a61e127
commit 35e6595311
6 changed files with 78 additions and 111 deletions

View File

@ -198,65 +198,6 @@ const loadAdminBoardPage = async () => {
await fetchAllEncryptedCards() await fetchAllEncryptedCards()
} }
// const fetchAllKicKBanTxData = async () => {
// const kickTxType = "GROUP_KICK"
// const banTxType = "GROUP_BAN"
// // Helper function to filter transactions
// const filterTransactions = (rawTransactions) => {
// // Group transactions by member
// const memberTxMap = rawTransactions.reduce((map, tx) => {
// if (!map[tx.member]) {
// map[tx.member] = []
// }
// map[tx.member].push(tx)
// return map
// }, {})
// // Filter out members with both pending and non-pending transactions
// return Object.values(memberTxMap)
// .filter(txs => txs.every(tx => tx.approvalStatus !== 'PENDING'))
// .flat()
// // .filter((txs) => !(txs.some(tx => tx.approvalStatus === 'PENDING') &&
// // txs.some(tx => tx.approvalStatus !== 'PENDING')))
// // .flat()
// }
// // Fetch ban transactions
// const rawBanTransactions = await searchTransactions({
// txTypes: [banTxType],
// address: '',
// confirmationStatus: 'CONFIRMED',
// limit: 0,
// reverse: true,
// offset: 0,
// startBlock: 1990000,
// blockLimit: 0,
// txGroupId: 0,
// })
// // Filter transactions for bans
// banTransactions = filterTransactions(rawBanTransactions)
// console.warn('banTxData (filtered):', banTransactions)
// // Fetch kick transactions
// const rawKickTransactions = await searchTransactions({
// txTypes: [kickTxType],
// address: '',
// confirmationStatus: 'CONFIRMED',
// limit: 0,
// reverse: true,
// offset: 0,
// startBlock: 1990000,
// blockLimit: 0,
// txGroupId: 0,
// })
// // Filter transactions for kicks
// kickTransactions = filterTransactions(rawKickTransactions)
// console.warn('kickTxData (filtered):', kickTransactions)
// }
// Example: fetch and save admin public keys and count // Example: fetch and save admin public keys and count
const updateOrSaveAdminGroupsDataLocally = async () => { const updateOrSaveAdminGroupsDataLocally = async () => {
@ -299,7 +240,7 @@ const loadOrFetchAdminGroupsData = async () => {
adminMemberCount = parsedData.keysCount adminMemberCount = parsedData.keysCount
adminPublicKeys = parsedData.publicKeys adminPublicKeys = parsedData.publicKeys
console.log(typeof adminPublicKeys); // Should be "object" console.log(typeof adminPublicKeys) // Should be "object"
console.log(Array.isArray(adminPublicKeys)) console.log(Array.isArray(adminPublicKeys))
console.log(`Loaded admins 'keysCount'=${adminMemberCount}, publicKeys=`, adminPublicKeys) console.log(`Loaded admins 'keysCount'=${adminMemberCount}, publicKeys=`, adminPublicKeys)
@ -1221,7 +1162,6 @@ const handleBanMinter = async (minterName) => {
alert(`No valid address found for minter name: ${minterName}, this should NOT have happened, please report to developers...`) alert(`No valid address found for minter name: ${minterName}, this should NOT have happened, please report to developers...`)
return return
} }
const adminPublicKey = await getPublicKeyByName(userState.accountName) const adminPublicKey = await getPublicKeyByName(userState.accountName)
const reason = 'Banned by Minter Admins' const reason = 'Banned by Minter Admins'
const fee = 0.01 const fee = 0.01
@ -1232,14 +1172,13 @@ const handleBanMinter = async (minterName) => {
action: "SIGN_TRANSACTION", action: "SIGN_TRANSACTION",
unsignedBytes: rawBanTransaction unsignedBytes: rawBanTransaction
}) })
if (!signedBanTransaction) { if (!signedBanTransaction) {
console.warn(`this only happens if the SIGN_TRANSACTION qortalRequest failed... are you using the legacy UI prior to this qortalRequest being added?`) console.warn(`this only happens if the SIGN_TRANSACTION qortalRequest failed... are you using the legacy UI prior to this qortalRequest being added?`)
alert(`this only happens if the SIGN_TRANSACTION qortalRequest failed... are you using the legacy UI prior to this qortalRequest being added? Please talk to developers.`) alert(`this only happens if the SIGN_TRANSACTION qortalRequest failed... are you using the legacy UI prior to this qortalRequest being added? Please talk to developers.`)
return return
} }
let txToProcess = signedBanTransaction let txToProcess = signedBanTransaction
const processedTx = await processTransaction(txToProcess) const processedTx = await processTransaction(txToProcess)
if (typeof processedTx === 'object') { if (typeof processedTx === 'object') {
@ -1304,6 +1243,18 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
showTopic = false showTopic = false
} }
} }
let publishedMinterAddress = minterAddress
if (publishedMinterAddress === 'notYetAdded' || publishedMinterAddress === 'undefined' || publishedMinterAddress === null || !publishedMinterAddress) {
console.warn(`minterAddress is not published in the card data... will have to extract from minterName...`)
publishedMinterAddress = null
} else {
const publishedMinterAddressInfo = await getAddressInfo(publishedMinterAddress)
if (publishedMinterAddressInfo) {
console.log(`minterAddress found in published data, and verified. Using published address for further checks.`)
publishedMinterAddress = publishedMinterAddressInfo.address
}
}
let cardColorCode = showTopic ? '#0e1b15' : '#151f28' let cardColorCode = showTopic ? '#0e1b15' : '#151f28'
@ -1329,7 +1280,7 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
const verifiedName = await validateMinterName(minterName) const verifiedName = await validateMinterName(minterName)
let levelText = '</h3>' let levelText = '</h3>'
const addressVerification = await getAddressInfo(minterName) const addressVerification = await getAddressInfo(minterName)
const verifiedAddress = addressVerification.address const verifiedAddress = publishedMinterAddress ? publishedMinterAddress : addressVerification.address
if (verifiedName || verifiedAddress) { if (verifiedName || verifiedAddress) {
let accountInfo let accountInfo
@ -1337,7 +1288,7 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
accountInfo = await getNameInfo(verifiedName) accountInfo = await getNameInfo(verifiedName)
} }
const accountAddress = verifiedAddress ? addressVerification.address : accountInfo.owner const accountAddress = verifiedAddress ? addressVerification.address : accountInfo.owner
const addressInfo = verifiedAddress ? addressVerification : await getAddressInfo(accountAddress) const addressInfo = verifiedAddress ? addressVerification : await getAddressInfo(accountAddress)
const minterGroupAddresses = minterGroupMembers.map(m => m.member) const minterGroupAddresses = minterGroupMembers.map(m => m.member)
const adminAddresses = minterAdmins.map(m => m.member) const adminAddresses = minterAdmins.map(m => m.member)
@ -1399,34 +1350,6 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
} }
} }
// if (banTransactions.some((banTx) => banTx.groupId === 694 && banTx.offender === accountAddress)){
// console.warn(`account was already banned, displaying as such...`)
// cardColorCode = 'rgb(24, 3, 3)'
// altText = `<h4 style="color:rgb(106, 2, 2); margin-bottom: 0.5em;">BANNED From MINTER Group</h4>`
// showRemoveHtml = ''
// if (!adminBoardState.bannedCards.has(cardIdentifier)){
// adminBoardState.bannedCards.add(cardIdentifier)
// }
// if (!showKickedBanned){
// console.warn(`kick/bank checkbox is unchecked, and card is banned, not displaying...`)
// return ''
// }
// }
// if (kickTransactions.some((kickTx) => kickTx.groupId === 694 && kickTx.member === accountAddress)){
// console.warn(`account was already kicked, displaying as such...`)
// cardColorCode = 'rgb(29, 7, 4)'
// altText = `<h4 style="color:rgb(143, 117, 21); margin-bottom: 0.5em;">KICKED From MINTER Group</h4>`
// showRemoveHtml = ''
// if (!adminBoardState.kickedCards.has(cardIdentifier)){
// adminBoardState.kickedCards.add(cardIdentifier)
// }
// if (!showKickedBanned) {
// console.warn(`kick/ban checkbox is unchecked, card is kicked, not displaying...`)
// return ''
// }
// }
} else { } else {
console.log(`name could not be validated, assuming topic card (or some other issue with name validation) for removalActions`) console.log(`name could not be validated, assuming topic card (or some other issue with name validation) for removalActions`)
showRemoveHtml = '' showRemoveHtml = ''

View File

@ -1468,14 +1468,22 @@ const checkAndDisplayInviteButton = async (adminYes, creator, cardIdentifier) =>
const minterAddress = minterNameInfo.owner const minterAddress = minterNameInfo.owner
// fetch all final KICK/BAN tx // fetch all final KICK/BAN tx
const { finalKickTxs, finalBanTxs } = await fetchAllKickBanTxData() const { finalKickTxs, finalBanTxs } = await fetchAllKickBanTxData()
const { finalInviteTxs, pendingInviteTxs } = await fetchAllInviteTransactions()
// check if there's a final (non-pending) KICK or BAN for this user // check if there's a final (non-pending) KICK or BAN for this user
const priorKick = finalKickTxs.some(tx => tx.member === minterAddress) const priorKick = finalKickTxs.some(tx => tx.member === minterAddress)
const priorBan = finalBanTxs.some(tx => tx.offender === minterAddress) const priorBan = finalBanTxs.some(tx => tx.offender === minterAddress)
const existingInvite = finalInviteTxs.some(tx => tx.invitee === minterAddress)
const pendingInvite = pendingInviteTxs.some(tx => tx.invitee === minterAddress)
const priorBanOrKick = (priorBan || priorKick) const priorBanOrKick = (priorBan || priorKick)
console.warn(`PriorBanOrKick determination for ${minterAddress}:`, priorBanOrKick) console.warn(`PriorBanOrKick determination for ${minterAddress}:`, priorBanOrKick)
// build the normal invite button & groupApprovalHtml // build the normal invite button & groupApprovalHtml
const inviteButtonHtml = isSomeTypaAdmin ? createInviteButtonHtml(creator, cardIdentifier) : "" let inviteButtonHtml = ""
if (existingInvite || pendingInvite){
console.warn(`There is an EXISTING INVITE for this user! No invite button being created... existing: (${existingInvite}, pending: ${pendingInvite})`)
inviteButtonHtml = ''
}
inviteButtonHtml = isSomeTypaAdmin ? createInviteButtonHtml(creator, cardIdentifier) : ""
const groupApprovalHtml = await checkGroupApprovalAndCreateButton(minterAddress, cardIdentifier, "GROUP_INVITE") const groupApprovalHtml = await checkGroupApprovalAndCreateButton(minterAddress, cardIdentifier, "GROUP_INVITE")
// if user had no prior KICK/BAN // if user had no prior KICK/BAN
@ -1501,7 +1509,7 @@ const checkAndDisplayInviteButton = async (adminYes, creator, cardIdentifier) =>
const findPendingApprovalTxForAddress = async (address, txType, limit = 0, offset = 0) => { const findPendingApprovalTxForAddress = async (address, txType, limit = 0, offset = 0) => {
// 1) Fetch all pending transactions // 1) Fetch all pending transactions
const pendingTxs = await searchPendingTransactions(limit, offset) const pendingTxs = await searchPendingTransactions(limit, offset, false)
// if a txType is passed, return the results related to that type, if not, then return any pending tx of the potential types. // if a txType is passed, return the results related to that type, if not, then return any pending tx of the potential types.
let relevantTypes let relevantTypes
if (txType) { if (txType) {
@ -1530,31 +1538,42 @@ const findPendingApprovalTxForAddress = async (address, txType, limit = 0, offse
} }
}) })
console.warn(`matchedTxs:`,matchedTxs) console.warn(`matchedTxs:`,matchedTxs)
//Sort oldest→newest by timestamp, so matchedTxs[0] is the oldest
matchedTxs.sort((a, b) => a.timestamp - b.timestamp)
return matchedTxs // Array of matching pending transactions return matchedTxs // Array of matching pending transactions
} }
const checkGroupApprovalAndCreateButton = async (address, cardIdentifier, transactionType) => { const checkGroupApprovalAndCreateButton = async (address, cardIdentifier, transactionType) => {
// We are going to be verifying that the address isn't already a minter, before showing GROUP_APPROVAL buttons potentially...
if (transactionType === "GROUP_INVITE") {
console.log(`This is a GROUP_INVITE check for group approval... Checking that user isn't already a minter...`)
const minterMembers = await fetchMinterGroupMembers()
const minterGroupAddresses = minterMembers.map(m => m.member)
if (minterGroupAddresses.includes(address)) {
console.warn(`User is already a minter, will not be creating group_approval buttons`)
return null
}
}
const approvalSearchResults = await searchTransactions({ const approvalSearchResults = await searchTransactions({
txTypes: ['GROUP_APPROVAL'], txTypes: ['GROUP_APPROVAL'],
confirmationStatus: 'CONFIRMED', confirmationStatus: 'CONFIRMED',
limit: 0, limit: 0,
reverse: true, reverse: false,
offset: 0, offset: 0,
startBlock: 1990000, startBlock: 1990000,
blockLimit: 0, blockLimit: 0,
txGroupId: 0 txGroupId: 0
}) })
const pendingApprovals = await findPendingApprovalTxForAddress(address, transactionType) const pendingApprovals = await findPendingApprovalTxForAddress(address, transactionType, 0, 0)
let isSomeTypaAdmin = userState.isAdmin || userState.isMinterAdmin let isSomeTypaAdmin = userState.isAdmin || userState.isMinterAdmin
// If no pending transaction found, return null // If no pending transaction found, return null
if (!pendingApprovals || pendingApprovals.length === 0) { if (!pendingApprovals || pendingApprovals.length === 0) {
console.warn("no pending approval transactions found, returning null...") console.warn("no pending approval transactions found, returning null...")
return null return null
} }
const txSig = pendingApprovals[0].signature const txSig = pendingApprovals[0].signature
// Among the already-confirmed GROUP_APPROVAL, filter for those referencing this txSig // Find the relevant signature. (First approval)
const relevantApprovals = approvalSearchResults.filter( const relevantApprovals = approvalSearchResults.filter(
(approvalTx) => approvalTx.pendingSignature === txSig (approvalTx) => approvalTx.pendingSignature === txSig
) )

View File

@ -1,4 +1,4 @@
const Q_MINTERSHIP_VERSION = "1.05.2" const Q_MINTERSHIP_VERSION = "1.06"
const messageIdentifierPrefix = `mintership-forum-message` const messageIdentifierPrefix = `mintership-forum-message`
const messageAttachmentIdentifierPrefix = `mintership-forum-attachment` const messageAttachmentIdentifierPrefix = `mintership-forum-attachment`

View File

@ -782,7 +782,7 @@ const searchAllWithOffset = async (service, query, limit, offset, room) => {
// NOTE - This function does a search and will return EITHER AN ARRAY OR A SINGLE OBJECT. if you want to guarantee a single object, pass 1 as limit. i.e. await searchSimple(service, identifier, "", 1) will return a single object. // NOTE - This function does a search and will return EITHER AN ARRAY OR A SINGLE OBJECT. if you want to guarantee a single object, pass 1 as limit. i.e. await searchSimple(service, identifier, "", 1) will return a single object.
const searchSimple = async (service, identifier, name, limit=1500, offset=0, room='', reverse=true, prefixOnly=true, after=0) => { const searchSimple = async (service, identifier, name, limit=1500, offset=0, room='', reverse=true, prefixOnly=true, after=0) => {
try { try {
let urlSuffix = `service=${service}&identifier=${identifier}&name=${name}&prefix=true&limit=${limit}&offset=${offset}&reverse=${reverse}&prefix=${prefixOnly}&fter=${after}` let urlSuffix = `service=${service}&identifier=${identifier}&name=${name}&prefix=true&limit=${limit}&offset=${offset}&reverse=${reverse}&prefix=${prefixOnly}&after=${after}`
if (name && !identifier && !room) { if (name && !identifier && !room) {
console.log('name only searchSimple', name) console.log('name only searchSimple', name)
@ -1840,13 +1840,14 @@ const searchTransactions = async ({
} }
} }
const searchPendingTransactions = async (limit = 20, offset = 0) => { const searchPendingTransactions = async (limit=20, offset=0, reverse=false) => {
try { try {
const queryParams = [] const queryParams = []
if (limit) queryParams.push(`limit=${limit}`) if (limit) queryParams.push(`limit=${limit}`)
if (offset) queryParams.push(`offset=${offset}`) if (offset) queryParams.push(`offset=${offset}`)
if (reverse) queryParams.push(`reverse=${reverse}`)
const queryString = queryParams.join('&'); const queryString = queryParams.join('&')
const url = `${baseUrl}/transactions/pending${queryString ? `?${queryString}` : ''}` const url = `${baseUrl}/transactions/pending${queryString ? `?${queryString}` : ''}`
const response = await fetch(url, { const response = await fetch(url, {
@ -1855,11 +1856,11 @@ const searchPendingTransactions = async (limit = 20, offset = 0) => {
}) })
if (!response.ok) { if (!response.ok) {
const errorText = await response.text(); const errorText = await response.text()
throw new Error(`Failed to search pending transactions: HTTP ${response.status}, ${errorText}`) throw new Error(`Failed to search pending transactions: HTTP ${response.status}, ${errorText}`)
} }
const result = await response.json(); const result = await response.json()
if (!Array.isArray(result)) { if (!Array.isArray(result)) {
throw new Error("Expected an array for pending transactions, but got something else.") throw new Error("Expected an array for pending transactions, but got something else.")
} }

View File

@ -163,9 +163,9 @@ const fetchAllKickBanTxData = async () => {
finalBanTxs, finalBanTxs,
pendingBanTxs, pendingBanTxs,
} }
} }
const partitionTransactions = (txSearchResults) => { const partitionTransactions = (txSearchResults) => {
const finalTx = [] const finalTx = []
const pendingTx = [] const pendingTx = []
@ -178,7 +178,31 @@ const fetchAllKickBanTxData = async () => {
} }
return { finalTx, pendingTx }; return { finalTx, pendingTx };
} }
const fetchAllInviteTransactions = async () => {
const inviteTxType = "GROUP_INVITE"
const allInviteTx = await searchTransactions({
txTypes: [inviteTxType],
confirmationStatus: 'CONFIRMED',
limit: 0,
reverse: true,
offset: 0,
startBlock: 1990000,
blockLimit: 0,
txGroupId: 0,
})
const { finalTx: finalInviteTxs, pendingTx: pendingInviteTxs } = partitionTransactions(allInviteTx)
console.log('Final kickTxs:', finalInviteTxs)
console.log('Pending kickTxs:', pendingInviteTxs)
return {
finalInviteTxs,
pendingInviteTxs,
}
}

View File

@ -201,13 +201,13 @@
<div class="col-12 col-lg-7 card"> <div class="col-12 col-lg-7 card">
<div class="title-wrapper"> <div class="title-wrapper">
<h2 class="mbr-section-title mbr-fonts-style display-2"> <h2 class="mbr-section-title mbr-fonts-style display-2">
v1.05.1beta 01-29-2025</h2> v1.06beta 01-31-2025</h2>
</div> </div>
</div> </div>
<div class="col-12 col-lg-5 card"> <div class="col-12 col-lg-5 card">
<div class="text-wrapper"> <div class="text-wrapper">
<p class="mbr-text mbr-fonts-style display-7"> <p class="mbr-text mbr-fonts-style display-7">
<b><u>v1.05.1b Fixes</u></b>- <b>This section will be moving </b> - See post in the <a href="MINTERSHIP-FORUM">FORUM</a> for RELEASE NOTES, too many to list here. This updates section will be getting moved to a section of the forum in the future. This version is simply a bump to resolve a typo in a variable on the MinterBoard. The majority of the changes took place in 1.05b. <b><u>v1.06b Fixes</u></b>- <b>EMERGENCY UPDATE </b> - See post in the <a href="MINTERSHIP-FORUM">FORUM</a> for RELEASE NOTES, This is an emergency update that is meant to prevent the issue that took place yesterday and ended up stalling quite a few nodes. This means that Q-Mintership should be the ONLY APP UTILIZED FOR THE FUNCTIONALITY IT PROVIDES.
</p> </p>
</div> </div>
</div> </div>