# Transfer NFTs Using JavaScript This example shows how to: 1. Create NFT Sell Offers. 2. Create NFT Buy Offers. 3. Accept NFT Sell Offers. 4. Accept NFT Buy Offers. 5. Get a list of offers for a particular NFT. 6. Cancel an offer. [![Transfer NFTs Test Harness](/assets/mt-transfer-nft-1-empty-form.46c5d8fa98b6e49f247914531f1a9ce91d75939662f9ffeee732a38439048ee7.ac57e6ef.png)](/assets/mt-transfer-nft-1-empty-form.46c5d8fa98b6e49f247914531f1a9ce91d75939662f9ffeee732a38439048ee7.ac57e6ef.png) You can download the [NFT Modular Tutorials](/assets/nft-modular-tutorials.0f7eb22b2ca15eaf6397b7c614a7c020f1ab844da76fa9bf842e720bfc80f1fe.4057f33c.zip) archive to try each of the samples in your own browser. # Usage ## Get Accounts 1. Open `transfer-nfts.html` in a browser. 2. Choose your preferred test network (**Devnet** or **Testnet**). 3. Get test accounts. 1. If you copied the gathered information from another tutorial: 1. Paste the gathered information to the **Result** field. 2. Click **Distribute Account Info**. 2. If you have an existing account seed: 1. Paste the account seed to the **Account 1 Seed** or **Account 2 Seed** field. 2. Click **Get Account 1 from Seed** or **Get Account 2 from Seed**. 3. If you do not have existing accounts: 1. Click **Get New Account 1**. 2. Click **Get New Account 2**. [![Form with account information](/assets/mt-transfer-nft-2-accounts-loaded.b93c2cab683a314e08ea97bea144a90503f871d942ed4864ab4f986e992de354.ac57e6ef.png)](/assets/mt-transfer-nft-2-accounts-loaded.b93c2cab683a314e08ea97bea144a90503f871d942ed4864ab4f986e992de354.ac57e6ef.png) ## Create a Sell Offer To create an NFT sell offer: 1. Click the Account 1 or Account 2 radio button. The account information populates the uneditable fields of the form. 2. Enter the **Amount** of the sell offer. 1. If using *XRP*, enter the **Amount** in drops (millionths of an XRP; for example, 20000000). 2. If using issued currency, enter the **Currency** code, **Issuer** account address, and the **Amount**. 3. Optionally, include a **Destination** account address. If present, only that account will have permission to accept the sell offer. 4. Optionally, enter a number of days until **Expiration** of the offer. 5. Enter the **NFT ID** of the NFT you want to sell. 6. Click **Create Sell Offer**. [![NFT Sell Offer](/assets/mt-transfer-nfts-3-create-sell-offer.e0c511dec927cbc5245d56197f0cb332f490d50360b59b213e0883662b9785fa.ac57e6ef.png)](/assets/mt-transfer-nfts-3-create-sell-offer.e0c511dec927cbc5245d56197f0cb332f490d50360b59b213e0883662b9785fa.ac57e6ef.png) ## Get Offers To list the buy and sell offers associated with an NFT: 1. Enter the **NFT ID**. 2. Click **Get Offers**. The key piece of information is the NFT Offer ID (labeled as `nft_offer_index`), which you use to accept a sell or buy offer. [![Get offers](/assets/mt-transfer-nfts-4-get-offers.999a100bee4d565556696da37484cb13d6cbadde9a7b34d9fdeb58835d82f87e.ac57e6ef.png)](/assets/mt-transfer-nfts-4-get-offers.999a100bee4d565556696da37484cb13d6cbadde9a7b34d9fdeb58835d82f87e.ac57e6ef.png) ## Accept Sell Offer Once a sell offer is available, another account can opt to accept the offer and buy the NFT. To accept an available sell offer: 1. Click the Account 1 or Account 2 radio button. The account information populates the uneditable fields of the form. 2. Enter the **NFT Offer Index** (labeled as `nft_offer_index` in the token offer results. This is different from the `NFTokenID`.) 3. Click **Accept Sell Offer**. [![Accept Sell Offer](/assets/mt-transfer-nfts-5-accept-sell-offer.51deca64776c6656de95d8584ddc49ac212bf73fce8e4658899aadec1a74fc75.ac57e6ef.png)](/assets/mt-transfer-nfts-5-accept-sell-offer.51deca64776c6656de95d8584ddc49ac212bf73fce8e4658899aadec1a74fc75.ac57e6ef.png) ## Create a Buy Offer You can offer to buy an NFT from another account. To create an offer to buy an NFT: 1. Click the Account 1 or Account 2 radio button to change to an account other than the NFT owner. 2. Enter the **Amount** of your offer. 1. If paying XRP, enter the **Amount** of XRP in drops (1000000 equals 1 XRP). 2. If paying an issued currency, enter the **Currency**, **Issuer**, and **Amount**. 3. Optionally, enter the number of days until **Expiration**. 4. Enter the **NFT ID**. 5. Enter the owner’s account address in the **NFT Owner Address** field. 6. Click **Create Buy Offer**. [![NFT Buy Offer](/assets/mt-transfer-nfts-6-create-buy-offer.b9ae0e3101d0721b978565a2b8096c82cfdc652ac52b3270388a3bf20087ab67.ac57e6ef.png)](/assets/mt-transfer-nfts-6-create-buy-offer.b9ae0e3101d0721b978565a2b8096c82cfdc652ac52b3270388a3bf20087ab67.ac57e6ef.png) ## Accept a Buy Offer To accept an offer to buy an NFT: 1. Click the Account 1 or Account 2 radio button to change to the NFT owner account. 2. Use **Get Offers**, above, if needed, to find the `nft_offer_index`. 3. Enter the `nft_offer_index` in the **NFT Offer ID** field. 4. Click **Accept Buy Offer**. [![Accept Buy Offer](/assets/mt-transfer-nfts-7-accept-buy-offer.d142ce234adbbcebb380a93cea339bcb4a2e1e34c4323eff96671aef77a045a4.ac57e6ef.png)](/assets/mt-transfer-nfts-7-accept-buy-offer.d142ce234adbbcebb380a93cea339bcb4a2e1e34c4323eff96671aef77a045a4.ac57e6ef.png) ## Cancel Offer To cancel a buy or sell offer that you have created: 1. Click the Account 1 or Account 2 radio button. The account information populates the uneditable fields of the form. 2. Enter the **NFT Offer Index**. 3. Click **Cancel Offer**. [![Cancel offer](/assets/mt-transfer-nfts-8-cancel-offer.dd8ea562aba892640e909e1c070ee6eff91b324cc06987cda9d30c583f6f4086.ac57e6ef.png)](/assets/mt-transfer-nfts-8-cancel-offer.dd8ea562aba892640e909e1c070ee6eff91b324cc06987cda9d30c583f6f4086.ac57e6ef.png) # Code Walkthrough You can download the [NFT Modular Examples](/assets/nft-modular-tutorials.0f7eb22b2ca15eaf6397b7c614a7c020f1ab844da76fa9bf842e720bfc80f1fe.4057f33c.zip) archive to try each of the samples in your own browser. ## Create Sell Offer ```javascript // ******************************************************* // ****************** Create Sell Offer ****************** // ******************************************************* async function createSellOffer() { ``` Get the account wallet and connect to the XRP Ledger. ```javascript const wallet = xrpl.Wallet.fromSeed(accountSeedField.value); let results = '\nCreating sell offer...'; resultField.value = results; try { const client = new xrpl.Client(getNet()); await client.connect(); try { ``` If the destination field is populated, capture the value. ```javascript const destination = destinationField.value || undefined; ``` If the **Expiration** field is populated, configure the expiration date for the sell offer. ```javascript const expiration = expirationField.value ? configureExpiration() : undefined; ``` Begin constructing the transaction JSON object. ```javascript const transactionJson = { TransactionType: "NFTokenCreateOffer", Account: wallet.classicAddress, NFTokenID: nftIdField.value, Flags: 1, }; ``` Configure the amount. To give the NFT away, set the **Amount** to 0. `configureAmount()` determines whether the currency is XRP or an issued currency, and returns the properly formattted object to add to the JSON transaction object. ```javascript const amount = configureAmount(); if (amount) { // Only add Amount if it's defined transactionJson.Amount = amount; } else { console.warn("Amount is undefined. Sell offer might be invalid."); resultField.value = results; } ``` If you have an expiration date or specified destination, add them to the JSON transaction object. ```javascript if (expiration) { transactionJson.Expiration = expiration; } if (destination) { transactionJson.Destination = destination; } ``` Submit the transaction, wait for and report the results. ```javascript const tx = await client.submitAndWait(transactionJson, { wallet }); results += `\nSell offer created successfully!\nTransaction Hash: ${tx.result.hash}\nEngine Result: ${tx.result.engine_result}`; resultField.value = results; ``` Disconnect from the XRP Ledger. ```javascript } finally { client.disconnect(); } ``` Catch and report any errors. ```javascript } catch (error) { console.error("Error creating sell offer:", error); results = `\nError: ${error.message || error}`; resultField.value = results; } }// End of createSellOffer() ``` ## Create Buy Offer ```javascript // ******************************************************* // ***************** Create Buy Offer ******************** // ******************************************************* async function createBuyOffer() { ``` Get the account wallet and connect to the ledger. ```javascript const wallet = xrpl.Wallet.fromSeed(accountSeedField.value); let net = getNet(); const client = new xrpl.Client(net); await client.connect(); let results = '\n=== Connected. Creating buy offer. ==='; resultField.value = results; ``` Configure the amount and expiration date, if present. ```javascript try { // Use the external configureAmount() function let amount = configureAmount(); // Use the external configureExpiration() function let expiration = configureExpiration(); // This will return a number or an empty string from the original logic ``` Start constructing the transactionJson object. ```javascript let transactionJson = { "TransactionType": "NFTokenCreateOffer", "Account": wallet.classicAddress, "Owner": nftOwnerField.value, "NFTokenID": nftIdField.value, "Flags": 0, // Ensure no tfSellNFToken flag for a buy offer }; ``` Add the configured amount to the transaction. ```javascript if (amount !== undefined && amount !== '') { transactionJson.Amount = amount; } else { results += "\nError: Amount field is required for a buy offer."; resultField.value = results; client.disconnect(); return; } ``` Add the **Destination** value, if it is set. ```javascript if (destinationField.value !== '') { transactionJson.Destination = destinationField.value; } ``` Add the Expiration date if it's not an empty string. ```javascript if (expiration > 0) { transactionJson.Expiration = expiration; } ``` Submit the transaction and wait for the results. List the sell offers and buy offers currently available. ```javascript const tx = await client.submitAndWait(transactionJson, { wallet: wallet }); results += "\n\n=== Sell Offers ===\n"; let nftSellOffers; try { nftSellOffers = await client.request({ method: "nft_sell_offers", nft_id: nftIdField.value }); } catch (err) { nftSellOffers = "=== No sell offers. ==="; } results += JSON.stringify(nftSellOffers, null, 2); results += "\n\n=== Buy Offers ===\n"; let nftBuyOffers; try { nftBuyOffers = await client.request({ method: "nft_buy_offers", nft_id: nftIdField.value }); results += JSON.stringify(nftBuyOffers, null, 2); } catch (err) { results += "=== No buy offers. ==="; } ``` Report the results of the transaction. ```javascript // Check transaction results ------------------------------------------------- results += "\n\n=== Transaction result:\n" + JSON.stringify(tx.result.meta.TransactionResult, null, 2); results += "\n\n=== Balance changes:\n" + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2); resultField.value = results; ``` Catch and report any errors. ```javascript } catch (error) { console.error('Error creating buy offer:', error); results += "\n\n=== Error: " + error; resultField.value = results; ``` Disconnect from the XRP Ledger. ```javascript } finally { client.disconnect(); } }// End of createBuyOffer() ``` ## Cancel Offer ```javascript // ******************************************************* // ******************** Cancel Offer ********************* // ******************************************************* async function cancelOffer() { ``` Get the account wallet and connect to the ledger. ```javascript const wallet = xrpl.Wallet.fromSeed(accountSeedField.value) let net = getNet() const client = new xrpl.Client(net) await client.connect() let results = "\n=== Connected. Cancelling offer. ===" resultField.value = results ``` Store the token offer ID in the `NFTokenOffers` array parameter. ```javascript const tokenOfferIDs = [nftOfferIdField.value] ``` Construct the NFTokenCancelOffer JSON transaction. ```javascript const transactionJson = { "TransactionType": "NFTokenCancelOffer", "Account": wallet.classicAddress, "NFTokenOffers": tokenOfferIDs } ``` Submit the transaction and wait for the results. ```javascript const tx = await client.submitAndWait(transactionJson, { wallet }) ``` List the remaining sell offers and buy offers. ```javascript results = "\n\n=== Sell Offers===\n" let nftSellOffers try { nftSellOffers = await client.request({ method: "nft_sell_offers", nft_id: nftIdField.value }) } catch (err) { nftSellOffers = '=== No sell offers. ===\n' } results += JSON.stringify(nftSellOffers, null, 2) results += "\n\n=== Buy Offers ===\n" let nftBuyOffers try { nftBuyOffers = await client.request({ method: "nft_buy_offers", nft_id: nftIdField.value }) } catch (err) { nftBuyOffers = '=== No buy offers. ===' } results += JSON.stringify(nftBuyOffers, null, 2) resultField.value += results ``` Report the transaction results and XRP balance changes. ```javascript results = "\n=== Transaction result:\n" + JSON.stringify(tx.result.meta.TransactionResult, null, 2) results += "\n\n=== Balance changes:\n" + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2) resultField.value += results ``` Disconnect from the XRP Ledger. ```javascript client.disconnect() // End of cancelOffer() } ``` ## Get Offers ```javascript // ******************************************************* // ******************** Get Offers *********************** // ******************************************************* async function getOffers() { ``` Get the account wallet and connect to the ledger. ```javascript const wallet = xrpl.Wallet.fromSeed(accountSeedField.value) let net = getNet() const client = new xrpl.Client(net) await client.connect() let results = '\nConnected. Getting offers...' resultField.value = results // --- Sell Offers --- results += '\n\n=== Sell Offers ===\n' ``` Prepare and an `nft_sell_offers` request for the selected NFT ID. Catch any errors and report the results. ```javascript let nftSellOffers try { nftSellOffers = await client.request({ method: "nft_sell_offers", nft_id: nftIdField.value }) } catch (err) { nftSellOffers = 'No sell offers found for this NFT ID.' } results += JSON.stringify(nftSellOffers, null, 2) resultField.value = results ``` Prepare and an `nft_buy_offers` request for the selected NFT ID. Catch any errors and report the results. ```javascript // --- Buy Offers --- results = '\n\n=== Buy Offers ===\n' let nftBuyOffers try { nftBuyOffers = await client.request({ method: "nft_buy_offers", nft_id: nftIdField.value }) } catch (err) { // Log the actual error for debugging nftBuyOffers = 'No buy offers found for this NFT ID.' // More descriptive } results += JSON.stringify(nftBuyOffers, null, 2) // Append the JSON string resultField.value += results // Update the display with buy offers ``` Disconnect from the XRP Ledger. ```javascript client.disconnect() }// End of getOffers() ``` ## Accept Sell Offer ```javascript // ******************************************************* // ****************** Accept Sell Offer ****************** // ******************************************************* async function acceptSellOffer() { ``` Get the account wallet and connect to the ledger. ```javascript const wallet = xrpl.Wallet.fromSeed(accountSeedField.value) let net = getNet() const client = new xrpl.Client(net) try { await client.connect() let results = '\n=== Connected. Accepting sell offer. ===\n\n' resultField.value = results ``` Prepare the transaction JSON object. ```javascript const transactionJson = { "TransactionType": "NFTokenAcceptOffer", "Account": wallet.classicAddress, "NFTokenSellOffer": nftOfferIdField.value, } ``` Submit the transaction and wait for the results. ```javascript const tx = await client.submitAndWait(transactionJson, { wallet: wallet }) ``` Get the current NFTs held by the account after the transaction. ```javascript const nfts = await client.request({ method: "account_nfts", account: wallet.classicAddress }) ``` Get the new XRP balance after the transaction. ```javascript xrpBalanceField.value = (await client.getXrpBalance(wallet.address)) ``` Report the results. ```javascript results += '=== Transaction result:\n' results += JSON.stringify(tx.result.meta.TransactionResult, null, 2) results += '\n=== Balance changes:' results += JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2) results += JSON.stringify(nfts, null, 2) resultField.value += results ``` Catch and report any errors. ```javascript } catch (error) { console.error('Error accepting sell offer:', error) resultField.value = `Error: ${error.message || error}` ``` Disconnect from the XRP Ledger. ```javascript } finally { client.disconnect() } }// End of acceptSellOffer() ### Accept Buy Offer ```javascript // ******************************************************* // ******************* Accept Buy Offer ****************** // ******************************************************* async function acceptBuyOffer() { ``` Get the account wallet and connect to the XRP Ledger. ```javascript async function acceptBuyOffer() { const wallet = xrpl.Wallet.fromSeed(accountSeedField.value); let net = getNet(); const client = new xrpl.Client(net); let results = '\n=== Connected. Accepting buy offer. ==='; // Declare results locally try { await client.connect(); resultField.value = results; ``` Create the transactionJson object, passing the account address and the buy offer ID. ```javascript const transactionJson = { "TransactionType": "NFTokenAcceptOffer", "Account": wallet.classicAddress, "NFTokenBuyOffer": nftOfferIdField.value }; ``` Submit the transaction and wait for the results. ```javascript const tx = await client.submitAndWait(transactionJson, { wallet: wallet }); ``` Report the current list of account NFTs after the transaction. ```javascript const nfts = await client.request({ method: "account_nfts", account: wallet.classicAddress }); results += JSON.stringify(nfts, null, 2); resultField.value = results; ``` Report the result of the transaction and update the XRP Balance field. ```javascript results += "\n\nTransaction result:\n" + JSON.stringify(tx.result.meta.TransactionResult, null, 2); results += "\nBalance changes:\n" + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2); xrpBalanceField.value = (await client.getXrpBalance(wallet.address)); resultField.value = results; ``` Catch and report any errors. ```javascript } catch (error) { console.error('Error in acceptBuyOffer:', error); // Log the full error results = `\n=== Error accepting buy offer: ${error.message || 'Unknown error'} ===`; resultField.value = results; ``` Disconnect from the XRP Ledger. ```javascript } finally { if (client && client.isConnected()) { client.disconnect(); } } } // End of acceptBuyOffer() ``` ## 4.transfer-nfts.html ```html Transfer NFTs

Transfer NFTs

Choose your ledger instance:      






  

  

  


```