Lesson 1
鑄造和銷燬NFTs
在XRPL鏈上鑄造和銷燬NFT。

本課將展示如何操作:
- 鑄造全新非同質性代幣(NFT)。
- 產生帳戶上現有NFTs藏品列表。
- 刪除(燃燒)一顆NFT。
程式實作:mint-and-burn-nfts.js
下面的互動式程式範例可以用於任何一種XRPL網路使用:測試網、開發網或主網。 在自行開發時,可以根據選擇的XRPL網路更新程式。
獲取帳戶
- 開啟上面的程式沙盒。 我們建議您在新視窗中點擊「在Codepen上編輯」(右上角的連結
- 獲取測試帳戶。
- 如果您已有NFT-Devnet帳戶種子:
- 將帳戶種子貼上到種子欄位中。
- 點擊「從種子中獲取帳戶」。
- 如果您沒有NFT-Devnet帳戶:
- 點按「獲取新的備用帳戶」。
- 點按「獲取新營運帳戶」
- 如果您已有NFT-Devnet帳戶種子:
鑄造一顆NFT代幣
鑄造一顆非同質性代幣物件:
- .設定「標誌」欄位。 基於測試目的,建議將數值設定為8。 設定tsTransferableflag,代表NFToken物件可以轉移到另一個帳戶。 否則,NFToken物件預設只能轉回NFT發行帳戶。 有關鑄造NFTokens的所有可用標誌的資訊,請參閱NFToken Mint。
- 輸入代幣網址。 這是一個URI,指向與NFToken物件關聯的資料或元數據。 如果您沒有自己的URI,您可以使用範例提供的URI。
- 輸入轉讓費,即未來銷售NFToken收益的百分比,該收益將歸還給原始NFTs建立者。 這是包含0-50000的區間值,允許0.000%到50.000%之間的轉移率,以0.001%為增量。 如果您沒有在「標誌」欄位設定允許NFToken的可轉讓性,需將此欄位設定為0。
- 點擊鑄造代幣。
獲取代幣
單擊「獲取代幣」以獲取帳戶內的NFToken藏品列表。
銷燬一顆代幣
NFToken的目前持有者可以銷燬(或燒燬)NFToken物件。
永久銷燬NFToken:
- 輸入代幣編號Token ID。
- 點擊燒毀代幣 Burn Token。
JavaScript程式演練:ripplex3-mint-nfts.js
mintToken()
連接到帳本並獲取帳戶錢包。
定義交易。
使用 convertStringToHex 工具將十六進位 URI 轉換成字串。
如果您希望 NFToken 可以轉讓給第三方,請將 Flags 欄位設為 8。
轉讓費用是一個介於0到50000之間的數值,用於設定版稅,範圍從0.000%到50.000%,以0.001為增量。
這句英文翻成繁體中文是:
TokenTaxon 是必填欄位。它是由發行者自行定義的任意值。如果您沒有使用此欄位的需求,可以將其設為 0。
發送交易並等待回應。
請求該帳戶所擁有的 NFT 清單。
報告結果。
從分類帳中斷連線。
// *******************************************************
// ********************** Mint Token *********************
// *******************************************************
async function mintToken() {
results = 'Connecting to ' + getNet() + '....'
standbyResultField.value = results
let net = getNet()
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const client = new xrpl.Client(net)
await client.connect()
results += 'nConnected. Minting NFToken.'
standbyResultField.value = results
// Note that you must convert the token URL to a hexadecimal
// value for this transaction.
// ------------------------------------------------------------------------
const transactionBlob = {
"TransactionType": "NFTokenMint",
"Account": standby_wallet.classicAddress,
"URI": xrpl.convertStringToHex(standbyTokenUrlField.value),
"Flags": parseInt(standbyFlagsField.value),
"TransferFee": parseInt(standbyTransferFeeField.value),
"NFTokenTaxon": 0 //Required, but if you have no use for it, set to zero.
}
// ----------------------------------------------------- Submit signed blob
const tx = await client.submitAndWait(transactionBlob, { wallet: standby_wallet} )
const nfts = await client.request({
method: "account_nfts",
account: standby_wallet.classicAddress
})
// ------------------------------------------------------- Report results
results += 'nnTransaction result: '+ tx.result.meta.TransactionResult
results += 'nnnfts: ' + JSON.stringify(nfts, null, 2)
standbyBalanceField.value =
(await client.getXrpBalance(standby_wallet.address))
standbyResultField.value = results
client.disconnect()
} //End of mintToken()
getTokens()
連接分類帳並取得帳戶錢包。
請求帳戶所擁有的 NFT 清單。
報告結果。
從分類帳中斷連線。
// *******************************************************
// ******************* Get Tokens ************************
// *******************************************************
async function getTokens() {
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
let net = getNet()
const client = new xrpl.Client(net)
results = 'Connecting to ' + net + '...'
standbyResultField.value = results
await client.connect()
results += 'nConnected. Getting NFTokens...'
standbyResultField.value = results
const nfts = await client.request({
method: "account_nfts",
account: standby_wallet.classicAddress
})
results += 'nNFTs:n ' + JSON.stringify(nfts,null,2)
standbyResultField.value = results
client.disconnect()
} //End of getTokens()
burnToken()
連接到分類帳並取得帳戶錢包。
定義該交易。
提交交易並等待結果。
請求一份客戶所擁有的 NFTokens 清單。
報告結果。
從分類帳斷開連接。
// *******************************************************
// ********************* Burn Token **********************
// *******************************************************
async function burnToken() {
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
let net = getNet()
const client = new xrpl.Client(net)
results = 'Connecting to ' + net + '...'
standbyResultField.value = results
await client.connect()
results += 'nConnected. Burning NFToken...'
standbyResultField.value = results
// ------------------------------------------------------- Prepare transaction
const transactionBlob = {
"TransactionType": "NFTokenBurn",
"Account": standby_wallet.classicAddress,
"NFTokenID": standbyTokenIdField.value
}
//---------------------------------- Submit transaction and wait for the results
const tx = await client.submitAndWait(transactionBlob,{wallet: standby_wallet})
const nfts = await client.request({
method: "account_nfts",
account: standby_wallet.classicAddress
})
results += 'nTransaction result: '+ tx.result.meta.TransactionResult
results += 'nBalance changes: ' +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
standbyResultField.value = results
standbyBalanceField.value =
(await client.getXrpBalance(standby_wallet.address))
results += 'nNFTs: n' + JSON.stringify(nfts,null,2)
standbyResultField.value = results
client.disconnect()
}// End of burnToken()
設定帳戶間交易費 oPmintToken(), oPgetTokens() and oPburnToken()
// **********************************************************************
// ****** Reciprocal Transactions ***************************************
// **********************************************************************
// *******************************************************
// ************** Operational Mint Token *****************
// *******************************************************
async function oPmintToken() {
results = 'Connecting to ' + getNet() + '....'
operationalResultField.value = results
let net = getNet()
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
const client = new xrpl.Client(net)
await client.connect()
results += 'nConnected. Minting NFToken.'
operationalResultField.value = results
// Note that you must convert the token URL to a hexadecimal
// value for this transaction.
// ------------------------------------------------------------------------
const transactionBlob = {
"TransactionType": 'NFTokenMint',
"Account": operational_wallet.classicAddress,
"URI": xrpl.convertStringToHex(operationalTokenUrlField.value),
"Flags": parseInt(operationalFlagsField.value),
"TransferFee": parseInt(operationalTransferFeeField.value),
"NFTokenTaxon": 0 //Required, but if you have no use for it, set to zero.
}
// ----------------------------------------------------- Submit signed blob
const tx = await client.submitAndWait(transactionBlob, { wallet: operational_wallet} )
const nfts = await client.request({
method: "account_nfts",
account: operational_wallet.classicAddress
})
// ------------------------------------------------------- Report results
results += 'nnTransaction result: '+ tx.result.meta.TransactionResult
results += 'nnnfts: ' + JSON.stringify(nfts, null, 2)
operationalBalanceField.value =
(await client.getXrpBalance(operational_wallet.address))
operationalResultField.value = results
client.disconnect()
} //End of oPmintToken
// *******************************************************
// ************** Operational Get Tokens *****************
// *******************************************************
async function oPgetTokens() {
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
let net = getNet()
const client = new xrpl.Client(net)
results = 'Connecting to ' + getNet() + '...'
operationalResultField.value = results
await client.connect()
results += 'nConnected. Getting NFTokens...'
operationalResultField.value = results
const nfts = await client.request({
method: "account_nfts",
account: operational_wallet.classicAddress
})
results += 'nNFTs:n ' + JSON.stringify(nfts,null,2)
operationalResultField.value = results
client.disconnect()
} //End of oPgetTokens
// *******************************************************
// ************* Operational Burn Token ******************
// *******************************************************
async function oPburnToken() {
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
let net = getNet()
const client = new xrpl.Client(net)
results = 'Connecting to ' + getNet() + '...'
operationalResultField.value = results
await client.connect()
results += 'nConnected. Burning NFToken...'
operationalResultField.value = results
// ------------------------------------------------------- Prepare transaction
const transactionBlob = {
"TransactionType": "NFTokenBurn",
"Account": operational_wallet.classicAddress,
"NFTokenID": operationalTokenIdField.value
}
//-------------------------------------------------------- Submit signed blob
const tx = await client.submitAndWait(transactionBlob,{wallet: operational_wallet})
const nfts = await client.request({
method: "account_nfts",
account: operational_wallet.classicAddress
})
results += 'nTransaction result: '+ tx.result.meta.TransactionResult
results += 'nBalance changes: ' +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
operationalResultField.value = results
operationalBalanceField.value =
(await client.getXrpBalance(operational_wallet.address))
operationalBalanceField.value =
(await client.getXrpBalance(operational_wallet.address))
results += 'nNFTs: n' + JSON.stringify(nfts,null,2)
operationalResultField.value = results
client.disconnect()
}
// End of oPburnToken()
網頁表單預覽: 3.mint-nfts.html
下方粗體字代表支援新功能的表單改變。
<html>
<head>
<title>Token Test Harness</title>
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
<style>
body{font-family: "Work Sans", sans-serif;padding: 20px;background: #fafafa;}
h1{font-weight: bold;}
input, button {padding: 6px;margin-bottom: 8px;}
button{font-weight: bold;font-family: "Work Sans", sans-serif;}
td{vertical-align: top;padding-right:10px;}
</style>
<script src='https://unpkg.com/xrpl@2.2.3'></script>
<script>
if (typeof module !== "undefined") {
const xrpl = require('xrpl')
}
</script>
</head>
<!-- ************************************************************** -->
<!-- ********************** The Form ****************************** -->
<!-- ************************************************************** -->
<body>
<h1>Token Test Harness</h1>
<form id="theForm">
Choose your ledger instance:
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233" >
<label for="testnet">Testnet</label>
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
<label for="devnet">Devnet</label>
<br/><br/>
<button type="button" onClick="getAccountsFromSeeds()">Get Accounts From Seeds</button>
<br/>
<textarea id="seeds" cols="40" rows= "2"></textarea>
<br/><br/>
<table>
<tr valign="top">
<td>
<button type="button" onClick="getAccount('standby')">Get New Standby Account</button>
<table>
<tr valign="top">
<td align="left">
Standby Account<br/> <input type="text" id="standbyAccountField" size="30" />
</td>
<td></td>
</tr>
<tr>
<td align="left">
Public Key<br/>
<input type="text" id="standbyPubKeyField" size="30"></input> </td>
<td align="left">
Private Key<br/>
<input type="text" id="standbyPrivKeyField" size="30"></input>
</td>
</tr>
<tr>
<td align="left">
Seed <br/>
<input type="text" id="standbySeedField" size="30"></input>
<br>
</td>
<td align="left">
XRP Balance <br/>
<input type="text" id="standbyBalanceField" size="30"></input>
</td>
</tr>
<tr>
<td align="left">
Amount<br/>
<input type="text" id="standbyAmountField" size="30"></input>
</td>
<td align="left">
Destination Account <br/>
<input type="text" id="standbyDestinationField" size="30"></input>
</td>
</tr>
<tr valign="top">
<td><button type="button" onClick="configureAccount('standby',document.querySelector('#standbyDefault').checked)">Configure Account</button><br/>
<input type="checkbox" id="standbyDefault" checked="true"/>
<label for="standbyDefault">Allow Rippling</label>
</td>
<td>
Currency<br/>
<input type="text" id="standbyCurrencyField" size="30" value="USD"></input>
</td>
</tr>
<tr>
<td colspan=2>NFToken URL<br/>
<input type="text" id="standbyTokenUrlField"
value = "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" size="70"/>
</td>
</tr>
<tr>
<td colspan=2>Flags<br/>
<input type="text" id="standbyFlagsField" value="1" size="10"/></td>
</tr>
<tr>
<td colspan=2>NFToken ID<br/>
<input type="text" id="standbyTokenIdField" value="" size="70"/></td>
</tr>
<tr>
<td colspan=2>Transfer Fee<br/>
<input type="text" id="standbyTransferFeeField" value="" size="70"/></td>
</tr>
<tr>
<td colspan=2>
<p align="right">
<button type="button" onClick="sendXRP()">Send XRP ↓</button>
<button type="button" onClick="createTrustline()">Create TrustLine</button>
<button type="button" onClick="sendCurrency()">Send Currency</button>
<button type="button" onClick="getBalances()">Get Balances</button>
<br/>
<button type="button" onClick="mintToken()">Mint NFToken</button>
<button type="button" onClick="getTokens()">Get NFTokens</button>
<button type="button" onClick="burnToken()">Burn NFToken</button>
</p>
</td>
</tr>
</table>
</td>
<td valign="top">
<textarea id="standbyResultField" cols="60" rows="20" ></textarea>
</td>
</tr>
</table>
<br/><br/>
<table>
<tr valign="top">
<td>
<button type="button" onClick="getAccount('operational')">Get New Operational Account</button>
<table>
<tr valign="top">
<td align="left">
Operational Account<br/> <input type="text" id="operationalAccountField" size="30" />
</td>
<td></td>
</tr>
<tr>
<td align="left">Public Key<br/>
<input type="text" id="operationalPubKeyField" size="30" /> </td>
<td align="left">
Private Key<br/>
<input type="text" id="operationalPrivKeyField" size="30"></input>
</td>
</tr>
<tr>
<td align="left">
Seed <br/>
<input type="text" id="operationalSeedField" size="30"></input>
<br>
</td>
<td align="left">
XRP Balance <br/>
<input type="text" id="operationalBalanceField" size="30" />
</td>
</tr>
<tr>
<td align="left">
Amount<br/>
<input type="text" id="operationalAmountField" size="30" />
</td>
<td align="left">
Destination Account <br/>
<input type="text" id="operationalDestinationField" size="30" />
</td>
</tr>
<tr valign="top">
<td><button type="button" onClick="configureAccount('operational',document.querySelector('#operationalDefault').checked)">Configure Account</button><br/>
<input type="checkbox" id="operatoinalDefault" checked="true"/>
<label for="operationalDefault">Allow Rippling</label>
</td>
<td>
Currency<br/>
<input type="text" id="operationalCurrencyField" size="30" value="USD"></input>
</td>
</tr>
<tr>
<td colspan=2>NFToken URL<br/>
<input type="text" id="operationalTokenUrlField"
value = "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" size="70"/>
</td>
</tr>
<tr>
<td colspan=2>Flags<br/>
<input type="text" id="operationalFlagsField" value="1" size="10"/></td>
</tr>
<tr>
<td colspan=2>NFToken ID<br/>
<input type="text" id="operationalTokenIdField" value="" size="70"/></td>
</tr>
<tr>
<td colspan=2>Transfer Fee<br/>
<input type="text" id="operationalTransferFeeField" value="" size="70"/></td>
</tr>
<tr>
<td colspan=2>
<p align="right">
<button type="button" onClick="oPsendXRP()">Send XRP ↑</button>
<button type="button" onClick="oPcreateTrustline()">Create TrustLine</button>
<button type="button" onClick="oPsendCurrency()">Send Currency</button>
<button type="button" onClick="getBalances()">Get Balances</button>
<br/>
<button type="button" onClick="oPmintToken()">Mint NFToken</button>
<button type="button" onClick="oPgetTokens()">Get NFTokens</button>
<button type="button" onClick="oPburnToken()">Burn NFToken</button>
</p>
</td>
</tr>
</table>
</td>
<td>
<textarea id="operationalResultField" cols="60" rows="20" ></textarea>
</td>
</tr>
</table>
</form>
</body>
<script src='ripplex1-send-xrp.js' async></script>
<script src='ripplex2-send-currency.js' async></script>
<script src='ripplex3-mint-nfts.js' async></script>
</html>