We request all of the records for the program and then filter the spent records to get the records representing the NFTs.
2. Request an Execution of the authorize Function
constaleoTransaction=Transaction.createTransaction( publicKey!,WalletAdapterNetwork.Testnet, NFTProgramId,'authorize', [nftRecords[0],'101u64'],// This should be a random number in production, generated on the back end of a DApp0,);consttxId=await (wallet?.adapter asLeoWalletAdapter).requestExecution(aleoTransaction);
The authorize function takes two parameters: the NFT record and a nonce . The nonce should be randomly generated on the backend of the application to prevent the user from choosing a specific random number. This prevents this authorization being used in replay attacks.
3. Get the execution
Additionally, you want to ensure the execution.global_state_root exists on chain and that the serial number execution.transitions[0].inputs[0].id does not exist on chain. It's extremely important to verify these two pieces of data. Otherwise, malicious users will be able to authorize using either a fraudulent NFT or an already spent NFT.
Together, these checks ensure that a valid record exists on-chain and it has not been spent all without paying any fees.
Additionally, by saving the serial number of the record, DApps can automatically invalidate the user session if the serial number appears on chain.
Some tips:
To get the verifying key for a given function, you can use the following helper methods:
The execution from the authorize function cannot be broadcast successfully. It will fail every time. To safely prevent all broadcasting attempts by potentially malicious DApps, ensure the finalize statement contains an always fail assertion. For example:
finalize authorize(
)
{
// fails on purpose, so that the nft is not burned.
assert_eq(0u8, 1u8);
}