[JA] Move files to a dir compatible with Redocly

The new folder will be compatible with both Dactyl and Redocly when it
comes to loading the Japanese translation for a given page.

Snippets are not moved for now because importing them would require
more complex changes to the actual Markdown pages, and wouldn't be
cross-compatible anyway (Redocly uses slightly different 'partial'
rather than 'include' syntax.)
This commit is contained in:
mDuo13
2023-10-09 11:33:55 -07:00
parent 6a7eebe758
commit 26b3939747
301 changed files with 302 additions and 302 deletions

View File

@@ -0,0 +1,237 @@
---
html: get-started-using-http-websocket-apis.html
parent: http-websocket-apis-tutorials.html
blurb: XRP Ledgerの操作に使用できるAPIとライブラリを使い始めましょう。
cta_text: 開始しよう
labels:
- 開発
top_nav_name: HTTP / WebSocket
top_nav_grouping: 始めましょう
showcase_icon: assets/img/logos/globe.svg
---
# HTTP / WebSocket APIの使用開始
XRP Ledgerのコアサーバーソフトウェアは[`rippled`](xrpl-servers.html)です。XRP Ledgerでの開発に進むには、`rippled`サーバーのAPIにアクセスします。
APIにアクセスする最も簡単な方法は、[**WebSocket API Tool**](websocket-api-tool.html)を使用するか、[XRP Ledger Explorer](https://livenet.xrpl.org/)を使用してレジャーの進行状況をその場で確認することです。
[`rippled`の独自のインスタンスを実行](install-rippled.html)したり、[公開サーバー](#公開サーバー)を使用したりすることもできます。
## 公開サーバー
Rippleは、XRP Ledgerコミュニティ向けにいくつかの公開サーバーを提供しています。
| 演算子 | [ネットワーク][] | JSON-RPC URL | WebSocket URL | 注記 |
|:----------|:----------|:----------|:----------|:----------|
| Ripple | **Mainnet** | `https://s1.ripple.com:51234/` | `wss://s1.ripple.com/` | 汎用サーバークラスター |
| Ripple | **Mainnet** | `https://s2.ripple.com:51234/` | `wss://s2.ripple.com/` | [すべての履歴が記録されるサーバー](ledger-history.html#すべての履歴)クラスター |
| Ripple | Testnet | `https://s.altnet.rippletest.net:51234/` | `wss://s.altnet.rippletest.net/` | Testnet公開サーバー |
| Ripple | Devnet | `https://s.devnet.rippletest.net:51234/` | `wss://s.devnet.rippletest.net/` | Devnet公開サーバー |
[ネットワーク]: parallel-networks.html
これらの公開サーバーは継続的な使用やビジネスでの使用を想定したものではなく、いつでも使用不可となる可能性があります。日常的な使用については、独自の`rippled`サーバーを自社で運用するか、信頼できる事業者と運用委託契約を締結します。
## 管理者アクセス権限
`rippled`サーバーの[管理メソッド](admin-api-methods.html)を使用するには、次のように行います。この場合、サーバーのバインド用として設定したIPアドレスとポートを使用する必要があります例えば`127.0.0.1:54321`。また、管理機能にアクセスするには、構成ファイルで管理用としてマークされているポートおよびIPアドレスから接続しなければなりません。
[構成ファイルの例](https://github.com/XRPLF/rippled/blob/8429dd67e60ba360da591bfa905b58a35638fda1/cfg/rippled-example.cfg#L1050-L1073)では、ローカルループバックネットワーク上127.0.0.1のポート5005でJSON-RPCHTTP、ポート6006でWebSocketWSの接続をリッスンし、接続されるすべてのクライアントを管理者として扱っています。
## WebSocket API
いくつかのメソッドをXRP Ledgerで試すことを予定している場合は、独自のWebSocketコードを記述することなく、[Ripple WebSocket APIツール](websocket-api-tool.html)でAPIをすぐに使用できます。後ほど、独自の`rippled`サーバーへの接続が必要となった時点で、[ブラウザー](monitor-incoming-payments-with-websocket.html)または[Node.jsで独自のクライアントをビルド](https://www.npmjs.com/package/ws)することが可能です。
### 要求フォーマット
`rippled`サーバーへのWebSocketを開いた後、以下の属性を使用して、コマンドを[JSON](https://en.wikipedia.org/wiki/JSON)オブジェクトとして送信できます。
* コマンド名を最上位の`"command"`フィールドに記述します。
* コマンドのすべての関連パラメーターも最上位に記述します。
* 任意の値を指定して`"id"`フィールドを記述します(省略可)。この要求への応答では、同一の`"id"`フィールドを使用します。そうすることで、応答が順不同で到達した場合も、どの要求によってどの応答を得られたのかがわかります。
応答はJSONオブジェクトとして返されます。
## JSON-RPC
任意のHTTPクライアント[RESTED for Firefox](https://addons.mozilla.org/en-US/firefox/addon/rested/)、[Postman for Chrome](https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en)、[Online HTTP client ExtendsClass](https://extendsclass.com/rest-client-online.html)などを使用して、JSON-RPCで`rippled`サーバーを呼び出すことができます。ほとんどのプログラミング言語には、HTTP要求を組み込むためのライブラリーが用意されています。
### 要求フォーマット
JSON-RPC要求を作成するには、`rippled`サーバーがJSON-RPC接続をリッスンしているポートおよびIPアドレス上で、HTTP **POST**要求をルートパス(`/`に送信します。HTTP/1.0またはHTTP/1.1を使用できます。HTTPSを使用する場合は、TLS v1.2を使用してください。セキュリティーの維持を理由として、`rippled`はSSL v3以前を _サポートしていません_
値を`application/json`として、`Content-Type`ヘッダーを常に記述してください。
複数の要求を作成することを予定している場合は、要求ごとに接続を閉じて再び開くことなく済むよう、[キープアライブ](http://tools.ietf.org/html/rfc7230#section-6.3)を使用します。
以下の属性を指定して、要求の本文を[JSON](https://en.wikipedia.org/wiki/JSON)オブジェクトとして送信します。
* コマンドを最上位の`"method"`フィールドに記述します。
* 最上位の`"params"`フィールドを記述します。このフィールドの内容は、コマンドのすべてのパラメーターが指定された1つの入れ子JSONオブジェクトのみを保持している**1要素配列**です。
応答もJSONオブジェクトになります。
## コマンドライン
このコマンドラインインターフェイスは、JSON-RPCのものと同一のサービスに接続するため、公開サーバーおよびサーバー構成は同一です。コマンドラインクライアントとして、`rippled`がローカルインスタンスに接続します。例:
```
rippled --conf=/etc/rippled.cfg server_info
```
**注記:** コマンドラインインターフェイスは、管理の目的でのみ使用されることを想定しています。 _サポートされるAPIではありません_
### 要求フォーマット
コマンドラインでは、通常の(先頭にダッシュが付いた)コマンドラインオプションに続けてコマンドを記述した後、一連の限定的なパラメーターを空白文字で区切って記述します。空白文字などの特殊な文字が含まれている可能性があるパラメーター値は、一重引用符で囲みます。
## 要求の例
<!-- MULTICODE_BLOCK_START -->
*WebSocket*
```
{
"id": 2,
"command": "account_info",
"account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"strict": true,
"ledger_index": "validated"
}
```
*JSON-RPC*
```
POST http://s1.ripple.com:51234/
{
"method": "account_info",
"params": [
{
"account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"strict": true,
"ledger_index": "validated"
}
]
}
```
*コマンドライン*
```
rippled account_info r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59 validated true
```
<!-- MULTICODE_BLOCK_END -->
## 応答フォーマット
### 成功した場合の応答の例
<!-- MULTICODE_BLOCK_START -->
*WebSocket*
```
{
"id": 2,
"status": "success",
"type": "response",
"result": {
"account_data": {
"Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"Balance": "27389517749",
"Flags": 0,
"LedgerEntryType": "AccountRoot",
"OwnerCount": 18,
"PreviousTxnID": "B6B410172C0B65575D89E464AF5B99937CC568822929ABF87DA75CBD11911932",
"PreviousTxnLgrSeq": 6592159,
"Sequence": 1400,
"index": "4F83A2CF7E70F77F79A307E6A472BFC2585B806A70833CCD1C26105BAE0D6E05"
},
"ledger_index": 6760970
}
}
```
*JSON-RPC*
```
HTTP Status:200 OK
{
"result": {
"account_data": {
"Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"Balance": "27389517749",
"Flags": 0,
"LedgerEntryType": "AccountRoot",
"OwnerCount": 18,
"PreviousTxnID": "B6B410172C0B65575D89E464AF5B99937CC568822929ABF87DA75CBD11911932",
"PreviousTxnLgrSeq": 6592159,
"Sequence": 1400,
"index": "4F83A2CF7E70F77F79A307E6A472BFC2585B806A70833CCD1C26105BAE0D6E05"
},
"ledger_index": 6761012,
"status": "success"
}
}
```
*コマンドライン*
```
{
"result": {
"account_data": {
"Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"Balance": "27389517749",
"Flags": 0,
"LedgerEntryType": "AccountRoot",
"OwnerCount": 18,
"PreviousTxnID": "B6B410172C0B65575D89E464AF5B99937CC568822929ABF87DA75CBD11911932",
"PreviousTxnLgrSeq": 6592159,
"Sequence": 1400,
"index": "4F83A2CF7E70F77F79A307E6A472BFC2585B806A70833CCD1C26105BAE0D6E05"
},
"ledger_index": 6761012,
"status": "success"
}
}
```
<!-- MULTICODE_BLOCK_END -->
成功した場合の応答に含まれているフィールドは、以下のとおりです。
| `Field` | 型 | 説明 |
|:----------|:----------|:----------|
| `id` | (場合により異なる) | WebSocketのみこの応答の要求元となった要求で提供されているID。 |
| `status` | 文字列 | WebSocketのみ値が`success`である場合、要求がサーバーによって正常に受信され、理解されたことを示します。 |
| `result.status` | 文字列 | JSON-RPCおよびコマンドライン値が`success`である場合、要求がサーバーによって正常に受信され、理解されたことを示します。 |
| `type` | 文字列 | WebSocketのみ値が`response`である場合、コマンドに対する正常な応答であることを示します。[非同期の通知](subscribe.html)では、`ledgerClosed``transaction`など異なる値が使用されます。 |
| `result` | オブジェクト | クエリーの結果。内容はコマンドによって異なります。 |
### コマンドライン
コマンドラインのメソッドはJSON-RPCと同一のインターフェイスを使用しているため、応答フォーマットはJSON-RPCの応答と同一です。
## 関連項目
- **コンセプト:**
- [XRP Ledgerの概要](xrp-ledger-overview.html)
- [ソフトウェアエコシステム](software-ecosystem.html)
- [並列ネットワーク](parallel-networks.html)
- **チュートリアル:**
- [xrpl.js for JavaScriptの使用開始](get-started-using-javascript.html)
- [信頼できるトランザクションの送信](reliable-transaction-submission.html)
- [rippledサーバーの管理](manage-the-rippled-server.html)
- **リファレンス:**
- [rippled APIリファレンス](http-websocket-apis.html)
- [Ripple Data API v2](data-api.html)

View File

@@ -0,0 +1,172 @@
---
html: get-started-using-javascript.html
parent: javascript.html
blurb: XRP Ledgerを参照するためのエントリーレベルのJavaScriptアプリケーションを構築します。
top_nav_name: JavaScript
top_nav_grouping: 始めましょう
labels:
- 開発
showcase_icon: assets/img/logos/javascript.svg
---
# JavaScriptを使ってみよう
このチュートリアルでは、JavaScriptまたはTypeScript向けのクライアントライブラリである [`xrpl.js`](https://github.com/XRPLF/xrpl.js/) を使用して、Node.jsまたはウェブブラウザでXRP Ledgerに接続されたアプリケーションを構築するための基本的な手順を説明します。
本ガイドで使用しているスクリプトや設定ファイルは、[本サイトのGitHubリポジトリ]({{target.github_forkurl}}/tree/{{target.github_branch}}/content/_code-samples/get-started/js/)で公開されています。
## 学習目標
このチュートリアルでは、以下のことを学びます。
* XRP Ledgerベースのアプリケーションの基本構成要素。
* xrpl.jsを使ったXRP Ledgerへの接続方法。
* xrpl.jsを使った[テストネット](xrp-testnet-faucet.html)でのウォレット生成方法。
* `xrpl.js`ライブラリを使った、XRP Ledgerアカウント情報の検索方法。
* How to put these steps together to create a simple JavaScript app or web-app.
## 前提条件
このチュートリアルを実行するには、JavaScriptでコードを書き、小さなJavaScriptプロジェクトを管理することにある程度慣れている必要があります。ブラウザでは、JavaScriptをサポートする最新のWebブラウザであれば問題なく使用できます。Node.jsでは、**バージョン14**を推奨します。Node.jsのバージョン12と16も定期的にテストされています。
## npmを使用したインストール
空のフォルダを作成して新しいプロジェクトを開始し、そのフォルダに移動して[NPM](https://www.npmjs.com/)で最新版のxrpl.jsをインストールします。
```sh
npm install xrpl
```
## 作り始めましょう
XRP Ledgerを使用する際には、XRPを[ウォレット](wallets.html)に追加したり、[分散型取引所](decentralized-exchange.html)と統合したり、[トークンを発行](issued-currencies.html)したりと、管理しなければならないことがいくつかあります。このチュートリアルでは、これらすべてのユースケースを始めるための共通の基本パターンを説明し、それらを実装するためのサンプルコードを提供します。
多くのXRP Ledgerプロジェクトで使用している手順をご紹介します。
1. [ライブラリのインポート](#1-ライブラリのインポート)
1. [XRP Ledgerへの接続](#2-xrp-ledgerへの接続)
1. [ウォレットの作成](#3-ウォレットの作成)
1. [XRP Ledgerの参照](#4-xrp-ledgerの参照)
1. [イベントのListen](#5-イベントのlisten)
### 1. ライブラリのインポート
プロジェクトに `xrpl.js` をどのように読み込むかは、開発環境によって異なります。
#### ブラウザ
以下のような`<script>`タグをHTMLに追加してください。
```html
<script src="https://unpkg.com/xrpl@2.0.0/build/xrpl-latest-min.js"></script>
```
上記の例のようにCDNからライブラリをロードすることも、リリースをダウンロードして自分のウェブサイトでホストすることもできます。
これは、モジュールを `xrpl` としてトップレベルにロードします。
#### Node.js
[npm](https://www.npmjs.com/)を使って、ライブラリを追加します。これにより、`package.json`ファイルが更新されます。まだ存在していなければ新しいファイルが作成されます。
```sh
npm install xrpl
```
その後、ライブラリをインポートします。
```js
const xrpl = require("xrpl")
```
### 2. XRP Ledgerへの接続
参照や取引を行うには、XRP Ledgerへの接続を確立する必要があります。`xrpl.js`でこれを行うには、`Client`クラスのインスタンスを作成し、`connect()`メソッドを使用します。
**Tip:** `xrpl.js` の多くのネットワーク関数は、[Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)を使って非同期に値を返します。ここで紹介するコードサンプルでは、[`async/await` パターン](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await)を使用して、Promises の実際の結果を待ちます。
{{ include_code("_code-samples/get-started/js/base.js", language="js") }}
#### XRP Ledger メインネットへの接続
前節のサンプルコードでは、利用可能な[並列ネットワーク](parallel-networks.html)の1つであるTestnetに接続する方法を紹介しました。本番環境に移行するには、XRP Ledger Mainnetに接続する必要があります。それには2つの方法があります。
* [コアサーバをインストール](install-rippled.html) (`rippled`)して、自分でードを動かしてみましょう。コアサーバーはデフォルトではMainnetに接続しますが、設定を変更してTestnetやDevnetを使うこともできます](connect-your-rippled-to-thexrp-test-net.html)。[独自のコアサーバーを運用するのには良い理由があります](networks-and-servers.html#reasons-to-run-your-own-server)。独自のサーバーを走らせた場合、次のようにして接続することができます。
const MY_SERVER = "ws://localhost:6006/"
const client = new xrpl.Client(MY_SERVER)
await client.connect()
デフォルト値の詳細については、[コアサーバー設定ファイル](https://github.com/XRPLF/rippled/blob/c0a0b79d2d483b318ce1d82e526bd53df83a4a2c/cfg/rippled-example.cfg#L1562)の例を参照してください。
* 利用可能な[公開サーバー][]を利用する:
const PUBLIC_SERVER = "wss://xrplcluster.com/"
const client = new xrpl.Client(PUBLIC_SERVER)
await client.connect()
### 3. ウォレットの作成
`xrpl.js` ライブラリには、XRP Ledgerアカウントのキーとアドレスを扱うための "Wallet "クラスが用意されています。Testnetでは、次のようにして新しいウォレットに資金を供給することができます。
{{ include_code("_code-samples/get-started/js/get-acct-info.js", start_with="// Create a wallet", end_before="// Get info", language="js") }}
キーを生成するだけであれば、次のように新しいWalletインスタンスを作成することができます。
```js
const test_wallet = xrpl.Wallet.generate()
```
また、[base58][]でエンコードされたシードをすでに持っている場合は、次のようにしてそのシードからWalletをインスタンス化することができます。
```js
const test_wallet = xrpl.Wallet.fromSeed("sn3nxiW7v8KXzPzAqzyHXbSSKNuN9") // テスト用シークレット、本番環境では使用しないでください
```
### 4. XRP Ledgerの参照
クライアントの`request()`メソッドを使って、XRP Ledgerの[WebSocket API](request-formatting.html)にアクセスします。例えば、以下のようになります。
{{ include_code("_code-samples/get-started/js/get-acct-info.js", start_with="// Get info", end_before="// Listen to ledger close events", language="js") }}
### 5. イベントのListen
XRP Ledgerの[コンセンサス プロセス](consensus.html)が新しい[レジャーバージョン](ledgers.html)を生成したときなど、`xrpl.js`ではさまざまなタイプのイベントのハンドラを設定することができます。そのためには、まず[subscribeメソッド][]を呼び出して欲しいイベントの種類を取得し、クライアントの`on(eventType, callback)`メソッドを使ってイベントハンドラをアタッチします。
{{ include_code("_code-samples/get-started/js/get-acct-info.js", start_with="// Listen to ledger close events", end_before="// Disconnect when done", language="js") }}
## 作り続けましょう
これで、`xrpl.js`を使って、XRP Ledgerに接続したり、ウォレットを生成したり、アカウントの情報を調べたりする方法がわかりました。
次のようなことも可能です。
* [XRPの送信](send-xrp.html).
* [代替可能トークンの発行](issue-a-fungible-token.html)
* アカウントに[安全な署名](secure-signing.html) を設定する。
## 関連記事
- **概念:**
- [XRP Ledger Overview](xrp-ledger-overview.html)
- [クライアントライブラリ](client-libraries.html)
- **Tutorials:**
- [XRPの送信](send-xrp.html)
- **References:**
- [`xrpl.js` リファレンス](https://js.xrpl.org/)
- [Public API Methods](public-api-methods.html)
- [API規約](api-conventions.html)
- [base58 エンコード](base58-encodings.html)
- [トランザクションフォーマット](transaction-formats.html)
<!--{# common link defs #}-->
{% include '_snippets/rippled-api-links.md' %}
{% include '_snippets/tx-type-links.md' %}
{% include '_snippets/rippled_versions.md' %}

View File

@@ -0,0 +1,513 @@
---
html: monitor-incoming-payments-with-websocket.html
parent: http-websocket-apis-tutorials.html
blurb: WebSocket APIを使用して、新しいXRPペイメントなどを積極的に監視します。
filters:
- interactive_steps
labels:
- 支払い
---
# WebSocketを使用した着信ペイメントの監視
このチュートリアルでは、[WebSocket `rippled` API](http-websocket-apis.html)を使用して、着信[ペイメント](payment-types.html)を監視する方法を説明します。すべてのXRP Ledgerトランザクションは公開されているため、誰もが任意のアドレスへの着信ペイメントを監視できます。
WebSocketは、クライアントとサーバーが1つの接続を確立し、その接続を経由して両方向にメッセージを送信するモデルに従います。この接続は、明示的に閉じるまたは接続に障害が発生するまで続きます。これは、要求ごとにクライアントが新しい接続を開いて閉じるHTTPベースのAPIモデルJSON-RPCやRESTful APIなどとは対照的です[¹](#footnote-1)<a id="from-footnote-1"></a>
**ヒント:** このページの例はJavaScriptを使用しているため、Webブラウザーでネイティブに実行できます。JavaScriptで開発している場合は、[JavaScript向けxrpl.jsライブラリ](https://js.xrpl.org/)も利用すると、一部の作業を簡素化できます。このチュートリアルでは、xrpl.jsを使用できないその他のプログラミング言語にステップを適合できるよう、xrpl.jsを使用 _しない_ でトランザクションを監視する方法を説明します。
## 前提条件
- このページの例では、すべての主要な最新ブラウザーで使用できるJavaScriptおよびWebSocketプロトコルを使用しています。JavaScriptにある程度習熟し、WebSocketクライアントを使用する他のプログラミング言語の専門知識があれば、選択する言語に手順を適合させながら進めていくことができます。
- 安定したインターネット接続と`rippled`サーバーへアクセスが必要です。埋め込まれている例では、Rippleの公開サーバーのプールに接続します。[独自の`rippled`サーバーを運用](install-rippled.html)する場合は、ローカルでそのサーバーに接続することもできます。
- 丸め方によるエラーを発生させることなくXRPの価値を適切に処理するには、64ビット符号なし整数で計算できる数値タイプを使用できる必要があります。このチュートリアルの例では、[big.js](https://github.com/MikeMcl/big.js/)を使用しています。[発行済み通貨](issued-currencies.html)を使用する場合は、さらに高い精度が求められます。詳細は、[通貨の精度](currency-formats.html#xrpの精度)を参照してください。
<!-- Helper for interactive tutorial breadcrumbs -->
<script type="application/javascript" src="assets/vendor/big.min.js"></script>
<script type="application/javascript" src="assets/js/interactive-tutorial.js"></script>
<script type="application/javascript">
// Helper stuff for this interactive tutorial specifically
function writeToConsole(console_selector, message) {
let write_msg = "<div class='console-entry'>" + message + "</div>"
$(console_selector).find(".placeholder").remove()
$(console_selector).append(write_msg)
// TODO: JSON pretty-printing, maybe w/ multiple input args?
}
</script>
{% set n = cycler(* range(1,99)) %}
## {{n.next()}}. XRP Ledgerへの接続
着信ペイメントを監視する最初のステップとして、XRP Ledger、つまり`rippled`サーバーに接続します。
以下のJavaScriptコードでは、Rippleの公開サーバーのクラスターの1つに接続します。その後、コンソールにメッセージを記録し、[pingメソッド][]を使用して要求を送信します。次に、サーバー側からのメッセージを受信するときに、ハンドラーを設定してコンソールに再度メッセージを記録します。
```js
const socket = new WebSocket('wss://s.altnet.rippletest.net:51233')
socket.addEventListener('open', (event) => {
// This callback runs when the connection is open
console.log("Connected!")
const command = {
"id": "on_open_ping_1",
"command": "ping"
}
socket.send(JSON.stringify(command))
})
socket.addEventListener('message', (event) => {
console.log('Got message from server:', event.data)
})
socket.addEventListener('close', (event) => {
// Use this event to detect when you have become disconnected
// and respond appropriately.
console.log('Disconnected...')
})
```
上記の例では、[Test Net](xrp-test-net-faucet.html)上にあるRippleの公開APIサーバーの1つに対して、安全な接続`wss://`)を開きます。代わりにデフォルトの構成を使用してローカルで運用している`rippled`サーバーに接続するには、最初の行に以下を使用して、ローカルのポート**6006**で _安全ではない_ 接続(`ws://`)を開きます。
```js
const socket = new WebSocket('ws://localhost:6006')
```
**ヒント:** デフォルトでは、ローカル`rippled`サーバーに接続することで、インターネット上の公開サーバーに接続する際に使用できる[パブリックメソッド](public-api-methods.html)以外に、すべての[管理メソッド](admin-api-methods.html)と、[server_info][server_infoメソッド]などの一部の応答に含まれる管理者専用データを利用できます。
例:
{{ start_step("Connect") }}
<button id="connect-socket-button" class="btn btn-primary">Connect</button>
<strong>Connection status:</strong>
<span id="connection-status">Not connected</span>
<h5>Console:</h5>
<div class="ws-console" id="monitor-console-connect"><span class="placeholder">(Log is empty)</span></div>
{{ end_step() }}
<script type="application/javascript">
let socket;
$("#connect-socket-button").click((event) => {
socket = new WebSocket('wss://s.altnet.rippletest.net:51233')
socket.addEventListener('open', (event) => {
// This callback runs when the connection is open
writeToConsole("#monitor-console-connect", "Connected!")
$("#connection-status").text("Connected")
const command = {
"id": "on_open_ping_1",
"command": "ping"
}
socket.send(JSON.stringify(command))
complete_step("Connect")
$("#connect-button").prop("disabled", "disabled")
$("#enable_dispatcher").prop("disabled",false)
})
socket.addEventListener('close', (event) => {
$("#connection-status").text("Disconnected")
$("#connect-button").prop("disabled", false)
})
socket.addEventListener('message', (event) => {
writeToConsole("#monitor-console-connect", "Got message from server: " +
JSON.stringify(event.data))
})
})
</script>
## {{n.next()}}. ハンドラーへの着信メッセージのディスパッチ
WebSocket接続では、複数のメッセージをどちらの方向にも送信することが可能で、要求と応答の間に厳密な1:1の相互関係がないため、各着信メッセージに対応する処理を識別する必要があります。この処理をコーディングする際の優れたモデルとして、「ディスパッチャー」関数の設定が挙げられます。この関数は着信メッセージを読み取り、各メッセージを正しいコードのパスに中継して処理します。メッセージを適切にディスパッチできるように、`rippled`サーバーでは、すべてのWebSocketメッセージで`type`フィールドを使用できます。
- クライアント側からの要求への直接の応答となるメッセージの場合、`type`は文字列の`response`です。この場合、サーバーは以下も提供します。
- この応答に対する要求で指定された`id`に一致する`id`フィールド(応答が順序どおりに到着しない可能性があるため、これは重要です)。
- APIが要求の処理に成功したかどうかを示す`status`フィールド。文字列値`success`は、[成功した応答](response-formatting.html)を示します。文字列値`error`は、[エラー](error-formatting.html)を示します。
**警告:** トランザクションを送信する際、WebSocketメッセージの先頭にある`success``status`は、必ずしもトランザクション自体が成功したことを意味しません。これは、サーバーによって要求が理解されたということのみを示します。トランザクションの実際の結果を確認するには、[トランザクションの結果の確認](look-up-transaction-results.html)を参照してください。
- [サブスクリプション](subscribe.html)からのフォローアップメッセージの場合、`type`は、新しいトランザクション、レジャーまたは検証の通知など、フォローアップメッセージのタイプを示します。または継続している[pathfinding要求](path_find.html)のフォローアップを示します。クライアントがこれらのメッセージを受信するのは、それらをサブスクライブしている場合のみです。
**ヒント:** [JavaScript向けxrpl.js](https://js.xrpl.org/)は、デフォルトでこのステップに対応しています。すべての非同期API要求はPromiseを使用して応答を提供します。また[`.on(event, callback)`メソッド](https://js.xrpl.org/classes/Client.html#on)を使用して、ストリームをリッスンできます。
以下のJavaScriptコードでは、API要求を便利な非同期[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)に変換するヘルパー関数を定義し、他のタイプのメッセージをグローバルハンドラーにマップするインターフェイスを設定します。
```js
const AWAITING = {}
const handleResponse = function(data) {
if (!data.hasOwnProperty("id")) {
console.error("Got response event without ID:", data)
return
}
if (AWAITING.hasOwnProperty(data.id)) {
AWAITING[data.id].resolve(data)
} else {
console.error("Response to un-awaited request w/ ID " + data.id)
}
}
let autoid_n = 0
function api_request(options) {
if (!options.hasOwnProperty("id")) {
options.id = "autoid_" + (autoid_n++)
}
let resolveHolder;
AWAITING[options.id] = new Promise((resolve, reject) => {
// Save the resolve func to be called by the handleResponse function later
resolveHolder = resolve
try {
// Use the socket opened in the previous example...
socket.send(JSON.stringify(options))
} catch(error) {
reject(error)
}
})
AWAITING[options.id].resolve = resolveHolder;
return AWAITING[options.id]
}
const WS_HANDLERS = {
"response": handleResponse
// Fill this out with your handlers in the following format:
// "type": function(event) { /* handle event of this type */ }
}
socket.addEventListener('message', (event) => {
const parsed_data = JSON.parse(event.data)
if (WS_HANDLERS.hasOwnProperty(parsed_data.type)) {
// Call the mapped handler
WS_HANDLERS[parsed_data.type](parsed_data)
} else {
console.log("Unhandled message from server", event)
}
})
// Demonstrate api_request functionality
async function pingpong() {
console.log("Ping...")
const response = await api_request({command: "ping"})
console.log("Pong!", response)
}
pingpong()
```
{{ start_step("Dispatch Messages") }}
<button id="enable_dispatcher" class="btn btn-primary" disabled="disabled">Enable Dispatcher</button>
<button id="dispatch_ping" class="btn btn-primary" disabled="disabled">Ping!</button>
<h5>Responses</h5>
<div class="ws-console" id="monitor-console-ping"><span class="placeholder">(Log is empty)</span></div>
{{ end_step() }}
<script type="application/javascript">
const AWAITING = {}
const handleResponse = function(data) {
if (!data.hasOwnProperty("id")) {
writeToConsole("#monitor-console-ping", "Got response event without ID:", data)
return
}
if (AWAITING.hasOwnProperty(data.id)) {
AWAITING[data.id].resolve(data)
} else {
writeToConsole("#monitor-console-ping", "Response to un-awaited request w/ ID " + data.id)
}
}
let autoid_n = 0
function api_request(options) {
if (!options.hasOwnProperty("id")) {
options.id = "autoid_" + (autoid_n++)
}
let resolveFunc;
AWAITING[options.id] = new Promise((resolve, reject) => {
// Save the resolve func to be called by the handleResponse function later
resolveFunc = resolve
try {
// Use the socket opened in the previous example...
socket.send(JSON.stringify(options))
} catch(error) {
reject(error)
}
})
AWAITING[options.id].resolve = resolveFunc
return AWAITING[options.id]
}
const WS_HANDLERS = {
"response": handleResponse
}
$("#enable_dispatcher").click((clickEvent) => {
socket.addEventListener('message', (event) => {
const parsed_data = JSON.parse(event.data)
if (WS_HANDLERS.hasOwnProperty(parsed_data.type)) {
// Call the mapped handler
WS_HANDLERS[parsed_data.type](parsed_data)
} else {
writeToConsole("#monitor-console-ping", "Unhandled message from server: " + event)
}
})
complete_step("Dispatch Messages")
$("#dispatch_ping").prop("disabled", false)
$("#tx_subscribe").prop("disabled", false)
})
async function pingpong() {
const response = await api_request({command: "ping"})
writeToConsole("#monitor-console-ping", "Pong! " + JSON.stringify(response))
}
$("#dispatch_ping").click((event) => {
pingpong()
})
</script>
## {{n.next()}}. アカウントのサブスクライブ
トランザクションがアカウントに影響を及ぼすたびに即座に通知を取得するには、[subscribeメソッド][]を使用してアカウントをサブスクライブします。実際には、このアカウントはあなた自身のアカウントでなくてもかまいません。すべてのトランザクションは公開されているため、任意のアカウントで、または複数のアカウントでもサブスクライブできます。
1つ以上のアカウントをサブスクライブした場合、指定したアカウントのいずれかに何らかの影響を及ぼす各検証済みトランザクションについて、`"type": "transaction"`が含まれるメッセージがサーバーから送信されます。これを確認するには、トランザクションメッセージで`"validated": true`を探します。
以下のコードサンプルは、Test Net Faucetの送信側アドレスをサブスクライブします。このコードサンプルでは、前のステップのディスパッチャーにハンドラーを追加することで、該当する各トランザクションのメッセージを記録します。
```js
async function do_subscribe() {
const sub_response = await api_request({
command:"subscribe",
accounts: ["rUCzEr6jrEyMpjhs4wSdQdz4g8Y382NxfM"]
})
if (sub_response.status === "success") {
console.log("Successfully subscribed!")
} else {
console.error("Error subscribing: ", sub_response)
}
}
do_subscribe()
const log_tx = function(tx) {
console.log(tx.transaction.TransactionType + " transaction sent by " +
tx.transaction.Account +
"\n Result: " + tx.meta.TransactionResult +
" in ledger " + tx.ledger_index +
"\n Validated? " + tx.validated)
}
WS_HANDLERS["transaction"] = log_tx
```
以下の例では、別のウィンドウまたは別のデバイスで[Transaction Sender](tx-sender.html)を開くことと、サブスクライブしているアドレスへのトランザクションの送信を試みます。
{{ start_step("Subscribe") }}
<label for="subscribe_address">Test Net Address:</label>
<input type="text" class="form-control" id="subscribe_address" value="rUCzEr6jrEyMpjhs4wSdQdz4g8Y382NxfM">
<button id="tx_subscribe" class="btn btn-primary" disabled="disabled">Subscribe</button>
<h5>Transactions</h5>
<div class="ws-console" id="monitor-console-subscribe"><span class="placeholder">(Log is empty)</span></div>
{{ end_step() }}
<script type="application/javascript">
async function do_subscribe() {
const sub_address = $("#subscribe_address").val()
const sub_response = await api_request({
command:"subscribe",
accounts: [sub_address]
})
if (sub_response.status === "success") {
writeToConsole("#monitor-console-subscribe", "Successfully subscribed!")
} else {
writeToConsole("#monitor-console-subscribe",
"Error subscribing: " + JSON.stringify(sub_response))
}
}
$("#tx_subscribe").click((event) => {
do_subscribe()
complete_step("Subscribe")
$("#tx_read").prop("disabled", false)
})
const log_tx = function(tx) {
writeToConsole("#monitor-console-subscribe",
tx.transaction.TransactionType + " transaction sent by " +
tx.transaction.Account +
"<br/>&nbsp;&nbsp;Result: " + tx.meta.TransactionResult +
" in ledger " + tx.ledger_index +
"<br/>&nbsp;&nbsp;Validated? " + tx.validated)
}
WS_HANDLERS["transaction"] = log_tx
</script>
## {{n.next()}}. 着信ペイメントの読み取り
アカウントをサブスクライブすると、 _アカウントへのすべてのトランザクションとアカウントからのすべてのトランザクション_ 、および _アカウントに間接的に影響を及ぼすトランザクション_ に関するメッセージが表示されます。この例として、[発行済み通貨](issued-currencies.html)の取引があります。アカウントが着信ペイメントを受け取った日時を認識することを目的とする場合、トランザクションストリームを絞り込んで、実際に支払われた額に基づいて支払いを処理する必要があります。以下の情報を探します。
- **`validated`フィールド**は、トランザクションの結果が[最終的である](finality-of-results.html)ことを示します。これは、`accounts`をサブスクライブする場合に常に当てはまりますが、`accounts_proposed`または`transactions_proposed`ストリーム _も_ サブスクライブしている場合は、サーバーは未確認のトランザクションに関して同様のメッセージを同じ接続で送信します。予防策として、`validated`フィールドを常に確認することをお勧めします。
- **`meta.TransactionResult`フィールド**は、[トランザクションの結果](transaction-results.html)です。結果が`tesSUCCESS`でない場合は、トランザクションは失敗したため、値を送信できません。
- **`transaction.Account`** フィールドはトランザクションの送信元です。他の人が送信したトランザクションのみを探している場合は、このフィールドがあなたのアドレスと一致するトランザクションを無視できます(自身に対する複数通貨間の支払いが _可能である_ 点に注意してください)。
- **`transaction.TransactionType`フィールド**はトランザクションのタイプです。アカウントに通貨を送金できる可能性があるトランザクションのタイプは以下のとおりです。
- **[Paymentトランザクション][]** はXRPまたは[発行済み通貨](issued-currencies.html)を送金できます。受取人のアドレスを含んでいる`transaction.Destination`フィールドによってこれらを絞り込み、必ず`meta.delivered_amount`を使用して実際に支払われた額を確認します。XRPの額は、[文字列のフォーマットで記述されます](basic-data-types.html#通貨額の指定)。
**警告:** 代わりに`transaction.Amount`フィールドを使用すると、[Partial Paymentの悪用](partial-payments.html#partial-paymentの悪用)に対して脆弱になる可能性があります。不正使用者はこの悪用を行ってあなたをだまし、あなたが支払ったよりも多くの金額を交換または引き出すことができます。
- **[CheckCashトランザクション][]**では、アカウントは別のアカウントの[CheckCreateトランザクション][]によって承認された金額を受け取ることができます。**CheckCashトランザクション**のメタデータを確認すると、アカウントが受け取った通貨の額を確認できます。
- **[EscrowFinishトランザクション][]** は、以前の[EscrowCreateトランザクション][]によって作成された[Escrow](escrow.html)を終了することでXRPを送金できます。**EscrowFinishトランザクション**のメタデータを確認すると、escrowからXRPを受け取ったアカウントと、その額を確認できます。
- **[OfferCreateトランザクション][]** はアカウントがXRP Ledgerの[分散型取引所](decentralized-exchange.html)で以前発行したオファーを消費することで、XRPまたは発行済み通貨を送金できます。オファーを発行しないと、この方法で金額を受け取ることはできません。メタデータを確認して、アカウントが受け取った通貨この情報がある場合と、金額を確認します。
- **[PaymentChannelClaimトランザクション][]** では、[Payment Channel](payment-channels.html)からXRPを送金できます。メタデータを確認して、トランザクションからXRPを受け取ったアカウントこの情報がある場合を確認します。
- **[PaymentChannelFundトランザクション][]** は、閉鎖された期限切れのPayment Channelから送金元にXRPを返金することができます。
- **`meta`フィールド**には、1つまたは複数の通貨の種類とその正確な金額、その送金先などを示す[トランザクションメタデータ](transaction-metadata.html)が示されています。トランザクションメタデータを理解する方法の詳細は、[トランザクションの結果の確認](look-up-transaction-results.html)を参照してください。
以下のサンプルコードは、上に示したすべてのトランザクションのタイプのトランザクションメタデータを確認し、アカウントが受け取ったXRPの金額をレポートします。
```js
{% include '_code-samples/monitor-payments-websocket/js/read-amount-received.js' %}
```
{{ start_step("Read Payments") }}
<button id="tx_read" class="btn btn-primary" disabled="disabled">Start Reading</button>
<h5>Transactions</h5>
<div class="ws-console" id="monitor-console-read"><span class="placeholder">(Log is empty)</span></div>
{{ end_step() }}
<script type="application/javascript">
function CountXRPDifference(affected_nodes, address) {
// Helper to find an account in an AffectedNodes array and see how much
// its balance changed, if at all. Fortunately, each account appears at most
// once in the AffectedNodes array, so we can return as soon as we find it.
// Note: this reports the net balance change. If the address is the sender,
// any XRP balance changes combined with the transaction cost.
for (let i=0; i<affected_nodes.length; i++) {
if ((affected_nodes[i].hasOwnProperty("ModifiedNode"))) {
// modifies an existing ledger entry
let ledger_entry = affected_nodes[i].ModifiedNode
if (ledger_entry.LedgerEntryType === "AccountRoot" &&
ledger_entry.FinalFields.Account === address) {
if (!ledger_entry.PreviousFields.hasOwnProperty("Balance")) {
writeToConsole("#monitor-console-read", "XRP balance did not change.")
}
// Balance is in PreviousFields, so it changed. Time for
// high-precision math!
const old_balance = new Big(ledger_entry.PreviousFields.Balance)
const new_balance = new Big(ledger_entry.FinalFields.Balance)
const diff_in_drops = new_balance.minus(old_balance)
const xrp_amount = diff_in_drops.div(1e6)
if (xrp_amount.gte(0)) {
writeToConsole("#monitor-console-read", "Received " + xrp_amount.toString()+" XRP.")
return
} else {
writeToConsole("#monitor-console-read", "Spent " + xrp_amount.abs().toString() + " XRP.")
return
}
}
} else if ((affected_nodes[i].hasOwnProperty("CreatedNode"))) {
// created a ledger entry. maybe the account got funded?
let ledger_entry = affected_nodes[i].CreatedNode
if (ledger_entry.LedgerEntryType === "AccountRoot" &&
ledger_entry.NewFields.Account === address) {
const balance_drops = new Big(ledger_entry.NewFields.Balance)
const xrp_amount = balance_drops.div(1e6)
writeToConsole("#monitor-console-read", "Received " + xrp_amount.toString() + " XRP (account funded).")
return
}
} // accounts cannot be deleted at this time, so we ignore DeletedNode
}
writeToConsole("#monitor-console-read", "Did not find address in affected nodes.")
return
}
function CountXRPReceived(tx, address) {
if (tx.meta.TransactionResult !== "tesSUCCESS") {
writeToConsole("#monitor-console-read", "Transaction failed.")
return
}
if (tx.transaction.TransactionType === "Payment") {
if (tx.transaction.Destination !== address) {
writeToConsole("#monitor-console-read", "Not the destination of this payment. (We're " +
address + "; they're " + tx.transaction.Destination + ")")
return
}
if (typeof tx.meta.delivered_amount === "string") {
const amount_in_drops = new Big(tx.meta.delivered_amount)
const xrp_amount = amount_in_drops.div(1e6)
writeToConsole("#monitor-console-read", "Received " + xrp_amount.toString() + " XRP.")
return
} else {
writeToConsole("#monitor-console-read", "Received non-XRP currency.")
return
}
} else if (["PaymentChannelClaim", "PaymentChannelFund", "OfferCreate",
"CheckCash", "EscrowFinish"].includes(
tx.transaction.TransactionType)) {
CountXRPDifference(tx.meta.AffectedNodes, address)
} else {
writeToConsole("#monitor-console-read", "Not a currency-delivering transaction type (" +
tx.transaction.TransactionType + ").")
}
}
$("#tx_read").click((event) => {
// Wrap the existing "transaction" handler to do the old thing and also
// do the CountXRPReceived thing
const sub_address = $("#subscribe_address").val()
const old_handler = WS_HANDLERS["transaction"]
const new_handler = function(data) {
old_handler(data)
CountXRPReceived(data, sub_address)
}
WS_HANDLERS["transaction"] = new_handler
// Disable the button so you can't stack up multiple levels of the new handler
$("#tx_read").prop("disabled", "disabled")
complete_step("Read Payments")
})
</script>
## 次のステップ
- [トランザクションの結果の確認](look-up-transaction-results.html)で、トランザクションの実行内容を確認し、適切に対応するソフトウェアを構築します。
- あなた自身のアドレスから[XRPの送金](send-xrp.html)を試します。
- [Escrow](escrow.html)、[Checks](checks.html)または[Payment Channel](payment-channels.html)のような高度なタイプのトランザクションの監視と着信通知への応答を試します。
<!--{# TODO: uncomment when it's ready. - To more robustly handle internet instability, [Follow a Transaction Chain](follow-a-transaction-chain.html) to detect if you missed a notification. #}-->
## その他のプログラミング言語
多くのプログラミング言語には、WebSocket接続を使用して、データの送受信を行うためのライブラリが用意されています。JavaScript以外の言語で`rippled`のWebSocket APIとの通信を効率良く始めるには、同様な機能を利用している以下の例を参考にしてください。
<!-- MULTICODE_BLOCK_START -->
_Go_
```go
{% include '_code-samples/monitor-payments-websocket/go/monitor-incoming-payments.go' %}
```
<!-- MULTICODE_BLOCK_END -->
**ヒント:** 目的のプログラミング言語の例がない場合があります。このページの最上部にある「GitHubで編集する」リンクをクリックして、作成したサンプルコードを提供してください。
## 脚注
[1.](#from-footnote-1)<a id="footnote-1"></a>実際には、HTTPベースのAPIを何度も呼び出す場合、クライアントとサーバーは複数の要求と応答を処理する際に同じ接続を再利用できます。この方法は、[HTTP永続接続、またはキープアライブ](https://en.wikipedia.org/wiki/HTTP_persistent_connection)と呼ばれます。開発の観点から見ると、基本となる接続が新しい場合でも、再利用される場合でも、HTTPベースのAPIを使用するコードは同じです。
## 関連項目
- **コンセプト:**
- [トランザクション](transactions.html)
- [結果のファイナリティー](finality-of-results.html) - トランザクションの成功また失敗が最終的なものとなるタイミングを判断する方法(簡単な説明: トランザクションが検証済みレジャーにある場合は、その結果とメタデータは最終的なものです)。
- **チュートリアル:**
- [信頼できるトランザクションの送信](reliable-transaction-submission.html)
- [トランザクションの結果の確認](look-up-transaction-results.html)
- **リファレンス:**
- [トランザクションのタイプ](transaction-types.html)
- [トランザクションのメタデータ](transaction-metadata.html) - メタデータフォーマットとメタデータに表示されるフィールドの概要
- [トランザクションの結果](transaction-results.html) - トランザクションのすべての結果コードを掲載した表一覧
<!--{# common link defs #}-->
{% include '_snippets/rippled-api-links.md' %}
{% include '_snippets/tx-type-links.md' %}
{% include '_snippets/rippled_versions.md' %}

View File

@@ -0,0 +1,33 @@
---
html: public-servers.html
parent: get-started.html
blurb: これらの公開サーバーを利用して、自社のインフラを必要とせずにXRP Ledgerにアクセスします。
labels:
- コアサーバー
---
# 公開サーバー
[自分で`rippled`サーバーを運営しない](install-rippled.html)場合は、以下の公開サーバーを利用して、トランザクションを送信したり、レジャーからデータを取得したりすることができます。
| 運営者 | [ネットワーク][] | JSON-RPC URL | WebSocket URL | 尾行 |
|:----------|:------------|:-------------|:--------------|:---------------------|
| XRP Ledger 財団 | **Mainnet** | `https://xrplcluster.com/` <br> `https://xrpl.ws/` [²][] | `wss://xrplcluster.com/` <br> `wss://xrpl.ws/` [²][] | CORSをサポートする全履歴サーバークラスター |
| Ripple[¹][] | **Mainnet** | `https://s1.ripple.com:51234/` | `wss://s1.ripple.com/` | 汎用サーバークラスター |
| Ripple[¹][] | **Mainnet** | `https://s2.ripple.com:51234/` | `wss://s2.ripple.com/` | [全履歴サーバ](ledger-history.html#すべての履歴) クラスター |
| Ripple[¹][] | Testnet | `https://s.altnet.rippletest.net:51234/` | `wss://s.altnet.rippletest.net:51233/` | Testnet 公開サーバー |
| XRPL Labs | Testnet | `https://testnet.xrpl-labs.com/` | `wss://testnet.xrpl-labs.com/` | CORSをサポートする Testnet 公開サーバー |
| Ripple[¹][] | Devnet | `https://s.devnet.rippletest.net:51234/` | `wss://s.devnet.rippletest.net:51233/` | Devnet 公開サーバー |
| Ripple[¹][] | AMM-Devnet | `https://amm.devnet.rippletest.net:51234/` | `wss://amm.devnet.rippletest.net:51233/` | [XLS-30d Automated Market Maker](https://github.com/XRPLF/XRPL-Standards/discussions/78)開発用の特別なdevnetサーバー |
[ネットワーク]: parallel-networks.html
[¹]: #footnote-1
[²]: #footnote-2
<a id="footnote-1"></a>¹ Ripple社の公開サーバーは、持続的な利用やビジネスでの利用には適しておらず、いつでも利用できなくなる可能性があります。定期的に使用する場合は、ご自身で `rippled` サーバーを運用するか、信頼できる人と契約してください。リップル社では、公開クラスターに[Reporting Mode][]サーバーが含まれています。
<a id="footnote-2"></a>² `xrpl.ws``xrplcluster.com` のエイリアスです。しかし、`.ws` というトップレベルドメインの信頼性は、本番での使用には適さないかもしれません。
<!--{# common link defs #}-->
{% include '_snippets/rippled-api-links.md' %}
{% include '_snippets/tx-type-links.md' %}
{% include '_snippets/rippled_versions.md' %}

View File

@@ -0,0 +1,330 @@
---
html: send-xrp.html
parent: tasks.html
blurb: Test Netを使用してXRPの送金をテストします。
cta_text: XRPを送金しよう
embed_xrpl_js: true
filters:
- interactive_steps
labels:
- 支払い
- XRP
top_nav_grouping: 人気ページ
---
# XRPの送金
このチュートリアルでは、xrpl.jsを使用してシンプルなXRP送金を行う方法について説明します。まずは、XRP Testnetを使用してプロセスを順に進めます。次に、そのプロセスと、本番で同様の処理を行う場合に発生する追加要件とを比較します。
## 前提条件
<!-- このチュートリアルのインタラクティブ部分のソースコード: -->
<script type="application/javascript" src="assets/js/tutorials/send-xrp.js"></script>
{% set use_network = "Testnet" %}
- このページでは、xrpl.jsライブラリーを使用するJavaScriptの例を紹介します。[xrpl.js入門ガイド](get-started-using-javascript.html)に、xrpl.jsを使用してJavaScriptからXRP Ledgerデータにアクセスする方法の説明があります。
- XRP Ledgerでトランザクションを送信するには、まずアドレスと秘密鍵、そしていくらかのXRPが必要となります。次のインターフェイスを使用して、XRP Test NetにあるアドレスとTestnet XRPを入手できます。
{% include '_snippets/interactive-tutorials/generate-step.ja.md' %}
## Testnetでの送金
{% set n = cycler(* range(1,99)) %}
### {{n.next()}}. Testnetサーバーへの接続
必須の自動入力可能フィールドに入力されるようにするために、ripple-libを、アカウントの現在のステータスと共有レジャー自体を取得できるサーバーに接続する必要があります。セキュリティを高めるために、トランザクションの署名はオフライン中に行うことを推奨します。ただしその場合は、自動入力可能フィールドに手動で入力する必要があります。トランザクションの送信先となるネットワークに接続する必要があります。
以下のサンプルコードでは公開XRP Testnetサーバーに接続します。
<!-- MULTICODE_BLOCK_START -->
_JavaScript_
{{ include_code("_code-samples/get-started/js/base.js", language="js") }}
_Python_
{{ include_code("_code-samples/send-xrp/py/send-xrp.py", start_with="# Connect", end_before="# Get credentials", language="py") }}
_Java_
{{ include_code("_code-samples/send-xrp/java/SendXrp.java", start_with="// Connect", end_before="// Prepare transaction", language="java") }}
<!-- MULTICODE_BLOCK_END -->
このチュートリアルでは、以下のボタンをクリックすることでブラウザーから直接接続できます。
{% include '_snippets/interactive-tutorials/connect-step.ja.md' %}
### {{n.next()}}. トランザクションの準備
通常は、XRP LedgerトランザクションをオブジェクトとしてJSON[トランザクションフォーマット](transaction-formats.html)で作成します。以下の例に、必要最小限の送金仕様を示します。
```json
{
"TransactionType": "Payment",
"Account": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
"Amount": "2000000",
"Destination": "rUCzEr6jrEyMpjhs4wSdQdz4g8Y382NxfM"
}
```
XRP送金に対して指定する必要がある必要最小限の指示は次のとおりです。
- これが送金であることを示すインディケーター(`"TransactionType": "Payment"`
- 送信元アドレス(`"Account"`
- XRPを受け取るアドレス`"Destination"`)。このアドレスは送信元アドレスと同じものではいけません。
- 送金するXRP額`"Amount"`。通常、XRPの「drop数」を示す整数として指定します。1,000,000ドロップは1 XRPです。
技術上、一部の追加のフィールドは実行可能なトランザクションに含める必要があり、また、省略可能なフィールドでも、`LastLedgerSequence`などは含めることを強く推奨します。[`autofill()`メソッド](https://js.xrpl.org/classes/Client.html#autofill)は、トランザクションの残りのフィールドに適切なデフォルトを自動的に入力します。上記の送金を準備する際の例を示します。
<!-- MULTICODE_BLOCK_START -->
_JavaScript_
{{ include_code("_code-samples/send-xrp/js/send-xrp.js", start_with="// Prepare", end_before="// Sign", language="js" ) }}
_Python_
{{ include_code("_code-samples/send-xrp/py/send-xrp.py", start_with="# Prepare", end_before="# Sign", language="py" ) }}
_Java_
{{ include_code("_code-samples/send-xrp/java/SendXrp.java", start_with="// Prepare", end_before="// Sign", language="java") }}
<!-- MULTICODE_BLOCK_END -->
{{ start_step("Prepare") }}
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">送金する額:</span>
</div>
<input type="number" class="form-control" value="22" id="xrp-amount"
aria-label="XRPの額小数" aria-describedby="xrp-amount-label"
min=".000001" max="100000000000" step="any">
<div class="input-group-append">
<span class="input-group-text" id="xrp-amount-label"> XRP</span>
</div>
</div>
<button id="prepare-button" class="btn btn-primary previous-steps-required">サンプルトランザクションを準備する</button>
<div class="output-area"></div>
{{ end_step() }}
### {{n.next()}}. トランザクションの指示への署名
xrpl.jsの[Wallet.sign()メソッド](https://js.xrpl.org/classes/Wallet.html#sign)を使用して、トランザクションに署名します。最初の引数は、署名するJSONトランザクションの文字列バージョンです。
<!-- MULTICODE_BLOCK_START -->
_JavaScript_
{{ include_code("_code-samples/send-xrp/js/send-xrp.js",
start_with="// Sign", end_before="// Submit", language="js" ) }}
_Python_
{{ include_code("_code-samples/send-xrp/py/send-xrp.py",
start_with="# Sign", end_before="# Submit", language="py" ) }}
_Java_
{{ include_code("_code-samples/send-xrp/java/SendXrp.java",
start_with="// Sign", end_before="// Submit", language="java" ) }}
<!-- MULTICODE_BLOCK_END -->
署名処理の結果は、署名を含むトランザクションオブジェクトになります。通常、XRP Ledger APIは、署名済みトランザクションがトランザクションの正規の[バイナリーフォーマット](serialization.html)「ブロブ」と呼ばれるの16進数表現になることを想定しています。
署名APIは、トランザクションのID、つまり識別用ハッシュを返します。この識別用ハッシュは、後でトランザクションを検索する際に使用します。識別用ハッシュは、このトランザクションに固有の64文字の16進文字列です。
{{ start_step("Sign") }}
<button id="sign-button" class="btn btn-primary previous-steps-required">サンプルトランザクションに署名する</button>
<div class="output-area"></div>
{{ end_step() }}
### {{n.next()}}. 署名済みブロブの送信
トランザクションをネットワークに送信します。
<!-- MULTICODE_BLOCK_START -->
_JavaScript_
{{ include_code("_code-samples/send-xrp/js/send-xrp.js", start_with="// Submit", end_before="// Wait", language="js" ) }}
_Python_
{{ include_code("_code-samples/send-xrp/py/send-xrp.py", start_with="# Submit", end_before="# Wait", language="py") }}
_Java_
{{ include_code("_code-samples/send-xrp/java/SendXrp.java", start_with="// Submit", end_before="// Wait", language="java" ) }}
<!-- MULTICODE_BLOCK_END -->
このメソッドは、ローカルでトランザクションを適用しようと試みたときの**一時的な**結果を返します。この結果は、トランザクションが検証済みレジャーに含まれた時点で変わる_可能性があります_。当初は成功していたトランザクションが最終的に失敗となったり、当初失敗していたトランザクションが最終的に成功する場合があります。しかしながら、一時的な結果はほとんどの場合は最終結果と一致するため、ここで`tesSUCCESS`が表示されたらひとまず安心しても問題ありません。😁
他の結果が表示された場合は、以下の点を確認します。
- 送信元および送信先の正しいアドレスを使用しているか。
- トランザクションの他のフィールドへの入力漏れ、ステップのスキップ、その他の入力ミスがないか。
- トランザクションの送信に必要なTest Net XRPが十分にあるか。送金できるXRPの額は、[必要準備金](reserves.html)によって制限されています。現時点では、20XRPに加えて、レジャー内に保有している各「オブジェクト」につき5XRPずつ追加となります。Test Net Faucetを使用して新しいアドレスを生成した場合は、保有するオブジェクトはありません。
- テストネットワークのサーバーに接続しているか。
他の可能性については、[トランザクション結果](transaction-results.html)の完全なリストを参照してください。
{{ start_step("Submit") }}
<button id="submit-button" class="btn btn-primary previous-steps-required" data-tx-blob-from="#signed-tx-blob" data-wait-step-name="Wait">サンプルトランザクションを送信する</button>
<div class="loader collapse"><img class="throbber" src="assets/img/xrp-loader-96.png"> 送信中...</div>
<div class="output-area"></div>
{{ end_step() }}
### {{n.next()}}. 検証の待機
ほとんどのトランザクションは送信後の次のレジャーバージョンに承認されます。つまり、47秒でトランザクションの結果が最終的なものになる可能性があります。XRP Ledgerがビジーになっているか、ネットワーク接続の品質が悪いためにトランザクションをネットワーク内で中継する処理が遅延した場合は、トランザクション確定までにもう少し時間がかかることがあります。トランザクションの有効期限を設定する方法については、[信頼できるトランザクションの送信](reliable-transaction-submission.html)を参照してください。)
<!-- MULTICODE_BLOCK_START -->
_JavaScript_
{{ include_code("_code-samples/send-xrp/js/send-xrp.js", start_with="// Wait", end_before="// Check", language="js" ) }}
_Python_
{{ include_code("_code-samples/send-xrp/py/send-xrp.py", start_with="# Wait", end_before="# Check", language="py") }}
_Java_
{{ include_code("_code-samples/send-xrp/java/SendXrp.java", start_with="// Wait", end_before="// Check", language="java" ) }}
<!-- MULTICODE_BLOCK_END -->
{{ start_step("Wait") }}
{% include '_snippets/interactive-tutorials/wait-step.ja.md' %}
{{ end_step() }}
### {{n.next()}}. トランザクションステータスの確認
トランザクションが行った内容を正確に把握するために、トランザクションが検証済みレジャーバージョンに記録されたときにトランザクションの結果を調べる必要があります。例えば、[txメソッド][]を使用して、トランザクションのステータスを確認できます。
<!-- MULTICODE_BLOCK_START -->
_JavaScript_
{{ include_code("_code-samples/send-xrp/js/send-xrp.js", start_with="// Check", end_before="// End of", language="js" ) }}
_Python_
{{ include_code("_code-samples/send-xrp/py/send-xrp.py", start_with="# Check", language="py") }}
_Java_
{{ include_code("_code-samples/send-xrp/java/SendXrp.java", start_with="// Check", language="java" ) }}
<!-- MULTICODE_BLOCK_END -->
**注意:** APIは、まだ検証されていないレジャーバージョンからの暫定的な結果を返す場合があります。例えば、`rippled` APIの[txメソッド][]を使用した場合は、応答内の`"validated": true`を探して、データが検証済みレジャーバージョンからのものであることを確認してください。検証済みレジャーバージョンからのものではないトランザクション結果は、変わる可能性があります。詳細は、[結果のファイナリティー](finality-of-results.html)を参照してください。
{{ start_step("Check") }}
<button id="get-tx-button" class="btn btn-primary previous-steps-required">トランザクションステータスを確認する</button>
<div class="output-area"></div>
{{ end_step() }}
## 本番環境の場合の相違点
本番XRP LedgerでXRPを送金する場合も、大部分の手順は同じです。ただし、必要なセットアップでは重要な相違点がいくつかあります。
- [実際のXRPは無料で取得できません。](#実際のxrpアカウントの取得)
- [本番XRP Ledgerネットワークと同期されているサーバーに接続する必要があります。](#本番xrp-ledgerへの接続)
### 実際のXRPアカウントの取得
このチュートリアルでは、Test Net XRPがすでに資金供給されているアドレスをボタンで取得しましたが、それが可能だったのはTest Net XRPに何の価値もないからです。実際のXRPでは、XRPを所有している他者からXRPを入手する必要があります。たとえば、取引所で購入する方法など。[xrpl.jsのWallet()クラス](https://js.xrpl.org/classes/Wallet.html)を使用して、本番またはTestnetで機能するアドレスとシークレットを生成できます。
<!-- MULTICODE_BLOCK_START -->
_JavaScript_
```js
const wallet = new xrpl.Wallet()
console.log(wallet.address) // Example: rGCkuB7PBr5tNy68tPEABEtcdno4hE6Y7f
console.log(wallet.seed) // Example: sp6JS7f14BuwFY8Mw6bTtLKWauoUs
```
_Python_
```py
from xrpl.wallet import Wallet
my_wallet = Wallet.create()
print(my_wallet.address) # Example: rGCkuB7PBr5tNy68tPEABEtcdno4hE6Y7f
print(my_wallet.seed) # Example: sp6JS7f14BuwFY8Mw6bTtLKWauoUs
```
_Java_
```java
WalletFactory walletFactory = DefaultWalletFactory.getInstance();
SeedWalletGenerationResult generationResult = walletFactory.randomWallet(false);
Wallet wallet = generationResult.wallet();
System.out.println(wallet.classicAddress()); // Example: rGCkuB7PBr5tNy68tPEABEtcdno4hE6Y7f
System.out.println(generationResult.seed()); // Example: sp6JS7f14BuwFY8Mw6bTtLKWauoUs
```
<!-- MULTICODE_BLOCK_END -->
**警告:** ローカルマシンで安全な方法で生成したアドレスとシークレットのみを使用してください。別のコンピューターでアドレスとシークレットを生成して、ネットワーク経由でそれらを自分に送信した場合は、ネットワーク上の他の人がその情報を見ることができる可能性があります。その情報見ることができる人は、あなたと同じようにあなたのXRPを操作できます。また、Test Netと本番で同じアドレスを使用しないことも推奨します。指定したパラメーターによっては、一方のネットワークに向けて作成したトランザクションが、もう一方のネットワークでも実行可能になるおそれがあるためです。
アドレスとシークレットを生成しても、直接XRPを入手できるわけではありません。単に乱数を選択しているだけです。また、そのアドレスでXRPを受け取って[アカウントに資金供給](accounts.html#アカウントの作成)する必要があります。XRPを取得する方法として最も一般的なのは、取引所から購入し、所有しているアドレスに入れる方法です。詳細は、[XRP Overview](xrp-overview.html)を参照してください。
### 本番XRP Ledgerへの接続
XRP Ledgerと同期しているサーバーを指定する必要があります。多くの場合は公開サーバーを、以下のスニペットなどで使用できます。
<!-- MULTICODE_BLOCK_START -->
_JavaScript_
```js
const xrpl = require('xrpl')
const api = new xrpl.Client('wss://xrplcluster.com')
api.connect()
```
_Python_
```py
from xrpl.clients import JsonRpcClient
client = JsonRpcClient("https://xrplcluster.com")
```
_Java_
```java
final HttpUrl rippledUrl = HttpUrl.get("https://xrplcluster.com");
XrplClient xrplClient = new XrplClient(rippledUrl);
```
<!-- MULTICODE_BLOCK_END -->
**ヒント:** ローカル接続では、WebSocketプロトコルのTLSで暗号化されたバージョン`wss`)ではなく、暗号化されていないバージョン(`ws`を使用します。この方式は、通信が同じマシンの中だけで行われてマシンの外に出て行かないという点で安全で、TLS証明書が不要であるため設定が簡単です。外部ネットワークとの接続では、必ず`wss`を使用してください。
## 次のステップ
このチュートリアルを完了後は、以下を試してみてください。
- 本番システム向けに[信頼できるトランザクションの送信](reliable-transaction-submission.html)を構築する
- [xrpl.jsリファレンス](https://js.xrpl.org/)を参照して、XRP Ledgerの全機能を確認する
- [アカウント設定](manage-account-settings.html)をカスタマイズする
- [トランザクションのメタデータ](transaction-metadata.html)にトランザクションの結果の詳細がどのように記述されているかを知る
- escrowやPayment Channelなどの[複雑な支払いタイプ](complex-payment-types.html)について調べる
<!--{# common link defs #}-->
{% include '_snippets/rippled-api-links.md' %}
{% include '_snippets/tx-type-links.md' %}
{% include '_snippets/rippled_versions.md' %}