Estimated reading time:

25分鐘

Difficulty:

Intermediate

Key takeaway:

瞭解如何在XRPL鏈上建立帳戶和傳送瑞波幣XRP,使用課程中的程式沙盒開始使用XRPL.js庫進行編碼。

Lesson 1

創建帳戶並發送瑞波幣XRP

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

本課將展示如何:

  1. 測試網上創建帳戶,由測試網水龍頭資助930顆沒有實際價值的瑞波測試幣XRP。
  2. 從種子值中檢索帳戶。
  3. 在帳戶間轉移瑞波幣XRP。

當您建立帳戶時,在離線狀態中您將收到一組配對的公鑰/私鑰。 這組公私鑰不會上鏈,必須要等到帳戶中出現XRP測試幣,才會寫入區塊鏈帳本。本課程展示如何在測試網建立帳戶,但不會展示如何建立可以在主網上使用的帳戶。

嘗試編輯一些程式:get-accounts-send-xrp.js

下面的互動式程式範例可以用在任何一個XRPL網路:測試網、開發網或主網。 自己構建程式時,您可以更新程式以選擇不同的XRPL網路或額外的網路。

Open the Token Test Harness and get test accounts:

  1. 開啟程式沙盒。
  2. 選擇測試網
  3. 點選獲取新的待機帳戶
  4. 單擊獲取新運營帳戶
  5. 種子欄位複製並貼上到持久的位置,例如記事本,以便您可以在重新載入表單後重複使用帳戶。

您可以在新帳戶之間轉移XRP,每個帳戶都有自己的欄位和按鈕。

在帳戶之間轉移 XRP:

  1. 輸入要傳送的XRP金額。
  2. 輸入目的地帳戶(例如,將操作帳戶欄位複製並貼上到備用目的地欄位中)。
  3. 點擊「傳送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>
END OF LESSON

現在您已經瞭解了一些關於在 XRP 分類帳上創建帳戶和發送 XRP 的知識,請通過測驗來測試您的理解。

Welcome to your Create accounts and send XRP (CH)

哪行代碼正確實例化 XRPL 上的用戶端?