diff --git a/content/_code-samples/non-fungible-token/js/list-nft-pages-and-buy-offers.py b/content/_code-samples/non-fungible-token/js/list-nft-pages-and-buy-offers.py new file mode 100644 index 0000000000..3e2e61145a --- /dev/null +++ b/content/_code-samples/non-fungible-token/js/list-nft-pages-and-buy-offers.py @@ -0,0 +1,52 @@ +if (typeof module !== "undefined") { + // Use var here because const/let are block-scoped to the if statement. + var xrpl = require('xrpl') + } + // List an account’s NFT pages and see token offers for that account’s NFTs + // https://xrpl.org/account_nfts.html#account_nfts + // https://xrpl.org/nft_buy_offers.html#nft_buy_offers + + async function main() { + // Testnet example: r3CJF73Ugs5cT4G58CDBp6RAmycGdnTAFN + account = "r3CJF73Ugs5cT4G58CDBp6RAmycGdnTAFN" + + // Connect to a testnet node + console.log("Connecting to testnet...") + const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233') + await client.connect() + + const response = await client.request({ + "command": "account_nfts", + "account": account, + "ledger_index": "validated" + }) + + // Only append the NFTs' NFT ID onto the nft_keylets list, other fields aren't needed + var nft_keylets = [] + for (var i = 0; i < response.result.account_nfts.length; i++) { + nft_keylets.push(response.result.account_nfts[i].NFTokenID) + } + + // Query through the NFTs' buy Offers + // For each NFT owned by the account (on nft_keylets[]), go through all their respective buy Offers on the DEX + for (var i = 0; i < nft_keylets.length ; i++) { + const response_1 = await client.request({ + "command": "nft_buy_offers", + "nft_id": nft_keylets[i], + "ledger_index": "validated" + }) + + console.log(`\nBuy Offers for NFT ${nft_keylets[i]}:`) + for (var i = 0; i < response_1.result.offers.length; i++) { + console.log(`\n${i+1}.`) + console.log(` NFT Offer Index: ${response_1.result.offers[i].nft_offer_index}`) + console.log(` Offer Amount: ${response_1.result.offers[i].amount} drops`) + console.log(` Offer Owner: ${response_1.result.offers[i].owner}`) + } + + } + client.disconnect() + // End main() + } + + main() diff --git a/content/_code-samples/non-fungible-token/py/authorize-minter.py b/content/_code-samples/non-fungible-token/py/authorize-minter.py new file mode 100644 index 0000000000..9ffc77b97e --- /dev/null +++ b/content/_code-samples/non-fungible-token/py/authorize-minter.py @@ -0,0 +1,87 @@ +from xrpl.transaction import safe_sign_and_autofill_transaction, send_reliable_submission +from xrpl.models.transactions.nftoken_mint import NFTokenMint, NFTokenMintFlag +from xrpl.models.transactions.account_set import AccountSet, AccountSetFlag +from xrpl.wallet import generate_faucet_wallet +from xrpl.models.requests import AccountNFTs +from xrpl.clients import JsonRpcClient +from xrpl.wallet import Wallet + +# Assign an authorized NFT minter on your account via AccountSet transaction with flag ASF_AUTHORIZED_NFTOKEN_MINTER +# Mint a NFT using the minter account on behalf of the issuer account +# https://xrpl.org/authorize-minter.html#set-minter + +seed = "" +custom_wallet = None + +if seed: + custom_wallet = Wallet(seed=seed, sequence=0) + +# Connect to a testnet node +print("Connecting to Testnet...") +JSON_RPC_URL = "https://s.altnet.rippletest.net:51234/" +client = JsonRpcClient(JSON_RPC_URL) + +# Initialize wallet from seed +issuer_wallet = generate_faucet_wallet(client=client, wallet=custom_wallet) +issuerAddr = issuer_wallet.classic_address + +# Get minter account credentials from the testnet faucet +print("Requesting address from the Testnet faucet...") +nftoken_minter_wallet = generate_faucet_wallet(client=client) +minterAddr = nftoken_minter_wallet.classic_address + +print(f"\nMinter Account: {issuerAddr}") +print(f" Seed: {issuer_wallet.seed}") + +print(f"\nAuthorized Minter Account: {minterAddr}") +print(f" Seed: {nftoken_minter_wallet.seed}") + +# Construct AccountSet transaction to authorize another account (Minter Account) to issue NFTs on our behalf +print(f"\nAuthorizing account {minterAddr} as a NFT minter on account {issuerAddr}...") +authorize_minter_tx = AccountSet( + account=issuerAddr, + set_flag=AccountSetFlag.ASF_AUTHORIZED_NFTOKEN_MINTER, + nftoken_minter=minterAddr +) + +# Sign authorize_minter_tx using issuer account +authorize_minter_tx_signed = safe_sign_and_autofill_transaction(transaction=authorize_minter_tx, wallet=issuer_wallet, client=client) +authorize_minter_tx_signed = send_reliable_submission(transaction=authorize_minter_tx_signed, client=client) +authorize_minter_tx_result = authorize_minter_tx_signed.result +print(f"\nAuthorize minter tx result: {authorize_minter_tx_result}") + +if authorize_minter_tx_result['meta']['TransactionResult'] == "tesSUCCESS": + print(f"\nTransaction was successfully validated, minter {minterAddr} is now authorized to issue NFTs on behalf of {issuerAddr}") +else: + print(f"Transaction failed, error code: {authorize_minter_tx_result['meta']['TransactionResult']}" + f"\nMinter {minterAddr} is not authorized to issue NFTS on behalf of {issuerAddr}") + +# Construct NFTokenMint transaction to mint a brand new NFT +print(f"Minting a NFT from the newly authorized account to prove that it works...") +mint_tx_1 = NFTokenMint( + account=minterAddr, + issuer=issuerAddr, + nftoken_taxon=1, + flags=NFTokenMintFlag.TF_TRANSFERABLE +) + +# Sign using previously authorized minter's account, this will result in the NFT's issuer field to be the Issuer Account +# while the NFT's owner would be the Minter Account +mint_tx_1_signed = safe_sign_and_autofill_transaction(transaction=mint_tx_1, wallet=nftoken_minter_wallet, client=client) +mint_tx_1_signed = send_reliable_submission(transaction=mint_tx_1_signed, client=client) +mint_tx_1_result = mint_tx_1_signed.result +print(f"\n Mint tx result: {mint_tx_1_result['meta']['TransactionResult']}") +print(f" Tx response: {mint_tx_1_result}") + +# Query the minter account for its account's NFTs +get_account_nfts = AccountNFTs( + account=minterAddr +) + +response = client.request(get_account_nfts) +response = response.result['account_nfts'][0] + +print(f"\n - NFToken metadata:" + f"\n Issuer: {response['Issuer']}" + f"\n NFT ID: {response['NFTokenID']}" + f"\n NFT Taxon: {response['NFTokenTaxon']}") diff --git a/content/_code-samples/non-fungible-token/py/burn-nft.py b/content/_code-samples/non-fungible-token/py/burn-nft.py new file mode 100644 index 0000000000..5c8ed0ac17 --- /dev/null +++ b/content/_code-samples/non-fungible-token/py/burn-nft.py @@ -0,0 +1,68 @@ +from xrpl.transaction import safe_sign_and_autofill_transaction, send_reliable_submission +from xrpl.models.transactions.nftoken_burn import NFTokenBurn +from xrpl.models.requests import AccountNFTs +from xrpl.clients import JsonRpcClient +from xrpl.wallet import Wallet + +# Burn an NFT on the XRPL via a NFTokenBurn transaction +# https://xrpl.org/nftokenburn.html#nftokenburn + +# For this code snippet to work, you need import an Account Seed with an issued NFT +# You could use 'mint_nft.py' on the same folder to import an account with its own minted NFT + +seed = "" + +if seed == "": + print("Please edit this code to update variable 'seed' to an account with a minted NFT to run this snippet. " + "You can get this by running 'mint-nft.py' and copying the printed seed.") +else: + # Connect to a testnet node + print("Connecting to Testnet...") + JSON_RPC_URL = "https://s.altnet.rippletest.net:51234/" + client = JsonRpcClient(JSON_RPC_URL) + + # Initialize wallet from seed + issuer_wallet = Wallet(seed=seed, sequence=0) + issuerAddr = issuer_wallet.classic_address + + print(f"\nIssuer Account: {issuerAddr}") + print(f" Seed: {issuer_wallet.seed}") + + # Query the minter account for its NFTs + get_account_nfts = client.request( + AccountNFTs(account=issuerAddr) + ) + + if get_account_nfts.result['account_nfts'] != []: + nft_int = 1 + print(f"\n - NFTs owned by {issuerAddr}:") + for nft in get_account_nfts.result['account_nfts']: + print(f"\n{nft_int}. NFToken metadata:" + f"\n Issuer: {nft['Issuer']}" + f"\n NFT ID: {nft['NFTokenID']}" + f"\n NFT Taxon: {nft['NFTokenTaxon']}") + nft_int += 1 + + print("\n/// --- ///") + print(f"Burning NFT {get_account_nfts.result['account_nfts'][0]['NFTokenID']}...") + + # Construct NFTokenBurn transaction to burn our previously minted NFT + burn_tx = NFTokenBurn( + account=issuerAddr, + nftoken_id=get_account_nfts.result['account_nfts'][0]['NFTokenID'] + ) + + # Sign burn_tx using the issuer account + burn_tx_signed = safe_sign_and_autofill_transaction(transaction=burn_tx, wallet=issuer_wallet, client=client) + burn_tx_signed = send_reliable_submission(transaction=burn_tx_signed, client=client) + burn_tx_result = burn_tx_signed.result + print(f"\nBurn tx result: {burn_tx_result['meta']['TransactionResult']}") + print(f" Tx response:{burn_tx_result}") + + if burn_tx_result['meta']['TransactionResult'] == "tesSUCCESS": + print(f"\nTransaction was successfully validated, NFToken {burn_tx_result['NFTokenID']} has been burned") + else: + print(f"\nTransaction failed, NFToken was not burned, error code: {burn_tx_result['meta']['TransactionResult']}") + else: + print(f"Account {issuerAddr} owns 0 NFTs, there are no NFTs to burn. Please provide an account that has minted a NFT in the past") + print("You could use 'mint_nft.py' on the same folder to import an account with its own minted NFT") diff --git a/content/_code-samples/non-fungible-token/py/cancel-offer-nft.py b/content/_code-samples/non-fungible-token/py/cancel-offer-nft.py new file mode 100644 index 0000000000..75a84c4ead --- /dev/null +++ b/content/_code-samples/non-fungible-token/py/cancel-offer-nft.py @@ -0,0 +1,72 @@ +from xrpl.transaction import safe_sign_and_autofill_transaction, send_reliable_submission +from xrpl.models.transactions.nftoken_cancel_offer import NFTokenCancelOffer +from xrpl.models.requests import AccountObjects, AccountObjectType +from xrpl.clients import JsonRpcClient +from xrpl.wallet import Wallet + +# Cancel an offer for a NFToken on the XRPL via a NFTokenCancelOffer transaction +# https://xrpl.org/nftokencanceloffer.html#nftokencanceloffer + +# For this code snippet to work, you need import an Account Seed with an existing Buy/Sell Offer for a NFT +# You could use 'create_sell_offer.py' OR 'create_buy_offer.py' on the same folder to import an account + +seed = "" + +if seed == "": + print("Please edit this code to update variable 'seed' to an account with a minted NFT to run this snippet. " + "You can get this by running 'mint-nft.py' and copying the printed seed.") +else: + # Connect to a testnet node + print("Connecting to Testnet...") + JSON_RPC_URL = "https://s.altnet.rippletest.net:51234/" + client = JsonRpcClient(JSON_RPC_URL) + + # Initialize wallet from seed + wallet = Wallet(seed=seed, sequence=0) + Addr = wallet.classic_address + + print(f"\n Account: {Addr}") + print(f" Seed: {seed}") + + get_offer_objects = client.request( + AccountObjects( + account=Addr, + type=AccountObjectType.NFT_OFFER + ) + ) + + offer_objects = get_offer_objects.result + + offer_int = 1 + print(f"\n - Existing Offers made by {Addr}:") + + if len(offer_objects['account_objects']) >= 1: + for offer in offer_objects['account_objects']: + print(f"\n{offer_int}. Offer metadata:" + f"\n NFT ID: {offer['NFTokenID']}" + f"\n Offer ID: {offer['index']}" + f"\n Offer amount: {offer['Amount']} drops" + f"\n Offer owner: {offer['Owner']}" + f"\n Raw metadata: {offer}") + offer_int += 1 + + cancel_offer = input("\nEnter the Offer (by ID) that you want to cancel: ") + + print(f"Cancelling offer {cancel_offer}...") + cancel_sell_offer_tx = NFTokenCancelOffer( + account=Addr, + nftoken_offers=[ + cancel_offer + ] + ) + + # Sign cancel_sell_offer_tx using minter account + cancel_sell_offer_tx_signed = safe_sign_and_autofill_transaction(transaction=cancel_sell_offer_tx, wallet=wallet, + client=client) + cancel_sell_offer_tx_signed = send_reliable_submission(transaction=cancel_sell_offer_tx_signed, client=client) + cancel_sell_offer_tx_result = cancel_sell_offer_tx_signed.result + print(f"\n Cancel Sell Offer tx result: {cancel_sell_offer_tx_result['meta']['TransactionResult']}" + f"\n Tx response: {cancel_sell_offer_tx_result}") + + else: + print(f"\nAccount {Addr} has 0 Offers, thus none to cancel!") diff --git a/content/_code-samples/non-fungible-token/py/create-buy-offer-nft.py b/content/_code-samples/non-fungible-token/py/create-buy-offer-nft.py new file mode 100644 index 0000000000..c82f8de54d --- /dev/null +++ b/content/_code-samples/non-fungible-token/py/create-buy-offer-nft.py @@ -0,0 +1,93 @@ +from xrpl.transaction import safe_sign_and_autofill_transaction, send_reliable_submission +from xrpl.models.transactions.nftoken_create_offer import NFTokenCreateOffer +from xrpl.wallet import generate_faucet_wallet +from xrpl.models.requests import AccountNFTs +from xrpl.clients import JsonRpcClient +from xrpl.models import NFTBuyOffers +from xrpl.wallet import Wallet + +# Put up a buy offer for a NFT on the XRPL via a NFTokenCreateOffer transaction +# https://xrpl.org/nftokencreateoffer.html#nftokencreateoffer + +# For this code snippet to work, you need import an Account Seed with an issued NFT +# You could use 'mint_nft.py' on the same folder to import an account + +seed = "" + +if seed == "": + print("Please edit this code to update variable 'seed' to an account with a minted NFT to run this snippet. " + "You can get this by running 'mint-nft.py' and copying the printed seed.") +else: + # Connect to a testnet node + print("Connecting to Testnet...") + JSON_RPC_URL = "https://s.altnet.rippletest.net:51234/" + client = JsonRpcClient(JSON_RPC_URL) + + # Initialize wallet from seed + issuer_wallet = Wallet(seed=seed, sequence=0) + issuerAddr = issuer_wallet.classic_address + + # Get buyer account credentials from the testnet faucet + print("Requesting address from the Testnet faucet...") + buyer_wallet = generate_faucet_wallet(client=client) + buyerAddr = buyer_wallet.classic_address + + print(f"\n Minter Account: {issuerAddr}") + print(f" Seed: {issuer_wallet.seed}") + + print(f"\n Buyer Account: {buyerAddr}") + print(f" Seed: {buyer_wallet.seed}") + + # Query the issuer account for its account's NFTs + get_account_nfts = AccountNFTs( + account=issuerAddr + ) + + response = client.request(get_account_nfts) + response = response.result['account_nfts'][0] + + # Put up a buy offer for the NFT on the open market + buy_offer_amount = "10000000" + print(f"Buying NFT {response['NFTokenID']} for {int(buy_offer_amount) / 1000000} XRP ") + buy_tx = NFTokenCreateOffer( + account=buyerAddr, + owner=issuerAddr, + nftoken_id=response['NFTokenID'], + amount=buy_offer_amount, # 10 XRP in drops, 1 XRP = 1,000,000 drops + ) + + # Sign buy_tx using the issuer account + buy_tx_signed = safe_sign_and_autofill_transaction(transaction=buy_tx, wallet=buyer_wallet, client=client) + buy_tx_signed = send_reliable_submission(transaction=buy_tx_signed, client=client) + buy_tx_result = buy_tx_signed.result + + print(f"\n NFTokenCreateOffer tx result: {buy_tx_result['meta']['TransactionResult']}") + print(f" Tx response: {buy_tx_result}") + + # Index through the tx's metadata and check the changes that occurred on the ledger (AffectedNodes) + for node in buy_tx_result['meta']['AffectedNodes']: + if "CreatedNode" in list(node.keys())[0] and "NFTokenOffer" in node['CreatedNode']['LedgerEntryType']: + print(f"\n - Buy Offer metadata:" + f"\n NFT ID: {node['CreatedNode']['NewFields']['NFTokenID']}" + f"\n Sell Offer ID: {node['CreatedNode']['LedgerIndex']}" + f"\n Offer amount: {node['CreatedNode']['NewFields']['Amount']} drops" + f"\n Offer owner: {node['CreatedNode']['NewFields']['Owner']}" + f"\n Raw metadata: {node}") + + # Query buy offers for the NFT + response_offers = client.request( + NFTBuyOffers(nft_id=response['NFTokenID']) + ) + + offer_objects = response_offers.result + + offer_int = 1 + print(f"\n - Existing Buy Offers for NFT {response['NFTokenID']}:") + for offer in offer_objects['offers']: + print(f"\n{offer_int}. Buy Offer metadata:" + f"\n NFT ID: {offer_objects['nft_id']}" + f"\n Sell Offer ID: {offer['nft_offer_index']}" + f"\n Offer amount: {offer['amount']} drops" + f"\n Offer owner: {offer['owner']}" + f"\n Raw metadata: {offer}") + offer_int += 1 diff --git a/content/_code-samples/non-fungible-token/py/create-sell-offer-nft.py b/content/_code-samples/non-fungible-token/py/create-sell-offer-nft.py new file mode 100644 index 0000000000..b965e94426 --- /dev/null +++ b/content/_code-samples/non-fungible-token/py/create-sell-offer-nft.py @@ -0,0 +1,94 @@ +from xrpl.models.transactions.nftoken_create_offer import NFTokenCreateOffer, NFTokenCreateOfferFlag +from xrpl.transaction import safe_sign_and_autofill_transaction, send_reliable_submission +from xrpl.models.requests import AccountNFTs +from xrpl.clients import JsonRpcClient +from xrpl.models import NFTSellOffers +from xrpl.wallet import Wallet + +# Put up a NFT sell offer on the XRPL via NFTokenCreateOffer transaction with flag TF_SELL_NFTOKEN +# https://xrpl.org/nftokencreateoffer.html#nftokencreateoffer + +# For this code snippet to work, you need import an Account Seed with an already issued NFT +# You could use 'mint_nft.py' on the same folder to import an account + +seed = "" + +if seed == "": + print("Please edit this code to update variable 'seed' to an account with a minted NFT to run this snippet. " + "You can get this by running 'mint-nft.py' and copying the printed seed.") +else: + # Connect to a testnet node + print("Connecting to Testnet...") + JSON_RPC_URL = "https://s.altnet.rippletest.net:51234/" + client = JsonRpcClient(JSON_RPC_URL) + + # Initialize wallet from seed + issuer_wallet = Wallet(seed=seed, sequence=0) + issuerAddr = issuer_wallet.classic_address + + print(f"\nIssuer Account: {issuerAddr}") + print(f" Seed: {issuer_wallet.seed}") + + # Query the issuer account for its NFTs + get_account_nfts = client.request(AccountNFTs(account=issuerAddr)) + + if get_account_nfts.result['account_nfts'] != []: + nft_int = 1 + print(f"\n - NFTs owned by {issuerAddr}:") + for nft in get_account_nfts.result['account_nfts']: + print(f"\n{nft_int}. NFToken metadata:" + f"\n NFT ID: {nft['NFTokenID']}" + f"\n Issuer: {nft['Issuer']}" + f"\n NFT Taxon: {nft['NFTokenTaxon']}") + nft_int += 1 + + nftoken_id = input("\nEnter which NFT (by ID) you want to put up for sell: ") + nftoken_amount = input("Enter how much you want the NFT to go for, in drops: ") + + # Sell the NFT on the open market + print(f"Selling NFT {nftoken_id} for {int(nftoken_amount) / 1000000} XRP on the open market...") + sell_tx = NFTokenCreateOffer( + account=issuerAddr, + nftoken_id=nftoken_id, + amount=nftoken_amount, # 10 XRP in drops, 1 XRP = 1,000,000 drops + flags=NFTokenCreateOfferFlag.TF_SELL_NFTOKEN, + ) + + # Sign sell_tx using the issuer account + sell_tx_signed = safe_sign_and_autofill_transaction(transaction=sell_tx, wallet=issuer_wallet, client=client) + sell_tx_signed = send_reliable_submission(transaction=sell_tx_signed, client=client) + sell_tx_result = sell_tx_signed.result + + print(f"\n Sell Offer tx result: {sell_tx_result['meta']['TransactionResult']}") + print(f" Tx response: {sell_tx_result}") + + # Index through the tx's metadata and check the changes that occurred on the ledger (AffectedNodes) + for node in sell_tx_result['meta']['AffectedNodes']: + if "CreatedNode" in list(node.keys())[0] and "NFTokenOffer" in node['CreatedNode']['LedgerEntryType']: + print(f"\n - Sell Offer metadata:" + f"\n NFT ID: {node['CreatedNode']['NewFields']['NFTokenID']}" + f"\n Sell Offer ID: {node['CreatedNode']['LedgerIndex']}" + f"\n Offer amount: {node['CreatedNode']['NewFields']['Amount']} drops" + f"\n Offer owner: {node['CreatedNode']['NewFields']['Owner']}" + f"\n Raw metadata: {node}") + + # Query past sell offer + response_offers = client.request( + NFTSellOffers(nft_id=nftoken_id) + ) + + offer_objects = response_offers.result + + offer_int = 1 + print(f"\n - Existing Sell Offers for NFT {nftoken_id}:") + for offer in offer_objects['offers']: + print(f"\n{offer_int}. Sell Offer metadata:" + f"\n NFT ID: {offer_objects['nft_id']}" + f"\n Sell Offer ID: {offer['nft_offer_index']}" + f"\n Offer amount: {offer['amount']} drops" + f"\n Offer owner: {offer['owner']}" + f"\n Raw metadata: {offer}") + offer_int += 1 + else: + print(f"\nError: account {issuerAddr} has no NFT, thus there are no NFTs to sell.") + diff --git a/content/_code-samples/non-fungible-token/py/list-nft-pages-and-offers.py b/content/_code-samples/non-fungible-token/py/list-nft-pages-and-offers.py new file mode 100644 index 0000000000..2d034bdbf2 --- /dev/null +++ b/content/_code-samples/non-fungible-token/py/list-nft-pages-and-offers.py @@ -0,0 +1,54 @@ +from xrpl.models.requests.account_nfts import AccountNFTs +from xrpl.models import NFTBuyOffers +from xrpl.clients import JsonRpcClient + +# This code sample lists an account’s NFT pages (https://xrpl.org/nftokenpage.html#nftokenpage) +# and see token offers for that account’s NFTs +# https://xrpl.org/non-fungible-tokens.html#nfts-on-the-xrp-ledger +# https://xrpl.org/nftokenpage.html#nftokenpage +# https://xrpl.org/nft_buy_offers.html#nft_buy_offers + +# Testnet example: r3CJF73Ugs5cT4G58CDBp6RAmycGdnTAFN +account = input("Enter wallet address: ") + +# Connect to a testnet node +JSON_RPC_URL = "https://s.altnet.rippletest.net:51234/" +client = JsonRpcClient(JSON_RPC_URL) + +# Query the account's NFTs +response = client.request( + AccountNFTs(account=account) +) + +if response.status[0:7] == "success": + nft_list = response.result['account_nfts'] + + # Only append the NFTs' NFT ID onto the nft_keylets list, other fields aren't needed + nft_keylets = [] + for x in nft_list: + nft_keylets.append(x['NFTokenID']) + + # Query through the NFTs' buy Offers + # For each NFT owned by the account (on nft_keylets), go through all their respective buy Offerss + for nft in nft_keylets: + response = client.request( + NFTBuyOffers( + nft_id=nft + ) + ) + + offer_objects = response.result + if 'error' not in offer_objects: + print(f"\nBuy Offers for NFT {nft}:") + x_int = 1 + for x in offer_objects['offers']: + print(f"\n{x_int}.") + print(f" NFT Offer Index: {x['nft_offer_index']}") + print(f" Offer Amount: {x['amount']} drops") + print(f" Offer Owner: {x['owner']}") + x_int += 1 + else: + print(f"\nNFT {nft} does not have any buy offers...") + +else: + print(f"Account {account} does not own any NFTs!") diff --git a/content/_code-samples/non-fungible-token/py/mint-nft.py b/content/_code-samples/non-fungible-token/py/mint-nft.py new file mode 100644 index 0000000000..e07e9327b6 --- /dev/null +++ b/content/_code-samples/non-fungible-token/py/mint-nft.py @@ -0,0 +1,67 @@ +from xrpl.transaction import safe_sign_and_autofill_transaction, send_reliable_submission +from xrpl.models.transactions.nftoken_mint import NFTokenMint, NFTokenMintFlag +from xrpl.wallet import generate_faucet_wallet +from xrpl.models.requests import AccountNFTs +from xrpl.clients import JsonRpcClient +from xrpl.wallet import Wallet + +# Mint an NFT on the XRPL via a NFTokenMint transaction +# https://xrpl.org/nftokenmint.html#nftokenmint + +# If you want to mint a NFT on an already existing account, enter in the seed. If not, an account will be provided +# Make sure the seed variable is empty "", if you want to use a brand new testing account + +seed = "" + +# Connect to a testnet node +print("Connecting to Testnet...") +JSON_RPC_URL = "https://s.altnet.rippletest.net:51234/" +client = JsonRpcClient(JSON_RPC_URL) + +# Get issuer account credentials from the testnet faucet +if seed == "": + print("Requesting address from the Testnet faucet...") + issuer_wallet = generate_faucet_wallet(client=client) + issuerAddr = issuer_wallet.classic_address +else: + issuer_wallet = Wallet(seed=seed, sequence=0) + issuerAddr = issuer_wallet.classic_address + +print(f"\nIssuer Account: {issuerAddr}") +print(f" Seed: {issuer_wallet.seed}") + +# Construct NFTokenMint transaction to mint 1 NFT +print(f"Minting a NFT...") +mint_tx = NFTokenMint( + account=issuerAddr, + nftoken_taxon=1, + flags=NFTokenMintFlag.TF_TRANSFERABLE +) + +# Sign mint_tx using the issuer account +mint_tx_signed = safe_sign_and_autofill_transaction(transaction=mint_tx, wallet=issuer_wallet, client=client) +mint_tx_signed = send_reliable_submission(transaction=mint_tx_signed, client=client) +mint_tx_result = mint_tx_signed.result + +print(f"\n Mint tx result: {mint_tx_result['meta']['TransactionResult']}") +print(f" Tx response: {mint_tx_result}") + +for node in mint_tx_result['meta']['AffectedNodes']: + if "CreatedNode" in list(node.keys())[0]: + print(f"\n - NFT metadata:" + f"\n NFT ID: {node['CreatedNode']['NewFields']['NFTokens'][0]['NFToken']['NFTokenID']}" + f"\n Raw metadata: {node}") + +# Query the minted account for its NFTs +get_account_nfts = client.request( + AccountNFTs(account=issuerAddr) +) + +nft_int = 1 +print(f"\n - NFTs owned by {issuerAddr}:") +for nft in get_account_nfts.result['account_nfts']: + print(f"\n{nft_int}. NFToken metadata:" + f"\n Issuer: {nft['Issuer']}" + f"\n NFT ID: {nft['NFTokenID']}" + f"\n NFT Taxon: {nft['NFTokenTaxon']}") + nft_int += 1 diff --git a/content/_code-samples/non-fungible-token/py/nft-general.py b/content/_code-samples/non-fungible-token/py/nft-general.py new file mode 100644 index 0000000000..cdc8702c13 --- /dev/null +++ b/content/_code-samples/non-fungible-token/py/nft-general.py @@ -0,0 +1,224 @@ +from xrpl.models.transactions.nftoken_create_offer import NFTokenCreateOffer, NFTokenCreateOfferFlag +from xrpl.transaction import safe_sign_and_autofill_transaction, send_reliable_submission +from xrpl.models.transactions.nftoken_mint import NFTokenMint, NFTokenMintFlag +from xrpl.models.transactions.nftoken_accept_offer import NFTokenAcceptOffer +from xrpl.models.transactions.nftoken_cancel_offer import NFTokenCancelOffer +from xrpl.models.transactions.account_set import AccountSet, AccountSetFlag +from xrpl.models.transactions.nftoken_burn import NFTokenBurn +from xrpl.wallet import generate_faucet_wallet +from xrpl.models.requests import AccountNFTs +from xrpl.clients import JsonRpcClient +from xrpl.models import NFTSellOffers + +# This code snippet walks you through on how to mint a NFT, burn a NFT, authorize another account to mint on your behalf +# And how to create an Offer, cancel an Offer, and accept an Offer native on the XRP Ledger + +# https://xrpl.org/non-fungible-tokens.html#nfts-on-the-xrp-ledger +# https://xrpl.org/nftokenmint.html#nftokenmint +# https://xrpl.org/nftokenburn.html#nftokenburn +# https://xrpl.org/authorize-minter.html#set-minter + +# This code flows as follows: +# 1. Create issuer, minter, buyer account (3 separate accounts) +# 2. Mint NFT using issuer account +# 3. Burn the previous NFT using issuer account +# 4. Assign an authorized NFT minter (minter account) on issuer account +# 5. Mint NFT using minter account but the issuer account as the NFT's Issuer +# 6. Sell NFT on the open market using minter account +# 7. Cancel NFT's sell offer using minter account +# 8. Sell NFT on the open market using minter account +# 9. Buy NFT using buyer account by accepting the sell offer via NFTokenAcceptOffer transaction +# -- END -- + +# Connect to a testnet node +print("Connecting to Testnet...") +JSON_RPC_URL = "https://s.altnet.rippletest.net:51234/" +client = JsonRpcClient(JSON_RPC_URL) + +# Get issuer, minter, buyer account credentials from the Testnet Faucet +print("Requesting address from the Testnet faucet...") +issuer_wallet = generate_faucet_wallet(client=client) +issuerAddr = issuer_wallet.classic_address + +nftoken_minter_wallet = generate_faucet_wallet(client=client) +minterAddr = nftoken_minter_wallet.classic_address + +buyer_wallet = generate_faucet_wallet(client=client) +buyerAddr = buyer_wallet.classic_address + +print(f" Minter Account: {issuerAddr}" + f"\n Authorized Minter Account: {minterAddr}" + f"\n Buyer Account: {buyerAddr}") + +# Construct NFTokenMint transaction to mint 1 NFT +print(f"\n - Minting a NFT on account {issuerAddr}...") +mint_tx = NFTokenMint( + account=issuerAddr, + nftoken_taxon=0 +) + +# Sign mint_tx using issuer account +mint_tx_signed = safe_sign_and_autofill_transaction(transaction=mint_tx, wallet=issuer_wallet, client=client) +mint_tx_signed = send_reliable_submission(transaction=mint_tx_signed, client=client) +mint_tx_result = mint_tx_signed.result +print(f"\n Mint tx result: {mint_tx_result['meta']['TransactionResult']}" + f"\n Tx response: {mint_tx_result}") + +# Query the issuer account for its NFTs +get_account_nfts = client.request(AccountNFTs(account=issuerAddr)) +response = get_account_nfts.result['account_nfts'][0] + +print(f"\n - NFToken metadata:" + f"\n Issuer: {response['Issuer']}" + f"\n NFT ID: {response['NFTokenID']}" + f"\n NFT Taxon: {response['NFTokenTaxon']}") + +# Construct NFTokenBurn transaction to burn our previously minted NFT +print(f"\n - Burning NFT {response['NFTokenID']} on account {issuerAddr}...") +burn_tx = NFTokenBurn( + account=issuerAddr, + nftoken_id=response['NFTokenID'] +) + +# Sign burn_tx using issuer account +burn_tx_signed = safe_sign_and_autofill_transaction(transaction=burn_tx, wallet=issuer_wallet, client=client) +burn_tx_signed = send_reliable_submission(transaction=burn_tx_signed, client=client) +burn_tx_result = burn_tx_signed.result +print(f"\n Burn tx result: {burn_tx_result['meta']['TransactionResult']}" + f"\n Tx response: {burn_tx_result}") + +if burn_tx_result['meta']['TransactionResult'] == "tesSUCCESS": + print(f"Transaction was successfully validated, NFToken {response['NFTokenID']} has been burned") +else: + print(f"Transaction failed, NFToken was not burned, error code: {burn_tx_result['meta']['TransactionResult']}") + +# Construct AccountSet transaction to authorize the minter account to issue NFTs on the issuer account's behalf +print(f"\n - Authorizing account {minterAddr} as a NFT minter on account {issuerAddr}...") +authorize_minter_tx = AccountSet( + account=issuerAddr, + set_flag=AccountSetFlag.ASF_AUTHORIZED_NFTOKEN_MINTER, + nftoken_minter=minterAddr +) + +# Sign authorize_minter_tx using issuer account +authorize_minter_tx_signed = safe_sign_and_autofill_transaction(transaction=authorize_minter_tx, wallet=issuer_wallet, client=client) +authorize_minter_tx_signed = send_reliable_submission(transaction=authorize_minter_tx_signed, client=client) +authorize_minter_tx_result = authorize_minter_tx_signed.result +print(f"\n Authorize minter tx result: {authorize_minter_tx_result['meta']['TransactionResult']}" + f"\n Tx response: {authorize_minter_tx_result}") + + +if authorize_minter_tx_result['meta']['TransactionResult'] == "tesSUCCESS": + print(f"Transaction was successfully validated, minter {minterAddr} is now authorized to issue NFTs on behalf of {issuerAddr}") +else: + print(f"Transaction failed, error code: {authorize_minter_tx_result['meta']['TransactionResult']}" + f"\nMinter {minterAddr} is not authorized to issue NFTS on behalf of {issuerAddr}") + +# Construct NFTokenMint transaction to mint a brand new NFT +print(f"\n - Minting a NFT from the newly authorized account to prove that it works...") +mint_tx_1 = NFTokenMint( + account=minterAddr, + issuer=issuerAddr, + nftoken_taxon=1, + flags=NFTokenMintFlag.TF_TRANSFERABLE +) + +# Sign using previously authorized minter's account, this will result in the NFT's issuer field to be the Issuer Account +# while the NFT's owner would be the Minter Account +mint_tx_1_signed = safe_sign_and_autofill_transaction(transaction=mint_tx_1, wallet=nftoken_minter_wallet, client=client) +mint_tx_1_signed = send_reliable_submission(transaction=mint_tx_1_signed, client=client) +mint_tx_1_result = mint_tx_1_signed.result +print(f"\n Mint tx result: {mint_tx_1_result['meta']['TransactionResult']}" + f"\n Tx response: {mint_tx_1_result}") + +# Query the minter account for its account's NFTs +get_account_nfts = AccountNFTs( + account=minterAddr +) + +response = client.request(get_account_nfts) +response = response.result['account_nfts'][0] + +print(f"\n - NFToken metadata:" + f"\n Issuer: {response['Issuer']}" + f"\n NFT ID: {response['NFTokenID']}" + f"\n NFT Taxon: {response['NFTokenTaxon']}") + +# Construct a NFTokenCreateOffer transaction to sell the previously minted NFT on the open market +nftoken_amount = "10000000" +print(f"\n - Selling NFT {response['NFTokenID']} for {int(nftoken_amount) / 1000000} XRP on the open market...") +sell_tx = NFTokenCreateOffer( + account=minterAddr, + nftoken_id=response['NFTokenID'], + amount=nftoken_amount, # 10 XRP in drops, 1 XRP = 1,000,000 drops + flags=NFTokenCreateOfferFlag.TF_SELL_NFTOKEN, +) + +# Sign sell_tx using minter account +sell_tx_signed = safe_sign_and_autofill_transaction(transaction=sell_tx, wallet=nftoken_minter_wallet, client=client) +sell_tx_signed = send_reliable_submission(transaction=sell_tx_signed, client=client) +sell_tx_result = sell_tx_signed.result +print(f"\n Sell Offer tx result: {sell_tx_result['meta']['TransactionResult']}" + f"\n Tx response: {sell_tx_result}") + +# Query the sell offer +response_offers = client.request( + NFTSellOffers(nft_id=response['NFTokenID']) +) + +offer_objects = response_offers.result + +# Cancel the previous Sell Offer +print(f"\n - Cancelling offer {offer_objects['offers'][0]['nft_offer_index']}...") +cancel_sell_offer_tx = NFTokenCancelOffer( + account=minterAddr, + nftoken_offers=[ + offer_objects['offers'][0]['nft_offer_index'] + ] +) + +# Sign cancel_sell_offer_tx using minter account +cancel_sell_offer_tx_signed = safe_sign_and_autofill_transaction(transaction=cancel_sell_offer_tx, wallet=nftoken_minter_wallet, client=client) +cancel_sell_offer_tx_signed = send_reliable_submission(transaction=cancel_sell_offer_tx_signed, client=client) +cancel_sell_offer_tx_result = cancel_sell_offer_tx_signed.result +print(f"\n Cancel Sell Offer tx result: {cancel_sell_offer_tx_result['meta']['TransactionResult']}" + f"\n Tx response: {cancel_sell_offer_tx_result}") + +# Construct a NFTokenCreateOffer transaction to sell the previously minted NFT on the open market +print(f"\n - Selling NFT {response['NFTokenID']} for {int(nftoken_amount) / 1000000} XRP on the open market...") +sell_1_tx = NFTokenCreateOffer( + account=minterAddr, + nftoken_id=response['NFTokenID'], + amount=nftoken_amount, # 10 XRP in drops, 1 XRP = 1,000,000 drops + flags=NFTokenCreateOfferFlag.TF_SELL_NFTOKEN, +) + +# Sign sell_1_tx using minter account +sell_1_tx_signed = safe_sign_and_autofill_transaction(transaction=sell_1_tx, wallet=nftoken_minter_wallet, client=client) +sell_1_tx_signed = send_reliable_submission(transaction=sell_1_tx_signed, client=client) +sell_1_tx_result = sell_1_tx_signed.result +print(f"\n Sell Offer tx result: {sell_1_tx_result['meta']['TransactionResult']}" + f"\n Tx response: {sell_1_tx_result}") + +# Query the sell offer +response = client.request( + NFTSellOffers( + nft_id=response['NFTokenID'] + ) +) + +offer_objects = response.result + +# Construct a NFTokenAcceptOffer offer to buy the NFT being listed for sale on the open market +print(f"\n - Accepting offer {offer_objects['offers'][0]['nft_offer_index']}...") +buy_tx = NFTokenAcceptOffer( + account=buyerAddr, + nftoken_sell_offer=offer_objects['offers'][0]['nft_offer_index'] +) + +# Sign buy_tx using buyer account +buy_tx_signed = safe_sign_and_autofill_transaction(transaction=buy_tx, wallet=buyer_wallet, client=client) +buy_tx_signed = send_reliable_submission(transaction=buy_tx_signed, client=client) +buy_tx_result = buy_tx_signed.result +print(f"\n Buy Offer result: {buy_tx_result['meta']['TransactionResult']}" + f"\n Tx response: {buy_tx_result}")