bitpro가 원문에서 글자만 모은 내용이에요. 표·그림·수식은 빠지거나 깨질 수 있어요. 전체 41쪽 중 36쪽
string
,
IsLeftChildNode
:
boolean
,
}
)
=>
(
{
hash
:
Hash
,
isLeftChildNode
:
IsLeftChildNode
,
}
)
)
;
return
{
merklePathNodes
:
formattedMerklePathNodes
}
;
}
catch
(
error
)
{
console
.
error
(
"Error fetching Merkle path:"
,
error
)
;
throw
new
Error
(
"Failed to get Merkle path by transaction ID."
)
;
}
}
;
What This Function Does:
Fetches Merkle Path
: It sends a request to fetch the merkle path using the transaction ID.
Parses Response
: It parses the response from the server as JSON.
Returns Merkle Path Nodes
: It extracts and returns the merkle path of the nodes from the JSON response.
Handles Errors
: If an error occurs, it clears the transaction status and logs the error.
Next, we'll write the
Create a Collection on the cross-chain
function.
Step 5: Write a function to create a collection on the side chain
Scroll up to find the comment
// step 5 - Create a collection on the dAppChain
.
Replace the existing
createCollectionOnSideChain
function with this code snippet:
create-nft/index.tsx
// step 5 - Create a collection on the dAppChain
const
createCollectionOnSideChain
=
async
(
transactionId
:
string
,
signedTx
:
string
,
BlockNumber
:
number
)
=>
{
let
crossChainLoadingId
;
try
{
crossChainLoadingId
=
toast
.
loading
(
"Creating Collection on dAppChain..."
)
;
const
merklePath
=
await
getMerklePathByTxId
(
aelf
,
transactionId
)
;
const
tdvwTokenContract
=
await
getTokenContract
(
tdvw
,
wallet
)
;
const
CROSS_CHAIN_CREATE_TOKEN_PARAMS
=
{
fromChainId
:
mainchain_from_chain_id
,
parentChainHeight
:
""
+
BlockNumber
,
transactionBytes
:
Buffer
.
from
(
signedTx
,
"hex"
)
.
toString
(
"base64"
)
,
merklePath
,
}
;
const
signedTx2
=
await
tdvwTokenContract
.
CrossChainCreateToken
.
getSignedTx
(
CROSS_CHAIN_CREATE_TOKEN_PARAMS
)
;
let
done
=
false
;
while
(
!
done
)
{
try
{
await
delay
(
10000
)
;
const
{
TransactionId
}
=
await
tdvw
.
chain
.
sendTransaction
(
signedTx2
)
;
const
txResult
=
await
tdvw
.
chain
.
getTxResult
(
TransactionId
)
;
if
(
txResult
.
Status
===
"SUCCESS"
||
txResult
.
Status
===
"MINED"
)
{
done
=
true
;
setIsNftCollectionCreated
(
true
)
;
toast
.
update
(
crossChainLoadingId
,
{
render
:
"Collection was Created Successfully On dAppChain"
,
type
:
"success"
,
isLoading
:
false
,
}
)
;
removeNotification
(
crossChainLoadingId
)
;
toast
.
info
(
"You Can Create NFT now"
)
;
setTransactionStatus
(
false
)
;
}
}
catch
(
err
)
{
if
(
(
err
as
{
Error
:
string
}
)
.
Error
.
includes
(
"Cross chain verification failed."
)
)
{
console
.
log
(
"Exit."
)
;
done
=
true
;
toast
.
update
(
crossChainLoadingId
,
{
render
:
"Please try again to create NFT using new NFT seed"
,
type
:
"error"
,
isLoading
:
false
,
}
)
;
removeNotification
(
crossChainLoadingId
)
;
}
else
{
console
.
error
(
"An unexpected error occurred:"
,
err
)
;
}
}
}
return
"success"
;
}
catch
(
error
)
{
handleError
(
crossChainLoadingId
as
number
,
error
)
;
return
"error"
;
}
}
;
What This Function Does:
Displays Loading Toast
: Shows a notification indicating the creation process of the collection on the dAppChain.
Fetches Merkle Path
: Retrieves the merkle path using the provided transactionId.
Prepares and Signs Transaction
: Constructs parameters for the cross-chain transaction and signs it.
Sends Transaction and Checks Status
: Sends the signed transaction and polls for its status every 10 seconds. Updates the notification and state, if successful.
Handles Errors
: Logs errors and returns "error" if something goes wrong.
Final Return
: Returns "success" upon successful completion.
Create NFT Token
Step 1: Write a Function to create NFTs on the mainchain
Now, let's write the
create NFTs on MainChain
function.
Scroll down to find the comment
// step 6 - Create an NFT on the mainchain
.
Replace the existing
createNFTOnMainChain
function with this code snippet:
create-nft/index.tsx
// step 6 - Create an NFT on the mainchain
const
createNFTOnMainChain
=
async
(
values
:
INftParams
)
=>
{
let
createMainChainNFTLoadingId
;
try
{
createMainChainNFTLoadingId
=
toast
.
loading
(
"Creating NFT on MainChain..."
)
;
// Preparing Parameter for Create Function
const
createNftMainChainInput
=
{
tokenName
:
values
.
tokenName
,
symbol
:
values
.
symbol
,
totalSupply
:
values
.
totalSupply
,
issuer
:
currentWalletAddress
,
isBurnable
:
true
,
issueChainId
:
sidechain_from_chain_id
,
owner
:
currentWalletAddress
,
externalInfo
:
{
}
,
}
;
const
resultMainchain
=
await
mainChainSmartContract
?.
callSendMethod
(
"Create"
,
currentWalletAddress
,
createNftMainChainInput
)
;
console
.
log
(
"========= result of createNewNft ========="
,
resultMainchain
)
;
toast
.
update
(
createMainChainNFTLoadingId
,
{
render
:
"NFT Created Successfully on MainChain"
,
type
:
"success"
,
isLoading
:
false
,
}
)
;
removeNotification
(
createMainChainNFTLoadingId
)
;
return
"success"
;
}
catch
(
error
)
{
handleError
(
createMainChainNFTLoadingId
as
number
,
error
)
;
return
"error"
;
}
}
;
What this function does:
Displays Loading Toast:
Shows a notification indicating the creation process of the NFT on the mainchain.
Prepares Parameters:
Constructs input parameters for creating the NFT, including token details and the issuer's information.
Calls Smart Contract:
Sends a request to the mainchain smart contract to create the NFT using the prepared parameters.
Handles Success:
Updates the notification to show successful NFT creation.
Handles Errors:
Displays an error message if the operation fails and logs the error.
Final Return:
Returns
"success"
if the NFT is created successfully; otherwise, returns
"error"
.
Step 2: Write the Function for Validate NFT Info Exist
Now, let's write the Validate NFT Info Exist function.
Scroll down to find the comment
// step 7 - Validate an NFT token on the mainchain
.
Replace the existing
validateNftToken
function with this code snippet:
create-nft/index.tsx
// step 7 - Validate an NFT token on the maincgit stashhain
const
validateNftToken
=
async
(
values
:
INftParams
)
=>
{
let
validateNFTLoadingId
;
try
{
// Start Loading before initiate the transaction
validateNFTLoadingId
=
toast
.
loading
(
<
CustomToast
title
=
"
Transaction is getting validated on aelf blockchain. Please wait!
"
message
=
"
Validation means transaction runs through a consensus algorithm to be selected or rejected. Once the status changes process will complete. It usually takes some time in distributed systems.
"
/>
)
;
// Create an object with the necessary information for token validation.
const
validateInput
=
{
symbol
:
values
.
symbol
,
tokenName
:
values
.
tokenName
,
totalSupply
:
values
.
totalSupply
,
issuer
:
currentWalletAddress
,
isBurnable
:
true
,
issueChainId
:
sidechain_from_chain_id
,
owner
:
currentWalletAddress
,
externalInfo
:
{
}
,
}
;
// get mainnet contract
const
aelfTokenContract
=
await
getTokenContract
(
aelf
,
wallet
)
;
// prepare Sign the transaction using contract method (ValidateTokenInfoExists Function)
const
signedTx
=
aelfTokenContract
.
ValidateTokenInfoExists
.
getSignedTx
(
validateInput
)
;
// send the transaction using signed Transaction
const
{
TransactionId
:
VALIDATE_TXID
}
=
await
aelf
.
chain
.
sendTransaction
(
signedTx
)
;
await
delay
(
3000
)
;
// get Validate Result
let
VALIDATE_TXRESULT
=
await
aelf
.
chain
.
getTxResult
(
VALIDATE_TXID
)
;
await
delay
(
3000
)
;
// if dAppChain index has a MainChain height greater than validateTokenInfoExist's
let
heightDone
=
false
;
while
(
!
heightDone
)
{
await
delay
(
5000
)
;
// Wait 5 seconds before checking again
// get latest index Hight
const
sideIndexMainHeight
=
await
GetParentChainHeight
(
)
;
if
(
// check the latest index Hight is grater than or equal
Number
(
sideIndexMainHeight
)
>=
VALIDATE_TXRESULT
.
Transaction
.
RefBlockNumber
)
{
VALIDATE_TXRESULT
=
await
aelf
.
chain
.
getTxResult
(
VALIDATE_TXID
)
;
heightDone
=
true
;
}
}
console
.
log
(
VALIDATE_TXRESULT
,
"VALIDATE_TXRESULT=====2"
)
;
const
merklePath
=
await
getMerklePathByTxId
(
aelf
,
VALIDATE_TXID
)
;
toast
.
update
(
validateNFTLoadingId
,
{
render
:
"Validating NFT Successfully Executed"
,
type
:
"success"
,
isLoading
:
false
,
}
)
;
removeNotification
(
validateNFTLoadingId
)
;
// return necessary values
return
{
parentChainHeight
:
VALIDATE_TXRESULT
.
BlockNumber
,
signedTx
:
signedTx
,
merklePath
:
merklePath
,
}
;
}
catch
(
error
)
{
handleError
(
validateNFTLoadingId
as
number
,
error
)
;
return
"error"
;
}
}
;
Here's what the function does:
Displays Loading Toast:
Shows a notification indicating that the NFT validation is in progress on the blockchain.
Prepares Validation Input:
Constructs the input parameters needed for validating the NFT token.
Gets Token Contract:
Retrieves the token contract instance from the MainChain.
Signs and Sends Transaction:
Signs the transaction to validate the token info and sends it to the blockchain.
Polls for Transaction Result:
Waits for the transaction result and ensures the transaction has reached the required block height.
Fetches Merkle Path:
Retrieves the Merkle path for the validated transaction.
Handles Success:
Updates the notification to show successful validation and returns necessary values.
Handles Errors:
Logs errors and returns
"error"
if something goes wrong.
Step 3: Write a Function for Create NFT on dAppChain
Now, let's write the Create NFT on dAppChain function.
Scroll down to find the comment
// step 8 - Create a NFT on dAppChain
.
Replace the existing
createNftTokenOnSideChain
function with this code snippet:
create-nft/index.tsx
// step 8 - Create a NFT on dAppChain.
const
createNftTokenOnSideChain
=
async
(
values
:
INftValidateResult
)
=>
{
let
createSideChainNFTLoadingId
;
try
{
createSideChainNFTLoadingId
=
toast
.
loading
(
"Creating NFT on SideChain..."
)
;
const
CROSS_CHAIN_CREATE_TOKEN_PARAMS
=
{
fromChainId
:
mainchain_from_chain_id
,
parentChainHeight
:
values
.
parentChainHeight
,
transactionBytes
:
Buffer
.
from
(
values
.
signedTx
,
"hex"
)
.
toString
(
"base64"
)
,
merklePath
:
values
.
merklePath
,
}
;
await
sideChainSmartContract
?.
callSendMethod
(
"CrossChainCreateToken"
,
currentWalletAddress
,
CROSS_CHAIN_CREATE_TOKEN_PARAMS
)
;
toast
.
update
(
createSideChainNFTLoadingId
,
{
render
:
"NFT Created Successfully On SideChain"
,
type
:
"success"
,
isLoading
:
false
,
}
)
;
removeNotification
(
createSideChainNFTLoadingId
)
;
return
"success"
;
}
catch
(
error
)
{
handleError
(
createSideChainNFTLoadingId
as
number
,
error
)
;
return
"error"
;
}
}
;
Here's what the function does:
Displays Loading Toast:
Shows a notification indicating that the NFT is being created on the dAppChain.
Prepares Cross-Chain Transaction Parameters:
Constructs the parameters needed for creating the NFT on the dAppChain, including chain IDs, block height, transaction data, and Merkle path.
Calls Smart Contract Method:
Sends the transaction to the dAppChain smart contract to create the NFT.
Handles Success:
Updates the notification to show successful NFT creation on the dAppChain.
Handles Errors:
Logs errors and returns
"error"
if something goes wrong.
Step 4: Write a Function for Issue NFT Token which has been Created on dAppChain.
Now, let's write the Issue NFT Function.
Scroll down to find the comment
// step 9 - Issue a NFT Function which has been Created on dAppChain
.
Replace the existing
issueNftOnSideChain
function with this code snippet:
create-nft/index.tsx
// step 9 - Issue a NFT Function which has been Created on dAppChain
const
issueNftOnSideChain
=
async
(
values
:
{
symbol
:
string
;
amount
:
string
;
memo
:
string
;
}
)
=>
{
let
issuingNFTLoadingId
try
{
issuingNFTLoadingId
=
toast
.
loading
(
"Issuing NFT on SideChain..."
)
;
const
issueNftInput
=
{
symbol
:
values
.
symbol
,
amount
:
values
.
amount
,
memo
:
values
.
memo
,
to
:
currentWalletAddress
,
}
;
const
result
=
await
sideChainSmartContract
?.
callSendMethod
(
"Issue"
,
currentWalletAddress
,
issueNftInput
)
;
console
.
log
(
"========= result of createNewNft ========="
,
result
)
;
toast
.
update
(
issuingNFTLoadingId
,
{
render
:
"NFT Issue Successfully Executed"
,
type
:
"success"
,
isLoading
:
false
,
}
)
;
removeNotification
(
issuingNFTLoadingId
)
;
toast
.
success
(
"You will get NFT on your Wallet! It can take sometimes to get into your wallet"
)
;
handleReturnClick
(
)
;
return
"success"
;
}
catch
(
error
)
{
handleError
(
issuingNFTLoadingId
as
number
,
error
)
;
setTransactionStatus
(
false
)
;
return
"error"
;
}
}
;
Here's what the function does:
Displays Loading Toast:
Shows a notification indicating that the NFT is being issued on the dAppChain.
Prepares Issuance Input:
Constructs the input parameters for issuing the NFT, including symbol, amount, memo, and recipient address.
Calls Smart Contract Method:
Sends the transaction to the dAppChain smart contract to issue the NFT.
Handles Success:
Updates the notification to show successful issuance and notifies the user that the NFT will appear in their wallet.
Handles Errors:
Logs and displays any error messages, updates the transaction status, and returns
"error"
.
Step 5: Create a Function to Call Necessary Functions for NFT Creation
Now, let's write the createNftToken Function.
Scroll down to find the comment
// step 10 - Call Necessary Function for Create NFT
.
Replace the existing
createNftToken
function with this code snippet:
create-nft/index.tsx
// step 10 - Call Necessary Function for Create NFT
const
createNftToken
=
async
(
values
:
INftParams
)
=>
{
try
{
const
mainChainResult
=
await
createNFTOnMainChain
(
values
)
;
if
(
mainChainResult
===
"error"
)
{
setTransactionStatus
(
false
)
;
return
;
}
await
delay
(
3000
)
;
const
validateNFTData
:
INftValidateResult
|
"error"
=
await
validateNftToken
(
values
)
;
if
(
validateNFTData
===
"error"
)
{
setTransactionStatus
(
false
)
;
return
;
}
const
sideChainResult
=
await
createNftTokenOnSideChain
(
validateNFTData
)
;
if
(
sideChainResult
===
"error"
)
{
setTransactionStatus
(
false
)
;
return
;
}
await
issueNftOnSideChain
(
{
symbol
:
values
.
symbol
,
amount
:
values
.
totalSupply
,
memo
:
"We are issuing nftToken"
,
}
)
;
setTransactionStatus
(
false
)
;
}
catch
(
error
)
{
setTransactionStatus
(
false
)
;
if
(
error
instanceof
Error
)
{
toast
.
error
(
error
.
message
)
;
}
else
{
toast
.
error
(
"An unexpected error occurred."
)
;
}
return
"error"
;
}
}
;
Here's what the function does:
Creates NFT on MainChain:
Calls
createNFTOnMainChain
to create the NFT on the MainChain. If it fails, it updates the transaction status and exits.
Validates NFT Token:
Waits for 3 seconds, then calls
validateNftToken
to validate the NFT. If validation fails, it updates the transaction status and exits.
Creates NFT on dAppChain:
Calls
createNftTokenOnSideChain
to create the NFT on the dAppChain using the validated data. If it fails, it updates the transaction status and exits.
Issues NFT on dAppChain:
Calls
issueNftOnSideChain
to issue the NFT. Updates the transaction status to false after completion.
Handles Errors:
Catches and logs any errors, updates the transaction status, and displays an error notification.
Configure Submit Form
Now, let's write a function to call necessary functions for NFT creation.
Scroll down to find the comment
//Step 11 - Handle Submit Form
.
Replace the existing
onSubmit
function with this code snippet:
create-nft/index.tsx
//Step 11 - Handle Submit Form
const
onSubmit
=
async
(
values
:
z
.
infer
<
typeof
formSchema
>
)
=>
{
setTransactionStatus
(
true
)
;
if
(
isNftCollectionCreated
)
{
// Already Collection Created
// create NFT Token
await
createNftToken
(
values
)
;
}
else
{
// create NFT Collection on MainChain
const
createResult
=
await
createNftCollectionOnMainChain
(
values
)
;
if
(
createResult
===
"error"
)
{
setTransactionStatus
(
false
)
;
return
;
}
// Validate NFT Collection
const
validateCollectionResult
=
await
validateNftCollectionInfo
(
createResult
)
;
if
(
validateCollectionResult
===
"error"
)
{
setTransactionStatus
(
false
)
;
return
;
}
// create NFT Collection on dAppChain
await
createCollectionOnSideChain
(
validateCollectionResult
.
transactionId
,
validateCollectionResult
.
signedTx
,
validateCollectionResult
.
BlockNumber
)
;
}
}
;
Here's what the function does:
Starts Transaction:
Sets the transaction status to true.
Checks NFT Collection Status:
If the NFT collection is already created, calls
createNftToken
to create the NFT token.
Creates and Validates NFT Collection:
If the collection isn’t created, calls
createNftCollectionOnMainChain
to create it. If successful, validates the NFT collection with
validateNftCollectionInfo
.
Creates Collection on dAppChain:
If validation is successful, calls
createCollectionOnSideChain
to create the collection on the dAppChain.
Handles Errors:
Updates the transaction status to false and exits if any step fails.
Fetch NFT Data
Let's write the Function for the fetch NFT data from user's Wallet using API.
Step 1: Locate the File
go to the
src/lib/commonFunctions.ts
file.
Step 2: Write the Helper Functions for fetch the NFT data
The
commonFunctions.ts
file is contains the helpers function for fetch NFT and etc.
Find the comment
// fetch NFT Data from Indexer API
.
Replace the existing
fetchUserNftData
function with this code snippet:
commonFunctions.ts
// fetch NFT Data from Indexer API
export
const
fetchUserNftData
=
async
(
address
:
string
)
=>
{
const
url
=
'add_your_aeindexer_api'
;
const
headers
=
{
'Content-Type'
:
'application/json'
}
;
const
body
=
JSON
.
stringify
(
{
query
:
`
query {
account(input: { chainId: "tDVW", address: "
${
address
}
" }) {
symbol
amount
address
tokenName
metadata {
chainId
block {
blockHeight
}
}
}
}
`
,
variables
:
{
}
,
}
)
;
try
{
const
response
=
await
fetch
(
url
,
{
method
:
'POST'
,
headers
:
headers
,
body
:
body
,
}
)
;
if
(
!
response
.
ok
)
{
throw
new
Error
(
`
HTTP error! status:
${
response
.
status
}
`
)
;
}
const
result
=
await
response
.
json
(
)
;
return
result
.
data
.
account
;
}
catch
(
error
)
{
console
.
error
(
'Error fetching data:'
,
error
)
;
return
"error"
;
}
}
;
info
ℹ️ Note: Ensure that you are updating your aeindexer api with
"add_your_aeindexer_api"
value in
url
variable.
Here's what the function does:
Retrieves NFT Data:
The function
fetchUserNftData
fetches the NFT data for a given owner using AeIndexer API.
We have Prepared all necessary function for fetch NFT Data from User's Wallet.
Now, Let's call
fetchUserNftData
on necessary page.
Step 3: Call fetchUserNftData Functions on Home Page
go to the
src/pages/home/index.tsx
file.
The
home/index.tsx
file contains the Home Page of NFT dApp
Find the comment
// get NFT Data from User's wallet
.
Replace the existing
getNFTData
function with this code snippet:
home/index.tsx
// get NFT Data from User's wallet
const
getNFTData
=
async
(
)
=>
{
const
result
=
await
fetchUserNftData
(
currentWalletAddress
as
string
)
;
if
(
result
!==
"error"
)
{
setUserNfts
(
result
)
;
}
setLoading
(
false
)
;
}
;
Here's what the function does:
Fetches NFT Data:
The f프로젝트로 돌아가기