레슨3
신뢰 라인을 생성하고 화폐를 이체하기
XRPL 테스트넷의 두 계정 간에 신뢰 라인을 생성하고 화폐를 이체합니다.
이 강의에서는 다음 방법을 보여줍니다.
- 제3자 계좌로 자금을 이체할 수 있도록 계좌를 구성합니다.
- 거래에 대한 화폐 유형을 설정합니다.
- standby account과 operational account 간에 신뢰 라인을 만듭니다.
- 발행된 화폐를 계좌 간에 전송합니다.
- 모든 화폐에 대한 계좌 잔액을 표시합니다.
일부 코드를 편집해 보세요: create-trustline-send-currency.js
아래의 대화형 코드 예제는 모든 XRP Ledger 네트워크에서 사용할 수 있습니다. 현재 테스트넷과 개발넷이 있으며, NFT 토큰을 지원하는 실험적 NFT-개발넷 서버가 있습니다. 코드를 직접 빌드할 때, 다른 XRP Ledger 네트워크나 추가 XRP Ledger 네트워크를 선택할 수 있도록 코드를 업데이트할 수 있습니다. 새 창에서 “Edit on Codepen”을 클릭해 보는 것을 추천합니다.
토큰 테스트 코드를 열고 계정을 얻으세요
- 위의 샌드박스를 사용하여 계정 간에 화폐를 보낼 수 있습니다. 새 창에서 “Edit on Codepen”을 클릭해 보는 것을 추천합니다.
- 테스트 계정을 받기.
- 기존 계정 시드가 있는 경우
- “seed” ****필드에 계정 시드를 붙여 넣습니다.
- “Get Accounts from Seeds”를 ****클릭합니다.
- 계정 시드가 없는 경우:
- “Get New Standby Account”를 ****클릭합니다.
- “Get New Operational Account”를 클릭합니다.
- 기존 계정 시드가 있는 경우
신뢰 라인 생성
계정 간에 신뢰 한도를 생성하려면:
- “Currency” 필드에 화폐 코드를 입력합니다. (여기서는 USD를 사용했습니다).
- “Amount” ****필드에 최대 이체 한도(예: 9999)를 입력합니다.
- “Destination” 필드에 목적지 계정 값을 입력합니다.
- “Create TrustLine” 을 ****클릭합니다.
발행된 화폐 토큰 보내기
발행된 화폐 토큰을 전송하려면 신뢰 라인를 생성한 후 다음을 수행합니다.
- “Amount” 를 입력합니다 .
- “Destination” 을 ****입력합니다 .
- “Currency” 유형을 입력합니다 .
- “Send Currency” 를 ****클릭합니다.
JavaScript code walkthrough: create-trustline-send-currency.js
configureAccount()
법정 화폐를 이체할 때 실제 자금 이체는 XRP와 달리 동시에 이루어지지 않습니다. 화폐를 다른 화폐로 제3자에게 이체하는 경우, 원래 계좌에 영향을 미치는 화폐 가치 감소가 발생할 수 있습니다. 이러한 상황을 피하기 위해, 리플링이라고 불리는 화폐의 이러한 상승과 하락 평가는 기본적으로 허용되지 않습니다. 한 계좌에서 이체된 화폐는 같은 계좌로만 다시 이체할 수 있습니다. 제3자에게 화폐 이체를 활성화하려면 rippleDefault 값을 true로 설정해야 합니다. 토큰 테스트 코드는 리플링을 활성화하거나 비활성화하는 체크박스를 제공합니다.
asfDefaultRipple
플래그를 설정합니다. false인 경우 asfDefaultRipple
플래그를 지웁니다.// *******************************************************
// **************** 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()
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()
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>