arrow-left 강좌 허브
레슨2: 계정 생성 및 XRP 보내기
예상 독서 시간

25분

난이도

중급

주요 요점

XRP 원장에서 계정을 생성하고 XRP를 보내는 방법을 알아보세요. XRPL.js 라이브러리로 코딩을 시작하려면 강의의 코드 샌드박스를 사용하세요.

레슨2

계정 생성 및 XRP 보내기

XRPL 테스트넷에 계정을 만들고 두 계정 간에 XRP를 전송하세요.

이 수업에서는 다음 방법을 보여줍니다.

  1. 실제 가치가 없는 930 XRP를 지원받은 계정을 테스트넷에 만듭니다.
  2. 시드 값에서 계정을 검색합니다.
  3. 계정 간에 XRP를 전송합니다.

계정을 생성하면 공개/ 개인키 쌍을 오프라인으로 받게 됩니다. 이는 XRP를 지원받을 때까지는 원장에 나타나지 않습니다. 이 수업에서는 테스트넷용 계정을 만드는 방법을 보여주지만, 메인넷에서 사용할 수 있는 계정을 만드는 방법은 보여주지 않습니다.

코드를 편집해 보세요: get-accounts-send-xrp.js

아래의 대화형 코드 예제는 모든 XRP Ledger 네트워크(테스트넷 , 개발넷 또는 메인넷) 와 함께 사용할 수 있습니다. 코드를 직접 빌드할 때, 다른 XRP Ledger 네트워크나 추가 XRP Ledger 네트워크를 선택할 수 있도록 코드를 업데이트할 수 있습니다.

토큰 테스트 코드를 열고 테스트 계정을 받으세요.

  1. CodeSandbox를 엽니다.
  2. 테스트넷을 ****선택합니다.
  3. “Create Standy Account” 를 ****클릭합니다 .
  4. “Create Operational Account” 를 클릭합니다.
  5. 메모장과 같은 영구적인 위치에 시드 ****필드를 복사하여 붙여 넣으면 폼을 다시 로드한 후 계정을 다시 사용할 수 있습니다.

새 계정 간에 XRP를 전송할 수 있습니다. 각 계정에는 고유한 필드와 버튼이 있습니다.

계정 간에 XRP를 전송하기:

  1. 보낼 XRP 금액을 입력합니다 .
  2. 대상 ****계정을 입력합니다 (예: Operational Account 필드를 Standby Destination Account 에 붙여넣기).
  3. Standby Account 에서 Operational Account 로 XRP를 이체하기 위해 “Send XRP→” 를 클릭합니다. 혹은, Operational Account 에서 Standby Account 로 XRP를 이체하기 위해 “←Send XRP” 를 클릭합니다.

 

JavaScript 코드 연습: get-accounts-send-xrp.js

이 예는 모든 XRP Ledger 네트워크(테스트넷 , 개발넷 또는 메인넷) 에서 사용할 수 있습니다 . 다른 XRP Ledger 네트워크나 추가 XRP Ledger 네트워크를 선택할 수 있도록 코드를 업데이트할 수 있습니다.

getNet() 함수는 무작위 if 문을 사용하여 라디오 버튼 값 확인하여 선택된 네트워크 인스턴스를 설정하고 URI를 반환합니다.

getAccount() 함수는 getNet()으로 선택한 장부를 가져오는 것으로 시작됩니다.

클라이언트를 생성합니다.
그 후 results 변수를 사용하여 진행 상황 정보를 기록하세요.
결과 변수를 HTML 필드에 보고합니다.
서버에 연결하세요.
테스트 계정 지갑을 생성하고 자금을 확보하세요.
계정의 현재 XRP 잔액을 확인하고 대기 계정인 경우 대기 계정 필드에 입력하세요.
그렇지 않으면 운영 계정 필드를 채우세요.
두 계정이 생성될 때 두 계정의 시드 값을 시드 필드에 삽입합니다. 이 값을 복사하여 오프라인으로 저장할 수 있습니다. 이 튜토리얼, 혹은 다른 양식을 다시 로드할 때 해당 양식을 복사하여 Seeds 필드에 붙여넣고 getAccountsFromSeeds() 함수로 계정을 조회하세요.

폼 필드 정의

코드 전체에서 JavaScript 함수 document.getElementById() 를 사용하는데, 이는 CSS ID로 HTML 요소를 타겟팅하는 데 사용됩니다. 이러한 함수를 사용하여 토큰 테스트 코드의 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(type)


// ************* 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()

 

getAccountsFromSeeds()

선택한 네트워크에 연결합니다.
Seeds 필드를 구문 분석합니다.
첫 번째 줄의 시드를 기반으로 standby_wallet을 가져오고, 두 번째 줄의 시드를 기반으로 operational_wallet을 가져옵니다.
계정의 현재 XRP 잔액을 가져옵니다.
대기 계정의 필드를 채웁니다.
운영 계정의 필드를 채웁니다.
XRP LEDGER와 연결을 끊습니다.
// *******************************************************
// ********** 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()

sendXRP()

선택한 원장에 연결합니다.
거래 준비를 시작합니다. 이는 standby wallet에서 operational wallet로의 지급 거래입니다.
결제 트랜잭션은 XRP가 드롭 단위로 표현되기를 기대합니다. 즉, XRP의 1/백만입니다.
xrpToDrops 유틸리티를 사용하여 전송 금액을 변환할 수 있습니다(1 XRP를 보내기 위해 추가로 6개의 0을 입력하는 것보다 편리합니다).
준비된 트랜잭션에 서명합니다.
트랜잭션을 제출하고 결과를 기다립니다.
트랜잭션으로 인해 발생한 잔액 변화를 요청하고 결과를 보고합니다.
XRP LEDGER와 연결을 끊습니다.
// // *******************************************************
// ******************** 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()

각 거래에는 operational account 에 대한 접두사 oP 가 붙은 동반 상호 거래가 있습니다. 코드 설명은 standby account에 대한 해당 기능을 참조하세요.

// *******************************************
// ****** 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()

HTML 폼 미리보기: 1.get-accounts-send-xrp.html

거래 및 요청을 보내고 결과를 표시하기 위한 표준 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>
수업 종료

지금까지 배운 내용을 테스트할 시간입니다!

1. XRPL에서 클라이언트를 올바르게 인스턴스화하는 코드는 무엇인가요?
2. 테스트넷에서 계정을 올바르게 생성하고 입금하는 코드는 무엇인가요?
3. 계좌 잔액을 확인하는 코드는 무엇인가요?