Calculate editBadge() fee on the go

This commit is contained in:
Serkan Reis 2023-02-21 00:00:11 +03:00
parent e1adf87dac
commit 080c74a110
5 changed files with 107 additions and 63 deletions

View File

@ -1,4 +1,5 @@
// import { AirdropUpload } from 'components/AirdropUpload'
import { toUtf8 } from '@cosmjs/encoding'
import type { DispatchExecuteArgs } from 'components/badges/actions/actions'
import { dispatchExecute, isEitherType, previewExecutePayload } from 'components/badges/actions/actions'
import { ActionsCombobox } from 'components/badges/actions/Combobox'
@ -18,6 +19,7 @@ import { useWallet } from 'contexts/wallet'
import type { Badge, BadgeHubInstance } from 'contracts/badgeHub'
import * as crypto from 'crypto'
import { toPng } from 'html-to-image'
import sizeof from 'object-sizeof'
import { QRCodeCanvas } from 'qrcode.react'
import type { FormEvent } from 'react'
import { useEffect, useRef, useState } from 'react'
@ -51,6 +53,8 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
const [badge, setBadge] = useState<Badge>()
const [transferrable, setTransferrable] = useState<TransferrableType>(undefined)
const [resolvedOwnerAddress, setResolvedOwnerAddress] = useState<string>('')
const [editFee, setEditFee] = useState<number | undefined>(undefined)
const [dispatch, setDispatch] = useState<boolean>(false)
const [createdBadgeId, setCreatedBadgeId] = useState<string | undefined>(undefined)
const [createdBadgeKey, setCreatedBadgeKey] = useState<string | undefined>(undefined)
@ -229,6 +233,7 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
youtube_url: youtubeUrlState.value || undefined,
},
id: badgeId,
editFee,
owner: resolvedOwnerAddress,
pubkey: pubkeyState.value,
signature: signatureState.value,
@ -241,6 +246,7 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
txSigner: wallet.address,
type,
}
const resolveOwnerAddress = async () => {
await resolveAddress(ownerState.value.trim(), wallet).then((resolvedAddress) => {
setResolvedOwnerAddress(resolvedAddress)
@ -333,6 +339,20 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
maxSupplyState.value,
])
useEffect(() => {
if (attributesState.values.length === 0)
attributesState.add({
trait_type: '',
value: '',
})
}, [])
useEffect(() => {
void dispatchEditBadge().catch((err) => {
toast.error(String(err), { style: { maxWidth: 'none' } })
})
}, [dispatch])
useEffect(() => {
const addresses: string[] = []
airdropAllocationArray.forEach((allocation) => {
@ -358,46 +378,48 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
throw new Error('Please enter the Badge Hub contract addresses.')
}
// if (wallet.client && type === 'update_mint_price') {
// const contractConfig = wallet.client.queryContractSmart(minterContractAddress, {
// config: {},
// })
// await toast
// .promise(
// wallet.client.queryContractSmart(minterContractAddress, {
// mint_price: {},
// }),
// {
// error: `Querying mint price failed!`,
// loading: 'Querying current mint price...',
// success: (price) => {
// console.log('Current mint price: ', price)
// return `Current mint price is ${Number(price.public_price.amount) / 1000000} STARS`
// },
// },
// )
// .then(async (price) => {
// if (Number(price.public_price.amount) / 1000000 <= priceState.value) {
// await contractConfig
// .then((config) => {
// console.log(config.start_time, Date.now() * 1000000)
// if (Number(config.start_time) < Date.now() * 1000000) {
// throw new Error(
// `Minting has already started on ${new Date(
// Number(config.start_time) / 1000000,
// ).toLocaleString()}. Updated mint price cannot be higher than the current price of ${
// Number(price.public_price.amount) / 1000000
// } STARS`,
// )
// }
// })
// .catch((error) => {
// throw new Error(String(error).substring(String(error).lastIndexOf('Error:') + 7))
// })
// }
// })
// }
if (wallet.client && type === 'edit_badge') {
const feeRateRaw = await wallet.client.queryContractRaw(
badgeHubContractAddress,
toUtf8(Buffer.from(Buffer.from('fee_rate').toString('hex'), 'hex').toString()),
)
const feeRate = JSON.parse(new TextDecoder().decode(feeRateRaw as Uint8Array))
await toast
.promise(
wallet.client.queryContractSmart(badgeHubContractAddress, {
badge: { id: badgeId },
}),
{
error: `Edit Fee calculation failed!`,
loading: 'Calculating Edit Fee...',
success: (currentBadge) => {
console.log('Current badge: ', currentBadge)
return `Current metadata is ${
Number(sizeof(currentBadge.metadata)) + Number(sizeof(currentBadge.metadata.attributes))
} bytes in size.`
},
},
)
.then((currentBadge) => {
const currentBadgeMetadataSize =
Number(sizeof(currentBadge.metadata)) + Number(sizeof(currentBadge.metadata.attributes))
console.log('Current badge metadata size: ', currentBadgeMetadataSize)
const newBadgeMetadataSize = Number(sizeof(badge?.metadata)) + Number(sizeof(badge?.metadata.attributes))
console.log('New badge metadata size: ', newBadgeMetadataSize)
if (newBadgeMetadataSize > currentBadgeMetadataSize) {
const calculatedFee = ((newBadgeMetadataSize - currentBadgeMetadataSize) * Number(feeRate.metadata)) / 2
setEditFee(calculatedFee)
setDispatch(!dispatch)
} else {
setEditFee(undefined)
setDispatch(!dispatch)
}
})
.catch((error) => {
throw new Error(String(error).substring(String(error).lastIndexOf('Error:') + 7))
})
} else {
const txHash = await toast.promise(dispatchExecute(payload), {
error: `${type.charAt(0).toUpperCase() + type.slice(1)} execute failed!`,
loading: 'Executing message...',
@ -406,6 +428,7 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
if (txHash) {
setLastTx(txHash)
}
}
},
{
onError: (error) => {
@ -414,6 +437,19 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
},
)
const dispatchEditBadge = async () => {
if (type) {
const txHash = await toast.promise(dispatchExecute(payload), {
error: `${type.charAt(0).toUpperCase() + type.slice(1)} execute failed!`,
loading: 'Executing message...',
success: (tx) => `Transaction ${tx} success!`,
})
if (txHash) {
setLastTx(txHash)
}
}
}
const airdropFileOnChange = (data: AirdropAllocation[]) => {
setAirdropAllocationArray(data)
}

View File

@ -100,7 +100,7 @@ export type DispatchExecuteArgs = {
} & (
| { type: undefined }
| { type: Select<'create_badge'>; badge: Badge }
| { type: Select<'edit_badge'>; id: number; metadata: Metadata }
| { type: Select<'edit_badge'>; id: number; metadata: Metadata; editFee?: number }
| { type: Select<'add_keys'>; id: number; keys: string[] }
| { type: Select<'purge_keys'>; id: number; limit?: number }
| { type: Select<'purge_owners'>; id: number; limit?: number }
@ -120,7 +120,7 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
return badgeHubMessages.createBadge(txSigner, args.badge)
}
case 'edit_badge': {
return badgeHubMessages.editBadge(txSigner, args.id, args.metadata)
return badgeHubMessages.editBadge(txSigner, args.id, args.metadata, args.editFee)
}
case 'add_keys': {
return badgeHubMessages.addKeys(txSigner, args.id, args.keys)

View File

@ -15,7 +15,7 @@ import { toast } from 'react-hot-toast'
import type { UploadServiceType } from 'services/upload'
export type UploadMethod = 'new' | 'existing'
export type MintRule = 'by_key' | 'by_minter' | 'by_keys'
export type MintRule = 'by_key' | 'by_minter' | 'by_keys' | 'not_resolved'
interface ImageUploadDetailsProps {
onChange: (value: ImageUploadDetailsDataProps) => void

View File

@ -67,7 +67,7 @@ export interface BadgeHubInstance {
//Execute
createBadge: (senderAddress: string, badge: Badge) => Promise<string>
editBadge: (senderAddress: string, id: number, metadata: Metadata) => Promise<string>
editBadge: (senderAddress: string, id: number, metadata: Metadata, editFee?: number) => Promise<string>
addKeys: (senderAddress: string, id: number, keys: string[]) => Promise<string>
purgeKeys: (senderAddress: string, id: number, limit?: number) => Promise<string>
purgeOwners: (senderAddress: string, id: number, limit?: number) => Promise<string>
@ -79,7 +79,7 @@ export interface BadgeHubInstance {
export interface BadgeHubMessages {
createBadge: (badge: Badge) => CreateBadgeMessage
editBadge: (id: number, metadata: Metadata) => EditBadgeMessage
editBadge: (id: number, metadata: Metadata, editFee?: number) => EditBadgeMessage
addKeys: (id: number, keys: string[]) => AddKeysMessage
purgeKeys: (id: number, limit?: number) => PurgeKeysMessage
purgeOwners: (id: number, limit?: number) => PurgeOwnersMessage
@ -314,7 +314,12 @@ export const badgeHub = (client: SigningCosmWasmClient, txSigner: string): Badge
return res.transactionHash.concat(`:${id}`)
}
const editBadge = async (senderAddress: string, id: number, metadata: Metadata): Promise<string> => {
const editBadge = async (
senderAddress: string,
id: number,
metadata: Metadata,
editFee?: number,
): Promise<string> => {
const res = await client.execute(
senderAddress,
contractAddress,
@ -326,6 +331,7 @@ export const badgeHub = (client: SigningCosmWasmClient, txSigner: string): Badge
},
'auto',
'',
editFee ? [coin(editFee, 'ustars')] : [],
)
return res.transactionHash
@ -524,7 +530,7 @@ export const badgeHub = (client: SigningCosmWasmClient, txSigner: string): Badge
}
}
const editBadge = (id: number, metadata: Metadata): EditBadgeMessage => {
const editBadge = (id: number, metadata: Metadata, editFee?: number): EditBadgeMessage => {
return {
sender: txSigner,
contract: contractAddress,
@ -534,7 +540,7 @@ export const badgeHub = (client: SigningCosmWasmClient, txSigner: string): Badge
metadata,
},
},
funds: [],
funds: editFee ? [coin(editFee, 'ustars')] : [],
}
}

View File

@ -113,7 +113,7 @@ const BadgeActionsPage: NextPage = () => {
})
.catch((err) => {
console.log(err)
setMintRule('by_key')
setMintRule('not_resolved')
console.log('Unable to retrieve Mint Rule. Defaulting to "by_key".')
})
}, [debouncedBadgeHubContractState, debouncedBadgeIdState, wallet.client])
@ -132,7 +132,8 @@ const BadgeActionsPage: NextPage = () => {
<AddressInput {...badgeHubContractState} className="mr-2" />
<div className="flex-row">
<NumberInput className="w-1/2" {...badgeIdState} />
<span className="mt-1 font-bold">Mint Rule: </span>
<div className="mt-2">
<span className="font-bold">Mint Rule: </span>
<span>
{mintRule
.toString()
@ -142,6 +143,7 @@ const BadgeActionsPage: NextPage = () => {
</span>
</div>
</div>
</div>
<div className="mt-4">
<div className="mr-2">
<div className="flex justify-items-start font-bold">