arrow-left 강좌 허브
레슨3: 신뢰 라인을 생성하고 화폐를 이체하기
예상 독서 시간

25분

난이도

중급

주요 요점

XRP 원장에서 신뢰 라인을 생성하고 통화를 보내는 방법을 알아보세요. XRPL.js 라이브러리 코드를 실험하려면 강의의 코드 샌드박스를 사용하세요.

레슨3

신뢰 라인을 생성하고 화폐를 이체하기

XRPL 테스트넷의 두 계정 간에 신뢰 라인을 생성하고 화폐를 이체합니다.

이 강의에서는 다음 방법을 보여줍니다.

  1. 제3자 계좌로 자금을 이체할 수 있도록 계좌를 구성합니다.
  2. 거래에 대한 화폐 유형을 설정합니다.
  3. standby account과 operational account 간에 신뢰 라인을 만듭니다.
  4. 발행된 화폐를 계좌 간에 전송합니다.
  5. 모든 화폐에 대한 계좌 잔액을 표시합니다.

일부 코드를 편집해 보세요: create-trustline-send-currency.js

아래의 대화형 코드 예제는 모든 XRP Ledger 네트워크에서 사용할 수 있습니다. 현재 테스트넷과 개발넷이 있으며, NFT 토큰을 지원하는 실험적 NFT-개발넷 서버가 있습니다. 코드를 직접 빌드할 때, 다른 XRP Ledger 네트워크나 추가 XRP Ledger 네트워크를 선택할 수 있도록 코드를 업데이트할 수 있습니다. 새 창에서 “Edit on Codepen”을 클릭해 보는 것을 추천합니다.

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

  1. 위의 샌드박스를 사용하여 계정 간에 화폐를 보낼 수 있습니다. 새 창에서 “Edit on Codepen”을 클릭해 보는 것을 추천합니다.
  2. 테스트 계정을 받기.
    1. 기존 계정 시드가 있는 경우
      1. “seed” ****필드에 계정 시드를 붙여 넣습니다.
      2. “Get Accounts from Seeds”를 ****클릭합니다.
    2. 계정 시드가 없는 경우:
      1. “Get New Standby Account”를 ****클릭합니다.
      2. “Get New Operational Account”를 클릭합니다.

신뢰 라인 생성

계정 간에 신뢰 한도를 생성하려면:

  1. “Currency” 필드에 화폐 코드를 입력합니다. (여기서는 USD를 사용했습니다).
  2. “Amount” ****필드에 최대 이체 한도(예: 9999)를 입력합니다.
  3. “Destination” 필드에 목적지 계정 값을 입력합니다.
  4. “Create TrustLine” 을 ****클릭합니다.

발행된 화폐 토큰 보내기

발행된 화폐 토큰을 전송하려면 신뢰 라인를 생성한 후 다음을 수행합니다.

  1. “Amount” 를 입력합니다 .
  2. “Destination” 을 ****입력합니다 .
  3. “Currency” 유형을 입력합니다 .
  4. “Send Currency” 를 ****클릭합니다.

JavaScript code walkthrough: create-trustline-send-currency.js

configureAccount()

법정 화폐를 이체할 때 실제 자금 이체는 XRP와 달리 동시에 이루어지지 않습니다. 화폐를 다른 화폐로 제3자에게 이체하는 경우, 원래 계좌에 영향을 미치는 화폐 가치 감소가 발생할 수 있습니다. 이러한 상황을 피하기 위해, 리플링이라고 불리는 화폐의 이러한 상승과 하락 평가는 기본적으로 허용되지 않습니다. 한 계좌에서 이체된 화폐는 같은 계좌로만 다시 이체할 수 있습니다. 제3자에게 화폐 이체를 활성화하려면 rippleDefault 값을 true로 설정해야 합니다. 토큰 테스트 코드는 리플링을 활성화하거나 비활성화하는 체크박스를 제공합니다.

XRPL에 연결합니다.
상태로 결과 필드를 업데이트합니다.
계정 지갑을 가져옵니다.
rippleDefault 인수가 true인 경우 asfDefaultRipple 플래그를 설정합니다. false인 경우 asfDefaultRipple 플래그를 지웁니다.
트랜잭션을 위한 기본 값을 자동으로 채웁니다.
트랜잭션에 서명합니다.
트랜잭션을 제출하고 결과를 기다립니다.
결과를 결과 필드에 보고합니다.
XRPL과 연결을 끊습니다.
// *******************************************************
// **************** Configure Account ********************
// *******************************************************
      
      async function configureAccount(type, rippleDefault) {
        let net = getNet()
        const client = new xrpl.Client(net)
        results = 'Connecting to ' + getNet() + '....'
        standbyResultField.value = results
        await client.connect()
        results += 'nConnected, finding wallet.'
        standbyResultField.value = results
 
        if (type=='standby') {
          my_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
        } else {
          my_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
        }
        results += 'Ripple Default Setting: ' + rippleDefault
        standbyResultField.value = results
        
        let settings_tx = {}
        if (rippleDefault) {
          settings_tx = {
          "TransactionType": "AccountSet",
          "Account": my_wallet.address,
          "SetFlag": xrpl.AccountSetAsfFlags.asfDefaultRipple
          } 
          results += 'n Set Default Ripple flag.' 
        } else {
          settings_tx = {
          "TransactionType": "AccountSet",
          "Account": my_wallet.address,
          "ClearFlag": xrpl.AccountSetAsfFlags.asfDefaultRipple
          }
          results += 'n Clear Default Ripple flag.' 
        }
          results += 'nSending account setting.'
          standbyResultField.value = results
      
          const cst_prepared = await client.autofill(settings_tx)

          const cst_signed = my_wallet.sign(cst_prepared)
          const cst_result = await client.submitAndWait(cst_signed.tx_blob)
          if (cst_result.result.meta.TransactionResult == "tesSUCCESS") {
          results += 'nAccount setting succeeded.'
          standbyResultField.value = results
          } else {
          throw 'Error sending transaction: ${cst_result}'
          results += 'nAccount setting failed.'
          standbyResultField.value = results
          }
      
        client.disconnect()
      } // End of configureAccount()
      
대기 및 운영 지갑을 가져옵니다.
대기 통화 필드에서 통화 코드를 캡처합니다.
트랜잭션을 정의하고, 양식 필드에서 통화 코드와 (제한) 금액을 캡처합니다.
기본 매개변수를 자동으로 채워 트랜잭션을 준비합니다.
트랜잭션에 서명합니다.
트랜잭션을 제출하고 결과를 기다립니다.
결과를 보고합니다.

createTrustline()

신뢰 라인은 두 계좌가 정해진 한도까지 정의된 화폐를 거래할 수 있도록 합니다. 이를 통해 참가자는 모든 거래가 합의된 최대 금액으로 알려진 개체 간에 이루어진다는 확신을 가질 수 있습니다.

// *******************************************************
// ***************** Create TrustLine ********************
// *******************************************************
      
      async function createTrustline() {
        let net = getNet()
        const client = new xrpl.Client(net)
        results = 'Connecting to ' + getNet() + '....'
        standbyResultField.value = results
        
        await client.connect()
        
        results += 'nConnected.'
        standbyResultField.value = results
          
        const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
        const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
        const currency_code = standbyCurrencyField.value

        const trustSet_tx = {
          "TransactionType": "TrustSet",
          "Account": standbyDestinationField.value,
          "LimitAmount": {
            "currency": standbyCurrencyField.value,
            "issuer": standby_wallet.address,
            "value": standbyAmountField.value
          }
        }
        const ts_prepared = await client.autofill(trustSet_tx)

        const ts_signed = operational_wallet.sign(ts_prepared)
        results += 'nCreating trust line from operational account to standby account...'
        standbyResultField.value = results
        const ts_result = await client.submitAndWait(ts_signed.tx_blob)
        if (ts_result.result.meta.TransactionResult == "tesSUCCESS") {
          results += 'nTrustline established between account n' + standbyDestinationField.value + ' n and accountn' + standby_wallet.address + '.'
          standbyResultField.value = results
        } else {
          results += 'nTrustLine failed. See JavaScript console for details.'
          standbyResultField.value = results     
          throw 'Error sending transaction: ${ts_result.result.meta.TransactionResult}'
        }
      } //End of createTrustline()
      
XRPL에 연결합니다.
계정 지갑, 통화 코드 및 금액을 가져옵니다.
트랜잭션 정보를 상수에 저장합니다.
기본 값을 자동으로 채워 트랜잭션을 준비합니다.
트랜잭션에 서명합니다.
트랜잭션을 제출하고 결과를 기다립니다.
결과를 보고합니다.
XRPL과 연결을 끊습니다.

sendCurrency() 로 발행된 화폐를 보냅니다.

한 계정에서 자신의 계정으로 신뢰 라인을 생성하면, 설정된 한도까지 발행된 화폐 토큰을 해당 계정으로 보낼 수 있습니다.

// *******************************************************
// *************** Send Issued Currency ******************
// *******************************************************
      
      async function sendCurrency() {
        let net = getNet()
        const client = new xrpl.Client(net)
        results = 'Connecting to ' + getNet() + '....'
        standbyResultField.value = results
        
        await client.connect()
        
        results += 'nConnected.'
        standbyResultField.value = results
          
        const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
        const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
        const currency_code = standbyCurrencyField.value
        const issue_quantity = standbyAmountField.value
        
        const send_token_tx = {
          "TransactionType": "Payment",
          "Account": standby_wallet.address,
          "Amount": {
            "currency": standbyCurrencyField.value,
            "value": standbyAmountField.value,
            "issuer": standby_wallet.address
          },
          "Destination": standbyDestinationField.value
        }
      
        const pay_prepared = await client.autofill(send_token_tx)

        const pay_signed = standby_wallet.sign(pay_prepared)
        results += 'Sending ' + standbyAmountField.value + standbyCurrencyField.value + 'to ' + standbyDestinationField.value + '...'
        standbyResultField.value = results
        const pay_result = await client.submitAndWait(pay_signed.tx_blob)
        if (pay_result.result.meta.TransactionResult == "tesSUCCESS") {
          results += 'Transaction succeeded: https://testnet.xrpl.org/transactions/${pay_signed.hash}'
          standbyResultField.value = results
        } else {
          results += 'Transaction failed: See JavaScript console for details.'
          standbyResultField.value = results
          throw 'Error sending transaction: ${pay_result.result.meta.TransactionResult}'
        }
        standbyBalanceField.value = 
              (await client.getXrpBalance(standby_wallet.address))
        operationalBalanceField.value = 
              (await client.getXrpBalance(operational_wallet.address))
        getBalances()
        client.disconnect()
      
      } // end of sendIOU()
      
XRPL에 연결합니다.
계정 지갑을 가져옵니다.
대기 계정에 대한 요청을 정의하고 전송한 후 결과를 기다립니다.
결과를 보고합니다.
운영 계정에 대한 요청을 정의하고 전송한 후 결과를 기다립니다.
결과를 보고합니다.
현재 XRP 잔액으로 양식을 업데이트합니다.
XRPL과 연결을 끊습니다.

getBalances()

// *******************************************************
// ****************** Get Balances ***********************
// *******************************************************

      async function getBalances() {
        let net = getNet()
        const client = new xrpl.Client(net)
        results = 'Connecting to ' + getNet() + '....'
        standbyResultField.value = results
        
        await client.connect()
        
        results += 'nConnected.'
        standbyResultField.value = results
       
        const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
        const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
      
        results= "nGetting standby account balances...n"
        const standby_balances = await client.request({
          command: "gateway_balances",
          account: standby_wallet.address,
          ledger_index: "validated",
          hotwallet: [operational_wallet.address]
        })
        results += JSON.stringify(standby_balances.result, null, 2)
        standbyResultField.value = results
      
        results= "nGetting operational account balances...n"
        const operational_balances = await client.request({
          command: "account_lines",
          account: operational_wallet.address,
          ledger_index: "validated"
        })
        results += JSON.stringify(operational_balances.result, null, 2)
        operationalResultField.value = results
      
        operationalBalanceField.value = 
          (await client.getXrpBalance(operational_wallet.address))
        standbyBalanceField.value = 
          (await client.getXrpBalance(standby_wallet.address))
          
        client.disconnect()
       
      } // End of getBalances()

상호 트랜잭션 oPcreateTrustline() 및 oPsendCurrency()

각 거래에는 operational account 에 대한 접두사 oP 와 함께 동반되는 상호 거래가 있습니다. 코드 설명은 standby account 에 해당하는 기능을 참조하세요. “getBalances()”요청에는 두 계정의 잔액이 보고되므로 상호 거래가 없습니다.

// **********************************************************************
// ****** Reciprocal Transactions ***************************************
// **********************************************************************
      
// *******************************************************
// ************ Create Operational TrustLine *************
// *******************************************************
      
      async function oPcreateTrustline() {
        let net = getNet()
        const client = new xrpl.Client(net)
        results = 'Connecting to ' + getNet() + '....'
        operationalResultField.value = results
        
        await client.connect()
        
        results += 'nConnected.'
        operationalResultField.value = results
          
        const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
        const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
        const trustSet_tx = {
          "TransactionType": "TrustSet",
          "Account": operationalDestinationField.value,
          "LimitAmount": {
            "currency": operationalCurrencyField.value,
            "issuer": operational_wallet.address,
            "value": operationalAmountField.value
          }
        }
        const ts_prepared = await client.autofill(trustSet_tx)
        const ts_signed = standby_wallet.sign(ts_prepared)
        results += 'nCreating trust line from operational account to ' + operationalDestinationField.value + ' account...'
        operationalResultField.value = results
        const ts_result = await client.submitAndWait(ts_signed.tx_blob)
        if (ts_result.result.meta.TransactionResult == "tesSUCCESS") {
          results += 'nTrustline established between account n' + standby_wallet.address + ' n and accountn' + operationalDestinationField.value + '.'
          operationalResultField.value = results
        } else {
          results += 'nTrustLine failed. See JavaScript console for details.'
          operationalResultField.value = results     
          throw 'Error sending transaction: ${ts_result.result.meta.TransactionResult}'
        }
      } //End of oPcreateTrustline
      
// *******************************************************
// ************* Operational Send Issued Currency ********
// *******************************************************
      
      async function oPsendCurrency() {
        let net = getNet()
        const client = new xrpl.Client(net)
        results = 'Connecting to ' + getNet() + '....'
        operationalResultField.value = results
        
        await client.connect()
        
        results += 'nConnected.'
        operationalResultField.value = results
          
        const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
        const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
        const currency_code = operationalCurrencyField.value
        const issue_quantity = operationalAmountField.value
        
        const send_token_tx = {
          "TransactionType": "Payment",
          "Account": operational_wallet.address,
          "Amount": {
            "currency": currency_code,
            "value": issue_quantity,
            "issuer": operational_wallet.address
          },
          "Destination": operationalDestinationField.value
        }
      
        const pay_prepared = await client.autofill(send_token_tx)
        const pay_signed = operational_wallet.sign(pay_prepared)
        results += 'Sending' + operationalAmountField.value + operationalCurrencyField.value + ' to ' + operationalDestinationField.value + '...'
        operationalResultField.value = results
        const pay_result = await client.submitAndWait(pay_signed.tx_blob)
        if (pay_result.result.meta.TransactionResult == "tesSUCCESS") {
          results += 'Transaction succeeded: https://testnet.xrpl.org/transactions/${pay_signed.hash}'
          operationalResultField.value = results
        } else {
          results += 'Transaction failed: See JavaScript console for details.'
          operationalResultField.value = results
          throw 'Error sending transaction: ${pay_result.result.meta.TransactionResult}'
        }
        standbyBalanceField.value = 
              (await client.getXrpBalance(standby_wallet.address))
        operationalBalanceField.value = 
              (await client.getXrpBalance(operational_wallet.address))
        getBalances()
        client.disconnect()

      } // end of oPsendCurrency()

HTML 폼 미리보기: 2.create-trustline-send-currency.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>
                  <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>
                  </p>
                </td>
              </tr>
            </table>
          </td>
          <td>
            <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>
                  <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>
                  </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>
</html>
수업 종료

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

1. 토큰과 화폐를 이용한 거래에 신뢰 라인이 필요한 이유는 무엇인가요?
2. 다음 중 신뢰 라인 사용 방식을 가장 잘 요약한 문장은 무엇인가요?
3. 어떤 코드가 거래를 신뢰 라인으로 정의하나요?