Lesson 1
創建帳戶並發送瑞波幣XRP
在XRPL測試網上建立一個帳戶,並在兩個帳戶之間移轉瑞波幣XRP。

本課將展示如何:
- 測試網上創建帳戶,由測試網水龍頭資助930顆沒有實際價值的瑞波測試幣XRP。
- 從種子值中檢索帳戶。
- 在帳戶間轉移瑞波幣XRP。
當您建立帳戶時,在離線狀態中您將收到一組配對的公鑰/私鑰。 這組公私鑰不會上鏈,必須要等到帳戶中出現XRP測試幣,才會寫入區塊鏈帳本。本課程展示如何在測試網建立帳戶,但不會展示如何建立可以在主網上使用的帳戶。
嘗試編輯一些程式:get-accounts-send-xrp.js
下面的互動式程式範例可以用在任何一個XRPL網路:測試網、開發網或主網。 自己構建程式時,您可以更新程式以選擇不同的XRPL網路或額外的網路。
Open the Token Test Harness and get test accounts:
- 開啟程式沙盒。
- 選擇測試網。
- 點選獲取新的待機帳戶。
- 單擊獲取新運營帳戶。
- 將種子欄位複製並貼上到持久的位置,例如記事本,以便您可以在重新載入表單後重複使用帳戶。
您可以在新帳戶之間轉移XRP,每個帳戶都有自己的欄位和按鈕。
在帳戶之間轉移 XRP:
- 輸入要傳送的XRP金額。
- 輸入目的地帳戶(例如,將操作帳戶欄位複製並貼上到備用目的地欄位中)。
- 點擊「傳送XRP」>將XRP從備用帳戶轉移到操作帳戶,或<傳送XRP將XRP從操作帳戶轉移到備用帳戶。
JavaScript程式練習:get-accounts-send-xrp.js
此範例可用於任何XRPL網路:測試網、開發網、主網,您可以修改程式,以配合你所選擇的任何一個XRPL網路。
getNet() 函數使用強制判斷的方式(if 陳述式)來檢查單選按鈕的值,設定所選的網路實例,並返回 URI。
getAccount() 函式首先透過 getNet() 取得所選的分類帳。
接著建立一個用戶端實例。
接著建立一個用戶端實例。
然後使用 results 變數來捕捉進度資訊。
將結果變數回報至結果的 HTML 欄位。
連接到伺服器。
建立並資助一個測試帳戶錢包。
取得該帳戶目前的 XRP 餘額,如果這是備用帳戶,則填入備用帳戶欄位。
否則,請填寫營運帳戶欄位。
將兩個帳戶的種子值在建立時一併填入「Seeds」欄位以方便使用。您可以將這些值複製並離線儲存。當您重新載入此表單或本教學中的其他表單時,只需將這些值複製並貼上到「Seeds」欄位,即可透過 getAccountsFromSeeds() 函式取回帳戶。
定義表單欄位
在整個程式中,我們使用JavaScript函式 document.getElementById(),它用於透過CSS ID來定位HTML元素。 我們使用這些函式在代幣測試框架中的表單欄位中設定和獲取數值。 為了保持程式的易讀性,我們定義了一些固定數值來取代函式呼叫。
// *** Define HTML Form Fields **
const xls = document.getElementById("xls")
const tn = document.getElementById("tn")
const dn = document.getElementById("dn")
const standbyResultField = document.getElementById('standbyResultField');
const operationalResultsField = document.getElementById('operationalResultField');
const standbyAccountField = document.getElementById('standbyAccountField');
const standbyPubKeyField = document.getElementById('standbyPubKeyField');
const standbyPrivKeyField = document.getElementById('standbyPrivKeyField');
const standbyBalanceField = document.getElementById('standbyBalanceField');
const standbySeedField = document.getElementById('standbySeedField');
const operationalAccountField = document.getElementById('operationalAccountField');
const operationalPubKeyField = document.getElementById('operationalPubKeyField');
const operationalPrivKeyField = document.getElementById('operationalPrivKeyField');
const operationalSeedField = document.getElementById('operationalSeedField');
const operationalBalanceField = document.getElementById('operationalBalanceField');
getNet()和getAccount(類別)
// ************* Get the Preferred Network **************
function getNet() {
let net
if (tn.checked) net = "wss://s.altnet.rippletest.net:51233"
if (dn.checked) net = "wss://s.devnet.rippletest.net:51233"
return net
} // End of getNet()
// *******************************************************
// ************* Get Account *****************************
// *******************************************************
async function getAccount(type) {
let net = getNet()
const client = new xrpl.Client(net)
results = 'Connecting to ' + net + '....'
// This uses the default faucet for Testnet/Devnet
let faucetHost = null
if(document.getElementById("xls").checked) {
faucetHost = "faucet-nft.ripple.com"
}
if (type == 'standby') {
standbyResultField.value = results
} else {
operationalResultField.value = results
}
await client.connect()
results += 'nConnected, funding wallet.'
if (type == 'standby') {
standbyResultField.value = results
} else {
operationalResultField.value = results
}
// -----------------------------------Create and fund a test account wallet
const my_wallet = (await client.fundWallet(null, { faucetHost })).wallet
results += 'nGot a wallet.'
if (type == 'standby') {
standbyResultField.value = results
} else {
operationalResultField.value = results
}
// -----------------------------------Get the current balance.
const my_balance = (await client.getXrpBalance(my_wallet.address))
if (type == 'standby') {
standbyAccountField.value = my_wallet.address
standbyPubKeyField.value = my_wallet.publicKey
standbyPrivKeyField.value = my_wallet.privateKey
standbyBalanceField.value =
(await client.getXrpBalance(my_wallet.address))
standbySeedField.value = my_wallet.seed
results += 'nStandby account created.'
standbyResultField.value = results
} else {
operationalAccountField.value = my_wallet.address
operationalPubKeyField.value = my_wallet.publicKey
operationalPrivKeyField.value = my_wallet.privateKey
operationalSeedField.value = my_wallet.seed
operationalBalanceField.value =
(await client.getXrpBalance(my_wallet.address))
results += 'nOperational account created.'
operationalResultField.value = results
}
// --------------- Capture the seeds for both accounts for ease of reload.
seeds.value = standbySeedField.value + 'n' + operationalSeedField.value
client.disconnect()
} // End of getAccount()
從種子中獲取帳戶()
連接到所選的網路。
解析 Seeds 欄位。
根據第一行的種子取得 standby_wallet,並根據第二行的種子取得 operational_wallet。
取得帳戶目前的 XRP 餘額。
請填寫待命帳戶的各個欄位。
請填寫營運帳戶的各項欄位。
與 XRP 分帳帳本斷開連線。
// *******************************************************
// ********** Get Accounts from Seeds ********************
// *******************************************************
async function getAccountsFromSeeds() {
let net = getNet()
const client = new xrpl.Client(net)
results = 'Connecting to ' + getNet() + '....'
standbyResultField.value = results
await client.connect()
results += 'nConnected, finding wallets.n'
standbyResultField.value = results
// -----------------------------------Find the test account wallets
var lines = seeds.value.split('n');
const standby_wallet = xrpl.Wallet.fromSeed(lines[0])
const operational_wallet = xrpl.Wallet.fromSeed(lines[1])
// -----------------------------------Get the current balance.
const standby_balance = (await client.getXrpBalance(standby_wallet.address))
const operational_balance = (await client.getXrpBalance(operational_wallet.address))
// ------------------Populate the fields for Standby and Operational accounts
standbyAccountField.value = standby_wallet.address
standbyPubKeyField.value = standby_wallet.publicKey
standbyPrivKeyField.value = standby_wallet.privateKey
standbySeedField.value = standby_wallet.seed
standbyBalanceField.value = (await client.getXrpBalance(standby_wallet.address))
operationalAccountField.value = operational_wallet.address
operationalPubKeyField.value = operational_wallet.publicKey
operationalPrivKeyField.value = operational_wallet.privateKey
operationalSeedField.value = operational_wallet.seed
operationalBalanceField.value = (await client.getXrpBalance(operational_wallet.address))
client.disconnect()
} // End of getAccountsFromSeeds()
傳送XRP()
連接到您選擇的帳本。
開始準備交易。這是一筆從備用錢包到操作錢包的付款交易。
付款交易預期以「滴」(drops)為單位表示XRP,也就是XRP的百萬分之一。
你可以使用 xrpToDrops 工具來幫你轉換發送的數量(這比起發送 1 XRP 時還要多打 6 個零方便多了)。
簽署已準備好的交易。
提交交易並等待結果。
請求該交易所引起的餘額變動並報告結果。
斷開與 XRP 帳本的連接。
// // *******************************************************
// ******************** Send XRP *************************
// *******************************************************
async function sendXRP() {
results = "Connecting to the selected ledger.n"
standbyResultField.value = results
let net = getNet()
results = 'Connecting to ' + getNet() + '....'
const client = new xrpl.Client(net)
await client.connect()
results += "nConnected. Sending XRP.n"
standbyResultField.value = results
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
const sendAmount = standbyAmountField.value
results += "nstandby_wallet.address: = " + standby_wallet.address
standbyResultField.value = results
// ------------------------------------------------------- Prepare transaction
// Note that the destination is hard coded.
const prepared = await client.autofill({
"TransactionType": "Payment",
"Account": standby_wallet.address,
"Amount": xrpl.xrpToDrops(sendAmount),
"Destination": standbyDestinationField.value
})
// ------------------------------------------------ Sign prepared instructions
const signed = standby_wallet.sign(prepared)
// -------------------------------------------------------- Submit signed blob
const tx = await client.submitAndWait(signed.tx_blob)
results += "nBalance changes: " +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
standbyResultField.value = results
standbyBalanceField.value =
(await client.getXrpBalance(standby_wallet.address))
operationalBalanceField.value =
(await client.getXrpBalance(operational_wallet.address))
client.disconnect()
} // End of sendXRP()
互惠交易:oPsendXRP()
對於每筆交易,都有一個附帶的互惠交易,帶有字首P,用於作業帳戶。 請參考備用帳戶的對應功能中有程式碼註解。
// *******************************************
// ****** Reciprocal Transactions ************
// *******************************************
// *****Send XRP from Operational account ****
// *******************************************
async function oPsendXRP() {
results = "Connecting to the selected ledger.n"
operationalResultField.value = results
let net = getNet()
results = 'Connecting to ' + getNet() + '....'
const client = new xrpl.Client(net)
await client.connect()
results += "nConnected. Sending XRP.n"
operationalResultField.value = results
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const sendAmount = operationalAmountField.value
results += "noperational_wallet.address: = " + operational_wallet.address
operationalResultField.value = results
// ------------------------------------------------------- Prepare transaction
// Note that the destination is hard coded.
const prepared = await client.autofill({
"TransactionType": "Payment",
"Account": operational_wallet.address,
"Amount": xrpl.xrpToDrops(operationalAmountField.value),
"Destination": operationalDestinationField.value
})
// ------------------------------------------------ Sign prepared instructions
const signed = operational_wallet.sign(prepared)
// -------------------------------------------------------- Submit signed blob
const tx = await client.submitAndWait(signed.tx_blob)
results += "nBalance changes: " +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
operationalResultField.value = results
standbyBalanceField.value =
(await client.getXrpBalance(standby_wallet.address))
operationalBalanceField.value =
(await client.getXrpBalance(operational_wallet.address))
client.disconnect()
} // End of oPsendXRP()
網頁表單預覽:1.get-accounts-send-xrp.html
建立一個標準的網頁表單來傳送交易和請求,然後顯示結果。
<html>
<head>
<title>Token Test Harness</title>
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
<script src='https://unpkg.com/xrpl@2.2.3'></script>
<script>
if (typeof module !== "undefined") {
const xrpl = require('xrpl')
}
</script>
<style>
body{font-family: "Work Sans", sans-serif;padding: 20px;background: #fafafa;font-size:.8em;}
h1{font-weight: bold;}
input, button {padding: 6px;margin-bottom: 8px;font-size:.8em;}
button{font-weight: bold;font-family: "Work Sans", sans-serif;}
td{vertical-align: top;padding-right:10px;}
</style>
</head>
<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">... You can use this later once you generate seeds</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>
<td>
<p align="right">
<button type="button" onClick="sendXRP()">Send XRP ↓</button>
</p>
</td>
</tr>
</table>
</td>
<td>
<textarea id="standbyResultField" cols="60" rows="20" ></textarea>
</td>
</tr>
</table>
<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>
<td>
<p align="right">
<button type="button" onClick="oPsendXRP()">Send XRP ↑</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>
</html>