kodadot/nft-gallery

View on GitHub
composables/transaction/mintToken/transactionMintStatemine.ts

Summary

Maintainability
A
0 mins
Test Coverage
import type { ApiPromise } from '@polkadot/api'
import type { ActionMintToken, MintedCollection, TokenToMint } from '../types'
import { constructMeta } from './constructMeta'
import type {
  Id } from './utils'
import {
  assignIds,
  calculateFees,
  expandCopies,
  lastIndexUsed,
  transactionFactory,
} from './utils'
import { constructDirectoryMeta } from './constructDirectoryMeta'
import type { SupportTokens } from '@/utils/support'
import { canSupport } from '@/utils/support'
import { usePreferencesStore } from '@/stores/preferences'

interface BuildTokenTxsParams {
  token: TokenToMint & Id
  metadata: string
  api: ApiPromise
}

const buildTokenTxs = ({ token, metadata, api }: BuildTokenTxsParams) => {
  const { accountId } = useAuth()
  const collectionId = token.selectedCollection?.id
  const { price, id: nextId, hasRoyalty, royalty } = token
  const create = api.tx.nfts.mint(
    collectionId,
    nextId,
    accountId.value,
    undefined,
  )
  const meta = api.tx.nfts.setMetadata(collectionId, nextId, metadata)

  const list
    = Number(price) > 0
      ? [api.tx.nfts.setPrice(collectionId, nextId, price, undefined)]
      : []
  const txs = [create, meta, ...list]

  if (royalty && isRoyaltyValid(royalty) && hasRoyalty) {
    const setRoyaltyAmount = api.tx.nfts.setAttribute(
      collectionId,
      nextId,
      'ItemOwner',
      'royalty',
      royalty.amount,
    )
    const setRoyaltyRecipient = api.tx.nfts.setAttribute(
      collectionId,
      nextId,
      'ItemOwner',
      'recipient',
      royalty.address,
    )
    txs.push(setRoyaltyAmount, setRoyaltyRecipient)
  }
  return txs
}

async function handleSingleToken(item: ActionMintToken, api: ApiPromise) {
  const enableCarbonOffset = usePreferencesStore().getHasCarbonOffset

  const tokens = await expandCopiesWithsIds(item, api)
  const metadataList = await Promise.all(
    tokens.map(token => constructMeta(token, { enableCarbonOffset })),
  )
  return tokens.map((token, index) => ({
    token,
    metadata: metadataList[index],
  }))
}

async function handleMultipleTokens(item: ActionMintToken, api: ApiPromise) {
  const enableCarbonOffset = usePreferencesStore().getHasCarbonOffset
  const tokens = item.token as TokenToMint[]
  const lastTokenId = await lastIndexUsed(
    tokens[0].selectedCollection as MintedCollection,
    api,
  )
  const tokensWithIds = assignIds(tokens, lastTokenId)
  const metadata = await constructDirectoryMeta(tokensWithIds, {
    enableCarbonOffset,
  })
  return tokensWithIds.map((token, index) => ({
    token,
    metadata: metadata[index],
  }))
}
export const expandCopiesWithsIds = async (item: ActionMintToken, api) => {
  const tokens = Array.isArray(item.token) ? item.token : [item.token]

  const lastTokenId = await lastIndexUsed(
    tokens[0].selectedCollection as MintedCollection,
    api,
  )
  const expandedTokens = expandCopies(tokens)

  return assignIds(expandedTokens, lastTokenId)
}

export const getSupportInteraction = (
  item: ActionMintToken,
  enabledFees: boolean,
  feeMultiplier: number,
  api: ApiPromise,
  tokenSymbol: SupportTokens,
) => {
  const howManyTimesToChargeSupportFees = Array.isArray(item.token)
    ? item.token.length
    : 1

  const totalFees = feeMultiplier * howManyTimesToChargeSupportFees
  return canSupport(api, enabledFees, totalFees, tokenSymbol)
}

const getArgs = async (item: ActionMintToken, api: ApiPromise) => {
  const { enabledFees, feeMultiplier, token: tokenSymbol } = calculateFees()
  const supportInteraction = await getSupportInteraction(
    item,
    enabledFees,
    feeMultiplier,
    api,
    tokenSymbol,
  )

  const isMultipleTokens = Array.isArray(item.token) && item.token.length > 1

  const tokenTxsArgs = isMultipleTokens
    ? await handleMultipleTokens(item, api)
    : await handleSingleToken(item, api)

  const arg = await Promise.all(
    tokenTxsArgs.map(({ token, metadata }) =>
      buildTokenTxs({ token, metadata, api }),
    ),
  )

  return [[...arg.flat(), ...supportInteraction]]
}

export const execMintStatemine = transactionFactory(getArgs)