diff --git a/components/Layout/Header/index.js b/components/Layout/Header/index.js
index fafbaceef..111467ec3 100644
--- a/components/Layout/Header/index.js
+++ b/components/Layout/Header/index.js
@@ -192,7 +192,7 @@ export default function Header({
hoverStates={hoverStates}
>
{t('menu.developers.faucet')}
- {xahauNetwork && {t('menu.services.nft-mint')}}
+ {t('menu.services.nft-mint')}
{t('menu.usernames')}
{t('menu.services.tax-reports')}
{t('menu.project-registration')}
@@ -239,7 +239,7 @@ export default function Header({
{t('menu.nft.offers')}
{t('menu.nft.distribution')}
{t('menu.nft.statistics')}
- {xahauNetwork && {t('menu.services.nft-mint')}}
+ {t('menu.services.nft-mint')}
{/* Hide AMM for XAHAU */}
diff --git a/components/Services/NftMint/NFTokenMint.js b/components/Services/NftMint/NFTokenMint.js
new file mode 100644
index 000000000..32df8bda5
--- /dev/null
+++ b/components/Services/NftMint/NFTokenMint.js
@@ -0,0 +1,398 @@
+import { useState, useEffect } from 'react'
+import Link from 'next/link'
+import { encode, server, network } from '../../../utils'
+import { isValidTaxon } from '../../../utils/nft'
+import CheckBox from '../../UI/CheckBox'
+import AddressInput from '../../UI/AddressInput'
+import ExpirationSelect from '../../UI/ExpirationSelect'
+
+export default function NFTokenMint({ setSignRequest }) {
+ const [uri, setUri] = useState('')
+ const [agreeToSiteTerms, setAgreeToSiteTerms] = useState(false)
+ const [agreeToPrivacyPolicy, setAgreeToPrivacyPolicy] = useState(false)
+ const [errorMessage, setErrorMessage] = useState('')
+ const [minted, setMinted] = useState('')
+ const [taxon, setTaxon] = useState('0')
+ const [flags, setFlags] = useState({
+ tfBurnable: false,
+ tfOnlyXRP: false,
+ tfTransferable: true,
+ tfMutable: false
+ })
+
+ const [issuer, setIssuer] = useState('')
+ const [transferFee, setTransferFee] = useState('')
+ const [destination, setDestination] = useState('')
+ const [amount, setAmount] = useState('')
+ const [expiration, setExpiration] = useState(0)
+ const [mintForOtherAccount, setMintForOtherAccount] = useState(false)
+ const [createSellOffer, setCreateSellOffer] = useState(false)
+
+ let uriRef
+ let taxonRef
+
+ useEffect(() => {
+ if (agreeToSiteTerms || agreeToPrivacyPolicy) {
+ setErrorMessage('')
+ }
+ }, [agreeToSiteTerms, agreeToPrivacyPolicy])
+
+ const onUriChange = (e) => {
+ let uri = e.target.value
+ setUri(uri)
+ }
+
+ const onTaxonChange = (e) => {
+ const value = e.target.value.replace(/[^\d]/g, '')
+ setTaxon(value)
+ }
+
+ const onTransferFeeChange = (e) => {
+ let value = e.target.value.replace(/[^\d\.]/g, '')
+ const decimalPoints = value.split('.').length - 1
+ if (decimalPoints > 1) {
+ const parts = value.split('.')
+ value = parts[0] + '.' + parts.slice(1).join('')
+ }
+ if (value === '' || parseFloat(value) <= 50) {
+ setTransferFee(value)
+ }
+ }
+
+ const onAmountChange = (e) => {
+ let value = e.target.value.replace(/[^\d\.]/g, '')
+ const decimalPoints = value.split('.').length - 1
+ if (decimalPoints > 1) {
+ const parts = value.split('.')
+ value = parts[0] + '.' + parts.slice(1).join('')
+ }
+ setAmount(value)
+ }
+
+ const onIssuerChange = (value) => {
+ if (typeof value === 'object' && value.address) {
+ setIssuer(value.address)
+ } else if (typeof value === 'string') {
+ setIssuer(value)
+ }
+ }
+
+ const onDestinationChange = (value) => {
+ if (typeof value === 'object' && value.address) {
+ setDestination(value.address)
+ } else if (typeof value === 'string') {
+ setDestination(value)
+ }
+ }
+
+ const onExpirationChange = (days) => {
+ setExpiration(days)
+ }
+
+ const onSubmit = async () => {
+ if (!uri) {
+ setErrorMessage('Please enter URI')
+ uriRef?.focus()
+ return
+ }
+
+ if (!agreeToSiteTerms) {
+ setErrorMessage('Please agree to the Terms and conditions')
+ return
+ }
+
+ if (!agreeToPrivacyPolicy) {
+ setErrorMessage('Please agree to the Privacy policy')
+ return
+ }
+
+ if (!isValidTaxon(taxon)) {
+ setErrorMessage('Please enter a valid Taxon value')
+ taxonRef?.focus()
+ return
+ }
+
+ if (mintForOtherAccount && (!issuer || !issuer.trim())) {
+ setErrorMessage('Please enter an Issuer address when minting for another account.')
+ return
+ }
+
+ setErrorMessage('')
+
+ let nftFlags = 0
+ if (flags.tfBurnable) nftFlags |= 1
+ if (flags.tfOnlyXRP) nftFlags |= 2
+ if (flags.tfTransferable) nftFlags |= 8
+ if (flags.tfMutable) nftFlags |= 16
+
+ let request = {
+ TransactionType: 'NFTokenMint',
+ NFTokenTaxon: parseInt(taxon),
+ Flags: nftFlags
+ }
+
+ if (uri && uri.trim()) {
+ request.URI = encode(uri)
+ }
+
+ if (issuer && issuer.trim()) {
+ request.Issuer = issuer.trim()
+ }
+
+ if (transferFee && transferFee.trim()) {
+ const feeValue = parseFloat(transferFee.trim())
+ if (!isNaN(feeValue) && feeValue >= 0 && feeValue <= 50) {
+ request.TransferFee = Math.round(feeValue * 1000)
+ }
+ }
+
+ if (createSellOffer && amount !== '' && !isNaN(parseFloat(amount)) && parseFloat(amount) >= 0) {
+ request.Amount = String(Math.round(parseFloat(amount) * 1000000))
+ if (destination && destination.trim()) {
+ request.Destination = destination.trim()
+ }
+ if (expiration > 0) {
+ request.Expiration = Math.floor(Date.now() / 1000) + expiration * 24 * 60 * 60 - 946684800
+ }
+ }
+
+ setSignRequest({
+ redirect: 'nft',
+ request,
+ callback: (id) => setMinted(id)
+ })
+ }
+
+ const handleFlagChange = (flag) => {
+ setFlags((prev) => ({ ...prev, [flag]: !prev[flag] }))
+ }
+
+ return (
+ <>
+
+ {!minted && (
+ <>
+ {/* URI */}
+
URI that points to the data or metadata associated with the NFT:
+
+ {
+ uriRef = node
+ }}
+ spellCheck="false"
+ maxLength="256"
+ name="uri"
+ />
+
+
+ {/* NFT Taxon */}
+
NFT Taxon (collection identifier, leave as 0 for the issuer's first collection):
+
+ {
+ taxonRef = node
+ }}
+ spellCheck="false"
+ name="taxon"
+ />
+
+
+ {/* Transferable */}
+
+ {
+ // If disabling and royalty is set, do nothing
+ if (flags.tfTransferable && transferFee && parseFloat(transferFee) > 0) {
+ return
+ }
+ handleFlagChange('tfTransferable')
+ }}
+ name="transferable"
+ >
+ Transferable (can be transferred to others)
+
+
+
+ {/* Royalty (Transfer Fee) - only show if Transferable is checked */}
+ {flags.tfTransferable && (
+ <>
+
Royalty (paid to the issuer, 0-50%):
+
+
+
+ >
+ )}
+
+ {/* Mutable */}
+ {network === 'devnet' && (
+
+ handleFlagChange('tfMutable')} name="mutable">
+ Mutable (URI can be updated)
+
+
+ )}
+
+ {/* Only XRP */}
+
+ handleFlagChange('tfOnlyXRP')} name="only-xrp">
+ Only XRP (can only be sold for XRP)
+
+
+
+ {/* Burnable */}
+
+ handleFlagChange('tfBurnable')} name="burnable">
+ Burnable (can be destroyed by the issuer)
+
+
+
+ {/* Create Sell Offer */}
+
+ setCreateSellOffer(!createSellOffer)}
+ name="create-sell-offer"
+ >
+ Create a Sell offer
+
+
+
+ {/* Sell Offer Fields */}
+ {createSellOffer && (
+ <>
+
Initial listing price in XRP (Amount):
+
+
+
+
+
Destination (optional - account to receive the NFT):
+
+
+
Offer expiration:
+
+
+
+ >
+ )}
+
+ {/* Mint on behalf of another account */}
+
+ {
+ if (mintForOtherAccount) {
+ setIssuer('')
+ }
+ setMintForOtherAccount(!mintForOtherAccount)
+ }}
+ name="mint-for-other"
+ >
+ Mint on behalf of another account
+
+
+
+ {mintForOtherAccount && (
+ <>
+
Issuer (account you're minting for):
+
+
+ Note: You must be authorized as a minter for this account, or the transaction will fail.
+
+ >
+ )}
+
+
+
+ {/* Terms and Privacy */}
+
+
+ I agree with the{' '}
+
+ Terms and conditions
+
+ .
+
+
+
+
+
+ I agree with the{' '}
+
+ Privacy policy
+
+ .
+
+
+
+
+
+ Mint NFT
+
+
+ >
+ )}
+
+ {minted && (
+ <>
+
The NFT was successfully minted:
+
+
+ {server}/nft/{minted}
+
+
+
+ setMinted('')} name="mint-another-nft">
+ Mint another NFT
+
+
+ >
+ )}
+
+
+
+ >
+ )
+}
diff --git a/components/Services/NftMint/URITokenMint.js b/components/Services/NftMint/URITokenMint.js
new file mode 100644
index 000000000..da76dd861
--- /dev/null
+++ b/components/Services/NftMint/URITokenMint.js
@@ -0,0 +1,362 @@
+import { useState, useEffect } from 'react'
+import { useTranslation } from 'next-i18next'
+import Link from 'next/link'
+import { useRouter } from 'next/router'
+import { sha512 } from 'crypto-hash'
+import axios from 'axios'
+import { addAndRemoveQueryParams, encode, isIdValid, isValidJson, server, xahauNetwork } from '../../../utils'
+const checkmark = '/images/checkmark.svg'
+import CheckBox from '../../UI/CheckBox'
+
+let interval
+let startTime
+
+export default function URITokenMint({ setSignRequest, uriQuery, digestQuery }) {
+ const { i18n } = useTranslation()
+ const router = useRouter()
+
+ const [uri, setUri] = useState(uriQuery)
+ const [digest, setDigest] = useState(digestQuery)
+ const [agreeToSiteTerms, setAgreeToSiteTerms] = useState(false)
+ const [agreeToPrivacyPolicy, setAgreeToPrivacyPolicy] = useState(false)
+ const [errorMessage, setErrorMessage] = useState('')
+ const [metadataError, setMetadataError] = useState('')
+ const [calculateDigest, setCalculateDigest] = useState(false)
+ const [metadata, setMetadata] = useState('')
+ const [metadataStatus, setMetadataStatus] = useState('')
+ const [metaLoadedFromUri, setMetaLoadedFromUri] = useState(false)
+ const [update, setUpdate] = useState(false)
+ const [minted, setMinted] = useState('')
+ const [uriValidDigest, setUriValidDigest] = useState(isIdValid(digestQuery))
+
+ let uriRef
+ let digestRef
+
+ useEffect(() => {
+ //on component unmount
+ return () => {
+ setUpdate(false)
+ clearInterval(interval)
+ }
+ }, [])
+
+ useEffect(() => {
+ if (update) {
+ interval = setInterval(() => getMetadata(), 5000) //5 seconds
+ } else {
+ clearInterval(interval)
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [update])
+
+ useEffect(() => {
+ setErrorMessage('')
+ }, [i18n.language])
+
+ const onUriChange = (e) => {
+ let uri = e.target.value
+ setUri(uri)
+ setMetaLoadedFromUri(false)
+ setMetadata('')
+ setDigest('')
+ setMetadataError('')
+ setUriValidDigest(false)
+ }
+
+ const getMetadata = async () => {
+ setMetadataStatus('Trying to load the metadata from URI...')
+ const nftType = xahauNetwork ? 'xls35' : 'xls20'
+ const response = await axios
+ .get('v2/metadata?url=' + encodeURIComponent(uri) + '&type=' + nftType)
+ .catch((error) => {
+ console.log(error)
+ setMetadataStatus('error')
+ })
+ if (response?.data) {
+ if (response.data?.metadata) {
+ setMetaLoadedFromUri(true)
+ setMetadata(JSON.stringify(response.data.metadata, undefined, 4))
+ checkDigest(response.data.metadata)
+ setMetadataStatus('')
+ setUpdate(false)
+ } else if (response.data?.message) {
+ setMetadataStatus(response.data.message)
+ setUpdate(false)
+ } else {
+ if (Date.now() - startTime < 120000) {
+ // 2 minutes
+ setUpdate(true)
+ setMetadataStatus(
+ 'Trying to load the metadata from URI... (' +
+ Math.ceil((Date.now() - startTime) / 1000 / 5) +
+ '/24 attempts)'
+ )
+ } else {
+ setUpdate(false)
+ setMetadataStatus('Load failed')
+ }
+ }
+ }
+ }
+
+ const loadMetadata = async () => {
+ if (uri) {
+ setMetaLoadedFromUri(false)
+ getMetadata()
+ startTime = Date.now()
+ } else {
+ setMetadataStatus('Please enter URI :)')
+ uriRef?.focus()
+ }
+ }
+
+ const onDigestChange = (e) => {
+ let digest = e.target.value
+ setDigest(digest)
+ }
+
+ const onSubmit = async () => {
+ if (!uri) {
+ setErrorMessage('Please enter URI')
+ uriRef?.focus()
+ return
+ }
+
+ if (digest && !isIdValid(digest)) {
+ setErrorMessage('Please enter a valid Digest')
+ digestRef?.focus()
+ return
+ }
+
+ if (!agreeToSiteTerms) {
+ setErrorMessage('Please agree to the Terms and conditions')
+ return
+ }
+
+ if (!agreeToPrivacyPolicy) {
+ setErrorMessage('Please agree to the Privacy policy')
+ return
+ }
+
+ setErrorMessage('')
+
+ let request = {
+ TransactionType: 'URITokenMint'
+ }
+
+ if (uri) {
+ request.URI = encode(uri)
+ }
+
+ if (digest) {
+ request.Digest = digest
+ }
+
+ setSignRequest({
+ redirect: 'nft',
+ request,
+ callback: afterSubmit
+ })
+ }
+
+ const afterSubmit = (id) => {
+ setMinted(id)
+ }
+
+ useEffect(() => {
+ if (agreeToSiteTerms || agreeToPrivacyPolicy) {
+ setErrorMessage('')
+ }
+ }, [agreeToSiteTerms, agreeToPrivacyPolicy])
+
+ useEffect(() => {
+ if (calculateDigest) {
+ setDigest('')
+ }
+ }, [calculateDigest])
+
+ useEffect(() => {
+ let queryAddList = []
+ let queryRemoveList = []
+ if (digest) {
+ queryAddList.push({
+ name: 'digest',
+ value: digest
+ })
+ setErrorMessage('')
+ } else {
+ queryRemoveList.push('digest')
+ }
+ if (uri) {
+ queryAddList.push({
+ name: 'uri',
+ value: uri
+ })
+ setErrorMessage('')
+ } else {
+ queryRemoveList.push('uri')
+ }
+ addAndRemoveQueryParams(router, queryAddList, queryRemoveList)
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [digest, uri])
+
+ const onMetadataChange = (e) => {
+ setDigest('')
+ setMetadataError('')
+ let metadata = e.target.value
+ setMetadata(metadata)
+ if (!metaLoadedFromUri) {
+ if (metadata && isValidJson(metadata)) {
+ checkDigest(metadata)
+ } else {
+ setMetadataError('Please enter valid JSON')
+ }
+ }
+ }
+
+ const checkDigest = async (metadata) => {
+ if (!metadata) return
+ if (typeof metadata === 'string') {
+ metadata = JSON.parse(metadata)
+ }
+ let ourDigest = await sha512(JSON.stringify(metadata)?.trim())
+ ourDigest = ourDigest.toString().slice(0, 64)
+ setDigest(ourDigest.toUpperCase())
+ }
+
+ return (
+ <>
+
+ {!minted && (
+ <>
+
URI that points to the data or metadata associated with the NFT:
+
+ {
+ uriRef = node
+ }}
+ spellCheck="false"
+ maxLength="256"
+ name="uri"
+ />
+
+
+ {!uriValidDigest && (
+ <>
+
+ Add Digest (recommended)
+
+
+ {calculateDigest && (
+ <>
+
+ The digest is calculated from the metadata. It is used to verify that the URI and the metadata
+ have not been tampered with.
+
+
+
+ Load metadata
+
+
+
+ {metadataStatus}
+
+
+
+ Metadata: {metadataError}
+
+
+ >
+ )}
+ >
+ )}
+
+ {(calculateDigest || uriValidDigest) && (
+ <>
+
Digest:
+
+
{
+ digestRef = node
+ }}
+ spellCheck="false"
+ maxLength="64"
+ readOnly={metaLoadedFromUri}
+ name="digest"
+ />
+ {isIdValid(digest) &&
}
+
+ >
+ )}
+
+
+ I agree with the{' '}
+
+ Terms and conditions
+
+ .
+
+
+
+ I agree with the{' '}
+
+ Privacy policy
+
+ .
+
+
+
+
+ Mint NFT
+
+
+ >
+ )}
+
+ {minted && (
+ <>
+ The NFT was successfully minted:
+
+
+ {server}/nft/{minted}
+
+
+
+
+ setMinted('')} name="mint-another-nft">
+ Mint another NFT
+
+
+ >
+ )}
+
+
+
+ >
+ )
+}
diff --git a/components/Tabs/FaucetTabs.js b/components/Tabs/NetworkTabs.js
similarity index 95%
rename from components/Tabs/FaucetTabs.js
rename to components/Tabs/NetworkTabs.js
index 73c28999f..ab1c4ceab 100644
--- a/components/Tabs/FaucetTabs.js
+++ b/components/Tabs/NetworkTabs.js
@@ -3,7 +3,7 @@ import Tabs from '.'
import { networks, network } from '../../utils'
import { useRouter } from 'next/router'
-export default function FaucetTabs() {
+export default function NetworkTabs() {
const router = useRouter()
let apiTabs = [
diff --git a/pages/faucet.js b/pages/faucet.js
index 1ea4beaa2..5776915e0 100644
--- a/pages/faucet.js
+++ b/pages/faucet.js
@@ -5,7 +5,7 @@ import SEO from '../components/SEO'
import { getIsSsrMobile } from '../utils/mobile'
import { devNet, ledgerName, nativeCurrency } from '../utils'
-import FaucetTabs from '../components/Tabs/FaucetTabs'
+import NetworkTabs from '../components/Tabs/NetworkTabs'
import Ads from '../components/Layout/Ads'
import { useTranslation } from 'next-i18next'
@@ -27,7 +27,7 @@ export default function FaucetPage({ account, showAds }) {
{t('menu.developers.faucet')}
-
+
diff --git a/pages/services/nft-mint.js b/pages/services/nft-mint.js
index 5f30002e5..f576a0a21 100644
--- a/pages/services/nft-mint.js
+++ b/pages/services/nft-mint.js
@@ -1,15 +1,11 @@
-import { useState, useEffect } from 'react'
-import { useTranslation } from 'next-i18next'
-import Link from 'next/link'
-import { useRouter } from 'next/router'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
+import { useTranslation } from 'next-i18next'
+import SEO from '../../components/SEO'
import { getIsSsrMobile } from '../../utils/mobile'
-import { sha512 } from 'crypto-hash'
-import axios from 'axios'
-
-import { addAndRemoveQueryParams, encode, isIdValid, isValidJson, server, xahauNetwork } from '../../utils'
-
-const checkmark = '/images/checkmark.svg'
+import { xahauNetwork } from '../../utils'
+import NetworkTabs from '../../components/Tabs/NetworkTabs'
+import URITokenMint from '../../components/Services/NftMint/URITokenMint'
+import NFTokenMint from '../../components/Services/NftMint/NFTokenMint'
export const getServerSideProps = async (context) => {
const { query, locale } = context
@@ -24,371 +20,35 @@ export const getServerSideProps = async (context) => {
}
}
-import CheckBox from '../../components/UI/CheckBox'
-import SEO from '../../components/SEO'
-
-let interval
-let startTime
-
export default function NftMint({ setSignRequest, uriQuery, digestQuery }) {
- const { i18n } = useTranslation()
- const router = useRouter()
-
- const [uri, setUri] = useState(uriQuery)
- const [digest, setDigest] = useState(digestQuery)
- const [agreeToSiteTerms, setAgreeToSiteTerms] = useState(false)
- const [agreeToPrivacyPolicy, setAgreeToPrivacyPolicy] = useState(false)
- const [errorMessage, setErrorMessage] = useState('')
- const [metadataError, setMetadataError] = useState('')
- const [calculateDigest, setCalculateDigest] = useState(false)
- const [metadata, setMetadata] = useState('')
- const [metadataStatus, setMetadataStatus] = useState('')
- const [metaLoadedFromUri, setMetaLoadedFromUri] = useState(false)
- const [update, setUpdate] = useState(false)
- const [minted, setMinted] = useState('')
- const [uriValidDigest, setUriValidDigest] = useState(isIdValid(digestQuery))
-
- let uriRef
- let digestRef
-
- useEffect(() => {
- //on component unmount
- return () => {
- setUpdate(false)
- clearInterval(interval)
- }
- }, [])
-
- useEffect(() => {
- if (update) {
- interval = setInterval(() => getMetadata(), 5000) //5 seconds
- } else {
- clearInterval(interval)
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [update])
-
- useEffect(() => {
- setErrorMessage('')
- }, [i18n.language])
-
- const onUriChange = (e) => {
- let uri = e.target.value
- setUri(uri)
- setMetaLoadedFromUri(false)
- setMetadata('')
- setDigest('')
- setMetadataError('')
- setUriValidDigest(false)
- }
-
- const getMetadata = async () => {
- setMetadataStatus('Trying to load the metadata from URI...')
- const nftType = xahauNetwork ? 'xls35' : 'xls20'
- const response = await axios
- .get('v2/metadata?url=' + encodeURIComponent(uri) + '&type=' + nftType)
- .catch((error) => {
- console.log(error)
- setMetadataStatus('error')
- })
- if (response?.data) {
- if (response.data?.metadata) {
- setMetaLoadedFromUri(true)
- setMetadata(JSON.stringify(response.data.metadata, undefined, 4))
- checkDigest(response.data.metadata)
- setMetadataStatus('')
- setUpdate(false)
- } else if (response.data?.message) {
- setMetadataStatus(response.data.message)
- setUpdate(false)
- } else {
- if (Date.now() - startTime < 120000) {
- // 2 minutes
- setUpdate(true)
- setMetadataStatus(
- 'Trying to load the metadata from URI... (' +
- Math.ceil((Date.now() - startTime) / 1000 / 5) +
- '/24 attempts)'
- )
- } else {
- setUpdate(false)
- setMetadataStatus('Load failed')
- }
- }
- }
- }
-
- const loadMetadata = async () => {
- if (uri) {
- setMetaLoadedFromUri(false)
- getMetadata()
- startTime = Date.now()
- } else {
- setMetadataStatus('Please enter URI :)')
- uriRef?.focus()
- }
- }
-
- const onDigestChange = (e) => {
- let digest = e.target.value
- setDigest(digest)
- }
-
- const onSubmit = async () => {
- if (!uri) {
- setErrorMessage('Please enter URI')
- uriRef?.focus()
- return
- }
-
- if (digest && !isIdValid(digest)) {
- setErrorMessage('Please enter a valid Digest')
- digestRef?.focus()
- return
- }
-
- if (!agreeToSiteTerms) {
- setErrorMessage('Please agree to the Terms and conditions')
- return
- }
-
- if (!agreeToPrivacyPolicy) {
- setErrorMessage('Please agree to the Privacy policy')
- return
- }
-
- setErrorMessage('')
-
- let request = {
- TransactionType: 'URITokenMint',
- Memos: [
- {
- Memo: {
- MemoData: encode('NFT Mint')
- }
- }
- ]
- }
-
- if (uri) {
- request.URI = encode(uri)
- }
-
- if (digest) {
- request.Digest = digest
- }
-
- setSignRequest({
- redirect: 'nft',
- request,
- callback: afterSubmit
- })
- }
-
- const afterSubmit = (id) => {
- setMinted(id)
- }
-
- useEffect(() => {
- if (agreeToSiteTerms || agreeToPrivacyPolicy) {
- setErrorMessage('')
- }
- }, [agreeToSiteTerms, agreeToPrivacyPolicy])
-
- useEffect(() => {
- if (calculateDigest) {
- setDigest('')
- }
- }, [calculateDigest])
-
- useEffect(() => {
- let queryAddList = []
- let queryRemoveList = []
- if (digest) {
- queryAddList.push({
- name: 'digest',
- value: digest
- })
- setErrorMessage('')
- } else {
- queryRemoveList.push('digest')
- }
- if (uri) {
- queryAddList.push({
- name: 'uri',
- value: uri
- })
- setErrorMessage('')
- } else {
- queryRemoveList.push('uri')
- }
- addAndRemoveQueryParams(router, queryAddList, queryRemoveList)
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [digest, uri])
-
- const onMetadataChange = (e) => {
- setDigest('')
- setMetadataError('')
- let metadata = e.target.value
- setMetadata(metadata)
- if (!metaLoadedFromUri) {
- if (metadata && isValidJson(metadata)) {
- checkDigest(metadata)
- } else {
- setMetadataError('Please enter valid JSON')
- }
- }
- }
-
- const checkDigest = async (metadata) => {
- if (!metadata) return
- if (typeof metadata === 'string') {
- metadata = JSON.parse(metadata)
- }
- let ourDigest = await sha512(JSON.stringify(metadata)?.trim())
- ourDigest = ourDigest.toString().slice(0, 64)
- setDigest(ourDigest.toUpperCase())
- }
+ const { t } = useTranslation()
return (
<>
-
+
-
NFT Mint
+
{t('nft-mint.header', 'Mint a New NFT')}
- You can use this page to create a new NFT, a unique digital asset that can be used in a variety of
- applications.
+ {t(
+ 'nft-mint.bidirectional-pointer',
+ 'You can use this page to create a new NFT, a unique digital asset that can be used in a variety of applications.'
+ )}
- {!minted && (
- <>
-
URI that points to the data or metadata associated with the NFT:
-
- {
- uriRef = node
- }}
- spellCheck="false"
- maxLength="256"
- name="uri"
- />
-
-
- {!uriValidDigest && (
- <>
-
- Add Digest (recommended)
-
-
- {calculateDigest && (
- <>
-
- The digest is calculated from the metadata. It is used to verify that the URI and the metadata
- have not been tampered with.
-
-
-
- Load metadata
-
-
-
- {metadataStatus}
-
-
-
- Metadata: {metadataError}
-
-
- >
- )}
- >
- )}
-
- {(calculateDigest || uriValidDigest) && (
- <>
-
Digest:
-
-
{
- digestRef = node
- }}
- spellCheck="false"
- maxLength="64"
- readOnly={metaLoadedFromUri}
- name="digest"
- />
- {isIdValid(digest) &&
}
-
- >
- )}
-
-
- I agree with the{' '}
-
- Terms and conditions
-
- .
-
-
-
- I agree with the{' '}
-
- Privacy policy
-
- .
-
-
-
-
- Mint NFT
-
-
- >
- )}
-
- {minted && (
- <>
- The NFT was sucefully minted:
-
-
- {server}/nft/{minted}
-
-
-
-
- setMinted('')} name="mint-another-nft">
- Mint another NFT
-
-
- >
- )}
+
-
+
+ {xahauNetwork ? (
+
+ ) : (
+
+ )}
+
>
)