mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-22 04:35:49 +00:00
Merge branch 'master' into add_php_xrpl_to_client_libraries
This commit is contained in:
@@ -1,237 +0,0 @@
|
||||
---
|
||||
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-RPC(HTTP)、ポート6006でWebSocket(WS)の接続をリッスンし、接続されるすべてのクライアントを管理者として扱っています。
|
||||
|
||||
|
||||
## 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)
|
||||
@@ -1,172 +0,0 @@
|
||||
---
|
||||
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' %}
|
||||
@@ -94,6 +94,7 @@ This method returns a [`Wallet` instance](https://xrpl-py.readthedocs.io/en/late
|
||||
print(test_wallet)
|
||||
|
||||
# print output
|
||||
|
||||
public_key:: 022FA613294CD13FFEA759D0185007DBE763331910509EF8F1635B4F84FA08AEE3
|
||||
private_key:: -HIDDEN-
|
||||
classic_address: raaFKKmgf6CRZttTVABeTcsqzRQ51bNR6Q
|
||||
|
||||
@@ -1,513 +0,0 @@
|
||||
---
|
||||
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/> Result: " + tx.meta.TransactionResult +
|
||||
" in ledger " + tx.ledger_index +
|
||||
"<br/> 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' %}
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
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' %}
|
||||
@@ -1,330 +0,0 @@
|
||||
---
|
||||
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()}}. 検証の待機
|
||||
|
||||
ほとんどのトランザクションは送信後の次のレジャーバージョンに承認されます。つまり、4~7秒でトランザクションの結果が最終的なものになる可能性があります。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' %}
|
||||
9
content/tutorials/http-websocket-apis/index.md
Normal file
9
content/tutorials/http-websocket-apis/index.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
html: http-websocket-apis-tutorials.html
|
||||
parent: tutorials.html
|
||||
top_nav_grouping: Article Types
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# HTTP / Websocket APIs
|
||||
|
||||
XRPL tutorials for HTTP / Websocket APIs.
|
||||
9
content/tutorials/java/index.md
Normal file
9
content/tutorials/java/index.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
html: java.html
|
||||
parent: tutorials.html
|
||||
top_nav_grouping: Article Types
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# Java
|
||||
|
||||
XRPL tutorials in Java.
|
||||
9
content/tutorials/javascript/index.md
Normal file
9
content/tutorials/javascript/index.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
html: javascript.html
|
||||
parent: tutorials.html
|
||||
top_nav_grouping: Article Types
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# JavaScript
|
||||
|
||||
XRPL tutorials in JavaScript.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
html: modular-tutorials-in-javascript.html
|
||||
parent: javascript.html
|
||||
top_nav_grouping: Article Types
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# Modular Tutorials in JavaScript
|
||||
|
||||
Modular XRPL tutorials in JavaScript.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
html: nfts-using-javascript.html
|
||||
parent: modular-tutorials-in-javascript.html
|
||||
top_nav_grouping: Article Types
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# NFTs Using JavaScript
|
||||
|
||||
Mint and sell NFTs on the XRP Ledger using JavaScript.
|
||||
@@ -1,683 +0,0 @@
|
||||
---
|
||||
html: assign-a-regular-key-pair.html
|
||||
parent: manage-account-settings.html
|
||||
blurb: アカウントからトランザクションに署名できるように第2キーペアを承認します。このキーペアは後から変更や削除が可能です。
|
||||
labels:
|
||||
- セキュリティ
|
||||
- アカウント
|
||||
---
|
||||
# レギュラーキーペアの割り当て
|
||||
|
||||
XRP Ledgerでは、アカウントはその後のトランザクションには _レギュラーキーペア_ と呼ばれるセカンダリキーペアで署名することができます。レギュラーキーペアの秘密鍵が漏えいした場合は、秘密鍵を削除または交換できます。その際に、アカウントの秘密鍵以外の設定を変更したり、他のアカウントとの関係を再設定する必要はありません。レギュラーキーペアを積極的にローテーションすることも可能です。(アカウントのアドレスに固有に関連付けられているアカウントのマスターキーペアでは、このような操作は実行できません。)
|
||||
|
||||
マスターキーペアとレギュラーキーペアの詳細は、[暗号鍵](cryptographic-keys.html)を参照してください。
|
||||
|
||||
このチュートリアルでは、レギュラーキーペアをアカウントに割り当てるために必要な手順を説明します。
|
||||
|
||||
1. [キーペアの生成](#1-キーペアの生成)
|
||||
2. [生成したキーペアをレギュラーキーペアとしてアカウントに割り当てる](#2-生成したキーペアをレギュラーキーペアとしてアカウントに割り当てる)
|
||||
3. [レギュラーキーペアの検証](#3-レギュラーキーペアの検証)
|
||||
4. [次のステップ](#4-次のステップ)
|
||||
|
||||
|
||||
## 1. キーペアの生成
|
||||
|
||||
[wallet_proposeメソッド][]を使用して、アカウントにレギュラーキーペアとして割り当てるキーペアを生成します。
|
||||
|
||||
### 要求フォーマット
|
||||
|
||||
要求フォーマットの例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"command":"wallet_propose"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"method":"wallet_propose"
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```sh
|
||||
#Syntax: wallet_propose
|
||||
rippled wallet_propose
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
### 応答フォーマット
|
||||
|
||||
処理が成功した応答の例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"result":{
|
||||
"account_id":"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7",
|
||||
"key_type":"secp256k1",
|
||||
"master_key":"KNEW BENT LYNN LED GAD BEN KENT SHAM HOBO RINK WALT ALLY",
|
||||
"master_seed":"sh8i92YRnEjJy3fpFkL8txQSCVo79",
|
||||
"master_seed_hex":"966C0F68643EFBA50D58D191D4CA8AA7",
|
||||
"public_key":"aBRNH5wUurfhZcoyR6nRwDSa95gMBkovBJ8V4cp1C1pM28H7EPL1",
|
||||
"public_key_hex":"03AEEFE1E8ED4BBC009DE996AC03A8C6B5713B1554794056C66E5B8D1753C7DD0E"
|
||||
},
|
||||
"status":"success",
|
||||
"type":"response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"result":{
|
||||
"account_id":"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7",
|
||||
"key_type":"secp256k1",
|
||||
"master_key":"KNEW BENT LYNN LED GAD BEN KENT SHAM HOBO RINK WALT ALLY",
|
||||
"master_seed":"sh8i92YRnEjJy3fpFkL8txQSCVo79",
|
||||
"master_seed_hex":"966C0F68643EFBA50D58D191D4CA8AA7",
|
||||
"public_key":"aBRNH5wUurfhZcoyR6nRwDSa95gMBkovBJ8V4cp1C1pM28H7EPL1",
|
||||
"public_key_hex":"03AEEFE1E8ED4BBC009DE996AC03A8C6B5713B1554794056C66E5B8D1753C7DD0E"
|
||||
"status":"success"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{
|
||||
"result" :{
|
||||
"account_id" :"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7",
|
||||
"key_type" :"secp256k1",
|
||||
"master_key" :"KNEW BENT LYNN LED GAD BEN KENT SHAM HOBO RINK WALT ALLY",
|
||||
"master_seed" :"sh8i92YRnEjJy3fpFkL8txQSCVo79",
|
||||
"master_seed_hex" :"966C0F68643EFBA50D58D191D4CA8AA7",
|
||||
"public_key" :"aBRNH5wUurfhZcoyR6nRwDSa95gMBkovBJ8V4cp1C1pM28H7EPL1",
|
||||
"public_key_hex" :"03AEEFE1E8ED4BBC009DE996AC03A8C6B5713B1554794056C66E5B8D1753C7DD0E",
|
||||
"status" :"success"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
次のステップでは、この応答の`account_id`を使用してキーペアをレギュラーキーペアとしてアカウントに割り当てます。また、`master_seed`値を安全な場所に保管してください。(この値以外は特に覚えておく必要はありません。)
|
||||
|
||||
|
||||
## 2. 生成したキーペアをレギュラーキーペアとしてアカウントに割り当てる
|
||||
|
||||
[SetRegularKeyトランザクション][]を使用して、ステップ1で生成したキーペアをレギュラーキーペアとしてアカウントに割り当てます。
|
||||
|
||||
SetRegularKeyトランザクションでレギュラーキーペアを初めてアカウントに割り当てる際には、アカウントのマスター秘密鍵(シークレット)による署名が必要です。マスター秘密鍵の送信は危険であるため、トランザクションの署名とネットワークへのトランザクション送信を切り離した2段階方式でこのトランザクションを実行します。
|
||||
|
||||
それ以降のSetRegularKeyトランザクションの送信時には、既存のレギュラー秘密鍵で署名し、レギュラー秘密鍵自体を置換または[削除](change-or-remove-a-regular-key-pair.html)できます。ネットワーク上でレギュラー秘密鍵を送信してはならないことに注意してください。
|
||||
|
||||
|
||||
### トランザクションの署名
|
||||
|
||||
{% include '_snippets/tutorial-sign-step.ja.md' %}
|
||||
<!--{#_ #}-->
|
||||
|
||||
要求フィールドに以下の値を指定します。
|
||||
|
||||
| 要求フィールド | 値 |
|
||||
|:--------------|:-------------------------------------------------------------|
|
||||
| `Account` | アカウントのアドレス。 |
|
||||
| `RegularKey` | ステップ1で生成された`account_id`。 |
|
||||
| `secret` | アカウントの`master_key`、`master_seed`、または`master_seed_hex`(マスター秘密鍵)。|
|
||||
|
||||
|
||||
#### 要求フォーマット
|
||||
|
||||
要求フォーマットの例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"command":"sign",
|
||||
"tx_json":{
|
||||
"TransactionType":"SetRegularKey",
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"RegularKey":"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7"
|
||||
},
|
||||
"secret":"ssCATR7CBvn4GLd1UuU2bqqQffHki"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"method":"sign",
|
||||
"params":[
|
||||
{
|
||||
"tx_json":{
|
||||
"TransactionType":"SetRegularKey",
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"RegularKey":"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7"
|
||||
},
|
||||
"secret":"ssCATR7CBvn4GLd1UuU2bqqQffHki"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```sh
|
||||
#Syntax: sign secret tx_json
|
||||
rippled sign ssCATR7CBvn4GLd1UuU2bqqQffHki '{"TransactionType":"SetRegularKey", "Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93", "RegularKey":"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7"}'
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
#### 応答フォーマット
|
||||
|
||||
処理が成功した応答の例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"result":{
|
||||
"tx_blob":"1200052280000000240000000468400000000000000A73210384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A7446304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C268114830923439D307E642CED308FD91EF701A7BAA74788141620D685FB08D81A70D0B668749CF2E130EA7540",
|
||||
"tx_json":{
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"RegularKey":"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7",
|
||||
"Sequence":4,
|
||||
"SigningPubKey":"0384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A",
|
||||
"TransactionType":"SetRegularKey",
|
||||
"TxnSignature":"304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C26",
|
||||
"hash":"AB73BBF7C99061678B59FB48D72CA0F5FC6DD2815B6736C6E9EB94439EC236CE"
|
||||
}
|
||||
},
|
||||
"status":"success",
|
||||
"type":"response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"result":{
|
||||
"status":"success",
|
||||
"tx_blob":"1200052280000000240000000768400000000000000A73210384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A7446304402201453CA3D4D17F0EE3828B9E3D6ACF65327F5D4FC2BA30953CACF6CBCB4145E3502202F2154BED1D7462CAC1E3DBB31864E48C3BA0B3133ACA5E37EC54F0D0C339E2D8114830923439D307E642CED308FD91EF701A7BAA74788141620D685FB08D81A70D0B668749CF2E130EA7540",
|
||||
"tx_json":{
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"RegularKey":"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7",
|
||||
"Sequence":4,
|
||||
"SigningPubKey":"0384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A",
|
||||
"TransactionType":"SetRegularKey",
|
||||
"TxnSignature":"304402201453CA3D4D17F0EE3828B9E3D6ACF65327F5D4FC2BA30953CACF6CBCB4145E3502202F2154BED1D7462CAC1E3DBB31864E48C3BA0B3133ACA5E37EC54F0D0C339E2D",
|
||||
"hash":"AB73BBF7C99061678B59FB48D72CA0F5FC6DD2815B6736C6E9EB94439EC236CE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{
|
||||
"result" :{
|
||||
"status" :"success",
|
||||
"tx_blob" :"1200052280000000240000000768400000000000000A73210384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A7446304402201453CA3D4D17F0EE3828B9E3D6ACF65327F5D4FC2BA30953CACF6CBCB4145E3502202F2154BED1D7462CAC1E3DBB31864E48C3BA0B3133ACA5E37EC54F0D0C339E2D8114830923439D307E642CED308FD91EF701A7BAA74788141620D685FB08D81A70D0B668749CF2E130EA7540",
|
||||
"tx_json" :{
|
||||
"Account" :"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee" :"10",
|
||||
"Flags" :2147483648,
|
||||
"RegularKey" :"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7",
|
||||
"Sequence" :4,
|
||||
"SigningPubKey" :"0384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A",
|
||||
"TransactionType" :"SetRegularKey",
|
||||
"TxnSignature" :"304402201453CA3D4D17F0EE3828B9E3D6ACF65327F5D4FC2BA30953CACF6CBCB4145E3502202F2154BED1D7462CAC1E3DBB31864E48C3BA0B3133ACA5E37EC54F0D0C339E2D",
|
||||
"hash" :"AB73BBF7C99061678B59FB48D72CA0F5FC6DD2815B6736C6E9EB94439EC236CE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
`sign`コマンドの応答には上記のような`tx_blob`値が含まれています。オフライン署名応答には`signedTransaction`値が含まれています。いずれもトランザクションの署名済みバイナリ表現(ブロブ)です。
|
||||
|
||||
次に`submit`コマンドを使用して、トランザクションブロブ(`tx_blob`または`signedTransaction`)をネットワークに送信します。
|
||||
|
||||
|
||||
### トランザクションの送信
|
||||
|
||||
オフライン署名応答の`signedTransaction`値、または`sign`コマンド応答の`tx_blob`値をとり、[submitメソッド][]を使用して`tx_blob`として値として送信します。
|
||||
|
||||
#### 要求フォーマット
|
||||
|
||||
要求フォーマットの例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"command":"submit",
|
||||
"tx_blob":"1200052280000000240000000468400000000000000A73210384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A7446304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C268114830923439D307E642CED308FD91EF701A7BAA74788141620D685FB08D81A70D0B668749CF2E130EA7540"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"method":"submit",
|
||||
"params":[
|
||||
{
|
||||
"tx_blob":"1200052280000000240000000468400000000000000A73210384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A7446304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C268114830923439D307E642CED308FD91EF701A7BAA74788141620D685FB08D81A70D0B668749CF2E130EA7540"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```sh
|
||||
#Syntax: submit tx_blob
|
||||
rippled submit 1200052280000000240000000468400000000000000A73210384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A7446304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C268114830923439D307E642CED308FD91EF701A7BAA74788141620D685FB08D81A70D0B668749CF2E130EA7540
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
#### 応答フォーマット
|
||||
|
||||
処理が成功した応答の例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"result":{
|
||||
"engine_result":"tesSUCCESS",
|
||||
"engine_result_code":0,
|
||||
"engine_result_message":"The transaction was applied.Only final in a validated ledger.",
|
||||
"tx_blob":"1200052280000000240000000468400000000000000A73210384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A7446304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C268114830923439D307E642CED308FD91EF701A7BAA74788141620D685FB08D81A70D0B668749CF2E130EA7540",
|
||||
"tx_json":{
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"RegularKey":"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7",
|
||||
"Sequence":4,
|
||||
"SigningPubKey":"0384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A",
|
||||
"TransactionType":"SetRegularKey",
|
||||
"TxnSignature":"304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C26",
|
||||
"hash":"AB73BBF7C99061678B59FB48D72CA0F5FC6DD2815B6736C6E9EB94439EC236CE"
|
||||
}
|
||||
},
|
||||
"status":"success",
|
||||
"type":"response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"result":{
|
||||
"engine_result":"tesSUCCESS",
|
||||
"engine_result_code":0,
|
||||
"engine_result_message":"The transaction was applied.Only final in a validated ledger.",
|
||||
"status":"success",
|
||||
"tx_blob":"1200052280000000240000000468400000000000000A73210384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A7446304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C268114830923439D307E642CED308FD91EF701A7BAA74788141620D685FB08D81A70D0B668749CF2E130EA7540",
|
||||
"tx_json":{
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"RegularKey":"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7",
|
||||
"Sequence":4,
|
||||
"SigningPubKey":"0384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A",
|
||||
"TransactionType":"SetRegularKey",
|
||||
"TxnSignature":"304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C26",
|
||||
"hash":"AB73BBF7C99061678B59FB48D72CA0F5FC6DD2815B6736C6E9EB94439EC236CE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{
|
||||
"result" :{
|
||||
"engine_result" :"tesSUCCESS",
|
||||
"engine_result_code" :0,
|
||||
"engine_result_message" :"The transaction was applied.Only final in a validated ledger.",
|
||||
"status" :"success",
|
||||
"tx_blob" :"1200052280000000240000000468400000000000000A73210384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A7446304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C268114830923439D307E642CED308FD91EF701A7BAA74788141620D685FB08D81A70D0B668749CF2E130EA7540",
|
||||
"tx_json" :{
|
||||
"Account" :"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee" :"10",
|
||||
"Flags" :2147483648,
|
||||
"RegularKey" :"rsprUqu6BHAffAeG4HpSdjBNvnA6gdnZV7",
|
||||
"Sequence" :4,
|
||||
"SigningPubKey" :"0384CA3C528F10C75F26E0917F001338BD3C9AA1A39B9FBD583DFFFD96CF2E2D7A",
|
||||
"TransactionType" :"SetRegularKey",
|
||||
"TxnSignature" :"304402204BCD5663F3A2BA02D2CE374439096EC6D27273522CD6E6E0BDBFB518730EAAE402200ECD02D8D2525D6FA4642613E71E395ECCEA01C42C35A668BF092A00EB649C26",
|
||||
"hash" :"AB73BBF7C99061678B59FB48D72CA0F5FC6DD2815B6736C6E9EB94439EC236CE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
応答に含まれるトランザクションの`hash`は、[トランザクションの最終結果を検索する](tx.html)ときに使用できることに注意してください。
|
||||
|
||||
|
||||
## 3. レギュラーキーペアの検証
|
||||
|
||||
アカウントにレギュラーキーペアが正しく設定されていることを検証するため、ステップ2でアカウントに割り当てたレギュラー秘密鍵で[AccountSetトランザクション][]に署名し、アカウントからこのトランザクションを送信します。
|
||||
|
||||
ステップ2で説明したように、マスター秘密鍵の送信は危険です。レギュラー秘密鍵の送信も同様に危険です。そのため、トランザクションの署名とネットワークへのトランザクションの送信を切り離した2段階方式でこのトランザクションを実行します。
|
||||
|
||||
|
||||
### トランザクションの署名
|
||||
|
||||
{% include '_snippets/tutorial-sign-step.ja.md' %}
|
||||
<!--{#_ #}-->
|
||||
|
||||
要求フィールドに以下の値を指定します。
|
||||
|
||||
| 要求フィールド | 値 |
|
||||
|:--------------|:-------------------------------------------------------------|
|
||||
| `Account` | アカウントのアドレス。 |
|
||||
| `secret` | ステップ1で生成し、ステップ2でアカウントに割り当てた`master_key`、`master_seed`、または`master_seed_hex`(レギュラー秘密鍵)。 |
|
||||
|
||||
|
||||
#### 要求フォーマット
|
||||
|
||||
要求フォーマットの例を示します。この要求には`AccountSet`オプションが含まれていないことに注意してください。つまり、トランザクションの成功による影響は、アカウントのレギュラーキーペアが正しく設定されていることを確認する(およびトランザクションコストを消却する)こと以外に何もありません。
|
||||
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"command":"sign",
|
||||
"tx_json":{
|
||||
"TransactionType":"AccountSet",
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93"
|
||||
},
|
||||
"secret":"sh8i92YRnEjJy3fpFkL8txQSCVo79"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"method":"sign",
|
||||
"params":[
|
||||
{
|
||||
"tx_json":{
|
||||
"TransactionType":"AccountSet",
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93"
|
||||
},
|
||||
"secret":"sh8i92YRnEjJy3fpFkL8txQSCVo79"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```sh
|
||||
#Syntax: sign secret tx_json
|
||||
rippled sign sh8i92YRnEjJy3fpFkL8txQSCVo79 '{"TransactionType":"AccountSet", "Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93"}'
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
#### 応答フォーマット
|
||||
|
||||
処理が成功した応答の例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"result":{
|
||||
"tx_blob":"1200032280000000240000000468400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB88114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json":{
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"Sequence":4,
|
||||
"SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType":"AccountSet",
|
||||
"TxnSignature":"3045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB8",
|
||||
"hash":"D9B305CB6E861D0994A5CDD4726129D91AC4277111DC444DE4CEE44AD4674A9F"
|
||||
}
|
||||
},
|
||||
"status":"success",
|
||||
"type":"response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"result":{
|
||||
"status":"success",
|
||||
"tx_blob":"1200032280000000240000000468400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB88114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json":{
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"Sequence":4,
|
||||
"SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType":"AccountSet",
|
||||
"TxnSignature":"3045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB8",
|
||||
"hash":"D9B305CB6E861D0994A5CDD4726129D91AC4277111DC444DE4CEE44AD4674A9F"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{
|
||||
"result" :{
|
||||
"status" :"success",
|
||||
"tx_blob" :"1200032280000000240000000468400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB88114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json" :{
|
||||
"Account" :"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee" :"10",
|
||||
"Flags" :2147483648,
|
||||
"Sequence" :4,
|
||||
"SigningPubKey" :"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType" :"AccountSet",
|
||||
"TxnSignature" :"3045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB8",
|
||||
"hash" :"D9B305CB6E861D0994A5CDD4726129D91AC4277111DC444DE4CEE44AD4674A9F"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
`sign`コマンドの応答には上記のような`tx_blob`値が含まれています。オフライン署名応答には`signedTransaction`値が含まれています。いずれもトランザクションの署名済みバイナリ表現(ブロブ)です。
|
||||
|
||||
次に`submit`コマンドを使用して、トランザクションブロブ(`tx_blob`または`signedTransaction`)をネットワークに送信します。
|
||||
|
||||
|
||||
### トランザクションの送信
|
||||
|
||||
オフライン署名応答の`signedTransaction`値、または`sign`コマンド応答の`tx_blob`値をとり、[submitメソッド][]を使用して`tx_blob`値として送信します。
|
||||
|
||||
#### 要求フォーマット
|
||||
|
||||
要求フォーマットの例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"command":"submit",
|
||||
"tx_blob":"1200032280000000240000000468400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB88114623B8DA4A0BFB3B61AB423391A182DC693DC159E"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"method":"submit",
|
||||
"params":[
|
||||
{
|
||||
"tx_blob":"1200032280000000240000000468400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB88114623B8DA4A0BFB3B61AB423391A182DC693DC159E"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```sh
|
||||
#Syntax: submit tx_blob
|
||||
rippled submit 1200032280000000240000000468400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB88114623B8DA4A0BFB3B61AB423391A182DC693DC159E
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
#### 応答フォーマット
|
||||
|
||||
処理が成功した応答の例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"result":{
|
||||
"engine_result":"tesSUCCESS",
|
||||
"engine_result_code":0,
|
||||
"engine_result_message":"The transaction was applied.Only final in a validated ledger.",
|
||||
"tx_blob":"1200032280000000240000000468400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB88114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json":{
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"Sequence":4,
|
||||
"SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType":"AccountSet",
|
||||
"TxnSignature":"3045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB8",
|
||||
"hash":"D9B305CB6E861D0994A5CDD4726129D91AC4277111DC444DE4CEE44AD4674A9F"
|
||||
}
|
||||
},
|
||||
"status":"success",
|
||||
"type":"response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"result":{
|
||||
"engine_result":"tesSUCCESS",
|
||||
"engine_result_code":0,
|
||||
"engine_result_message":"The transaction was applied.Only final in a validated ledger.",
|
||||
"status":"success",
|
||||
"tx_blob":"1200032280000000240000000468400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB88114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json":{
|
||||
"Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"Sequence":4,
|
||||
"SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType":"AccountSet",
|
||||
"TxnSignature":"3045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB8",
|
||||
"hash":"D9B305CB6E861D0994A5CDD4726129D91AC4277111DC444DE4CEE44AD4674A9F"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{
|
||||
"result" :{
|
||||
"engine_result" :"tesSUCCESS",
|
||||
"engine_result_code" :0,
|
||||
"engine_result_message" :"The transaction was applied.Only final in a validated ledger.",
|
||||
"status" :"success",
|
||||
"tx_blob" :"1200032280000000240000000468400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB88114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json" :{
|
||||
"Account" :"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93",
|
||||
"Fee" :"10",
|
||||
"Flags" :2147483648,
|
||||
"Sequence" :4,
|
||||
"SigningPubKey" :"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType" :"AccountSet",
|
||||
"TxnSignature" :"3045022100A50E867D3B1B5A39F23F1ABCA5C7C3EC755442FDAA357EFD897B865ACA7686DB02206077BF459BCE39BCCBFE1A128DA986D1E00CBEC5F0D6B0E11710F60BE2976FB8",
|
||||
"hash" :"D9B305CB6E861D0994A5CDD4726129D91AC4277111DC444DE4CEE44AD4674A9F"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
## 4. 次のステップ
|
||||
|
||||
これで、レギュラーキーペアをアカウントに割り当てるメリットについて理解しました。次に以下の関連トピックとチュートリアルを参照してください。
|
||||
|
||||
- [レギュラーキーペアの変更または削除](change-or-remove-a-regular-key-pair.html)
|
||||
- [マルチシグの設定](set-up-multi-signing.html)
|
||||
- [発行アドレスと運用アドレス](account-types.html)
|
||||
- [取引所としてのXRPの上場](list-xrp-as-an-exchange.html)
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,369 +0,0 @@
|
||||
---
|
||||
html: change-or-remove-a-regular-key-pair.html
|
||||
parent: manage-account-settings.html
|
||||
blurb: アカウントですでに承認されているレギュラーキーペアを削除するか更新します。
|
||||
labels:
|
||||
- セキュリティ
|
||||
- アカウント
|
||||
---
|
||||
# レギュラーキーペアの変更または削除
|
||||
|
||||
XRP Ledgerでは、アカウントはその後のトランザクションには _レギュラーキーペア_ と呼ばれるセカンダリキーペアで署名することができます。アカウントのレギュラーキーペアが漏えいした場合、またはセキュリティ対策としてレギュラーキーペアを定期的に変更する必要がある場合は、[SetRegularKeyトランザクション][]を使用してアカウントレギュラーキーペアを削除または変更します。
|
||||
|
||||
マスターキーペアとレギュラーキーペアの詳細は、[暗号鍵](cryptographic-keys.html)を参照してください。
|
||||
|
||||
|
||||
## レギュラーキーペアの変更
|
||||
|
||||
既存のレギュラーキーペアを変更する手順は、初めて[レギュラーキーを割り当てる](assign-a-regular-key-pair.html)手順とほぼ同じです。キーペアを生成し、レギュラーキーペアとしてアカウントに割り当てます。これにより既存のレギュラーキーペアが上書きされます。ただし大きく異なる点は、既存のレギュラーキーペアを変更するときには既存のレギュラー秘密鍵を使用して秘密鍵自体を置き換えることができますが、レギュラーキーペアをアカウントに初めて割り当てるときにはアカウントのマスター秘密鍵を使用する必要があることです。
|
||||
|
||||
マスターキーペアとレギュラーキーペアの詳細は、[暗号鍵](cryptographic-keys.html)を参照してください。
|
||||
|
||||
|
||||
## レギュラーキーペアの削除
|
||||
|
||||
漏えいしたレギュラーキーペアを単にアカウントから削除する場合は、キーペアを最初に生成する必要はありません。`RegularKey`フィールドを省略した[SetRegularKeyトランザクション][]を使用します。アカウントの別の署名手段(マスターキーペアまたは[署名者リスト](multi-signing.html))が現在有効になっていない場合は、トランザクションが失敗することに注意してください。
|
||||
|
||||
|
||||
アカウントのレギュラーキーペアを削除する場合、`SetRegularKey`トランザクションでは、アカウントのマスター秘密鍵(シークレット)または既存のレギュラーキーペアによる署名が必要です。マスター秘密鍵またはレギュラー秘密鍵の送信は危険であるため、トランザクションの署名とネットワークへのトランザクションの送信を切り離した2段階方式でこのトランザクションを実行します。
|
||||
|
||||
### トランザクションの署名
|
||||
|
||||
{% include '_snippets/tutorial-sign-step.ja.md' %}
|
||||
<!--{#_ #}-->
|
||||
|
||||
要求フィールドに以下の値を指定します。
|
||||
|
||||
| 要求フィールド | 値 |
|
||||
|:--------------|:-------------------------------------------------------------|
|
||||
| `Account` | アカウントのアドレス。 |
|
||||
| `secret` | アカウントの`master_key`、`master_seed`、または`master_seed_hex`(マスター秘密鍵またはレギュラー秘密鍵) |
|
||||
|
||||
|
||||
#### 要求フォーマット
|
||||
|
||||
要求フォーマットの例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```
|
||||
{
|
||||
"command":"sign",
|
||||
"tx_json":{
|
||||
"TransactionType":"SetRegularKey",
|
||||
"Account":"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8"
|
||||
},
|
||||
"secret":"snoPBrXtMeMyMHUVTgbuqAfg1SUTb"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```
|
||||
{
|
||||
"method":"sign",
|
||||
"params":[
|
||||
{
|
||||
"secret" :"snoPBrXtMeMyMHUVTgbuqAfg1SUTb",
|
||||
"tx_json" :{
|
||||
"TransactionType" :"SetRegularKey",
|
||||
"Account" :"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```
|
||||
#Syntax: sign secret tx_json
|
||||
rippled sign snoPBrXtMeMyMHUVTgbuqAfg1SUTb '{"TransactionType":"SetRegularKey", "Account":"rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93"}'
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
#### 応答フォーマット
|
||||
|
||||
処理が成功した応答の例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```
|
||||
{
|
||||
"result":{
|
||||
"tx_blob":"1200052280000000240000000268400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E838114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json":{
|
||||
"Account":"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"Sequence":2,
|
||||
"SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType":"SetRegularKey",
|
||||
"TxnSignature":"3045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E83",
|
||||
"hash":"59BCAB8E5B9D4597D6A7BFF22F6C555D0F41420599A2E126035B6AF19261AD97"
|
||||
}
|
||||
},
|
||||
"status":"success",
|
||||
"type":"response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```
|
||||
{NEWWWWWWWWWWWW
|
||||
"result":{
|
||||
"status":"success",
|
||||
"tx_blob":"1200052280000000240000000268400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E838114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json":{
|
||||
"Account":"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"Sequence":2,
|
||||
"SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType":"SetRegularKey",
|
||||
"TxnSignature":"3045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E83",
|
||||
"hash":"59BCAB8E5B9D4597D6A7BFF22F6C555D0F41420599A2E126035B6AF19261AD97"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```
|
||||
{
|
||||
"result" :{
|
||||
"status" :"success",
|
||||
"tx_blob" :"1200052280000000240000000268400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E838114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json" :{
|
||||
"Account" :"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8",
|
||||
"Fee" :"10",
|
||||
"Flags" :2147483648,
|
||||
"Sequence" :2,
|
||||
"SigningPubKey" :"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType" :"SetRegularKey",
|
||||
"TxnSignature" :"3045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E83",
|
||||
"hash" :"59BCAB8E5B9D4597D6A7BFF22F6C555D0F41420599A2E126035B6AF19261AD97"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
`sign`コマンドの応答には上記のような`tx_blob`値が含まれています。オフライン署名応答には`signedTransaction`値が含まれています。いずれもトランザクションの署名済みバイナリ表現(ブロブ)です。
|
||||
|
||||
次に`submit`コマンドを使用して、トランザクションブロブ(`tx_blob`または`signedTransaction`)をネットワークに送信します。
|
||||
|
||||
|
||||
### トランザクションの送信
|
||||
|
||||
オフライン署名応答の`signedTransaction`値、または`sign`コマンド応答の`tx_blob`値をとり、[submitメソッド][]を使用して`tx_blob`として送信します。
|
||||
|
||||
#### 要求フォーマット
|
||||
|
||||
要求フォーマットの例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```
|
||||
{
|
||||
"command":"submit",
|
||||
"tx_blob":"1200052280000000240000000268400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E838114623B8DA4A0BFB3B61AB423391A182DC693DC159E"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```
|
||||
{
|
||||
"method":"submit",
|
||||
"params":[
|
||||
{
|
||||
"tx_blob":"1200052280000000240000000268400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E838114623B8DA4A0BFB3B61AB423391A182DC693DC159E"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```
|
||||
#Syntax: submit tx_blob
|
||||
rippled submit 1200052280000000240000000268400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E838114623B8DA4A0BFB3B61AB423391A182DC693DC159E
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
#### 応答フォーマット
|
||||
|
||||
処理が成功した応答の例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```
|
||||
{
|
||||
"result":{
|
||||
"engine_result":"tesSUCCESS",
|
||||
"engine_result_code":0,
|
||||
"engine_result_message":"The transaction was applied.Only final in a validated ledger.",
|
||||
"tx_blob":"1200052280000000240000000268400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E838114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json":{
|
||||
"Account":"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"Sequence":2,
|
||||
"SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType":"SetRegularKey",
|
||||
"TxnSignature":"3045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E83",
|
||||
"hash":"59BCAB8E5B9D4597D6A7BFF22F6C555D0F41420599A2E126035B6AF19261AD97"
|
||||
}
|
||||
},
|
||||
"status":"success",
|
||||
"type":"response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```
|
||||
{
|
||||
"result":{
|
||||
"engine_result":"tesSUCCESS",
|
||||
"engine_result_code":0,
|
||||
"engine_result_message":"The transaction was applied.Only final in a validated ledger.",
|
||||
"status":"success",
|
||||
"tx_blob":"1200052280000000240000000268400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E838114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json":{
|
||||
"Account":"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8",
|
||||
"Fee":"10",
|
||||
"Flags":2147483648,
|
||||
"Sequence":2,
|
||||
"SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType":"SetRegularKey",
|
||||
"TxnSignature":"3045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E83",
|
||||
"hash":"59BCAB8E5B9D4597D6A7BFF22F6C555D0F41420599A2E126035B6AF19261AD97"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```
|
||||
{
|
||||
"result" :{
|
||||
"engine_result" :"tesSUCCESS",
|
||||
"engine_result_code" :0,
|
||||
"engine_result_message" :"The transaction was applied.Only final in a validated ledger.",
|
||||
"status" :"success",
|
||||
"tx_blob" :"1200052280000000240000000268400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E838114623B8DA4A0BFB3B61AB423391A182DC693DC159E",
|
||||
"tx_json" :{
|
||||
"Account" :"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8",
|
||||
"Fee" :"10",
|
||||
"Flags" :2147483648,
|
||||
"Sequence" :2,
|
||||
"SigningPubKey" :"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType" :"SetRegularKey",
|
||||
"TxnSignature" :"3045022100CAB9A6F84026D57B05760D5E2395FB7BE86BF39F10DC6E2E69DC91238EE0970B022058EC36A8EF9EE65F5D0D8CAC4E88C8C19FEF39E40F53D4CCECBB59701D6D1E83",
|
||||
"hash" :"59BCAB8E5B9D4597D6A7BFF22F6C555D0F41420599A2E126035B6AF19261AD97"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
レギュラーキーペアの削除が成功したかどうかを確認するには、削除したレギュラー秘密鍵を使用してトランザクションを送信できないことを確認します。
|
||||
|
||||
前述の`SetRegularKey`トランザクションにより削除されたレギュラー秘密鍵を使用して[AccountSetトランザクション][]に署名した際のエラー応答の例を以下に示します。
|
||||
|
||||
|
||||
### 応答フォーマット
|
||||
|
||||
処理が成功した応答の例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```
|
||||
{
|
||||
"error":"badSecret",
|
||||
"error_code":41,
|
||||
"error_message":"Secret does not match account.",
|
||||
"request":{
|
||||
"command":"submit",
|
||||
"secret":"snoPBrXtMeMyMHUVTgbuqAfg1SUTb",
|
||||
"tx_json":{
|
||||
"Account":"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8",
|
||||
"TransactionType":"AccountSet"
|
||||
}
|
||||
},
|
||||
"status":"error",
|
||||
"type":"response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```
|
||||
{NEWWWWWWWWWWWW
|
||||
"result":{
|
||||
"error":"badSecret",
|
||||
"error_code":41,
|
||||
"error_message":"Secret does not match account.",
|
||||
"request":{
|
||||
"command":"submit",
|
||||
"secret":"snoPBrXtMeMyMHUVTgbuqAfg1SUTb",
|
||||
"tx_json":{
|
||||
"Account":"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8",
|
||||
"TransactionType":"AccountSet"
|
||||
}
|
||||
},
|
||||
"status":"error"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```
|
||||
{
|
||||
"result" :{
|
||||
"error" :"badSecret",
|
||||
"error_code" :41,
|
||||
"error_message" :"Secret does not match account.",
|
||||
"request" :{
|
||||
"command" :"submit",
|
||||
"secret" :"snoPBrXtMeMyMHUVTgbuqAfg1SUTb",
|
||||
"tx_json" :{
|
||||
"Account" :"r9xQZdFGwbwTB3g9ncKByWZ3du6Skm7gQ8",
|
||||
"TransactionType" :"AccountSet"
|
||||
}
|
||||
},
|
||||
"status" :"error"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
場合によっては、`SetRegularKey`トランザクションを使用して、[トランザクションコスト](transaction-cost.html)を支払わずに[Key Resetトランザクション](transaction-cost.html#key-resetトランザクション)を送信できます。FeeEscalation Amendmentを有効にすると、Key Resetトランザクションの名目トランザクションコストがゼロであっても、`rippled`は他のトランザクションよりもKey Resetトランザクションを優先します。
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,509 +0,0 @@
|
||||
---
|
||||
html: disable-master-key-pair.html
|
||||
parent: manage-account-settings.html
|
||||
blurb: アドレスに数学的に関連付けられたマスターキーを無効にする。
|
||||
labels:
|
||||
- セキュリティ
|
||||
- アカウント
|
||||
---
|
||||
# マスターキーペアの無効化
|
||||
|
||||
このページでは、[アカウント](accounts.html)のアドレスに数学的に関連付けられた[マスターキーペア](cryptographic-keys.html)を無効化する方法について説明します。あなたのアカウントのマスターキーペアが漏洩した可能性がある場合、または[マルチシグ](multi-signing.html)をあなたのアカウントからトランザクションを送信する _唯一_ の方法としたい場合、これを行う必要があります。
|
||||
|
||||
**注意:** マスターキーペアを無効にすると、[トランザクションの承認](transactions.html#トランザクションの承認)の方法の1つが削除されます。マスターキーペアを無効にする前に、レギュラーキーやマルチ・サインなど、他のトランザクションの承認方法のいずれかを使用できることを確認する必要があります。(例えば、[レギュラーキーペアを割り当てた場合](assign-a-regular-key-pair.html)は、そのレギュラーキーで正常にトランザクションを送信できることを確認してください)。XRP Ledgerは分散型であるため、残りの取引承認方法を使用できない場合、誰もあなたのアカウントへのアクセスを回復することができません。
|
||||
|
||||
**マスターキーペアを無効にするには、マスターキーペアを使用する必要があります。**
|
||||
ただし、他のトランザクションの認証方法を使用してマスターキーペアを _再有効化_ することは可能です。
|
||||
|
||||
## 前提条件
|
||||
|
||||
アカウントのマスターキーペアを無効にするには、次の前提条件を満たしている必要があります。
|
||||
|
||||
- XRP Ledger[アカウント](accounts.html)を持ち、そのアカウントからマスターキーペアを用いてトランザクションの署名と提出ができることが必要です。[安全な署名の設定](secure-signing.html) を参照してください。これには2つの一般的な方法があります。
|
||||
- アカウントのマスターシード値を知っている。シード値は一般的に `sn3nxiW7v8KXzPzAqzyHXbSSKNuN9`のような "s" で始まる [base58][] 値で表されます。
|
||||
- あるいは、シード値を知る必要がなく、安全に保存する[専用の署名デバイス](secure-signing.html#専用の署名デバイスを使用する) を使用します
|
||||
- あなたのアカウントには、マスターキーペア以外のトランザクションを認証する方法が少なくとも1つ必要です。つまり、以下のいずれか、または両方を行う必要があります。
|
||||
- [レギュラーキーペアを割り当てる](assign-a-regular-key-pair.html).
|
||||
- [マルチシグの設定](set-up-multi-signing.html).
|
||||
|
||||
## 手順
|
||||
|
||||
{% set n = cycler(* range(1,99)) %}
|
||||
|
||||
### {{n.next()}}. トランザクションJSONの作成
|
||||
|
||||
アカウントから、`"SetValue": 4`のフィールドを持つ[AccountSet トランザクション][]を準備します。これは AccountSet フラグ "Disable Master" (`asfDisableMaster`) に対応する値です。このトランザクションの他の必須フィールドは、必須の[共通フィールド](transaction-common-fields.html)のみです。例えば、[自動入力可能なフィールド](transaction-common-fields.html#自動入力可能なフィールド) を省けば、以下のトランザクション指示で十分である。
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"SetFlag": 4
|
||||
}
|
||||
```
|
||||
|
||||
**ヒント:** [予測可能な時間内にトランザクションの結果を確実に得る](reliable-transaction-submission.html)ために、`LastLedgerSequence`フィールドも提供することが強く推奨されています。
|
||||
|
||||
### {{n.next()}}. トランザクションへの署名
|
||||
|
||||
トランザクションの署名には、**マスターキーペア**を使用する必要があります。
|
||||
|
||||
**注意:** 自分が管理していないサーバーに秘密鍵を提出したり、暗号化されていない状態でネットワーク上に送信したりしないでください。これらの例は、[ローカルの `rippled` サーバー](secure-signing.html#ローカルでrippledを実行する) を使っていることを前提にしています。他の[安全な署名方法](secure-signing.html)を使っている場合は、これらの手順を変更する必要があります。
|
||||
|
||||
#### リクエストの例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"command": "sign",
|
||||
"tx_json": {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"SetFlag": 4
|
||||
},
|
||||
"secret": "s████████████████████████████"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "sign",
|
||||
"params": [
|
||||
{
|
||||
"tx_json": {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"SetFlag": 4
|
||||
},
|
||||
"secret": "s████████████████████████████"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```sh
|
||||
$ rippled sign s████████████████████████████ '{"TransactionType":"AccountSet",
|
||||
"Account":"rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "SetFlag":4}'
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
#### レスポンスの例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"deprecated": "This command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
|
||||
"tx_blob": "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "10",
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 380,
|
||||
"SetFlag": 4,
|
||||
"SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType": "AccountSet",
|
||||
"TxnSignature": "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
},
|
||||
"status": "success",
|
||||
"type": "response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"deprecated": "This command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
|
||||
"status": "success",
|
||||
"tx_blob": "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "10",
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 380,
|
||||
"SetFlag": 4,
|
||||
"SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType": "AccountSet",
|
||||
"TxnSignature": "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```sh
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2020-Feb-13 00:13:24.783570867 HTTPClient:NFO Connecting to 127.0.0.1:5005
|
||||
|
||||
{
|
||||
"result" : {
|
||||
"deprecated" : "This command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
|
||||
"status" : "success",
|
||||
"tx_blob" : "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "10",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 380,
|
||||
"SetFlag" : 4,
|
||||
"SigningPubKey" : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
サーバーがトランザクションに正常に署名したことを示す `"status": "success"` を探してください。代わりに `"status": "error"` が表示された場合は、 `error` と `error_message` フィールドをチェックして、より詳しい情報を確認してください。よくある可能性としては、以下のようなものがあります。
|
||||
|
||||
- `"error": "badSecret"` は通常、リクエストの`secret`にタイプミスがあったことを意味します。
|
||||
- `"error": "masterDisabled"` は、このアドレスのマスターキーペアが _既に_ 無効であることを意味します。
|
||||
|
||||
レスポンスに含まれる `tx_blob` の値をメモしておきます。これはネットワークに送信できる署名済みトランザクションバイナリである。
|
||||
|
||||
### {{n.next()}}. トランザクションの送信
|
||||
|
||||
前のステップで署名されたトランザクションblobをXRP Ledgerに提出します。
|
||||
|
||||
#### リクエストの例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"command": "submit",
|
||||
"tx_blob": "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"method":"submit",
|
||||
"params": [
|
||||
{
|
||||
"tx_blob": "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```
|
||||
$ rippled submit 1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
#### レスポンスの例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"engine_result" : "tesSUCCESS",
|
||||
"engine_result_code" : 0,
|
||||
"engine_result_message" : "The transaction was applied. Only final in a validated ledger.",
|
||||
"tx_blob" : "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "10",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 380,
|
||||
"SetFlag" : 4,
|
||||
"SigningPubKey" : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
},
|
||||
"status": "success",
|
||||
"type": "response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"result" : {
|
||||
"engine_result" : "tesSUCCESS",
|
||||
"engine_result_code" : 0,
|
||||
"engine_result_message" : "The transaction was applied. Only final in a validated ledger.",
|
||||
"status" : "success",
|
||||
"tx_blob" : "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "10",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 380,
|
||||
"SetFlag" : 4,
|
||||
"SigningPubKey" : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```sh
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2020-Feb-13 00:25:49.361743460 HTTPClient:NFO Connecting to 127.0.0.1:5005
|
||||
|
||||
{
|
||||
"result" : {
|
||||
"engine_result" : "tesSUCCESS",
|
||||
"engine_result_code" : 0,
|
||||
"engine_result_message" : "The transaction was applied. Only final in a validated ledger.",
|
||||
"status" : "success",
|
||||
"tx_blob" : "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "10",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 380,
|
||||
"SetFlag" : 4,
|
||||
"SigningPubKey" : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
トランザクションが `tecNO_ALTERNATIVE_KEY` という結果で失敗した場合、あなたのアカウントでは現在トランザクションを認証するための別の方法が有効になっていません。[レギュラーキーペアを割り当てる](assign-a-regular-key-pair.html)か [マルチシグを設定](set-up-multi-signing.html) した後、再度マスターキーペアの無効化を試してみてください。
|
||||
|
||||
|
||||
### {{n.next()}}. 検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
### {{n.next()}}. アカウントフラグの確認
|
||||
|
||||
[account_infoメソッド][]で、アカウントのマスターキーが無効になっていることを確認します。以下のパラメータを必ず指定してください。
|
||||
|
||||
| フィールド | 値 |
|
||||
|:---------------|:-----------------------------------------------------------------------------|
|
||||
| `account` | アカウントのアドレス |
|
||||
| `ledger_index` | `"validated"` とすると、検証済みの最新バージョンのレジャーから結果を得ることができます。 |
|
||||
|
||||
#### リクエストの例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"command": "account_info",
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "account_info",
|
||||
"params": [{
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```sh
|
||||
rippled account_info rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn validated
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
#### レスポンスの例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"account_data": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"Balance": "423013688",
|
||||
"Domain": "6D64756F31332E636F6D",
|
||||
"EmailHash": "98B4375E1D753E5B91627516F6D70977",
|
||||
"Flags": 9633792,
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"MessageKey": "0000000000000000000000070000000300",
|
||||
"OwnerCount": 9,
|
||||
"PreviousTxnID": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"PreviousTxnLgrSeq": 53391321,
|
||||
"RegularKey": "rD9iJmieYHn8jTtPjwwkW2Wm9sVDvPXLoJ",
|
||||
"Sequence": 381,
|
||||
"TransferRate": 4294967295,
|
||||
"index": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"urlgravatar": "http://www.gravatar.com/avatar/98b4375e1d753e5b91627516f6d70977"
|
||||
},
|
||||
"ledger_hash": "A90CEBD4AEDA24470AAC5CD307B6D26267ACE79C03669A0A0B8C41ACAEDAA6F0",
|
||||
"ledger_index": 53391576,
|
||||
"validated": true
|
||||
},
|
||||
"status": "success",
|
||||
"type": "response"
|
||||
}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"account_data": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"Balance": "423013688",
|
||||
"Domain": "6D64756F31332E636F6D",
|
||||
"EmailHash": "98B4375E1D753E5B91627516F6D70977",
|
||||
"Flags": 9633792,
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"MessageKey": "0000000000000000000000070000000300",
|
||||
"OwnerCount": 9,
|
||||
"PreviousTxnID": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"PreviousTxnLgrSeq": 53391321,
|
||||
"RegularKey": "rD9iJmieYHn8jTtPjwwkW2Wm9sVDvPXLoJ",
|
||||
"Sequence": 381,
|
||||
"TransferRate": 4294967295,
|
||||
"index": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"urlgravatar": "http://www.gravatar.com/avatar/98b4375e1d753e5b91627516f6d70977"
|
||||
},
|
||||
"ledger_hash": "4C4AC95149B13B539369998675FE6860C52695E83658366F18872181C9F1AEBF",
|
||||
"ledger_index": 53391589,
|
||||
"status": "success",
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```sh
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2020-Feb-13 00:41:38.642710734 HTTPClient:NFO Connecting to 127.0.0.1:5005
|
||||
|
||||
{
|
||||
"result" : {
|
||||
"account_data" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"Balance" : "423013688",
|
||||
"Domain" : "6D64756F31332E636F6D",
|
||||
"EmailHash" : "98B4375E1D753E5B91627516F6D70977",
|
||||
"Flags" : 9633792,
|
||||
"LedgerEntryType" : "AccountRoot",
|
||||
"MessageKey" : "0000000000000000000000070000000300",
|
||||
"OwnerCount" : 9,
|
||||
"PreviousTxnID" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"PreviousTxnLgrSeq" : 53391321,
|
||||
"RegularKey" : "rD9iJmieYHn8jTtPjwwkW2Wm9sVDvPXLoJ",
|
||||
"Sequence" : 381,
|
||||
"TransferRate" : 4294967295,
|
||||
"index" : "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"urlgravatar" : "http://www.gravatar.com/avatar/98b4375e1d753e5b91627516f6d70977"
|
||||
},
|
||||
"ledger_hash" : "BBA4034FB5D5D89987E0987A9491E7B62B16708EECFF04CDB0367BD4D28EB1B5",
|
||||
"ledger_index" : 53391568,
|
||||
"status" : "success",
|
||||
"validated" : true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
レスポンスの `account_data` オブジェクトで、 `Flags` フィールドと `lsfDisableMaster` フラグの値 (16 進数では `0x00100000`、10 進数では `1048576`) を ビット論理積 (ほとんどのプログラミング言語では `&` オペレーター) で比較します。
|
||||
|
||||
コード例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*JavaScript*
|
||||
|
||||
```js
|
||||
// 上記のJSON-RPCレスポンスがaccount_info_responseとして保存されていると仮定します。
|
||||
const lsfDisableMaster = 0x00100000;
|
||||
let acct_flags = account_info_response.result.account_data.Flags;
|
||||
if ((lsfDisableMaster & acct_flags) === lsfDisableMaster) {
|
||||
console.log("マスターキーペアが無効化されています");
|
||||
} else {
|
||||
console.log("マスターキーペアが使用可能です");
|
||||
}
|
||||
```
|
||||
|
||||
*Python*
|
||||
|
||||
```python
|
||||
# 上記のJSON-RPCレスポンスがJSONから解析され、
|
||||
# 変数account_info_responseとして保存されたと仮定すると、以下のようになります。
|
||||
lsfDisableMaster = 0x00100000
|
||||
acct_flags = account_info_response["result"]["account_data"]["Flags"]
|
||||
if lsfDisableMaster & acct_flags == lsfDisableMaster:
|
||||
console.log("マスターキーペアが無効化されています");
|
||||
else:
|
||||
console.log("マスターキーペアが使用可能です");
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
この操作の結果は次の2つしかありません。
|
||||
|
||||
- 結果が0でない場合は `lsfDisableMaster` の値と等しく、 **マスターキーが正常に無効化されたこと** を示します。
|
||||
- 結果が0の場合は、そのアカウントのマスターキーが無効になっていないことを示します。
|
||||
|
||||
結果が予想と異なる場合は、前の手順で送信したトランザクションが正常に実行されたかどうかを確認してください。それは、その口座のトランザクション履歴([account_tx メソッド][])の中で最も新しいもので、結果コード `tesSUCCESS` がついているはずです。それ以外の[結果コード](transaction-results.html)が表示された場合、そのトランザクションは正常に実行されませんでした。エラーの原因によっては、これらの手順を最初からやり直した方がよいかもしれません。
|
||||
|
||||
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,348 +0,0 @@
|
||||
---
|
||||
html: offline-account-setup.html
|
||||
parent: manage-account-settings.html
|
||||
blurb: 物理的に隔離されたオフラインのマシンを使用して暗号鍵を保管するXRP Ledgerアカウントを設定します。
|
||||
labels:
|
||||
- アカウント
|
||||
- セキュリティ
|
||||
---
|
||||
# オフラインでのアカウント設定のチュートリアル
|
||||
|
||||
きわめて安全な[署名構成](secure-signing.html)では、XRP Ledger[アカウント](accounts.html)の[暗号鍵](cryptographic-keys.html)をオフラインの物理的に隔離されたマシンに安全に保管します。この構成を設定すると、さまざまなトランザクションに署名して、署名済みトランザクションのみをオンラインコンピューターに転送し、秘密鍵をオンラインにいる不正使用者に見せることなくそれらのトランザクションをXRP Ledgerネットワークに送信できます。
|
||||
|
||||
**注意:** オフラインマシンを保護するためには、適切な運用セキュリティ対策が必要です。例えば、オフラインマシンは信頼できない人がアクセスできない場所に物理的に設置する必要があり、信頼できるオペレーターはマシンに悪用されたソフトウェアを転送しないように注意する必要があります。(例えば、ネットワークに接続されたコンピューターに接続したことがあるUSBドライブは使用してはいけません。)
|
||||
|
||||
## 前提条件
|
||||
|
||||
オフライン署名を使用するには、次の前提条件を満たしている必要があります。
|
||||
|
||||
- オフラインマシンとして使用する1台のコンピューターを用意していること。このマシンは[サポートされているオペレーティングシステム](system-requirements.html)でセットアップされている必要があります。オフラインセットアップの手順については、使用するオペレーティングシステムのサポートを参照してください(例: [Red Hat Enterprise Linux DVD ISOインストール手順](https://access.redhat.com/solutions/7227))。使用するソフトウェアと物理メディアがマルウェアに感染していないことを確認します。
|
||||
- オンラインマシンとして使用する別のコンピューターを用意していること。このマシンは`rippled`を実行する必要はありませんが、XRP Ledgerネットワークに接続し、共有レジャーの状態についての正確な情報を受信できる必要があります。例えば、[公開サーバーへのWebSocket接続](get-started-using-http-websocket-apis.html)を使用できます。
|
||||
- 署名済みのトランザクションバイナリデータをオフラインマシンからオンラインマシンに転送する安全な方法を用意していること。
|
||||
- その方法の1つは、オフラインマシンでQRコードジェネレーターを使用し、オンラインマシンでQRコードスキャナーを使用することです。(この場合、「オンラインマシン」はスマートフォンなどの携帯デバイスだとよいでしょう。)
|
||||
- 別の方法としては、物理メディアを使ってオフラインマシンからオンラインマシンにファイルをコピーします。この方法を使用する場合、オフラインマシンが悪意のあるソフトウェアに感染するおそれのある物理メディアは使用しないよう注意します。(例えば、オンラインマシンとオフラインマシンで同じUSBドライブを再利用しないようにします。)
|
||||
- オンラインマシンにデータを手動で入力することも _可能_ ですが、面倒でミスが発生しやすくなります。
|
||||
|
||||
|
||||
## 手順
|
||||
|
||||
{% set n = cycler(* range(1,99)) %}
|
||||
|
||||
### {{n.next()}}. オフラインマシンの設定
|
||||
|
||||
オフラインマシンには、安全な永続ストレージ(暗号化されたディスクドライブなど)と[トランザクションに署名する](secure-signing.html)ための方法が必要です。一般的には、必要なソフトウェアをオンラインマシンでダウンロードして、物理メディアを使ってオフラインマシンに転送します。オンラインマシン、物理メディア、ソフトウェア自体がマルウェアに感染していないことを確認する必要があります。
|
||||
|
||||
XRP Ledgerで署名するためのソフトウェアオプションは次のとおりです。
|
||||
|
||||
- パッケージ(`.deb`または`.rpm`。使用するLinuxディストリビューションによって異なる)ファイルから[`rippled`をインストール](install-rippled.html)し、[スタンドアロンモードで実行します](rippled-server-modes.html)。
|
||||
- [xrpl.js](https://github.com/XRPLF/xrpl.js/)とその依存関係をオフラインでインストールします。例えば、Yarn Package Managerでは、[オフラインでの使用に関して推奨される手順](https://yarnpkg.com/blog/2016/11/24/offline-mirror/)があります。
|
||||
- 関連項目: [安全な署名の設定](secure-signing.html)
|
||||
|
||||
オフラインマシンでトランザクションの指示を生成するプロセスを容易にするために、カスタムソフトウェアを設定することもできます。例えば、ソフトウェアで次に使用する[シーケンス番号][]を追跡したり、送信するトランザクションのタイプに応じた設定済みテンプレートを含めるといったことが可能です。
|
||||
|
||||
### {{n.next()}}.暗号鍵の生成
|
||||
|
||||
**オフラインマシン**で、アカウントで使用する[暗号鍵](cryptographic-keys.html)のペアを生成します。鍵は、単純なパスフレーズやエントロピーが十分でないその他のソースから生成するのではなく、安全なランダム手続きで生成してください。(例えば、`rippled`の[wallet_proposeメソッド][]を使用することができます。)
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
|
||||
_rippledコマンドライン_
|
||||
|
||||
```sh
|
||||
$ ./rippled wallet_propose
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2019-Dec-09 22:58:24.110862955 HTTPClient:NFO Connecting to 127.0.0.1:5005
|
||||
|
||||
{
|
||||
"result" : {
|
||||
"account_id" : "r4MRc4BArFPXmiDjmLdrufyFManSYhfKE6",
|
||||
"key_type" : "secp256k1",
|
||||
"master_key" : "JANE GIBE LIST TEND NU RUDE JIG PA FLOG DEFT SAME NASH",
|
||||
"master_seed" : "shYHSiJod8CLPTj1SNJ2PdUFj4pFk",
|
||||
"master_seed_hex" : "8465FDB80B2E2620A7D58274C26291A0",
|
||||
"public_key" : "aBQLW8imt7VChRJU1NMVCB7fE3jSL3VNEgLDKf88ygAhnfuZh3oo",
|
||||
"public_key_hex" : "03396074ED4B8155ACF9A8DC3665EFA53B5CFA0A1E91C3879303D37721EB222644",
|
||||
"status" : "success"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
次の値をメモします。
|
||||
|
||||
- **`account_id`**: これはキーペアに関連付けられているアドレスです。このアドレスは、XRPを供給(このプロセスの先で実行)した後に、XRP Ledgerでの **[アカウント](accounts.html)アドレス**になります。`account_id`は公開しても安全です。
|
||||
- **`master_seed`**: これはキーペアの秘密シード値です。この値は、アカウントからのトランザクションに署名する際に使用します。最高レベルのセキュリティを実現するために、この値をオフラインマシンのディスクに書き込む前に暗号化してください。暗号化キーとして、人間のオペレーターが覚えやすい安全なパスフレーズや、物理的に安全な場所に書き留めたパスフレーズを使います。例えば、適切な重さのサイコロを使用して作成する[ダイスウェアパスフレーズ](https://theworld.com/~reinhold/diceware.html)などがあります。第2の要素として物理セキュリティキーを使用することもできます。この段階で取る対策の程度はご自身で決めてください。
|
||||
- **`key_type`**: これは、このキーペアに使用する暗号化アルゴリズムです。有効なトランザクションに署名するには、どのようなタイプのキーペアを所有しているかを知る必要があります。デフォルトは`secp256k1`です。
|
||||
|
||||
`master_key`、`master_seed`、`master_seed_hex`の値はどこにも共有**しないでください**。これらはこのアドレスに関連付けられている秘密鍵を再作成するために使用できます。
|
||||
|
||||
|
||||
|
||||
### {{n.next()}}.新しいアドレスへの資金の供給
|
||||
|
||||
オンラインマシンから、ステップ1でメモした**アカウントアドレス** に十分なXRPを送金します。詳細は、[アカウントの作成](accounts.html#アカウントの作成)を参照してください。
|
||||
|
||||
**ヒント:** テストの目的で、[Testnet Faucet](xrp-testnet-faucet.html)を使用して、テスト用のXRPが入った新しいアカウントを取得できます。そのアカウントを使用して、オフラインで生成されたアドレスに資金を供給します。
|
||||
|
||||
|
||||
|
||||
### {{n.next()}}.アカウントの詳細の確認
|
||||
|
||||
前のステップからのトランザクションがコンセンサスにより検証されたら、アカウントが作成されたことになります。オンラインマシンから、[account_infoメソッド][]を使用して、アカウントのステータスを確認します。応答に`"validated": true`が含まれていることを確認し、この結果が最終的なものであることを確認します。
|
||||
|
||||
結果の`account_data`の`Sequence`フィールドにある、アカウントのシーケンス番号をメモします。この後のステップでアカウントのトランザクションに署名するために、このシーケンス番号を把握しておく必要があります。
|
||||
|
||||
[DeletableAccounts Amendment](known-amendments.html#deletableaccounts)がenabledになっている場合、新しく資金を供給したアカウントの`Sequence`番号は、資金を供給したときの[レジャーインデックス][]と一致します。enabledになっていない場合、新しく資金を供給したアカウントの`Sequence`番号は常に1です。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_rippledコマンドライン_
|
||||
|
||||
```sh
|
||||
$ ./rippled account_info rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn
|
||||
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2019-Dec-11 01:06:21.728637950 HTTPClient:NFO Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"account_data" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Balance" : "5000000000000",
|
||||
"Flags" : 0,
|
||||
"LedgerEntryType" : "AccountRoot",
|
||||
"OwnerCount" : 0,
|
||||
"PreviousTxnID" : "00C5B713B11DA775C6F932D38CE162C16FA88B7269BAFC6FDF4C6ADB74419670",
|
||||
"PreviousTxnLgrSeq" : 3,
|
||||
"Sequence" : 1,
|
||||
"index" : "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8"
|
||||
},
|
||||
"ledger_current_index" : 4,
|
||||
"status" : "success",
|
||||
"validated" : false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
### {{n.next()}}.オフラインマシンでのシーケンス番号の入力
|
||||
|
||||
オフラインマシンでアカウントの開始シーケンス番号を保存します。オフラインマシンを使用してトランザクションを準備するときは、必ずこの保存されたシーケンス番号を使用し、シーケンス番号を1増やして、新しい値を保存します。
|
||||
|
||||
この方法で複数のトランザクションを前もって準備しておき、署名済みのトランザクションを一度にオンラインマシンに転送して、すべてを送信できます。各トランザクションの形式が有効で、十分な[トランザクションコスト](transaction-cost.html)を支払っていれば、XRP Ledgerネットワークは最終的にこれらのトランザクションを検証済みレジャーに含めて、共有XRP Ledgerにあるアカウントのシーケンス番号と、オフラインマシンで追跡している「現在の」シーケンス番号と同期が保たれるようにします。(ほとんどのトランザクションでは、ネットワークに送信して15秒以内に最終的な検証済みの結果が得られます。)
|
||||
|
||||
任意で、現在のレジャーインデックスをオフラインマシンに保存します。この値を使用して、今後のトランザクションに適切な`LastLedgerSequence`値を選択できます。
|
||||
|
||||
|
||||
|
||||
### {{n.next()}}.初期設定トランザクションの署名(ある場合)
|
||||
|
||||
オフラインマシンで、アカウントの設定用のトランザクションを準備して署名します。詳細は、アカウントを使用する目的によって異なります。例えば次のようなことができます。
|
||||
|
||||
- 定期的なローテーションで使用できる[レギュラーキーペアを割り当てる](assign-a-regular-key-pair.html)。
|
||||
- ユーザーが送金理由や送金相手をタグ付けせずに送金できないようにするために、[宛先タグを要求する](require-destination-tags.html)。
|
||||
- アカウントセキュリティを強化するために、[マルチシグを設定する](set-up-multi-signing.html)。
|
||||
- 明示的に承認した送金、または事前に承認した相手からの送金のみを受け取れるようにするために、[DepositAuthを有効にする](depositauth.html)。
|
||||
- ユーザーがあなたの許可なくあなたへの[トラストライン](trust-lines-and-issuing.html)を開けないようにするために、[RequireAuthを有効にする](authorized-trust-lines.html#requireauthの有効化)。XRP Ledgerの分散型取引所や発行済み通貨機能を使用する予定がない場合は、これを対策として行うことをお勧めします。
|
||||
- 発行済み通貨[ゲートウェイ](stablecoin-issuer.html)には次のような追加の設定がある場合があります。
|
||||
- 発行済み通貨を送金するユーザーに対して[TransferRateを設定する](stablecoin-issuer.html#transfer-fees)。
|
||||
- このアドレスを発行済み通貨のみに使用する予定の場合は、[XRPペイメントを禁止する](stablecoin-issuer.html#disallow-xrp)。
|
||||
|
||||
この段階では、トランザクションに署名をするだけで、まだ送信しません。各トランザクションに対して、`Fee`([トランザクションコスト](transaction-cost.html))や`Sequence`([シーケンス番号][])など、通常は自動入力可能なフィールドを含めて、すべてのフィールドに入力する必要があります。一度に複数のトランザクションを準備する場合は、トランザクションの実行順にシーケンシャルに増やした`Sequence`番号を使用する必要があります。
|
||||
|
||||
例(RequireAuthを有効にする):
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_rippledコマンドライン_
|
||||
|
||||
```sh
|
||||
$ rippled sign sn3nxiW7v8KXzPzAqzyHXbSSKNuN9 '{"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Fee": "12", "Sequence": 1, "TransactionType": "AccountSet", "SetFlag": 2}' offline
|
||||
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2019-Dec-11 00:18:31.865955978 HTTPClient:NFO Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"deprecated" : "This command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
|
||||
"status" : "success",
|
||||
"tx_blob" : "1200032280000000240000000120210000000268400000000000000C7321039543A0D3004CDA0904A09FB3710251C652D69EA338589279BC849D47A7B019A174473045022100D5C92D7705036CD7EBB601C8DFCD90927FA591A62AF832C489E9C898EC8E2FA0022052F1819340EB73E9749B8930A6935727362B8E141D1B2E246B49F912223FFD4381144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "12",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 1,
|
||||
"SetFlag" : 2,
|
||||
"SigningPubKey" : "039543A0D3004CDA0904A09FB3710251C652D69EA338589279BC849D47A7B019A1",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "3045022100D5C92D7705036CD7EBB601C8DFCD90927FA591A62AF832C489E9C898EC8E2FA0022052F1819340EB73E9749B8930A6935727362B8E141D1B2E246B49F912223FFD43",
|
||||
"hash" : "F81C34E7F05423DC1C973CB5008CA41AE984DE142EAA3975A749FABF0D08FA63"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
一定の時間内に _すべて_ のトランザクションで最終結果が得られるように、[`LastLedgerSequence`](reliable-transaction-submission.html#lastledgersequence)フィールドに入力してください。この値は、現行のレジャーインデックス(オンラインマシンから検索する必要がある)と、トランザクションを有効に保つ時間に基づいたものである必要があります。オンラインマシンからオフラインマシンへ、オフラインマシンからオンラインマシンへ切り替える時間を取れるだけの十分に大きな`LastLedgerSequence`値を設定するようにしてください。例えば、現行のレジャーインデックスより256大きな値では、トランザクションは約15分間有効になります。詳細は、[結果のファイナリティー](finality-of-results.html)と[信頼できるトランザクションの送信](reliable-transaction-submission.html)を参照してください。
|
||||
|
||||
|
||||
### {{n.next()}}.オンラインマシンへのトランザクションのコピー
|
||||
|
||||
トランザクションに署名したら、次のステップは署名済みのトランザクションデータをオンラインマシンに入れることです。その方法の例については、[前提条件](#前提条件)を参照してください。
|
||||
|
||||
|
||||
|
||||
### {{n.next()}}.設定したトランザクションの送信
|
||||
|
||||
次のステップはトランザクションの送信です。ほとんどのトランザクションは、送信後の次の検証済みレジャー(約4秒後)、またはキューに入っている場合はその後のレジャー(10秒未満)で最終結果が得られるはずです。トランザクションの最終結果を追跡する詳細な手順については、[信頼できるトランザクションの送信](reliable-transaction-submission.html)を参照してください。
|
||||
|
||||
単純なトランザクションを送信する例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_rippledコマンドライン_
|
||||
|
||||
```sh
|
||||
$ rippled submit 1200032280000000240000000120210000000268400000000000000C7321039543A0D3004CDA0904A09FB3710251C652D69EA338589279BC849D47A7B019A174473045022100D5C92D7705036CD7EBB601C8DFCD90927FA591A62AF832C489E9C898EC8E2FA0022052F1819340EB73E9749B8930A6935727362B8E141D1B2E246B49F912223FFD4381144B4E9C06F24296074F7BC48F92A97916C6DC5EA9
|
||||
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2019-Dec-11 01:14:25.988839227 HTTPClient:NFO Connecting to 127.0.0.1:5005
|
||||
|
||||
{
|
||||
"result" : {
|
||||
"deprecated" : "Signing support in the 'submit' command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
|
||||
"engine_result" : "tesSUCCESS",
|
||||
"engine_result_code" : 0,
|
||||
"engine_result_message" : "The transaction was applied. Only final in a validated ledger.",
|
||||
"status" : "success",
|
||||
"tx_blob" : "1200032280000000240000000120210000000268400000000000000C7321039543A0D3004CDA0904A09FB3710251C652D69EA338589279BC849D47A7B019A174473045022100D5C92D7705036CD7EBB601C8DFCD90927FA591A62AF832C489E9C898EC8E2FA0022052F1819340EB73E9749B8930A6935727362B8E141D1B2E246B49F912223FFD4381144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "12",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 1,
|
||||
"SetFlag" : 2,
|
||||
"SigningPubKey" : "039543A0D3004CDA0904A09FB3710251C652D69EA338589279BC849D47A7B019A1",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "3045022100D5C92D7705036CD7EBB601C8DFCD90927FA591A62AF832C489E9C898EC8E2FA0022052F1819340EB73E9749B8930A6935727362B8E141D1B2E246B49F912223FFD43",
|
||||
"hash" : "F81C34E7F05423DC1C973CB5008CA41AE984DE142EAA3975A749FABF0D08FA63"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
**ヒント:** 一度に10件を超えるトランザクションを送信しようとしている場合、10件未満のグループに分けて送信すると成功の可能性が高まります。[トランザクションキュー](transaction-queue.html)では同じ送信者から一度に送信されるトランザクションを10件に制限しているためです。10件の1グループのトランザクションを送信した後に、すべてのトランザクションがキューから出るのを待ってから、次のグループを送信します。
|
||||
|
||||
[最終的でない結果](finality-of-results.html)が得られて失敗したトランザクションの送信をやり直します。同じトランザクションが2回以上処理される可能性はありません。
|
||||
|
||||
### {{n.next()}}.トランザクションの最終ステータスの確認
|
||||
|
||||
送信した各トランザクションについて、トランザクションの[最終結果](finality-of-results.html)をメモします。例えば、[txメソッド][]を使用します。例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_rippledコマンドライン_
|
||||
|
||||
```sh
|
||||
$ ./rippled tx F81C34E7F05423DC1C973CB5008CA41AE984DE142EAA3975A749FABF0D08FA63
|
||||
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2019-Dec-11 01:38:30.124771464 HTTPClient:NFO Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "12",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 1,
|
||||
"SetFlag" : 2,
|
||||
"SigningPubKey" : "039543A0D3004CDA0904A09FB3710251C652D69EA338589279BC849D47A7B019A1",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "3045022100D5C92D7705036CD7EBB601C8DFCD90927FA591A62AF832C489E9C898EC8E2FA0022052F1819340EB73E9749B8930A6935727362B8E141D1B2E246B49F912223FFD43",
|
||||
"date" : 629343510,
|
||||
"hash" : "F81C34E7F05423DC1C973CB5008CA41AE984DE142EAA3975A749FABF0D08FA63",
|
||||
"inLedger" : 4,
|
||||
"ledger_index" : 4,
|
||||
"meta" : {
|
||||
"AffectedNodes" : [
|
||||
{
|
||||
"ModifiedNode" : {
|
||||
"FinalFields" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Balance" : "4999999999988",
|
||||
"Flags" : 262144,
|
||||
"OwnerCount" : 0,
|
||||
"Sequence" : 2
|
||||
},
|
||||
"LedgerEntryType" : "AccountRoot",
|
||||
"LedgerIndex" : "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"PreviousFields" : {
|
||||
"Balance" : "5000000000000",
|
||||
"Flags" : 0,
|
||||
"Sequence" : 1
|
||||
},
|
||||
"PreviousTxnID" : "00C5B713B11DA775C6F932D38CE162C16FA88B7269BAFC6FDF4C6ADB74419670",
|
||||
"PreviousTxnLgrSeq" : 3
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex" : 0,
|
||||
"TransactionResult" : "tesSUCCESS"
|
||||
},
|
||||
"status" : "success",
|
||||
"validated" : true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
すべてのトランザクションが処理された後で送信側アカウントの[account_info][account_infoメソッド]を確認すると便利です。アカウントの現在のシーケンス番号(`Sequence`フィールド)と、必要に応じてXRP残高をメモします。
|
||||
|
||||
失敗したトランザクションについては、どうするか決める必要があります。
|
||||
|
||||
- トランザクションが`tefMAX_LEDGER`コードで失敗した場合、トランザクションが処理されるように、より高い[トランザクションコスト](transaction-cost.html)を指定する必要があります。(これはXRP Ledgerネットワークに負荷がかかっていることを示している可能性があります。)トランザクションを、より高いコストを支払い、より高い`LastLedgerSequence`パラメーター(ある場合)を持つ新しいバージョンに置き換えるのも1つの方法です。
|
||||
- トランザクションが[`tem`クラスコードで](tem-codes.html)で失敗した場合は、トランザクションの生成時にスペルミスなどのミスをした可能性があります。トランザクションを再度確認し、有効な形式に置き換えます。
|
||||
- トランザクションが[`tec`クラスコード](tec-codes.html)で失敗した場合は、失敗した具体的な理由に応じてケースバイケースで対処する必要があります。
|
||||
|
||||
調整や置き換えをするトランザクションについては、オフラインマシンに戻るタイミングについての詳細をメモします。
|
||||
|
||||
|
||||
|
||||
### {{n.next()}}.オフラインマシンのステータスの調整
|
||||
|
||||
オフラインマシンに戻り、カスタムサーバーに保存されている設定に必要な変更を加えます。例えば次のような変更です。
|
||||
|
||||
- アカウントの現在の`Sequence`番号を更新する。すべてのトランザクションが検証済みレジャーに含まれている場合(成功または`tec`コードで終了)、オフラインマシンに保存されているシーケンス番号はすでに正確であるはずです。含まれていない場合は、保存されているシーケンス番号を、前のステップでメモした`Sequence`値と一致するように変更する必要があります。
|
||||
- 新しいトランザクションで適切な`LastLedgerSequence`値を使用できるように、現在のレジャーインデックスを更新する。(新しいトランザクションを生成する直前に必ずこれを行う必要があります。)
|
||||
- _(省略可)_ オフラインマシンで使用可能なXRPの金額を追跡している場合は、使用可能なXRPの実際の金額を更新する。
|
||||
|
||||
その後で、前のステップで失敗したトランザクションの置き換えとなるトランザクションを調整して署名します。以前の手順と同様に、オフラインマシンでトランザクションを生成し、オンラインマシンから送信します。
|
||||
|
||||
|
||||
|
||||
## 関連項目
|
||||
|
||||
- **コンセプト:**
|
||||
- [アカウント](accounts.html)
|
||||
- [暗号鍵](cryptographic-keys.html)
|
||||
- **チュートリアル:**
|
||||
- [安全な署名の設定](secure-signing.html)
|
||||
- [レギュラーキーペアの割り当て](assign-a-regular-key-pair.html)
|
||||
- [マルチシグの設定](set-up-multi-signing.html)
|
||||
- **リファレンス:**
|
||||
- [基本的なデータタイプ: ](basic-data-types.html#アカウントシーケンス)[ ](basic-data-types.html#アカウントシーケンス)[アカウントシーケンス](basic-data-types.html#アカウントシーケンス)
|
||||
- [account_infoメソッド][]
|
||||
- [signメソッド][]
|
||||
- [submitメソッド][]
|
||||
- [txメソッド][]
|
||||
- [AccountSetトランザクション][]
|
||||
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,99 +0,0 @@
|
||||
---
|
||||
html: require-destination-tags.html
|
||||
parent: manage-account-settings.html
|
||||
blurb: ユーザーがあなたのアドレスに送金するときに宛先タグを必ず指定しなければならないようにします。
|
||||
labels:
|
||||
- アカウント
|
||||
---
|
||||
# 宛先タグの要求
|
||||
|
||||
`RequireDest`設定は、送金先を識別する[宛先タグ](source-and-destination-tags.html)を顧客が付け忘れている場合にあなたのアドレスに[送金](payment-types.html)できないようにするためのものです。有効にすると、XRP Ledgerは宛先タグが付いていないあなたのアドレスへの送金を拒否します。
|
||||
|
||||
以下は、ローカルでホストされている`rippled`の[submitメソッド][]を使用して、`RequireDest`フラグを有効にする[AccountSetトランザクション][]を送信する例です。
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [
|
||||
{
|
||||
"secret": "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "15000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 1,
|
||||
"TransactionType": "AccountSet"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
{% include '_snippets/secret-key-warning.md' %}
|
||||
<!--{#_ #}-->
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
200 OK
|
||||
|
||||
{
|
||||
"result" : {
|
||||
"deprecated" : "Signing support in the 'submit' command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
|
||||
"engine_result" : "tesSUCCESS",
|
||||
"engine_result_code" : 0,
|
||||
"engine_result_message" : "The transaction was applied. Only final in a validated ledger.",
|
||||
"status" : "success",
|
||||
"tx_blob" : "12000322000000002400000179202100000001684000000000003A98732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402201C430B4C29D0A0AB94286AE55FB9981B00F84C7985AF4BD44570782C5E0C5E290220363B68B81580231B32176F8C477B822ECB9EC673B84237BEF15BE6F59108B97D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "15000",
|
||||
"Flags" : 0,
|
||||
"Sequence" : 377,
|
||||
"SetFlag" : 1,
|
||||
"SigningPubKey" : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "304402201C430B4C29D0A0AB94286AE55FB9981B00F84C7985AF4BD44570782C5E0C5E290220363B68B81580231B32176F8C477B822ECB9EC673B84237BEF15BE6F59108B97D",
|
||||
"hash" : "3F2B233907BE9EC51AE1C822EC0B6BB0965EFD2400B218BE988DDA9529F53CA4"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
## 関連項目
|
||||
|
||||
- **コンセプト:**
|
||||
- [アカウント](accounts.html)
|
||||
- [ソースタグと宛先タグ](source-and-destination-tags.html)
|
||||
- [トランザクションコスト](transaction-cost.html)
|
||||
- [支払いタイプ](payment-types.html)
|
||||
- **リファレンス:**
|
||||
- [account_infoメソッド][]
|
||||
- [AccountSetトランザクション][]
|
||||
- [AccountRootのフラグ](accountroot.html#accountrootのフラグ)
|
||||
|
||||
|
||||
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,393 +0,0 @@
|
||||
---
|
||||
html: send-a-multi-signed-transaction.html
|
||||
parent: manage-account-settings.html
|
||||
blurb: マルチシグトランザクションを作成、署名、送信する。
|
||||
labels:
|
||||
- セキュリティ
|
||||
---
|
||||
# マルチシグトランザクションの送信
|
||||
|
||||
マルチシグトランザクションを作成、署名、送信する方法を以下で説明します。
|
||||
|
||||
## 前提条件
|
||||
|
||||
- 事前にアドレスの[マルチシグの設定](set-up-multi-signing.html)をする必要があります。
|
||||
|
||||
- マルチシグは使用可能である必要があります。マルチシグは、XRP Ledgerコンセンサスプロトコルに対する[**Amendment**](amendments.html)により2016/06/27以降利用可能になりました。
|
||||
|
||||
|
||||
## 1.トランザクションの作成
|
||||
|
||||
送信するトランザクションを表すJSONオブジェクトを作成します。`Fee`や`Sequence`をはじめ、このトランザクションに関する _すべての_ 情報を指定する必要があります。また、トランザクションがマルチシグトランザクションであることを示すため、`SigningPubKey`を空の文字列として指定します。
|
||||
|
||||
マルチシグトランザクションの`Fee`は、標準の署名済みトランザクションよりもかなり高額ですので、ご注意ください。手数料は通常の[トランザクションコスト](transaction-cost.html)の(N+1)倍以上となります(Nは付与する予定の署名数です)。複数のソースから署名を収集するのに時間がかかることがあるため、その間に[トランザクションコスト](transaction-cost.html)の増加に備えて現行の最小値よりも大きな値を指定できます。
|
||||
|
||||
マルチシグが可能なトランザクションの例を以下に示します。
|
||||
|
||||
{
|
||||
"TransactionType":"TrustSet",
|
||||
"Account":"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Flags":262144,
|
||||
"LimitAmount":{
|
||||
"currency":"USD",
|
||||
"issuer":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value":"100"
|
||||
},
|
||||
"Sequence":2,
|
||||
"SigningPubKey":"",
|
||||
"Fee":"30000"
|
||||
}
|
||||
|
||||
(このトランザクションは、残高上限額が100 USDのrEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQCから rHb9CJAWyB4rj91VRWn96DkukG4bwdtyThへの会計上の関係を作成します。)
|
||||
|
||||
|
||||
## 2.1つの署名の取得
|
||||
|
||||
SlignerListのメンバーの1人のシークレットキーとアドレスを指定した[sign_forメソッド][]を使用して、そのメンバーの署名を取得します。
|
||||
|
||||
{% include '_snippets/secret-key-warning.md' %}
|
||||
<!--{#_ #}-->
|
||||
|
||||
$ rippled sign_for rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW <rsA2L..'s secret> '{
|
||||
> "TransactionType":"TrustSet",
|
||||
> "Account":"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
> "Flags":262144,
|
||||
> "LimitAmount":{
|
||||
> "currency":"USD",
|
||||
> "issuer":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
> "value":"100"
|
||||
> },
|
||||
> "Sequence":2,
|
||||
> "SigningPubKey":"",
|
||||
> "Fee":"30000"
|
||||
> }'
|
||||
Loading:"/etc/opt/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" :{
|
||||
"status" :"success",
|
||||
"tx_blob" :"1200142200040000240000000263D5038D7EA4C680000000000000000000000000005553440000000000B5F762798A53D543A014CAF8B297CFF8F2F937E868400000000000753073008114A3780F5CB5A44D366520FC44055E8ED44D9A2270F3E010732102B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF744730450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E58114204288D2E47F8EF6C99BCC457966320D12409711E1F1",
|
||||
"tx_json" :{
|
||||
"Account" :"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Fee" :"30000",
|
||||
"Flags" :262144,
|
||||
"LimitAmount" :{
|
||||
"currency" :"USD",
|
||||
"issuer" :"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value" :"100"
|
||||
},
|
||||
"Sequence" :2,
|
||||
"Signers" :[
|
||||
{
|
||||
"Signer" :{
|
||||
"Account" :"rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SigningPubKey" :"02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
"TxnSignature" :"30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
}
|
||||
}
|
||||
],
|
||||
"SigningPubKey" :"",
|
||||
"TransactionType" :"TrustSet",
|
||||
"hash" :"A94A6417D1A7AAB059822B894E13D322ED3712F7212CE9257801F96DE6C3F6AE"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
応答の`tx_json`フィールドを保存します。このフィールドの`Signers`フィールドに新しい署名が入力されています。`tx_blob`フィールドの値は無視できます。
|
||||
|
||||
スタンドアロンモードまたは本番環境以外のネットワークで問題が発生した場合は、[マルチシグが有効であること](start-a-new-genesis-ledger-in-stand-alone-mode.html#新しいジェネシスレジャーの設定)を確認してください。
|
||||
|
||||
## 3.追加の署名の取得
|
||||
|
||||
追加の署名は平行して取得するか、または順次取得することができます。
|
||||
|
||||
* 並行して取得する場合: トランザクションの元のJSONを指定した`sign_for`コマンドを使用します。各応答の`Signers`配列に1つの署名が含まれています。
|
||||
* 順次取得する場合: 前の`sign_for`応答の`tx_json`値を指定した`sign_for`コマンドを使用します。各応答の既存の`Signers`配列に新しい署名が追加されます。
|
||||
|
||||
{% include '_snippets/secret-key-warning.md' %}
|
||||
<!--{#_ #}-->
|
||||
|
||||
$ rippled sign_for rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v <rUpy..'s secret> '{
|
||||
> "Account" :"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
> "Fee" :"30000",
|
||||
> "Flags" :262144,
|
||||
> "LimitAmount" :{
|
||||
> "currency" :"USD",
|
||||
> "issuer" :"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
> "value" :"100"
|
||||
> },
|
||||
> "Sequence" :2,
|
||||
> "Signers" :[
|
||||
> {
|
||||
> "Signer" :{
|
||||
> "Account" :"rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
> "SigningPubKey" :"02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
> "TxnSignature" :"30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
> }
|
||||
> }
|
||||
> ],
|
||||
> "SigningPubKey" :"",
|
||||
> "TransactionType" :"TrustSet",
|
||||
> "hash" :"A94A6417D1A7AAB059822B894E13D322ED3712F7212CE9257801F96DE6C3F6AE"
|
||||
> }'
|
||||
Loading:"/etc/opt/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" :{
|
||||
"status" :"success",
|
||||
"tx_blob" :"1200142200040000240000000263D5038D7EA4C680000000000000000000000000005553440000000000B5F762798A53D543A014CAF8B297CFF8F2F937E868400000000000753073008114A3780F5CB5A44D366520FC44055E8ED44D9A2270F3E010732102B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF744730450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E58114204288D2E47F8EF6C99BCC457966320D12409711E1E0107321028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B744630440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC181147908A7F0EDD48EA896C3580A399F0EE78611C8E3E1F1",
|
||||
"tx_json" :{
|
||||
"Account" :"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Fee" :"30000",
|
||||
"Flags" :262144,
|
||||
"LimitAmount" :{
|
||||
"currency" :"USD",
|
||||
"issuer" :"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value" :"100"
|
||||
},
|
||||
"Sequence" :2,
|
||||
"Signers" :[
|
||||
{
|
||||
"Signer" :{
|
||||
"Account" :"rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SigningPubKey" :"02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
"TxnSignature" :"30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Signer" :{
|
||||
"Account" :"rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SigningPubKey" :"028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
||||
"TxnSignature" :"30440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"SigningPubKey" :"",
|
||||
"TransactionType" :"TrustSet",
|
||||
"hash" :"BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
構成したSignerListによっては、必要なすべての当事者からの署名を取得するためにこのステップを複数回繰り返す必要があります。
|
||||
|
||||
|
||||
## 4.署名の結合と送信
|
||||
|
||||
署名を順次収集した場合、最後の`sign_for`応答の`tx_json`ではすべての署名が結合されているので、これを[submit_multisignedメソッド][]の引数として使用できます。
|
||||
|
||||
署名を並行して収集した場合、すべての署名を含む`tx_json`オブジェクトを手動で作成する必要があります。すべての`sign_for`応答の`Signers`配列の内容を1つの`Signers`配列に結合します。この配列には各署名が含まれます。結合された`Signers`配列を元のトランザクションのJSON値に追加し、これを[submit_multisignedメソッド][]の引数として使用します。
|
||||
|
||||
$ rippled submit_multisigned '{
|
||||
> "Account" :"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
> "Fee" :"30000",
|
||||
> "Flags" :262144,
|
||||
> "LimitAmount" :{
|
||||
> "currency" :"USD",
|
||||
> "issuer" :"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
> "value" :"100"
|
||||
> },
|
||||
> "Sequence" :2,
|
||||
> "Signers" :[
|
||||
> {
|
||||
> "Signer" :{
|
||||
> "Account" :"rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
> "SigningPubKey" :"02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
> "TxnSignature" :"30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
> }
|
||||
> },
|
||||
> {
|
||||
> "Signer" :{
|
||||
> "Account" :"rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
> "SigningPubKey" :"028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
||||
> "TxnSignature" :"30440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC1"
|
||||
> }
|
||||
> }
|
||||
> ],
|
||||
> "SigningPubKey" :"",
|
||||
> "TransactionType" :"TrustSet",
|
||||
> "hash" :"BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6"
|
||||
> }'
|
||||
Loading:"/etc/opt/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result":{
|
||||
"engine_result":"tesSUCCESS",
|
||||
"engine_result_code":0,
|
||||
"engine_result_message":"The transaction was applied.Only final in a validated ledger.",
|
||||
"status":"success",
|
||||
"tx_blob":"1200142200040000240000000263D5038D7EA4C680000000000000000000000000005553440000000000B5F762798A53D543A014CAF8B297CFF8F2F937E868400000000000753073008114A3780F5CB5A44D366520FC44055E8ED44D9A2270F3E010732102B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF744730450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E58114204288D2E47F8EF6C99BCC457966320D12409711E1E0107321028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B744630440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC181147908A7F0EDD48EA896C3580A399F0EE78611C8E3E1F1",
|
||||
"tx_json":{
|
||||
"Account":"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Fee":"30000",
|
||||
"Flags":262144,
|
||||
"LimitAmount":{
|
||||
"currency":"USD",
|
||||
"issuer":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value":"100"
|
||||
},
|
||||
"Sequence":2,
|
||||
"Signers":[{
|
||||
"Signer":{
|
||||
"Account":"rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SigningPubKey":"02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
"TxnSignature":"30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
}
|
||||
}, {
|
||||
"Signer":{
|
||||
"Account":"rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SigningPubKey":"028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
||||
"TxnSignature":"30440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC1"
|
||||
}
|
||||
}],
|
||||
"SigningPubKey":"",
|
||||
"TransactionType":"TrustSet",
|
||||
"hash":"BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
応答の`hash`値をメモしておきます。これにより、後でトランザクションの結果を確認できます。(この例ではハッシュは`BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6`です。)
|
||||
|
||||
|
||||
## 5.レジャーの閉鎖
|
||||
|
||||
本番環境のネットワークを使用している場合は、レジャーが自動的に閉鎖するまで4~7秒待つことがあります。
|
||||
|
||||
スタンドアロンモードで`rippled`を実行している場合は、[ledger_acceptメソッド][]を使用してレジャーを手動で閉鎖します。
|
||||
|
||||
$ rippled ledger_accept
|
||||
Loading:"/etc/opt/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" :{
|
||||
"ledger_current_index" :7,
|
||||
"status" :"success"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
## 6.トランザクション結果の確認
|
||||
|
||||
`submit_multisigned`コマンドの応答のハッシュ値を使用して、[txメソッド][]でトランザクションを検索します。特に`TransactionResult`が文字列`tesSUCCESS`であることを確認してください。
|
||||
|
||||
本番環境のネットワークでは、`validated`フィールドがブール値`true`に設定されていることも確認する必要があります。このフィールドが`true`ではない場合は、コンセンサスプロセスの完了までしばらく待機する必要があるか、または何らかの理由でトランザクションをレジャーに記録できない可能性があります。
|
||||
|
||||
スタンドアロンモードでは、サーバーは手動で閉鎖されたレジャーを自動的に`validated`とみなします。
|
||||
|
||||
$ rippled tx BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6
|
||||
Loading:"/etc/opt/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result":{
|
||||
"Account":"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Fee":"30000",
|
||||
"Flags":262144,
|
||||
"LimitAmount":{
|
||||
"currency":"USD",
|
||||
"issuer":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value":"100"
|
||||
},
|
||||
"Sequence":2,
|
||||
"Signers":[{
|
||||
"Signer":{
|
||||
"Account":"rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SigningPubKey":"02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
"TxnSignature":"30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
}
|
||||
}, {
|
||||
"Signer":{
|
||||
"Account":"rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SigningPubKey":"028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
||||
"TxnSignature":"30440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC1"
|
||||
}
|
||||
}],
|
||||
"SigningPubKey":"",
|
||||
"TransactionType":"TrustSet",
|
||||
"date":512172510,
|
||||
"hash":"BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6",
|
||||
"inLedger":6,
|
||||
"ledger_index":6,
|
||||
"meta":{
|
||||
"AffectedNodes":[{
|
||||
"ModifiedNode":{
|
||||
"LedgerEntryType":"AccountRoot",
|
||||
"LedgerIndex":"2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8",
|
||||
"PreviousTxnID":"B7E1D33DB7DEA3BB65BFAB2C80E02125F47FCCF6C957A7FDECD915B3EBE0C1DD",
|
||||
"PreviousTxnLgrSeq":4
|
||||
}
|
||||
}, {
|
||||
"CreatedNode":{
|
||||
"LedgerEntryType":"RippleState",
|
||||
"LedgerIndex":"93E317B32022977C77810A2C558FBB28E30E744C68E73720622B797F957EC5FA",
|
||||
"NewFields":{
|
||||
"Balance":{
|
||||
"currency":"USD",
|
||||
"issuer":"rrrrrrrrrrrrrrrrrrrrBZbvji",
|
||||
"value":"0"
|
||||
},
|
||||
"Flags":2162688,
|
||||
"HighLimit":{
|
||||
"currency":"USD",
|
||||
"issuer":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value":"0"
|
||||
},
|
||||
"LowLimit":{
|
||||
"currency":"USD",
|
||||
"issuer":"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"value":"100"
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"ModifiedNode":{
|
||||
"FinalFields":{
|
||||
"Account":"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Balance":"999960000",
|
||||
"Flags":0,
|
||||
"OwnerCount":6,
|
||||
"Sequence":3
|
||||
},
|
||||
"LedgerEntryType":"AccountRoot",
|
||||
"LedgerIndex":"A6B1BA6F2D70813100908EA84ABB7783695050312735E2C3665259F388804EA0",
|
||||
"PreviousFields":{
|
||||
"Balance":"999990000",
|
||||
"OwnerCount":5,
|
||||
"Sequence":2
|
||||
},
|
||||
"PreviousTxnID":"8FDC18960455C196A8C4DE0D24799209A21F4A17E32102B5162BD79466B90222",
|
||||
"PreviousTxnLgrSeq":5
|
||||
}
|
||||
}, {
|
||||
"ModifiedNode":{
|
||||
"FinalFields":{
|
||||
"Flags":0,
|
||||
"Owner":"rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"RootIndex":"C2728175908D82FB1DE6676F203D8D3C056995A9FA9B369EF326523F1C65A1DE"
|
||||
},
|
||||
"LedgerEntryType":"DirectoryNode",
|
||||
"LedgerIndex":"C2728175908D82FB1DE6676F203D8D3C056995A9FA9B369EF326523F1C65A1DE"
|
||||
}
|
||||
}, {
|
||||
"CreatedNode":{
|
||||
"LedgerEntryType":"DirectoryNode",
|
||||
"LedgerIndex":"D8120FC732737A2CF2E9968FDF3797A43B457F2A81AA06D2653171A1EA635204",
|
||||
"NewFields":{
|
||||
"Owner":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"RootIndex":"D8120FC732737A2CF2E9968FDF3797A43B457F2A81AA06D2653171A1EA635204"
|
||||
}
|
||||
}
|
||||
}],
|
||||
"TransactionIndex":0,
|
||||
"TransactionResult":"tesSUCCESS"
|
||||
},
|
||||
"status":"success",
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,229 +0,0 @@
|
||||
---
|
||||
html: set-up-multi-signing.html
|
||||
parent: manage-account-settings.html
|
||||
blurb: アカウントに署名者リストを追加して、マルチシグを有効にします。
|
||||
labels:
|
||||
- セキュリティ
|
||||
---
|
||||
# マルチシグの設定
|
||||
|
||||
[マルチシグ](multi-signing.html)は、XRP Ledgerの[トランザクション](transactions.html)を承認する3種類の方法の1つです。マルチシグの他に[レギュラーキーとマスターキー](cryptographic-keys.html)で署名する方法があります。3種類のトランザクション承認方法を自由に組み合わせて使用できるように[アドレス](accounts.html)を設定できます。
|
||||
|
||||
このチュートリアルでは、アドレスのマルチシグを有効にする方法を説明します。
|
||||
|
||||
|
||||
## 前提条件
|
||||
|
||||
- トランザクションを送信するための十分なXRPが供給されていて、新しい署名者リストの[必要準備金](reserves.html)を満たしている資金供給のあるXRP Ledger[アドレス](accounts.html)が必要です。
|
||||
|
||||
- [MultiSignReserve Amendment][]が有効な場合、マルチシグを使用するには、使用する署名と署名者の数に関わらず、アカウントの準備金として2 XRPが必要です。(MultiSignReserve Amendmentは**2019年4月7日**以降、本番環境のXRP Ledgerで有効になっています。)
|
||||
|
||||
- [MultiSignReserve Amendment][]が有効ではないテストネットワークでは、マルチシグを使用するには[アカウント準備金](reserves.html)に通常よりも多くのXRPが必要となります。必要額は、リストの署名者の数に応じて増加します。
|
||||
|
||||
- XRP Ledgerフォーマットでキーペアを生成するツールを利用できる必要があります。この処理に`rippled`サーバーを使用する場合は、[wallet_proposeメソッド][]が管理者専用であるため、管理者アクセス権限が必要です。
|
||||
|
||||
- あるいは、すでにXRP Ledgerアドレスを持っている人をあなたのアドレスの署名者として承認するには、その人または組織のアカウントアドレスを知っている必要があります。
|
||||
|
||||
- マルチシグは使用可能である必要があります。(MultiSign Amendmentは**2016年6月27日**以降、本番環境のXRP Ledgerで有効になっています。)
|
||||
|
||||
## 1. 構成の設計
|
||||
|
||||
含めたい署名者の数を決定します(最大8)。特定のトランザクションに必要な署名の数に基づいて、署名者リストの定数と署名者の重みを選択します。シンプルな「M-of-N」の署名設定では、各署名者に重み **`1`** を割り当て、リストの定数が「M」になるように設定します。これが必要な署名の数です。
|
||||
|
||||
|
||||
## 2. メンバーキーの準備
|
||||
|
||||
署名者リストにメンバーとして加える有効な形式のXRP Ledgerアドレスが1つ以上必要です。あなた、またはあなたが選択した署名者は、これらのアドレスに関連付けられた秘密鍵を知っておく必要があります。アドレスは、レジャーに存在する資金供給されたアカウントにすることもできますが、必ずしもそうである必要はありません。
|
||||
|
||||
[wallet_proposeメソッド][]を使用して新しいアドレスを生成できます。例:
|
||||
|
||||
$ rippled wallet_propose
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"account_id" : "rnRJ4dpSBKDR2M1itf4Ah6tZZm5xuNZFPH",
|
||||
"key_type" : "secp256k1",
|
||||
"master_key" : "FLOG SEND GOES CUFF GAGE FAT ANTI DEL GUM TIRE ISLE BEAR",
|
||||
"master_seed" : "snheH5UUjU4CWqiNVLny2k21TyKPC",
|
||||
"master_seed_hex" : "A9F859765EB8614D26809836382AFB82",
|
||||
"public_key" : "aBR4hxFXcDNHnGYvTiqb2KU8TTTV1cYV9wXTAuz2DjBm7S8TYEBU",
|
||||
"public_key_hex" : "03C09A5D112B393D531E4F092E3A5769A5752129F0A9C55C61B3A226BB9B567B9B",
|
||||
"status" : "success"
|
||||
}
|
||||
}
|
||||
|
||||
生成した各アドレスの`account_id`(XRP Ledgerアドレス)と`master_seed`(シークレットキー)をメモします。
|
||||
|
||||
|
||||
## 3. SignerListSetトランザクションの送信
|
||||
|
||||
通常の方法(シングルシグネチャー)で[SignerListSetトランザクション][]に[署名して送信](transactions.html#トランザクションへの署名とトランザクションの送信)します。これによりSignerListがXRP Ledgerのアドレスに関連付けられるので、これ以降はSignerListの複数メンバーがあなたの代わりにトランザクションに署名するマルチシグが可能となります。
|
||||
|
||||
この例ではSignerListに3人のメンバーが含まれています。また、マルチシグトランザクションにはrsA2LpzuawewSBQXkiju3YQTMzW13pAAdWの署名と、リストの他の2人のメンバーからの少なくとも1つの署名を必要とするように、重みと定数が設定されています。
|
||||
|
||||
{% include '_snippets/secret-key-warning.md' %}
|
||||
<!--{#_ #}-->
|
||||
|
||||
$ rippled submit shqZZy2Rzs9ZqWTCQAdqc3bKgxnYq '{
|
||||
> "Flags": 0,
|
||||
> "TransactionType": "SignerListSet",
|
||||
> "Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
||||
> "Fee": "10000",
|
||||
> "SignerQuorum": 3,
|
||||
> "SignerEntries": [
|
||||
> {
|
||||
> "SignerEntry": {
|
||||
> "Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
> "SignerWeight": 2
|
||||
> }
|
||||
> },
|
||||
> {
|
||||
> "SignerEntry": {
|
||||
> "Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
> "SignerWeight": 1
|
||||
> }
|
||||
> },
|
||||
> {
|
||||
> "SignerEntry": {
|
||||
> "Account": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
> "SignerWeight": 1
|
||||
> }
|
||||
> }
|
||||
> ]
|
||||
> }'
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"engine_result" : "tesSUCCESS",
|
||||
"engine_result_code" : 0,
|
||||
"engine_result_message" : "The transaction was applied. Only final in a validated ledger.",
|
||||
"status" : "success",
|
||||
"tx_blob" : "12000C2200000000240000000120230000000368400000000000271073210303E20EC6B4A39A629815AE02C0A1393B9225E3B890CAE45B59F42FA29BE9668D74473045022100BEDFA12502C66DDCB64521972E5356F4DB965F553853D53D4C69B4897F11B4780220595202D1E080345B65BAF8EBD6CA161C227F1B62C7E72EA5CA282B9434A6F04281142DECAB42CA805119A9BA2FF305C9AFA12F0B86A1F4EB1300028114204288D2E47F8EF6C99BCC457966320D12409711E1EB13000181147908A7F0EDD48EA896C3580A399F0EE78611C8E3E1EB13000181143A4C02EA95AD6AC3BED92FA036E0BBFB712C030CE1F1",
|
||||
"tx_json" : {
|
||||
"Account" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
||||
"Fee" : "10000",
|
||||
"Flags" : 0,
|
||||
"Sequence" : 1,
|
||||
"SignerEntries" : [
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SignerWeight" : 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SignerWeight" : 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
"SignerWeight" : 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerQuorum" : 3,
|
||||
"SigningPubKey" : "0303E20EC6B4A39A629815AE02C0A1393B9225E3B890CAE45B59F42FA29BE9668D",
|
||||
"TransactionType" : "SignerListSet",
|
||||
"TxnSignature" : "3045022100BEDFA12502C66DDCB64521972E5356F4DB965F553853D53D4C69B4897F11B4780220595202D1E080345B65BAF8EBD6CA161C227F1B62C7E72EA5CA282B9434A6F042",
|
||||
"hash" : "3950D98AD20DA52EBB1F3937EF32F382D74092A4C8DF9A0B1A06ED25200B5756"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[トランザクションの結果](transaction-results.html)が[**tesSUCCESS**](tes-success.html)であることを確認します。それ以外の場合、トランザクションは失敗しています。スタンドアロンモードまたは本番環境以外のネットワークで問題が発生した場合は、[マルチシグが有効であること](start-a-new-genesis-ledger-in-stand-alone-mode.html#新しいジェネシスレジャーの設定)を確認してください。
|
||||
|
||||
**注記:** [MultiSignReserve Amendment][]が有効ではない場合は、SignerListのメンバーの増加に応じて、アドレスの[所有者準備金](reserves.html#所有者準備金)のXRP額を増加する必要があります。アドレスに十分なXRPがないと、トランザクションは[tecINSUFFICIENT_RESERVE](tec-codes.html)で失敗します。[MultiSignReserve Amendment][]が有効な場合は、SignerListの署名者の数に関係なく[所有者準備金](reserves.html#所有者準備金)として必要なXRPは5 XRPです。関連項目: [SignerListと準備金](signerlist.html#signerlistと準備金)
|
||||
|
||||
|
||||
## 4. 検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
|
||||
## 5. 新しい署名者リストの確認
|
||||
|
||||
[account_objectsメソッド][]を使用して、SignerListに最新の検証済みレジャーのアドレスが関連付けられていることを確認します。
|
||||
|
||||
通常、アカウントは異なるタイプのオブジェクト(トラストラインやオファーなど)を複数所有できます。このチュートリアルで新しいアドレスに資金を供給した場合、SignerListが応答の唯一のオブジェクトになります。
|
||||
|
||||
$ rippled account_objects rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC validated
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"account_objects" : [
|
||||
{
|
||||
"Flags" : 0,
|
||||
"LedgerEntryType" : "SignerList",
|
||||
"OwnerNode" : "0000000000000000",
|
||||
"PreviousTxnID" : "8FDC18960455C196A8C4DE0D24799209A21F4A17E32102B5162BD79466B90222",
|
||||
"PreviousTxnLgrSeq" : 5,
|
||||
"SignerEntries" : [
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SignerWeight" : 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SignerWeight" : 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SignerWeight" : 2
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerListID" : 0,
|
||||
"SignerQuorum" : 3,
|
||||
"index" : "79FD203E4DDDF2EA78B798C963487120C048C78652A28682425E47C96D016F92"
|
||||
}
|
||||
],
|
||||
"ledger_hash" : "56E81069F06492FB410A70218C08169BE3AB3CFD5AEA20E999662D81DC361D9F",
|
||||
"ledger_index" : 5,
|
||||
"status" : "success",
|
||||
"validated" : true
|
||||
}
|
||||
}
|
||||
|
||||
SignerListが予期した内容で存在していれば、アドレスでマルチシグができるようになります。
|
||||
|
||||
## 6. その他のステップ
|
||||
|
||||
これで、アドレスから[マルチシグトランザクションを送信](send-a-multi-signed-transaction.html)できます。次の操作も実行できます。
|
||||
|
||||
* `asfDisableMaster`フラグを使用して[AccountSetトランザクション][]を送信し、アドレスのマスターキーペアを無効化。
|
||||
* [SetRegularKeyトランザクション][]を送信して[アドレスのレギュラーキーペアを削除](change-or-remove-a-regular-key-pair.html)(レギュラーキーペアをすでに設定している場合)。
|
||||
|
||||
## 関連項目
|
||||
|
||||
- **コンセプト:**
|
||||
- [暗号鍵](cryptographic-keys.html)
|
||||
- [マルチシグ](multi-signing.html)
|
||||
- **チュートリアル:**
|
||||
- [rippledのインストール](install-rippled.html)
|
||||
- [レギュラーキーペアの割り当て](assign-a-regular-key-pair.html)
|
||||
- [信頼できるトランザクションの送信](reliable-transaction-submission.html)
|
||||
- [パブリック署名の有効化](enable-public-signing.html)
|
||||
- **リファレンス:**
|
||||
- [wallet_proposeメソッド][]
|
||||
- [account_objectsメソッド][]
|
||||
- [sign_forメソッド][]
|
||||
- [submit_multisignedメソッド][]
|
||||
- [SignerListSetトランザクション][]
|
||||
- [SignerListオブジェクト](signerlist.html)
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,260 +0,0 @@
|
||||
---
|
||||
html: use-tickets.html
|
||||
parent: manage-account-settings.html
|
||||
blurb: チケットは、通常のシーケンス順序以外でトランザクションを送信するために使用します。
|
||||
embed_xrpl_js: true
|
||||
filters:
|
||||
- interactive_steps
|
||||
labels:
|
||||
- アカウント
|
||||
---
|
||||
# チケットの使用
|
||||
|
||||
[チケット](ticket.html)は、通常の順序ではないトランザクションを送信する方法を提供します。このチュートリアルでは、チケットを作成し、それを使って別のトランザクションを送信する手順を説明します。
|
||||
|
||||
## 前提条件
|
||||
|
||||
<!-- Source for this specific tutorial's interactive bits: -->
|
||||
<script type="application/javascript" src="assets/js/tutorials/use-tickets.js"></script>
|
||||
{% set use_network = "Devnet" %}<!--TODO: change to Testnet eventually. NOTE, Testnet is a few days behind Mainnet in getting the amendment one enabled -->
|
||||
|
||||
このページでは、[xrpl.js](https://js.xrpl.org/)ライブラリを使用したJavaScriptのサンプルを提供しています。設定方法は、[JavaScriptを使ってみよう](get-started-using-javascript.html)をご覧ください。
|
||||
|
||||
JavaScriptはWebブラウザ上で動作するため、セットアップなしで読み進められ、インタラクティブな手順を利用することができます。
|
||||
|
||||
|
||||
|
||||
## 手順
|
||||
{% set n = cycler(* range(1,99)) %}
|
||||
|
||||
このチュートリアルはいくつかの段階に分かれています。
|
||||
|
||||
- (Steps 1-2) **準備:** XRP Ledgerのアドレスとシークレットが必要です。本番環境では、同じアドレスとシークレットを一貫して使用することができます。このチュートリアルでは、必要に応じて新しいテスト認証情報を生成することができます。また、ネットワークに接続されている必要があります。
|
||||
- (Steps 3-6) **チケットの作成:** トランザクションを送信して、いくつかのチケットを確保します。
|
||||
- (任意) **休憩:** チケットを作成した後、以下のステップの前、中、後にいつでも様々な他のトランザクションを送信することができます。
|
||||
- (Steps 7-10) **チケットの使用:** 設定されているチケットのうち1枚を使ってトランザクションを送信します。使用するチケットが1枚でも残っていれば、前の部分を飛ばしてこの手順を繰り返すことができます。
|
||||
|
||||
### {{n.next()}}. クレデンシャルの入手
|
||||
|
||||
XRP Ledgerでトランザクションを送信するには、アドレスと秘密鍵、そしてXRPが必要です。開発用には、[{{use_network}}](parallel-networks.html)で以下のようなインターフェースを使ってこれらを入手することができます。
|
||||
|
||||
{% include '_snippets/interactive-tutorials/generate-step.md' %}
|
||||
|
||||
[本番環境のソフトウェアを作成する場合](production-readiness.html)には、既存のアカウントを使用し、[安全な署名](secure-signing.html)を使用して鍵を管理する必要があります。
|
||||
|
||||
|
||||
### {{n.next()}}. ネットワークへの接続
|
||||
|
||||
トランザクションをネットワークに送信するには、ネットワークに接続している必要があります。チケットは今のところDevnetでしか利用できないので、Devnetサーバーに接続する必要があります。例えば、以下のようになります。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_JavaScript_
|
||||
|
||||
{{ include_code("_code-samples/use-tickets/js/use-tickets.js", language="js", start_with="// Connect to", end_before="// Get credentials") }}
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
**注記:** このチュートリアルのコードサンプルでは、JavaScriptの[`async`/`await`パターン](https://javascript.info/async-await)を使用しています。`await`は`async`関数の中で使用する必要があるため、残りのコードサンプルはここから始まる`main()`関数の中で続けるように書かれています。なお、`async`/`await`の代わりにPromiseのメソッド`.then()`や`.catch()`を使うこともできます。
|
||||
|
||||
このチュートリアルでは、以下のボタンをクリックして接続します。
|
||||
|
||||
{% include '_snippets/interactive-tutorials/connect-step.md' %}
|
||||
|
||||
|
||||
### {{n.next()}}. シーケンス番号の確認
|
||||
|
||||
チケットを作成する前に、自分のアカウントの[シーケンス番号][]を確認しておきましょう。次のステップのために現在のシーケンス番号が必要であり、設定されるチケットのシーケンス番号はこの番号から始まります。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_JavaScript_
|
||||
|
||||
{{ include_code("_code-samples/use-tickets/js/use-tickets.js", language="js", start_with="// Check Sequence", end_before="// Prepare and Sign TicketCreate") }}
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
{{ start_step("Check Sequence") }}
|
||||
<button id="check-sequence" class="btn btn-primary previous-steps-required">Check Sequence Number</button>
|
||||
<div class="loader collapse"><img class="throbber" src="assets/img/xrp-loader-96.png">Querying...</div>
|
||||
<div class="output-area"></div>
|
||||
{{ end_step() }}
|
||||
|
||||
|
||||
|
||||
### {{n.next()}}. TicketCreateの準備と署名
|
||||
|
||||
前のステップで決定したシーケンス番号を使用して、[TicketCreate トランザクション][]を構築します。`TicketCount`フィールドを使って、作成するチケットの枚数を指定します。例えば、10枚のチケットを作成するトランザクションを準備するには、次のようにします。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_JavaScript_
|
||||
|
||||
{{ include_code("_code-samples/use-tickets/js/use-tickets.js", language="js", start_with="// Prepare and Sign TicketCreate", end_before="// Submit TicketCreate") }}
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
トランザクションのハッシュと`LastLedgerSequence`の値を記録しておけば、[後で検証されたかどうかを確認](reliable-transaction-submission.html)することができます。
|
||||
|
||||
|
||||
{{ start_step("Prepare & Sign") }}
|
||||
<button id="prepare-and-sign" class="btn btn-primary previous-steps-required">Prepare & Sign</button>
|
||||
<div class="output-area"></div>
|
||||
{{ end_step() }}
|
||||
|
||||
|
||||
|
||||
### {{n.next()}}. TicketCreateの提出
|
||||
|
||||
前のステップで作成した署名付きトランザクションBlobを送信します。例えば、以下のようになります。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_JavaScript_
|
||||
|
||||
{{ include_code("_code-samples/use-tickets/js/use-tickets.js", language="js", start_with="// Submit TicketCreate", end_before="// Wait for Validation") }}
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
{{ start_step("Submit") }}
|
||||
<button id="ticketcreate-submit" class="btn btn-primary previous-steps-required" data-tx-blob-from="#tx_blob" data-wait-step-name="Wait">Submit</button>
|
||||
<div class="loader collapse"><img class="throbber" src="assets/img/xrp-loader-96.png">Sending...</div>
|
||||
<div class="output-area"></div>
|
||||
{{ end_step() }}
|
||||
|
||||
|
||||
### {{n.next()}}. 検証の待機
|
||||
|
||||
ほとんどのトランザクションは、送信された後に次の台帳のバージョンに受け入れられます。つまり、トランザクションの結果が確定するまでに4~7秒かかることがあります。XRP Ledgerが混雑している場合や、ネットワークの接続性が悪いためにトランザクションがネットワーク全体に中継されない場合は、トランザクションが確定するまでに時間がかかることがあります。(トランザクションの有効期限を設定する方法については、[信頼できるトランザクションの送信](reliable-transaction-submission.html)を参照してください)。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_JavaScript_
|
||||
|
||||
{{ include_code("_code-samples/use-tickets/js/use-tickets.js", language="js", start_with="// Wait for Validation", end_before="// Check Available") }}
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
{{ start_step("Wait") }}
|
||||
{% include '_snippets/interactive-tutorials/wait-step.md' %}
|
||||
{{ end_step() }}
|
||||
|
||||
|
||||
### (任意) 休憩
|
||||
|
||||
チケットの強みは、チケットを使ったトランザクションの準備をしている間も、アカウントの業務を通常通り行うことができる点にあります。チケットを使用してトランザクションを送信する場合、別のチケットを使用しているものも含め、他のトランザクションの送信と並行して行うことができ、いつでもチケット付きトランザクションを送信することができます。唯一の制約は、1つのチケットは1回しか使用できないということです。
|
||||
|
||||
**ヒント:** 以下のステップの間または途中で、ここに戻ってきてシーケンス取引を送信することができますが、その際、チケット取引の成功を妨げることはありません。
|
||||
|
||||
{{ start_step("Intermission") }}
|
||||
<button id="intermission-payment" class="btn btn-primary previous-steps-required">Payment</button>
|
||||
<button id="intermission-escrowcreate" class="btn btn-primary previous-steps-required">EscrowCreate</button>
|
||||
<button id="intermission-accountset" class="btn btn-primary previous-steps-required">AccountSet</button>
|
||||
<div class="output-area"></div>
|
||||
{{ end_step() }}
|
||||
|
||||
|
||||
|
||||
### {{n.next()}}. 有効なチケットの確認
|
||||
|
||||
チケット付きのトランザクションを送信したい場合、どのチケットシーケンス番号を使用するかを知る必要があります。アカウントを注意深く管理していれば、どのチケットを持っているかはすでにわかっていると思いますが、よくわからない場合は、[account_objects メソッド][]を使って、利用可能なチケットを調べることができます。例えば、以下のようになります。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_JavaScript_
|
||||
|
||||
{{ include_code("_code-samples/use-tickets/js/use-tickets.js", language="js", start_with="// Check Available Tickets", end_before="// Prepare and Sign Ticketed") }}
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
{{ start_step("Check Tickets") }}
|
||||
<button id="check-tickets" class="btn btn-primary previous-steps-required">Check Tickets</button>
|
||||
<div class="output-area"></div>
|
||||
{{ end_step() }}
|
||||
|
||||
**ヒント:** チケットが残っている限り、ここから最後まで同じ手順を繰り返すことができます。
|
||||
|
||||
### {{n.next()}}. チケット付きトランザクションの準備
|
||||
|
||||
チケットが利用できるようになったので、それを使用するトランザクションを準備します。
|
||||
|
||||
ここでは、好きな[トランザクションのタイプ](transaction-types.html)を使用することができます。次の例では、何も行わない[AccountSet トランザクション][]を使用していますが、これはレジャーに他の設定を必要としないからです。`Sequence`フィールドを`0`に設定して、利用可能なチケットの1つのチケットシーケンス番号を持つ`TicketSequence`フィールドを含めます。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_JavaScript_
|
||||
|
||||
{{ include_code("_code-samples/use-tickets/js/use-tickets.js", language="js", start_with="// Prepare and Sign Ticketed", end_before="// Submit Ticketed Transaction") }}
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
> **ヒント:** TicketCreateトランザクションをすぐに送信する予定がない場合は、トランザクションが期限切れにならないように、`LastLedgerSequence`を設定しないようにする必要があります。これを行う方法はライブラリによって異なります。
|
||||
>
|
||||
> - **xrpl.js:** トランザクションの自動入力の際に、`"LastLedgerSequence": null`を指定する。
|
||||
> - **`rippled`:** 用意された指示から`LastLedgerSequence`を省略します。サーバーはデフォルトでは値を提供しません。
|
||||
|
||||
{{ start_step("Prepare Ticketed Tx") }}
|
||||
<div id="ticket-selector">
|
||||
<h4>Select a Ticket:</h4>
|
||||
<div class="form-area"></div>
|
||||
</div>
|
||||
<button id="prepare-ticketed-tx" class="btn btn-primary previous-steps-required">Prepare Ticketed Transaction</button>
|
||||
<div class="output-area"></div>
|
||||
{{ end_step() }}
|
||||
|
||||
|
||||
### {{n.next()}}. チケット付きトランザクションの送信
|
||||
|
||||
前のステップで作成した署名付きトランザクションBlobを送信します。例えば、以下のようになります。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_JavaScript_
|
||||
|
||||
{{ include_code("_code-samples/use-tickets/js/use-tickets.js", language="js", start_with="// Submit Ticketed Transaction", end_before="// Wait for Validation (again)") }}
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
{{ start_step("Submit Ticketed Tx") }}
|
||||
<button id="ticketedtx-submit" class="btn btn-primary previous-steps-required" data-tx-blob-from="#tx_blob_t" data-wait-step-name="Wait Again">Submit</button>
|
||||
<div class="output-area"></div>
|
||||
{{ end_step() }}
|
||||
|
||||
|
||||
### {{n.next()}}. 検証の待機
|
||||
|
||||
チケット付きトランザクションは、シーケンス付きトランザクションと同じようにコンセンサスプロセスを経ます。
|
||||
|
||||
{{ start_step("Wait Again") }}
|
||||
{% include '_snippets/interactive-tutorials/wait-step.md' %}
|
||||
{{ end_step() }}
|
||||
|
||||
## マルチシグで使用する
|
||||
|
||||
チケットの主な使用例としては、複数の[マルチシグ](multi-signing.html)を並行して集めることができます。チケットを使用することで、複数署名されたトランザクションが完全に署名されて準備が整った時点で、どれが先に準備されるかを気にすることなく送信することができます。
|
||||
|
||||
このシナリオでは、[step8,「チケット付きトランザクションの準備」](#8-チケット付きトランザクションの準備)が若干異なります。準備と署名を一度に行うのではなく、[任意のマルチシグトランザクションの送信](send-a-multi-signed-transaction.html)の手順に従うことになります。まずトランザクションを準備し、次に信頼できる署名者の間でトランザクションを循環させて署名を集め、最後に署名を組み合わせて最終的なマルチシグトランザクションを作成します。
|
||||
|
||||
複数の異なるトランザクションを処理する場合、それぞれが異なるチケットを使用する限り、この作業を並行して行うことができます。
|
||||
|
||||
|
||||
## 関連項目
|
||||
|
||||
- **Concepts:**
|
||||
- [チケット](tickets.html)
|
||||
- [マルチシグ](multi-signing.html)
|
||||
- **Tutorials:**
|
||||
- [マルチシグの設定](set-up-multi-signing.html)
|
||||
- [信頼出来るトランザクションの送信](reliable-transaction-submission.html)
|
||||
- **References:**
|
||||
- [account_objects メソッド][]
|
||||
- [sign_for メソッド][]
|
||||
- [submit_multisigned メソッド][]
|
||||
- [TicketCreate トランザクション][]
|
||||
- [トランザクションの共通フィールド](transaction-common-fields.html)
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
9
content/tutorials/python/index.md
Normal file
9
content/tutorials/python/index.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
html: python.html
|
||||
parent: tutorials.html
|
||||
top_nav_grouping: Article Types
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# Python
|
||||
|
||||
XRPL tutorials in Python.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
html: modular-tutorials-in-python.html
|
||||
parent: python.html
|
||||
top_nav_grouping: Article Types
|
||||
template: pagetype-category.html.jinja
|
||||
blurb: Modular XRPL tutorials in Python.
|
||||
---
|
||||
# Modular Tutorials in Python
|
||||
|
||||
These tutorials take an incremental approach to implementing functionality, so you can reuse parts from the earlier tutorials on your way to making more advanced software.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
html: nfts-using-python.html
|
||||
parent: modular-tutorials-in-python.html
|
||||
top_nav_grouping: Article Types
|
||||
template: pagetype-category.html.jinja
|
||||
blurb: Mint and sell NFTs on the XRP Ledger using Python.
|
||||
---
|
||||
# NFTs Using Python
|
||||
|
||||
Mint and sell NFTs on the XRP Ledger using Python.
|
||||
@@ -46,6 +46,10 @@ To authorize another account to create NFTs for your account:
|
||||
|
||||
## Mint an NFT for Another Account
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/cXvyu2ZDCBM?si=AFrGzgV4CAF2LoAk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
This example uses the Operational account, which was authorized in the previous step, to mint a token on behalf of the Standby account.
|
||||
|
||||
To mint a non-fungible token for another account:
|
||||
|
||||
@@ -33,6 +33,10 @@ You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-port
|
||||
|
||||
## Batch Mint NFTs
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/tJeDnEMZ7RU?si=mHwKbSRMxQ1cO4Fh" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
This example lets you mint multiple NFTs for a single unique item. The NFT might represent "prints" of an original artwork, tickets to an event, or another limited set of unique items.
|
||||
|
||||
To batch mint a non-fungible token objects:
|
||||
|
||||
@@ -41,6 +41,10 @@ You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-port
|
||||
|
||||
## Prepare a Brokered Transaction
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/GemQ-t7g9fo?si=zVTLXFg3v-XX4Rf_" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
1. Use the Standby account to create an NFT Sell Offer with the Broker account as the destination.
|
||||
1. Enter the **Amount** of the sell offer in drops (millionths of an XRP).
|
||||
2. Set the **Flags** field to _1_.
|
||||
|
||||
@@ -34,6 +34,10 @@ Download and expand the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-p
|
||||
|
||||
## Usage
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/GX436F-FaV4?si=OyuTUD4zHZ5a0Dgx" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To get test accounts:
|
||||
|
||||
1. Open `1.get-accounts-send-xrp.html` in a browser
|
||||
@@ -46,6 +50,10 @@ To get test accounts:
|
||||
|
||||
You can transfer XRP between your new accounts. Each account has its own fields and buttons.
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/sjYJOcKXZvY?si=IRx_AFMaZarOIOPY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To transfer XRP from the Standby account to the Operational account:
|
||||
|
||||
1. On the Standby (left) side of the form, enter the **Amount** of XRP to send.
|
||||
|
||||
@@ -60,7 +60,11 @@ To get test accounts:
|
||||
|
||||
### Create Conditional Escrow:
|
||||
|
||||
When you create a conditional escrow, you need to specify the `Condition` value you generated above. You must also set a cancel date and time, after which the escrow is no longer available.
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/jUQ2nM5JXjc?si=-ajV2EFw8xv4djgG" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
When you create a conditional escrow, you need to specify the amount you want to reserve and the `Condition` value you generated above. You can also set a cancel date and time, after which the escrow is no longer available.
|
||||
|
||||
To create a conditional escrow:
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ To get test accounts:
|
||||
|
||||
## Create Escrow
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/mNPSSZxcq7s?si=ZZewy6EKpxSMfxak" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
You can create a time-based escrow with a minimum time to finish the escrow and a cancel time after which the funds in escrow are no longer available to the recipient. This is a test harness: while a practical scenario might express time in days or weeks, this form lets you set the finish and cancel times in seconds so that you can quickly run through a variety of scenarios. (There are 86,400 seconds in a day, if you want to play with longer term escrows.)
|
||||
|
||||
To create a time-based escrow:
|
||||
|
||||
@@ -40,6 +40,10 @@ Open the Token Test Harness and get accounts:
|
||||
|
||||
## Create Trust Line
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/HpcyZt1jG3E?si=evreLRsmgF5rrQrW" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To create a trust line between accounts:
|
||||
|
||||
1. Enter a [currency code](https://www.iban.com/currency-codes) in the **Currency** field.
|
||||
|
||||
@@ -13,7 +13,7 @@ This example shows how to:
|
||||
|
||||
1. Mint new Non-fungible Tokens (NFTs).
|
||||
2. Get a list of existing NFTs.
|
||||
3. Delete (Burn) a NFT.
|
||||
3. Delete (Burn) an NFT.
|
||||
|
||||
[](img/quickstart8.png)
|
||||
|
||||
@@ -34,7 +34,11 @@ You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-port
|
||||
|
||||
[](img/quickstart9.png)
|
||||
|
||||
## Mint a NFT
|
||||
## Mint an NFT
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Qyb_x_GlUDg?si=fow07WIV6DjuHZ3K" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To mint a non-fungible token object:
|
||||
|
||||
@@ -54,9 +58,9 @@ Click **Get NFTs** to get a list of NFTs owned by the account.
|
||||
|
||||
## Burn a Token
|
||||
|
||||
The current owner of a NFT can always destroy (or _burn_) a NFT object.
|
||||
The current owner of an NFT can always destroy (or _burn_) an NFT object.
|
||||
|
||||
To permanently destroy a NFT:
|
||||
To permanently destroy an NFT:
|
||||
|
||||
1. Enter the **Token ID**.
|
||||
2. Click **Burn NFT**.
|
||||
|
||||
@@ -43,6 +43,10 @@ You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-port
|
||||
|
||||
## Authorize an Account to Create NFTs
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/miVhXbph2ls?si=U1mRxlzul3k30R6O" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To authorize another account to create NFTs for your account (for example, allow the operational account to mint NFTs for the standby account):
|
||||
|
||||
1. Copy the **Operational Account** value.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
html: py-batch-minting.html
|
||||
parent: quickstart-python.html
|
||||
parent: nfts-using-python.html
|
||||
blurb: Mint multiple NFTs with the press of a button.
|
||||
labels:
|
||||
- Accounts
|
||||
@@ -28,20 +28,26 @@ You can download or clone the [Quickstart Samples](https://github.com/XRPLF/xrpl
|
||||
1. If you want to use an existing account seed:
|
||||
1. Paste the account seed in the **Standby Seed** field.
|
||||
2. Click **Get Standby Account**.
|
||||
2. If you do not want to use an existing account seed, click **Get Standby Account**.
|
||||
2. If you do not want to use an existing account seed, just click **Get Standby Account**.
|
||||
3. Click **Get Standby Account Info** to get the current XRP balance.
|
||||
|
||||
|
||||
## Batch Mint NFTs
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/NjEqEWcqhwc?si=E8ws75gts_7TtOuU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
This example lets you mint multiple NFTs for a single unique item. The NFT might represent "prints" of an original artwork, tickets to an event, or another limited set of unique items.
|
||||
|
||||
To batch mint non-fungible token objects:
|
||||
|
||||
1. Set the **Flags** field. For testing purposes, we recommend setting the value to _8_. This sets the _tsTransferable_ flag, meaning that the NFT object can be transferred to another account. Otherwise, the NFT object can only be transferred back to the issuing account. See [NFTokenMint](nftokenmint.html) for available NFT minting flags.
|
||||
2. Enter the **NFT URI**. This is a URI that points to the data or metadata associated with the NFT object. You can use the sample URI provided if you do not have one of your own.
|
||||
3. Enter an **NFT Count** of up to 200 NFTs to create in one batch.
|
||||
4. Enter the **Transfer Fee**, a percentage of the proceeds that the original creator receives from future sales of the NFT. This is a value of 0-50000 inclusive, allowing transfer fees between 0.000% and 50.000% in increments of 0.001%. If you do not set the **Flags** field to allow the NFT to be transferrable, set this field to 0.
|
||||
5. Click **Batch Mint NFTs**.
|
||||
1. Enter the **NFT URI**. This is a URI that points to the data or metadata associated with the NFT object. You can use this sample URI if you do not have one of your own: ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi.
|
||||
2. Set the **Flags** field. For testing purposes, we recommend setting the value to _8_. This sets the _tsTransferable_ flag, meaning that the NFT object can be transferred to another account. Otherwise, the NFT object can only be transferred back to the issuing account. See [NFTokenMint](nftokenmint.html) for available NFT minting flags.
|
||||
3. Enter the **Transfer Fee**, a percentage of the proceeds that the original creator receives from future sales of the NFT. This is a value of 0-50000 inclusive, allowing transfer fees between 0.000% and 50.000% in increments of 0.001%. If you do not set the **Flags** field to allow the NFT to be transferrable, set this field to 0.
|
||||
4. Enter the **Taxon** for the NFT. If you do not have a need for the Taxon field, set this value to 0.
|
||||
5. Enter an **NFT Count** of up to 200 NFTs to create in one batch.
|
||||
6. Click **Batch Mint NFTs**.
|
||||
|
||||
## Get Batch NFTs
|
||||
|
||||
@@ -235,11 +241,7 @@ import tkinter as tk
|
||||
import xrpl
|
||||
import json
|
||||
|
||||
from mod1 import get_account, get_account_info, send_xrp
|
||||
from mod2 import (
|
||||
get_balance,
|
||||
configure_account,
|
||||
)
|
||||
from mod1 import get_account, get_account_info
|
||||
```
|
||||
|
||||
Import dependencies from `mod7.py`.
|
||||
@@ -265,17 +267,11 @@ def batch_mint_nfts():
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def get_batch_nfts():
|
||||
results = get_batch(ent_standby_seed.get(), ent_standby_account.get())
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0",json.dumps(results, indent=4))
|
||||
|
||||
# Module 2 Handlers
|
||||
|
||||
def standby_configure_account():
|
||||
results = configure_account(
|
||||
def standby_get_batch_nfts():
|
||||
results = get_batch(
|
||||
ent_standby_seed.get(),
|
||||
standbyRippling)
|
||||
ent_standby_account.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
@@ -298,12 +294,10 @@ def get_standby_account_info():
|
||||
Rename the window for Module 7.
|
||||
|
||||
```python
|
||||
# Create a new window with the title "Quickstart Module 7"
|
||||
# Create a new window with the title "Python Module - Batch Minting"
|
||||
window = tk.Tk()
|
||||
window.title("Quickstart Module 7")
|
||||
window.title("Python Module - Batch Minting")
|
||||
|
||||
standbyRippling = tk.BooleanVar()
|
||||
operationalRippling = tk.BooleanVar()
|
||||
|
||||
|
||||
# Form frame
|
||||
@@ -315,11 +309,8 @@ lbl_standy_seed = tk.Label(master=frm_form, text="Standby Seed")
|
||||
ent_standby_seed = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_account = tk.Label(master=frm_form, text="Standby Account")
|
||||
ent_standby_account = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standy_amount = tk.Label(master=frm_form, text="Amount")
|
||||
ent_standby_amount = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_standby_balance = tk.Entry(master=frm_form, width=50)
|
||||
cb_standby_allow_rippling = tk.Checkbutton(master=frm_form, text="Allow Rippling", variable=standbyRippling, onvalue=True, offvalue=False)
|
||||
lbl_standby_uri = tk.Label(master=frm_form, text="NFT URI")
|
||||
ent_standby_uri = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_flags = tk.Label(master=frm_form, text="Flags")
|
||||
@@ -330,6 +321,8 @@ lbl_standby_taxon = tk.Label(master=frm_form, text="Taxon")
|
||||
ent_standby_taxon = tk.Entry(master=frm_form, width="50")
|
||||
lbl_standby_nft_id = tk.Label(master=frm_form, text="NFT ID")
|
||||
ent_standby_nft_id = tk.Entry(master=frm_form, width="50")
|
||||
lbl_standby_nft_offer_index = tk.Label(master=frm_form, text="NFT Offer Index")
|
||||
ent_standby_nft_offer_index = tk.Entry(master=frm_form, width="50")
|
||||
```
|
||||
|
||||
Add the **NFT Count** field for batch minting.
|
||||
@@ -345,11 +338,8 @@ lbl_standy_seed.grid(row=0, column=0, sticky="w")
|
||||
ent_standby_seed.grid(row=0, column=1)
|
||||
lbl_standby_account.grid(row=2, column=0, sticky="e")
|
||||
ent_standby_account.grid(row=2, column=1)
|
||||
lbl_standy_amount.grid(row=3, column=0, sticky="e")
|
||||
ent_standby_amount.grid(row=3, column=1)
|
||||
lbl_standby_balance.grid(row=5, column=0, sticky="e")
|
||||
ent_standby_balance.grid(row=5, column=1)
|
||||
cb_standby_allow_rippling.grid(row=7,column=1, sticky="w")
|
||||
lbl_standby_uri.grid(row=8, column=0, sticky="e")
|
||||
ent_standby_uri.grid(row=8, column=1, sticky="w")
|
||||
lbl_standby_flags.grid(row=9, column=0, sticky="e")
|
||||
@@ -358,8 +348,6 @@ lbl_standby_transfer_fee.grid(row=10, column=0, sticky="e")
|
||||
ent_standby_transfer_fee.grid(row=10, column=1, sticky="w")
|
||||
lbl_standby_taxon.grid(row=11, column=0, sticky="e")
|
||||
ent_standby_taxon.grid(row=11, column=1, sticky="w")
|
||||
lbl_standby_nft_id.grid(row=12, column=0, sticky="e")
|
||||
ent_standby_nft_id.grid(row=12, column=1, sticky="w")
|
||||
```
|
||||
|
||||
Place the **NFT Count** field in the grid.
|
||||
@@ -369,7 +357,6 @@ lbl_standby_nft_count.grid(row=13, column=0, sticky="e")
|
||||
ent_standby_nft_count.grid(row=13, column=1, sticky="w")
|
||||
lbl_standby_results.grid(row=14, column=0, sticky="ne")
|
||||
text_standby_results.grid(row=14, column=1, sticky="nw")
|
||||
cb_standby_allow_rippling.select()
|
||||
|
||||
#############################################
|
||||
## Buttons ##################################
|
||||
@@ -383,22 +370,19 @@ btn_get_standby_account_info = tk.Button(master=frm_form,
|
||||
text="Get Standby Account Info",
|
||||
command = get_standby_account_info)
|
||||
btn_get_standby_account_info.grid(row=1, column=2, sticky = "nsew")
|
||||
btn_standby_configure_account = tk.Button(master=frm_form,
|
||||
text="Configure Account",
|
||||
command = standby_configure_account)
|
||||
btn_standby_configure_account.grid(row=7,column=0, sticky = "nsew")
|
||||
```
|
||||
|
||||
Add the **Batch Mint NFTs** and **Get Batch NFTs** buttons.
|
||||
|
||||
```python
|
||||
btn_standby_mint_token = tk.Button(master=frm_form, text="Batch Mint NFTs",
|
||||
command = batch_mint_nfts)
|
||||
btn_standby_mint_token.grid(row=8, column=2, sticky="nsew")
|
||||
btn_standby_get_tokens = tk.Button(master=frm_form, text="Get Batch NFTs",
|
||||
command = get_batch_nfts)
|
||||
btn_standby_get_tokens.grid(row=9, column=2, sticky="nsew")
|
||||
|
||||
btn_standby_batch_mint = tk.Button(master=frm_form,
|
||||
text="Batch Mint NFTs",
|
||||
command = standby_batch_mint)
|
||||
btn_standby_batch_mint.grid(row=5, column=2, sticky = "nsew")
|
||||
btn_standby_get_batch_nfts = tk.Button(master=frm_form,
|
||||
text="Get Batch NFTs",
|
||||
command = standby_get_batch_nfts)
|
||||
btn_standby_get_batch_nfts.grid(row=8, column=2, sticky = "nsew")
|
||||
# Start the application
|
||||
window.mainloop()
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@ You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-port
|
||||
|
||||
## Prepare a Brokered Transaction
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/2dhWDnhCBuY?si=qpHSd6Y0ftVOe46E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
1. Use the Standby account to create an NFT Sell Offer with the Broker account as the destination.
|
||||
1. Enter the **Amount** of the sell offer in drops (millionths of an XRP).
|
||||
2. Enter the **NFT ID** of the NFT you want to sell.
|
||||
|
||||
@@ -34,6 +34,10 @@ Download and expand the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-p
|
||||
|
||||
## Usage
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Uu36ga0iMv0?si=jUoxQDcmqXpg1c_5" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To get test accounts:
|
||||
|
||||
1. Open and launch `lesson1-send-xrp.py`.
|
||||
@@ -47,6 +51,10 @@ To get test accounts:
|
||||
|
||||
You can transfer XRP between your new accounts. Each account has its own fields and buttons.
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/qUd-CTFdiks?si=chUPgcHZssL54x6U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To transfer XRP from the Standby account to the Operational account:
|
||||
|
||||
1. On the Standby (left) side of the form, enter the **Amount** of XRP to send.
|
||||
|
||||
608
content/tutorials/quickstart/py-create-conditional-escrows.md
Normal file
608
content/tutorials/quickstart/py-create-conditional-escrows.md
Normal file
@@ -0,0 +1,608 @@
|
||||
---
|
||||
html: py-create-conditional-escrows.html
|
||||
parent: send-payments-using-python.html
|
||||
blurb: Create, finish, or cancel condition-based escrow transactions.
|
||||
labels:
|
||||
- Accounts
|
||||
- Quickstart
|
||||
- Transaction Sending
|
||||
- XRP
|
||||
---
|
||||
# Create Conditional Escrows Using Python
|
||||
|
||||
This example shows how to:
|
||||
|
||||
1. Create escrow payments that become available when an account enters a fulfillment code.
|
||||
|
||||
2. Complete a conditional escrow transaction.
|
||||
|
||||
3. Cancel a conditional escrow transaction.
|
||||
|
||||
[](img/quickstart-py-conditional-escrow-1.png)
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Download and expand the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/py/){.github-code-download} archive.
|
||||
|
||||
You need the `cryptoconditions` module to generate your condition/fulfillment pair. You can install the module using [pip](https://pip.pypa.io/en/stable/).
|
||||
|
||||
In a terminal window, install the `cryptoconditions` module with this command:
|
||||
|
||||
```bash
|
||||
pip install cryptoconditions
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Get Test Accounts
|
||||
|
||||
To get test accounts:
|
||||
|
||||
1. Open and run `lesson9-conditional-escrow.py`.
|
||||
2. Get test accounts.
|
||||
1. If you have existing account seeds
|
||||
1. Paste Standby account seed in the **Standby Seed** field.
|
||||
2. Click **Get Standby Account**.
|
||||
3. Click **Get Standby Account Info**.
|
||||
4. Paste Operational account seed in the **Operational Seed** field.
|
||||
5. Click **Get Operational Account**.
|
||||
6. Click **Get Op Account Info**.
|
||||
2. If you do not have account seeds:
|
||||
1. Click **Get Standby Account**.
|
||||
2. Click **Get Standby Account Info**.
|
||||
3. Click **Get Operational Account**.
|
||||
4. Click **Get Op Account Info**.
|
||||
|
||||
[](img/quickstart-py-conditional-escrow-2.png)
|
||||
|
||||
#### Get a Condition and Fulfillment
|
||||
|
||||
Click **Get Condition** to generate a condition/fulfillment pair and populate the fields on the form. You can copy the values and store them in a text file for safe keeping.
|
||||
|
||||
[](img/quickstart-py-conditional-escrow-3.png)
|
||||
|
||||
### Create Conditional Escrow
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/IUfSX5RKahs?si=7kV0T2NTtqsZfpvX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
When you create a conditional escrow, you need to specify the `Condition` value you generated above. You must also set a cancel date and time, after which the escrow is no longer available.
|
||||
|
||||
To create a conditional escrow:
|
||||
|
||||
1. Enter an **Amount** to transfer.
|
||||
2. Copy the **Operational Account** value.
|
||||
3. Paste it in the **Destination Account** field.
|
||||
4. Enter the **Escrow Cancel (seconds)** value.
|
||||
5. Click **Create Escrow**.
|
||||
6. Copy and save the _Sequence Number_ of the escrow called out in the **Standby Result** field.
|
||||
|
||||
The escrow is created on the XRP Ledger instance, reserving your requested XRP amount plus the transaction cost.
|
||||
|
||||
When you create an escrow, capture and save the _Sequence Number_ so that you can use it to finish the escrow transaction.
|
||||
|
||||
[](img/quickstart-py-conditional-escrow-4.png)
|
||||
|
||||
## Finish Conditional Escrow
|
||||
|
||||
Any account can finish the conditional escrow any time before the _Escrow Cancel_ time. Following on the example above, you can use the _Sequence Number_ to finish the transaction once the Escrow Cancel time has passed.
|
||||
|
||||
To finish a conditional escrow:
|
||||
|
||||
1. Paste the sequence number in the Operational account **Sequence Number** field.
|
||||
2. Enter the **Escrow Condition** value.
|
||||
3. Enter the **Escrow Fulfillment** code for the `Condition`.
|
||||
4. Copy the **Standby Account** value.
|
||||
5. Paste it into the **Escrow Owner** field.
|
||||
4. Click **Finish Conditional Escrow**.
|
||||
|
||||
The transaction completes and balances are updated for both the Standby and Operational accounts.
|
||||
|
||||
[](img/quickstart-py-conditional-escrow-5.png)
|
||||
|
||||
## Get Escrows
|
||||
|
||||
Click **Get Escrows** for either the Standby account or the Operational account to see their current list of escrows.
|
||||
|
||||
## Cancel Escrow
|
||||
|
||||
When the Escrow Cancel time passes, the escrow is no longer available to the recipient. The initiator of the escrow can reclaim the XRP, less the transaction fees. Any account can cancel an escrow once the cancel time has elapsed. Accounts that try to cancel the transaction prior to the **Escrow Cancel** time are charged the nominal transaction cost (about 10-15 drops), but the actual escrow cannot be cancelled until after the Escrow Cancel time.
|
||||
|
||||
## Oh No! I Forgot to Save the Sequence Number!
|
||||
|
||||
If you forget to save the sequence number, you can find it in the escrow transaction record.
|
||||
|
||||
1. Create a new escrow as described in [Create Conditional Escrow](#create-conditional-escrow), above.
|
||||
2. Click **Get Escrows** to get the escrow information.
|
||||
3. Copy the _PreviousTxnLgrSeq_ value from the results.
|
||||

|
||||
4. Paste the _PreviousTxnLgrSeq_ in the **Transaction to Look Up** field.
|
||||

|
||||
5. Click **Get Transaction**.
|
||||
6. Locate the _Sequence_ value in the results.
|
||||
|
||||

|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Modular Tutorials](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/py/){.github-code-download} in the source repository for this website.
|
||||
|
||||
## mod9.py
|
||||
|
||||
Import dependencies.
|
||||
|
||||
```python
|
||||
import xrpl
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.wallet import Wallet
|
||||
from datetime import datetime
|
||||
from xrpl.models.transactions import EscrowCreate, EscrowFinish
|
||||
from os import urandom
|
||||
from cryptoconditions import PreimageSha256
|
||||
```
|
||||
|
||||
Create a global variable pointing to Testnet.
|
||||
|
||||
```python
|
||||
testnet_url = "https://s.altnet.rippletest.net:51234"
|
||||
```
|
||||
|
||||
### generate_condition
|
||||
|
||||
Generate the _condition_ and _fulfillment_ values for the escrow.
|
||||
|
||||
```python
|
||||
def generate_condition():
|
||||
```
|
||||
|
||||
Set a variable to 32 random bytes.
|
||||
|
||||
```python
|
||||
randy = urandom(32)
|
||||
```
|
||||
|
||||
Use the 32-byte random variable as the argument for the `PreimageSha256` functino.
|
||||
|
||||
```python
|
||||
fulfillment = PreimageSha256(preimage=randy)
|
||||
```
|
||||
|
||||
Return the binary condition and the binary serialized (fulfillment) value.
|
||||
|
||||
```python
|
||||
return (fulfillment.condition_binary.hex().upper(),
|
||||
fulfillment.serialize_binary().hex().upper())
|
||||
```
|
||||
|
||||
### add_seconds
|
||||
|
||||
Create a date in the Ripple epoch, adding the specified number of seconds.
|
||||
|
||||
```python
|
||||
def add_seconds(numOfSeconds):
|
||||
```
|
||||
|
||||
Create a new_date variable.
|
||||
|
||||
```python
|
||||
new_date = datetime.now()
|
||||
```
|
||||
|
||||
Convert the date to a Ripple time object.
|
||||
|
||||
```python
|
||||
if new_date != '':
|
||||
new_date = xrpl.utils.datetime_to_ripple_time(new_date)
|
||||
```
|
||||
|
||||
Add the requested seconds to the Ripple formatted date variable.
|
||||
|
||||
```python
|
||||
new_date = new_date + int(numOfSeconds)
|
||||
```
|
||||
|
||||
Return the result.
|
||||
|
||||
```python
|
||||
return new_date
|
||||
```
|
||||
|
||||
### create_conditional_escrow
|
||||
|
||||
You create conditional escrows using the same **EscrowCreate** model you used for a time-based escrow, but instead of a finish time, you provide a condition that must be met to complete the transaction.
|
||||
|
||||
Pass the _seed_ for the sending account, the _amount_ to hold in escrow, the _destination_ account to receive the escrow funds, the number of seconds until the escrow will _cancel_, and a _condition_ value that will be matched with a _fulfillment_ value to complete the escrow.
|
||||
|
||||
```python
|
||||
def create_conditional_escrow(seed, amount, destination, cancel, condition):
|
||||
```
|
||||
|
||||
Instantiate a wallet and connect to Testnet.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Create a *cancel_date* variable, adding your specified number of seconds to the current Ripple epoch date.
|
||||
|
||||
```python
|
||||
cancel_date = add_seconds(cancel)
|
||||
```
|
||||
|
||||
Define the transaction with your provided values.
|
||||
|
||||
```python
|
||||
escrow_tx=xrpl.models.transactions.EscrowCreate(
|
||||
account=wallet.address,
|
||||
amount=amount,
|
||||
destination=destination,
|
||||
cancel_after=cancel_date,
|
||||
condition=condition
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and return the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(escrow_tx,client,wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
### finish_conditional_escrow
|
||||
|
||||
At any time prior to the cancel date, the destination account can fulfill the escrow.
|
||||
|
||||
Pass the _seed_ for the receiving account, the _owner_ (sending account), the _sequence_ number for the escrow, the _condition_ value, and the matching _fulfillment_ value.
|
||||
|
||||
```python
|
||||
def finish_conditional_escrow(seed, owner, sequence, condition, fulfillment):
|
||||
```
|
||||
|
||||
Instantiate the account wallet and connect to Testnet.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the **EscrowFinish** transaction, including both the condition and the fulfillment values.
|
||||
|
||||
```python
|
||||
finish_tx=xrpl.models.transactions.EscrowFinish(
|
||||
account=wallet.address,
|
||||
owner=owner,
|
||||
offer_sequence=int(sequence),
|
||||
condition=condition,
|
||||
fulfillment=fulfillment
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and report the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(finish_tx,client,wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
## lesson9-conditional-escrow.py
|
||||
|
||||
This example builds on `lesson8-time-escrow.py` to reuse fields, buttons, and functions that apply to both time-based and conditional escrows. Updates are highlighted below.
|
||||
|
||||
```python
|
||||
import tkinter as tk
|
||||
import xrpl
|
||||
import json
|
||||
|
||||
from mod1 import get_account, get_account_info, send_xrp
|
||||
from mod8 import get_escrows, cancel_time_escrow, get_transaction
|
||||
```
|
||||
|
||||
Import new functions for conditional escrows from module 9.
|
||||
|
||||
```python
|
||||
from mod9 import create_conditional_escrow, finish_conditional_escrow, generate_condition
|
||||
|
||||
```
|
||||
|
||||
Add handlers for creating and finishing conditional escrows.
|
||||
|
||||
```python
|
||||
def get_condition():
|
||||
results = generate_condition()
|
||||
ent_standby_escrow_condition.delete(0, tk.END)
|
||||
ent_standby_escrow_condition.insert(0, results[0])
|
||||
ent_operational_escrow_fulfillment.delete(0, tk.END)
|
||||
ent_operational_escrow_fulfillment.insert(0, results[1])
|
||||
|
||||
def standby_create_conditional_escrow():
|
||||
results = create_conditional_escrow(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_amount.get(),
|
||||
ent_standby_destination.get(),
|
||||
ent_standby_escrow_cancel.get(),
|
||||
ent_standby_escrow_condition.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_finish_conditional_escrow():
|
||||
results = finish_conditional_escrow(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_escrow_owner.get(),
|
||||
ent_operational_sequence_number.get(),
|
||||
ent_standby_escrow_condition.get(),
|
||||
ent_operational_escrow_fulfillment.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
## Mod 8 Handlers
|
||||
|
||||
def operational_get_escrows():
|
||||
results = get_escrows(ent_operational_account.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def standby_cancel_time_escrow():
|
||||
results = cancel_time_escrow(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_escrow_owner.get(),
|
||||
ent_standby_escrow_sequence_number.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_get_transaction():
|
||||
results = get_transaction(ent_operational_account.get(),
|
||||
ent_operational_look_up.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
## Mod 1 Handlers
|
||||
|
||||
def get_standby_account():
|
||||
new_wallet = get_account(ent_standby_seed.get())
|
||||
ent_standby_account.delete(0, tk.END)
|
||||
ent_standby_seed.delete(0, tk.END)
|
||||
ent_standby_account.insert(0, new_wallet.classic_address)
|
||||
ent_standby_seed.insert(0, new_wallet.seed)
|
||||
|
||||
|
||||
def get_standby_account_info():
|
||||
accountInfo = get_account_info(ent_standby_account.get())
|
||||
ent_standby_balance.delete(0, tk.END)
|
||||
ent_standby_balance.insert(0,accountInfo['Balance'])
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0",json.dumps(accountInfo, indent=4))
|
||||
|
||||
|
||||
def standby_send_xrp():
|
||||
response = send_xrp(ent_standby_seed.get(),ent_standby_amount.get(),
|
||||
ent_standby_destination.get())
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0",json.dumps(response.result, indent=4))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
|
||||
def get_operational_account():
|
||||
new_wallet = get_account(ent_operational_seed.get())
|
||||
ent_operational_account.delete(0, tk.END)
|
||||
ent_operational_account.insert(0, new_wallet.classic_address)
|
||||
ent_operational_seed.delete(0, tk.END)
|
||||
ent_operational_seed.insert(0, new_wallet.seed)
|
||||
|
||||
|
||||
def get_operational_account_info():
|
||||
accountInfo = get_account_info(ent_operational_account.get())
|
||||
ent_operational_balance.delete(0, tk.END)
|
||||
ent_operational_balance.insert(0,accountInfo['Balance'])
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0",json.dumps(accountInfo, indent=4))
|
||||
|
||||
|
||||
def operational_send_xrp():
|
||||
response = send_xrp(ent_operational_seed.get(),ent_operational_amount.get(),
|
||||
ent_operational_destination.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0",json.dumps(response.result,indent=4))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
```
|
||||
|
||||
Rename the window.
|
||||
|
||||
```python
|
||||
window = tk.Tk()
|
||||
window.title("Conditional Escrow Example")
|
||||
|
||||
# Form frame
|
||||
frm_form = tk.Frame(relief=tk.SUNKEN, borderwidth=3)
|
||||
frm_form.pack()
|
||||
|
||||
# Create the Label and Entry widgets for "Standby Account"
|
||||
lbl_standy_seed = tk.Label(master=frm_form, text="Standby Seed")
|
||||
ent_standby_seed = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_account = tk.Label(master=frm_form, text="Standby Account")
|
||||
ent_standby_account = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standy_amount = tk.Label(master=frm_form, text="Amount")
|
||||
ent_standby_amount = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_destination = tk.Label(master=frm_form, text="Destination")
|
||||
ent_standby_destination = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_standby_balance = tk.Entry(master=frm_form, width=50)
|
||||
```
|
||||
|
||||
Add a field for the escrow condition.
|
||||
|
||||
```python
|
||||
lbl_standby_escrow_condition = tk.Label(master=frm_form, text="Escrow Condition")
|
||||
ent_standby_escrow_condition = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_cancel = tk.Label(master=frm_form, text="Escrow Cancel (seconds)")
|
||||
ent_standby_escrow_cancel = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_sequence_number = tk.Label(master=frm_form, text="Sequence Number")
|
||||
ent_standby_escrow_sequence_number = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_owner = tk.Label(master=frm_form, text="Escrow Owner")
|
||||
ent_standby_escrow_owner = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_results = tk.Label(master=frm_form, text="Results")
|
||||
text_standby_results = tk.Text(master=frm_form, height = 20, width = 65)
|
||||
|
||||
# Place fields in a grid.
|
||||
lbl_standy_seed.grid(row=0, column=0, sticky="e")
|
||||
ent_standby_seed.grid(row=0, column=1)
|
||||
lbl_standby_account.grid(row=2, column=0, sticky="e")
|
||||
ent_standby_account.grid(row=2, column=1)
|
||||
lbl_standy_amount.grid(row=3, column=0, sticky="e")
|
||||
ent_standby_amount.grid(row=3, column=1)
|
||||
lbl_standby_destination.grid(row=4, column=0, sticky="e")
|
||||
ent_standby_destination.grid(row=4, column=1)
|
||||
lbl_standby_balance.grid(row=5, column=0, sticky="e")
|
||||
ent_standby_balance.grid(row=5, column=1)
|
||||
```
|
||||
|
||||
Insert the condition field in the standby grid.
|
||||
|
||||
```python
|
||||
lbl_standby_escrow_condition.grid(row=6, column=0, sticky="e")
|
||||
ent_standby_escrow_condition.grid(row=6, column=1)
|
||||
lbl_standby_escrow_cancel.grid(row=7, column=0, sticky="e")
|
||||
ent_standby_escrow_cancel.grid(row=7, column=1)
|
||||
lbl_standby_escrow_sequence_number.grid(row=8, column=0, sticky="e")
|
||||
ent_standby_escrow_sequence_number.grid(row=8, column=1)
|
||||
lbl_standby_escrow_owner.grid(row=9, column=0, sticky="e")
|
||||
ent_standby_escrow_owner.grid(row=9, column=1)
|
||||
lbl_standby_results.grid(row=10, column=0, sticky="ne")
|
||||
text_standby_results.grid(row=10, column=1, sticky="nw")
|
||||
|
||||
###############################################
|
||||
## Operational Account ########################
|
||||
###############################################
|
||||
|
||||
# Create the Label and Entry widgets for "Operational Account"
|
||||
lbl_operational_seed = tk.Label(master=frm_form, text="Operational Seed")
|
||||
ent_operational_seed = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_account = tk.Label(master=frm_form, text="Operational Account")
|
||||
ent_operational_account = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_amount = tk.Label(master=frm_form, text="Amount")
|
||||
ent_operational_amount = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_destination = tk.Label(master=frm_form, text="Destination")
|
||||
ent_operational_destination = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_operational_balance = tk.Entry(master=frm_form, width=50)
|
||||
```
|
||||
|
||||
Add a field for the escrow fulfillment value.
|
||||
|
||||
```python
|
||||
lbl_operational_escrow_fulfillment = tk.Label(master=frm_form, text="Escrow Fulfillment")
|
||||
ent_operational_escrow_fulfillment = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_sequence_number = tk.Label(master=frm_form, text="Sequence Number")
|
||||
ent_operational_sequence_number = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_escrow_owner=tk.Label(master=frm_form, text="Escrow Owner")
|
||||
ent_operational_escrow_owner=tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_look_up = tk.Label(master=frm_form, text="Transaction to Look Up")
|
||||
ent_operational_look_up = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_results = tk.Label(master=frm_form,text='Results')
|
||||
text_operational_results = tk.Text(master=frm_form, height = 20, width = 65)
|
||||
|
||||
|
||||
#Place the widgets in a grid
|
||||
lbl_operational_seed.grid(row=0, column=4, sticky="e")
|
||||
ent_operational_seed.grid(row=0, column=5, sticky="w")
|
||||
lbl_operational_account.grid(row=2,column=4, sticky="e")
|
||||
ent_operational_account.grid(row=2,column=5, sticky="w")
|
||||
lbl_operational_amount.grid(row=3, column=4, sticky="e")
|
||||
ent_operational_amount.grid(row=3, column=5, sticky="w")
|
||||
lbl_operational_destination.grid(row=4, column=4, sticky="e")
|
||||
ent_operational_destination.grid(row=4, column=5, sticky="w")
|
||||
lbl_operational_balance.grid(row=5, column=4, sticky="e")
|
||||
ent_operational_balance.grid(row=5, column=5, sticky="w")
|
||||
```
|
||||
|
||||
Insert the **Fulfillment** field in the operational grid, moving the other fields down so as to align the **Condition** and **Fulfillment** fields horizontally.
|
||||
|
||||
```python
|
||||
lbl_operational_escrow_fulfillment.grid(row=6, column=4, sticky="e")
|
||||
ent_operational_escrow_fulfillment.grid(row=6, column=5, sticky="w")
|
||||
lbl_operational_sequence_number.grid(row=7, column=4, sticky="e")
|
||||
ent_operational_sequence_number.grid(row=7, column=5, sticky="w")
|
||||
lbl_operational_escrow_owner.grid(row=8, column=4, sticky="e")
|
||||
ent_operational_escrow_owner.grid(row=8, column=5, sticky="w")
|
||||
lbl_operational_look_up.grid(row=9, column=4, sticky="e")
|
||||
ent_operational_look_up.grid(row=9, column=5, sticky="w")
|
||||
lbl_operational_results.grid(row=10, column=4, sticky="ne")
|
||||
text_operational_results.grid(row=10, column=5, sticky="nw")
|
||||
|
||||
#############################################
|
||||
## Buttons ##################################
|
||||
#############################################
|
||||
|
||||
# Create the Get Standby Account Buttons
|
||||
btn_get_standby_account = tk.Button(master=frm_form, text="Get Standby Account",
|
||||
command = get_standby_account)
|
||||
btn_get_standby_account.grid(row = 0, column = 2, sticky = "nsew")
|
||||
btn_get_standby_account_info = tk.Button(master=frm_form,
|
||||
text="Get Standby Account Info",
|
||||
command = get_standby_account_info)
|
||||
btn_get_standby_account_info.grid(row = 1, column = 2, sticky = "nsew")
|
||||
btn_standby_send_xrp = tk.Button(master=frm_form, text="Send XRP >",
|
||||
command = standby_send_xrp)
|
||||
btn_standby_send_xrp.grid(row = 2, column = 2, sticky = "nsew")
|
||||
```
|
||||
|
||||
Add a **Create Conditional Escrow** button to the Standby grid.
|
||||
|
||||
```python
|
||||
btn_standby_get_condition = tk.Button(master=frm_form, text="Get Condition",
|
||||
command = get_condition)
|
||||
btn_standby_get_condition.grid(row=4, column=2, sticky="nsew")
|
||||
btn_standby_create_escrow = tk.Button(master=frm_form, text="Create Conditional Escrow",
|
||||
command = standby_create_conditional_escrow)
|
||||
btn_standby_create_escrow.grid(row=5, column = 2, sticky="nsew")
|
||||
btn_standby_cancel_escrow = tk.Button(master=frm_form, text="Cancel Escrow",
|
||||
command = standby_cancel_time_escrow)
|
||||
btn_standby_cancel_escrow.grid(row=6,column = 2, sticky="nsew")
|
||||
|
||||
# Create the Operational Account Buttons
|
||||
btn_get_operational_account = tk.Button(master=frm_form,
|
||||
text="Get Operational Account",
|
||||
command = get_operational_account)
|
||||
btn_get_operational_account.grid(row=0, column=3, sticky = "nsew")
|
||||
btn_get_op_account_info = tk.Button(master=frm_form, text="Get Op Account Info",
|
||||
command = get_operational_account_info)
|
||||
btn_get_op_account_info.grid(row=1, column=3, sticky = "nsew")
|
||||
btn_op_send_xrp = tk.Button(master=frm_form, text="< Send XRP",
|
||||
command = operational_send_xrp)
|
||||
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
|
||||
```
|
||||
|
||||
Add a **Finish Escrow** button to the operational grid.
|
||||
|
||||
```python
|
||||
btn_op_finish_escrow = tk.Button(master=frm_form, text="Finish Escrow",
|
||||
command = operational_finish_conditional_escrow)
|
||||
btn_op_finish_escrow.grid(row = 4, column = 3, sticky="nsew")
|
||||
btn_op_get_escrows = tk.Button(master=frm_form, text="Get Escrows",
|
||||
command = operational_get_escrows)
|
||||
btn_op_get_escrows.grid(row = 5, column = 3, sticky="nsew")
|
||||
btn_op_get_transaction = tk.Button(master=frm_form, text="Get Transaction",
|
||||
command = operational_get_transaction)
|
||||
btn_op_get_transaction.grid(row = 6, column = 3, sticky = "nsew")
|
||||
|
||||
# Start the application
|
||||
window.mainloop()
|
||||
```
|
||||
|
||||
637
content/tutorials/quickstart/py-create-time-based-escrows.md
Normal file
637
content/tutorials/quickstart/py-create-time-based-escrows.md
Normal file
@@ -0,0 +1,637 @@
|
||||
---
|
||||
html: py-create-time-based-escrows.html
|
||||
parent: send-payments-using-python.html
|
||||
blurb: Create, finish, or cancel time-based escrow transactions.
|
||||
labels:
|
||||
- Accounts
|
||||
- Quickstart
|
||||
- Transaction Sending
|
||||
- XRP
|
||||
---
|
||||
# Create Time-based Escrows Using Python
|
||||
|
||||
This example shows how to:
|
||||
|
||||
|
||||
1. Create escrow payments that become available at a specified time and expire at a specified time.
|
||||
2. Finish an escrow payment.
|
||||
3. Retrieve information on escrows attached to an account.
|
||||
3. Cancel an escrow payment and return the XRP to the sending account.
|
||||
|
||||
|
||||
[](img/quickstart-py-escrow1.png)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Download the [Python Modular Code Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/py/){.github-code-download}.
|
||||
|
||||
## Usage
|
||||
|
||||
To get test accounts:
|
||||
|
||||
1. Open `lesson8-time-escrow.py.`
|
||||
2. Get test accounts.
|
||||
1. If you have existing account seeds
|
||||
1. Paste Standby account seed in the **Standby Seed** field.
|
||||
2. Click **Get Standby Account**.
|
||||
3. Click **Get Standby Account Info**.
|
||||
4. Paste Operational account seed in the **Operational Seed** field.
|
||||
5. Click **Get Operational Account**.
|
||||
6. Click **Get Op Account Info**.
|
||||
2. If you do not have account seeds:
|
||||
1. Click **Get Standby Account**.
|
||||
2. Click **Get Standby Account Info**.
|
||||
3. Click **Get Operational Account**.
|
||||
4. Click **Get Op Account Info**.
|
||||
|
||||
[](img/quickstart-py-escrow2.png)
|
||||
|
||||
## Create Escrow
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/L_2sKokW5E4?si=6r9vn4ojr6b42H2E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
You can create a time-based escrow with a minimum time to finish the escrow and a cancel time after which the funds in escrow are no longer available to the recipient. This is a test harness: while a practical scenario might express time in days or weeks, this form lets you set the finish and cancel times in seconds so that you can quickly run through a variety of scenarios. (There are 86,400 seconds in a day, if you want to play with longer term escrows.)
|
||||
|
||||
To create a time-based escrow:
|
||||
|
||||
1. Enter an **Amount** to transfer. For example, _100000000_.
|
||||
2. Copy the **Operational Account** value.
|
||||
3. Paste it in the **Destination Account** field.
|
||||
4. Set the **Escrow Finish (seconds)** value. For example, enter _10_.
|
||||
5. Set the **Escrow Cancel (seconds)** value. For example, enter _120_.
|
||||
6. Click **Create Time-based Escrow**.
|
||||
7. Copy the _Sequence Number_ of the escrow called out in the **Standby Result** field.
|
||||
|
||||
The escrow is created on the XRP Ledger instance, reserving 100 XRP plus the transaction cost and reserve requirements. When you create an escrow, capture and save the **Sequence Number** so that you can use it to finish the escrow transaction.
|
||||
|
||||
[](img/quickstart-py-escrow3.png)
|
||||
|
||||
## Finish Escrow
|
||||
|
||||
The recipient of the XRP held in escrow can finish the transaction any time within the time window after the Escrow Finish date and time but before the Escrow Cancel date and time. Following on the example above, you can use the _Sequence Number_ to finish the transaction once 10 seconds have passed.
|
||||
|
||||
To finish a time-based escrow:
|
||||
|
||||
1. Paste the sequence number in the Operational account **Sequence Number** field.
|
||||
2. Click **Finish Escrow**.
|
||||
3. Click **Get Op Account Info** and **Get Standby Account Info** to update their **XRP Balance**.
|
||||
|
||||
The transaction completes and balances are updated for both the Standby and Operational accounts.
|
||||
|
||||
[](img/quickstart-py-escrow4.png)
|
||||
|
||||
## Get Escrows
|
||||
|
||||
Click **Get Escrows** to see the current list of escrows for the Operational account. If you click the button now, there are no escrows at the moment.
|
||||
|
||||
For the purposes of this tutorial, you can follow the steps in [Create Escrow](#create-escrow), above, to create a new escrow transaction that you can then look up. Remember to capture the _Sequence Number_ from the transaction results.
|
||||
|
||||
[](img/quickstart-py-escrow5.png)
|
||||
|
||||
|
||||
## Cancel Escrow
|
||||
|
||||
When the Escrow Cancel time passes, the escrow is no longer available to the recipient. The initiator of the escrow can reclaim the XRP. If you try to cancel the transaction prior to the **Escrow Cancel** time, you are charged for the transaction, but the actual escrow cannot be cancelled until the time limit is reached.
|
||||
|
||||
You can wait the allotted time for the escrow you created in the previous step, then use it to try out the **Cancel Escrow** button
|
||||
|
||||
To cancel an expired escrow:
|
||||
|
||||
1. Enter the sequence number in the Standby **Sequence Number** field.
|
||||
2. Copy the **Standby Account** value and paste it in the **Escrow Owner** field.
|
||||
2. Click **Cancel Time-based Escrow**.
|
||||
|
||||
The funds are returned to the Standby account, less the initial transaction fee.
|
||||
|
||||
[](img/quickstart-py-escrow6.png)
|
||||
|
||||
## Oh No! I Forgot to Save the Sequence Number!
|
||||
|
||||
If you forget to save the sequence number, you can find it in the escrow transaction record.
|
||||
|
||||
1. Create a new escrow as described in [Create Escrow](#create-escrow), above.
|
||||
2. Click **Get Escrows** to get the escrow information.
|
||||
3. Copy the _PreviousTxnLgrSeq_ value from the results.
|
||||

|
||||
4. Paste the _PreviousTxnLgrSeq_ in the **Transaction to Look Up** field.
|
||||
5. Click **Get Transaction**.
|
||||
6. Locate the _Sequence_ value in the results.
|
||||

|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Python Modular Code Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/py/){.github-code-download} in the source repository for this website.
|
||||
|
||||
## mod8.py
|
||||
|
||||
This example can be used with the XRP Ledger network, _Testnet_. You can update the code to choose different or additional XRP Ledger networks.
|
||||
|
||||
### add_seconds
|
||||
|
||||
This function accomplishes two things. It creates a new date object and adds the number of seconds taken from a form field. Then, it adjusts the date from the Python format to the XRP Ledger format.
|
||||
|
||||
Provide the _numOfSeconds_ argument.
|
||||
|
||||
```python
|
||||
def add_seconds(numOfSeconds):
|
||||
```
|
||||
|
||||
Create a new Python date object.
|
||||
|
||||
```python
|
||||
new_date = datetime.now()
|
||||
```
|
||||
|
||||
Convert the date variable for the Ripple epoch.
|
||||
|
||||
```python
|
||||
if new_date != '':
|
||||
new_date = xrpl.utils.datetime_to_ripple_time(new_date)
|
||||
```
|
||||
|
||||
Add your seconds to the date.
|
||||
|
||||
```python
|
||||
new_date = new_date + int(numOfSeconds)
|
||||
```
|
||||
|
||||
Return the resulting date value.
|
||||
|
||||
```python
|
||||
return new_date
|
||||
```
|
||||
|
||||
### create_time_escrow
|
||||
|
||||
Call the create_time_escrow function, passing the _seed_, _amount_, _destination_, _finish_ interval, and _cancel_ interval.
|
||||
|
||||
```python
|
||||
def create_time_escrow(seed, amount, destination, finish, cancel):
|
||||
```
|
||||
|
||||
Get the client wallet.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
```
|
||||
|
||||
Connect to Testnet.
|
||||
|
||||
```python
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Create variables for the finish and cancel dates using the add_seconds function.
|
||||
|
||||
```python
|
||||
finish_date = add_seconds(finish)
|
||||
cancel_date = add_seconds(cancel)
|
||||
```
|
||||
|
||||
Define the **EscrowCreate** transaction.
|
||||
|
||||
```python
|
||||
escrow_tx=xrpl.models.transactions.EscrowCreate(
|
||||
account=wallet.address,
|
||||
amount=amount,
|
||||
destination=destination,
|
||||
finish_after=finish_date,
|
||||
cancel_after=cancel_date
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and report the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(escrow_tx,client,wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
### finish_time_escrow
|
||||
|
||||
Pass the operational account _seed_, escrow _owner_ (in these examples, the standby address), and the escrow _sequence_ number.
|
||||
|
||||
```python
|
||||
def finish_time_escrow(seed, owner, sequence):
|
||||
```
|
||||
|
||||
Instantiate the wallet and client.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the **EscrowFinish** transaction.
|
||||
|
||||
```python
|
||||
finish_tx=xrpl.models.transactions.EscrowFinish(
|
||||
account=wallet.address,
|
||||
owner=owner,
|
||||
offer_sequence=int(sequence)
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and report the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(finish_tx,client,wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
### get_escrows
|
||||
|
||||
This request only requires the _account_ argument.
|
||||
|
||||
```python
|
||||
def get_escrows(account):
|
||||
```
|
||||
|
||||
Since this is a request, there's no need to sign in with an account to perform the query. You can just instantiate a client on Testnet.
|
||||
|
||||
```python
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the **AccountObjects** request, specifying objects of type _escrow_.
|
||||
|
||||
```python
|
||||
acct_escrows=AccountObjects(
|
||||
account=account,
|
||||
ledger_index="validated",
|
||||
type="escrow"
|
||||
)
|
||||
```
|
||||
|
||||
Submit the request and return the results.
|
||||
|
||||
```python
|
||||
response=client.request(acct_escrows)
|
||||
return response.result
|
||||
```
|
||||
|
||||
### cancel_time_escrows
|
||||
|
||||
Pass the issuer account _seed_, the _owner_ account, and the escrow _sequence_ number.
|
||||
|
||||
```python
|
||||
def cancel_time_escrow(seed, owner, sequence):
|
||||
```
|
||||
|
||||
Get the wallet and instantiate a client on _Testnet_.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the cancel transaction
|
||||
|
||||
```python
|
||||
cancel_tx=xrpl.models.transactions.EscrowCancel(
|
||||
account=wallet.address,
|
||||
owner=owner,
|
||||
offer_sequence=int(sequence)
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and report the results
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(cancel_tx,client,wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
### get_transaction
|
||||
|
||||
Pass the requesting account number and the previous transaction ledger sequence number.
|
||||
|
||||
```python
|
||||
def get_transaction(account, ledger_index):
|
||||
```
|
||||
|
||||
Create a client instance.
|
||||
|
||||
```python
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Create the **AccountTx** request.
|
||||
|
||||
```python
|
||||
tx_info=AccountTx(
|
||||
account=account,
|
||||
ledger_index=int(ledger_index)
|
||||
)
|
||||
```
|
||||
|
||||
Send the request and report the results.
|
||||
|
||||
```python
|
||||
response=client.request(tx_info)
|
||||
return response.result
|
||||
```
|
||||
|
||||
## lesson8-time-escrow.py
|
||||
|
||||
This module builds on `lesson1-send-xrp.py`. Changes are noted below.
|
||||
|
||||
```python
|
||||
import tkinter as tk
|
||||
import xrpl
|
||||
import json
|
||||
|
||||
from mod1 import get_account, get_account_info, send_xrp
|
||||
```
|
||||
|
||||
Import new functions from mod8.py.
|
||||
|
||||
```python
|
||||
from mod8 import create_time_escrow, finish_time_escrow, get_escrows, cancel_time_escrow, get_transaction
|
||||
```
|
||||
|
||||
Module 8 Handlers
|
||||
|
||||
```python
|
||||
def standby_create_time_escrow():
|
||||
results = create_time_escrow(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_amount.get(),
|
||||
ent_standby_destination.get(),
|
||||
ent_standby_escrow_finish.get(),
|
||||
ent_standby_escrow_cancel.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_finish_time_escrow():
|
||||
results = finish_time_escrow(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_escrow_owner.get(),
|
||||
ent_operational_sequence_number.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_get_escrows():
|
||||
results = get_escrows(ent_operational_account.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def standby_cancel_time_escrow():
|
||||
results = cancel_time_escrow(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_escrow_owner.get(),
|
||||
ent_standby_escrow_sequence_number.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_get_transaction():
|
||||
results = get_transaction(ent_operational_account.get(),
|
||||
ent_operational_look_up.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
## Mod 1 Handlers
|
||||
|
||||
def get_standby_account():
|
||||
new_wallet = get_account(ent_standby_seed.get())
|
||||
ent_standby_account.delete(0, tk.END)
|
||||
ent_standby_seed.delete(0, tk.END)
|
||||
ent_standby_account.insert(0, new_wallet.classic_address)
|
||||
ent_standby_seed.insert(0, new_wallet.seed)
|
||||
|
||||
|
||||
def get_standby_account_info():
|
||||
accountInfo = get_account_info(ent_standby_account.get())
|
||||
ent_standby_balance.delete(0, tk.END)
|
||||
ent_standby_balance.insert(0,accountInfo['Balance'])
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0",json.dumps(accountInfo, indent=4))
|
||||
|
||||
|
||||
def standby_send_xrp():
|
||||
response = send_xrp(ent_standby_seed.get(),ent_standby_amount.get(),
|
||||
ent_standby_destination.get())
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0",json.dumps(response.result, indent=4))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
|
||||
def get_operational_account():
|
||||
new_wallet = get_account(ent_operational_seed.get())
|
||||
ent_operational_account.delete(0, tk.END)
|
||||
ent_operational_account.insert(0, new_wallet.classic_address)
|
||||
ent_operational_seed.delete(0, tk.END)
|
||||
ent_operational_seed.insert(0, new_wallet.seed)
|
||||
|
||||
|
||||
def get_operational_account_info():
|
||||
accountInfo = get_account_info(ent_operational_account.get())
|
||||
ent_operational_balance.delete(0, tk.END)
|
||||
ent_operational_balance.insert(0,accountInfo['Balance'])
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0",json.dumps(accountInfo, indent=4))
|
||||
|
||||
|
||||
def operational_send_xrp():
|
||||
response = send_xrp(ent_operational_seed.get(),ent_operational_amount.get(),
|
||||
ent_operational_destination.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0",json.dumps(response.result,indent=4))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
|
||||
# Create a new window with the title "Quickstart Module 1"
|
||||
window = tk.Tk()
|
||||
window.title("Time-based Escrow Example")
|
||||
|
||||
# Form frame
|
||||
frm_form = tk.Frame(relief=tk.SUNKEN, borderwidth=3)
|
||||
frm_form.pack()
|
||||
|
||||
# Create the Label and Entry widgets for "Standby Account"
|
||||
lbl_standy_seed = tk.Label(master=frm_form, text="Standby Seed")
|
||||
ent_standby_seed = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_account = tk.Label(master=frm_form, text="Standby Account")
|
||||
ent_standby_account = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standy_amount = tk.Label(master=frm_form, text="Amount")
|
||||
ent_standby_amount = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_destination = tk.Label(master=frm_form, text="Destination")
|
||||
ent_standby_destination = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_standby_balance = tk.Entry(master=frm_form, width=50)
|
||||
```
|
||||
|
||||
Add supporting fields for escrow commands.
|
||||
|
||||
```python
|
||||
lbl_standby_escrow_finish = tk.Label(master=frm_form, text="Escrow Finish (seconds)")
|
||||
ent_standby_escrow_finish = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_cancel = tk.Label(master=frm_form, text="Escrow Cancel (seconds)")
|
||||
ent_standby_escrow_cancel = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_sequence_number = tk.Label(master=frm_form, text="Sequence Number")
|
||||
ent_standby_escrow_sequence_number = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_owner = tk.Label(master=frm_form, text="Escrow Owner")
|
||||
ent_standby_escrow_owner = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_results = tk.Label(master=frm_form, text="Results")
|
||||
text_standby_results = tk.Text(master=frm_form, height = 20, width = 65)
|
||||
|
||||
# Place fields in a grid.
|
||||
lbl_standy_seed.grid(row=0, column=0, sticky="e")
|
||||
ent_standby_seed.grid(row=0, column=1)
|
||||
lbl_standby_account.grid(row=2, column=0, sticky="e")
|
||||
ent_standby_account.grid(row=2, column=1)
|
||||
lbl_standy_amount.grid(row=3, column=0, sticky="e")
|
||||
ent_standby_amount.grid(row=3, column=1)
|
||||
lbl_standby_destination.grid(row=4, column=0, sticky="e")
|
||||
ent_standby_destination.grid(row=4, column=1)
|
||||
lbl_standby_balance.grid(row=5, column=0, sticky="e")
|
||||
ent_standby_balance.grid(row=5, column=1)
|
||||
```
|
||||
|
||||
Add supporting fields for escrow to the standby side of the form.
|
||||
|
||||
```python
|
||||
lbl_standby_escrow_finish.grid(row=6, column=0, sticky="e")
|
||||
ent_standby_escrow_finish.grid(row=6, column=1)
|
||||
lbl_standby_escrow_cancel.grid(row=7, column=0, sticky="e")
|
||||
ent_standby_escrow_cancel.grid(row=7, column=1)
|
||||
lbl_standby_escrow_sequence_number.grid(row=8, column=0, sticky="e")
|
||||
ent_standby_escrow_sequence_number.grid(row=8, column=1)
|
||||
lbl_standby_escrow_owner.grid(row=9, column=0, sticky="e")
|
||||
ent_standby_escrow_owner.grid(row=9, column=1)
|
||||
lbl_standby_results.grid(row=10, column=0, sticky="ne")
|
||||
text_standby_results.grid(row=10, column=1, sticky="nw")
|
||||
|
||||
###############################################
|
||||
## Operational Account ########################
|
||||
###############################################
|
||||
|
||||
# Create the Label and Entry widgets for "Operational Account"
|
||||
lbl_operational_seed = tk.Label(master=frm_form, text="Operational Seed")
|
||||
ent_operational_seed = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_account = tk.Label(master=frm_form, text="Operational Account")
|
||||
ent_operational_account = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_amount = tk.Label(master=frm_form, text="Amount")
|
||||
ent_operational_amount = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_destination = tk.Label(master=frm_form, text="Destination")
|
||||
ent_operational_destination = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_operational_balance = tk.Entry(master=frm_form, width=50)
|
||||
```
|
||||
|
||||
Define escrow supporting fields for the operational side of the form.
|
||||
|
||||
```python
|
||||
lbl_operational_sequence_number = tk.Label(master=frm_form, text="Sequence Number")
|
||||
ent_operational_sequence_number = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_escrow_owner=tk.Label(master=frm_form, text="Escrow Owner")
|
||||
ent_operational_escrow_owner=tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_look_up = tk.Label(master=frm_form, text="Transaction to Look Up")
|
||||
ent_operational_look_up = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_results = tk.Label(master=frm_form,text='Results')
|
||||
text_operational_results = tk.Text(master=frm_form, height = 20, width = 65)
|
||||
|
||||
#Place the widgets in a grid
|
||||
lbl_operational_seed.grid(row=0, column=4, sticky="e")
|
||||
ent_operational_seed.grid(row=0, column=5, sticky="w")
|
||||
lbl_operational_account.grid(row=2,column=4, sticky="e")
|
||||
ent_operational_account.grid(row=2,column=5, sticky="w")
|
||||
lbl_operational_amount.grid(row=3, column=4, sticky="e")
|
||||
ent_operational_amount.grid(row=3, column=5, sticky="w")
|
||||
lbl_operational_destination.grid(row=4, column=4, sticky="e")
|
||||
ent_operational_destination.grid(row=4, column=5, sticky="w")
|
||||
lbl_operational_balance.grid(row=5, column=4, sticky="e")
|
||||
ent_operational_balance.grid(row=5, column=5, sticky="w")
|
||||
```
|
||||
|
||||
Add supporting fields for escrow to the operational side of the form.
|
||||
|
||||
```python
|
||||
lbl_operational_sequence_number.grid(row=6, column=4, sticky="e")
|
||||
ent_operational_sequence_number.grid(row=6, column=5, sticky="w")
|
||||
lbl_operational_escrow_owner.grid(row=7, column=4, sticky="e")
|
||||
ent_operational_escrow_owner.grid(row=7, column=5, sticky="w")
|
||||
lbl_operational_look_up.grid(row=8, column=4, sticky="e")
|
||||
ent_operational_look_up.grid(row=8, column=5, sticky="w")
|
||||
lbl_operational_results.grid(row=10, column=4, sticky="ne")
|
||||
text_operational_results.grid(row=10, column=5, sticky="nw")
|
||||
|
||||
#############################################
|
||||
## Buttons ##################################
|
||||
#############################################
|
||||
|
||||
# Create the Get Standby Account Buttons
|
||||
btn_get_standby_account = tk.Button(master=frm_form, text="Get Standby Account",
|
||||
command = get_standby_account)
|
||||
btn_get_standby_account.grid(row = 0, column = 2, sticky = "nsew")
|
||||
btn_get_standby_account_info = tk.Button(master=frm_form,
|
||||
text="Get Standby Account Info",
|
||||
command = get_standby_account_info)
|
||||
btn_get_standby_account_info.grid(row = 1, column = 2, sticky = "nsew")
|
||||
btn_standby_send_xrp = tk.Button(master=frm_form, text="Send XRP >",
|
||||
command = standby_send_xrp)
|
||||
btn_standby_send_xrp.grid(row = 2, column = 2, sticky = "nsew")
|
||||
```
|
||||
|
||||
Add buttons for escrow activity on the standby side of the form.
|
||||
|
||||
```python
|
||||
btn_standby_create_escrow = tk.Button(master=frm_form, text="Create Time-based Escrow",
|
||||
command = standby_create_time_escrow)
|
||||
btn_standby_create_escrow.grid(row = 4, column = 2, sticky="nsew")
|
||||
btn_standby_cancel_escrow = tk.Button(master=frm_form, text="Cancel Time-based Escrow",
|
||||
command = standby_cancel_time_escrow)
|
||||
btn_standby_cancel_escrow.grid(row=5,column = 2, sticky="nsew")
|
||||
|
||||
# Create the Operational Account Buttons
|
||||
btn_get_operational_account = tk.Button(master=frm_form,
|
||||
text="Get Operational Account",
|
||||
command = get_operational_account)
|
||||
btn_get_operational_account.grid(row=0, column=3, sticky = "nsew")
|
||||
btn_get_op_account_info = tk.Button(master=frm_form, text="Get Op Account Info",
|
||||
command = get_operational_account_info)
|
||||
btn_get_op_account_info.grid(row=1, column=3, sticky = "nsew")
|
||||
btn_op_send_xrp = tk.Button(master=frm_form, text="< Send XRP",
|
||||
command = operational_send_xrp)
|
||||
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
|
||||
```
|
||||
|
||||
Add buttons to support escrow activity on the operational side of the form.
|
||||
|
||||
```python
|
||||
btn_op_finish_escrow = tk.Button(master=frm_form, text="Finish Escrow",
|
||||
command = operational_finish_time_escrow)
|
||||
btn_op_finish_escrow.grid(row = 4, column = 3, sticky="nsew")
|
||||
btn_op_finish_escrow = tk.Button(master=frm_form, text="Get Escrows",
|
||||
command = operational_get_escrows)
|
||||
btn_op_finish_escrow.grid(row = 5, column = 3, sticky="nsew")
|
||||
btn_op_get_transaction = tk.Button(master=frm_form, text="Get Transaction",
|
||||
command = operational_get_transaction)
|
||||
btn_op_get_transaction.grid(row = 6, column = 3, sticky = "nsew")
|
||||
|
||||
|
||||
# Start the application
|
||||
window.mainloop()
|
||||
```
|
||||
@@ -39,6 +39,11 @@ Open the Quickstart window and get accounts:
|
||||
|
||||
## Create Trust Line
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/6KWP0PV6J8Y?si=SSxFGrvfTo6pOPLD" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
|
||||
To create a trust line between accounts:
|
||||
|
||||
1. Enter a [currency code](https://www.iban.com/currency-codes) in the **Currency** field.
|
||||
|
||||
@@ -41,6 +41,10 @@ You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-port
|
||||
|
||||
## Mint an NFT
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/StOLO9Bx9n8?si=IgMtoYRQlheaXzsG" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To mint a non-fungible token object:
|
||||
|
||||
1. Set the **Flags** field. For testing purposes, we recommend setting the value to _8_. This sets the _tsTransferable_ flag, meaning that the NFT can be transferred to another account. Otherwise, the NFT can only be transferred back to the issuing account. See [NFToken Mint](https://xrpl.org/nftokenmint.html#:~:text=Example%20NFTokenMint%20JSON-,NFTokenMint%20Fields,-NFTokenMint%20Flags) for information about all of the available flags for minting NFTs.
|
||||
|
||||
@@ -47,6 +47,10 @@ You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-port
|
||||
|
||||
## Create a Sell Offer
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/tL3wIJXBt7Q?si=t3LYsxIVkZU7yAx_" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To create a NFT sell offer:
|
||||
|
||||
1. Enter the **Amount** of the sell offer in drops (millionths of an XRP).
|
||||
@@ -547,7 +551,7 @@ def standby_cancel_offer():
|
||||
ent_standby_nft_offer_index.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
def op_create_sell_offer():
|
||||
results = create_sell_offer(
|
||||
ent_operational_seed.get(),
|
||||
@@ -575,7 +579,7 @@ def op_create_buy_offer():
|
||||
ent_operational_destination.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
def op_accept_buy_offer():
|
||||
results = accept_buy_offer (
|
||||
ent_operational_seed.get(),
|
||||
@@ -593,7 +597,7 @@ def op_cancel_offer():
|
||||
ent_operational_nft_offer_index.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
# Module 3 Handlers
|
||||
@@ -686,10 +690,10 @@ def operational_configure_account():
|
||||
def get_balances():
|
||||
results = get_balance(ent_operational_account.get(), ent_standby_account.get())
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
results = get_balance(ent_standby_account.get(), ent_operational_account.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
# Module 1 Handlers
|
||||
def get_standby_account():
|
||||
@@ -992,7 +996,7 @@ btn_op_burn_token = tk.Button(master=frm_form, text="Burn NFT",
|
||||
btn_op_burn_token.grid(row=10, column=3, sticky="nsew")
|
||||
```
|
||||
|
||||
Add buttons for transferring NFTs.
|
||||
Add buttons for transferring NFTs.
|
||||
|
||||
```python
|
||||
btn_op_create_sell_offer = tk.Button(master=frm_form, text="Create Sell Offer",
|
||||
|
||||
@@ -40,6 +40,10 @@ You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-port
|
||||
|
||||
## Create a Sell Offer
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/He5PpO7TQbQ?si=mejmPLh-Z7ocbJVV" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To create a NFT sell offer:
|
||||
|
||||
1. Enter the **Amount** of the sell offer in drops (millionths of an XRP).
|
||||
|
||||
9
content/tutorials/tasks/index.md
Normal file
9
content/tutorials/tasks/index.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
html: tasks.html
|
||||
parent: tutorials.html
|
||||
top_nav_grouping: Article Types
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# Tasks
|
||||
|
||||
Common tasks on the XRP Ledger.
|
||||
8
content/tutorials/tasks/manage-account-settings/index.md
Normal file
8
content/tutorials/tasks/manage-account-settings/index.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
html: manage-account-settings.html
|
||||
parent: tasks.html
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# Manage Account Settings
|
||||
|
||||
Set up your XRP Ledger account to send and receive payments the way you want it to.
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
html: use-specialized-payment-types.html
|
||||
parent: tasks.html
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# Use Specialized Payment Types
|
||||
|
||||
Use advanced features like Escrow and Payment Channels to build smart applications on the XRP Ledger.
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
html: use-escrows.html
|
||||
parent: use-specialized-payment-types.html
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# Use Escrows
|
||||
|
||||
The XRP Ledger supports escrows that can be executed only after a certain time has passed or a cryptographic condition has been fulfilled. Escrows can only send XRP, not issued currencies.
|
||||
8
content/tutorials/tasks/use-tokens/index.md
Normal file
8
content/tutorials/tasks/use-tokens/index.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
html: use-tokens.html
|
||||
parent: tasks.html
|
||||
template: pagetype-category.html.jinja
|
||||
---
|
||||
# Use Tokens
|
||||
|
||||
Create and trade tokens (fungible or otherwise) in the XRP Ledger.
|
||||
@@ -1,198 +0,0 @@
|
||||
---
|
||||
html: cancel-a-check.html
|
||||
parent: use-checks.html
|
||||
blurb: 送金を行わずにCheckを取り消す。
|
||||
labels:
|
||||
- Checks
|
||||
---
|
||||
# Checkの取消し
|
||||
|
||||
_[Checks Amendment][]が必要です。_
|
||||
|
||||
このチュートリアルでは、[Check](checks.html)を取り消す手順を説明します。この手順を実行すると、送金を行わずに[レジャーのCheckオブジェクト](check.html)が削除されます。
|
||||
|
||||
着信したCheckが不要な場合、取り消すことができます。送信時に内容を誤って入力した場合や状況が変化した場合に、送信したCheckを取り消すこともできます。有効期限切れのCheckはレジャーから削除する必要があります。これにより、送金元に[所有者準備金](reserves.html#所有者準備金)が戻ります。
|
||||
|
||||
{% set cancel_n = cycler(* range(1,99)) %}
|
||||
|
||||
## 前提条件
|
||||
|
||||
このチュートリアルでCheckを取り消すには、以下が必要です。
|
||||
|
||||
- 現在レジャーに記録されているCheckオブジェクトのIDが必要です。
|
||||
- たとえばこのチュートリアルの例では、IDが`49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0`のCheckを取り消しますが、この手順を自身で実行する場合は異なるIDを使用する必要があります。
|
||||
- CheckCancelトランザクションを送信する資金供給のあるアカウントの**アドレス**と**シークレットキー**。Checkが有効期限切れでない限り、このアドレスは、Checkの送金元または受取人のいずれかでなければなりません。
|
||||
- トランザクションに[安全に署名できる手段](secure-signing.html)。
|
||||
- [クライアントライブラリ](client-libraries.html)またはHTTPライブラリ、WebSocketライブラリなど。
|
||||
|
||||
|
||||
## {{cancel_n.next()}}.CheckCancelトランザクションの準備
|
||||
|
||||
[CheckCancelトランザクション][]のフィールドの値を決定します。以下のフィールドは必要最小限のフィールドです。その他のフィールドはオプションまたは署名時に[自動入力](transaction-common-fields.html#自動入力可能なフィールド)可能なフィールドです。
|
||||
|
||||
| フィールド | 値 | 説明 |
|
||||
|:------------------|:-----------------|:--------------------------------------|
|
||||
| `TransactionType` | 文字列 | Checkを取り消す場合は文字列`CheckCancel`を使用します。 |
|
||||
| `Account` | 文字列(アドレス) | Checkを取り消す送信元のアドレス。(あなたのアドレスです。) |
|
||||
| `CheckID` | 文字列 | レジャーで取り消すCheckオブジェクトのID。この情報を確認するには、[txメソッド][]を使用してCheckCreateトランザクションのメタデータを調べるか、または[account_objectsメソッド][]を使用してCheckを探します。 |
|
||||
|
||||
### CheckCancelトランザクションの準備の例
|
||||
|
||||
Checkを取り消す例を以下に示します。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*JSON-RPC、WebSocket、またはコマンドライン*
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "CheckCancel",
|
||||
"Account": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
|
||||
"CheckID": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0",
|
||||
"Fee": "12"
|
||||
}
|
||||
```
|
||||
|
||||
*ripple-lib 1.x*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/prepareCancel.js' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## {{cancel_n.next()}}.CheckCancelトランザクションの署名
|
||||
|
||||
{% include '_snippets/tutorial-sign-step.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*ripple-lib 1.x*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/signCancel.js' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/sign-cancel-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*ripple-lib 1.x*
|
||||
|
||||
```
|
||||
{% include '_code-samples/checks/js/sign-cancel-resp.txt' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/sign-cancel-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
## {{cancel_n.next()}}.署名済みCheckCancelトランザクションの送信
|
||||
|
||||
{% set step_1_link = "#1checkcancelトランザクションの準備" %}
|
||||
{% include '_snippets/tutorial-submit-step.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*ripple-lib 1.x*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/submitCancel.js' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/submit-cancel-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*ripple-lib 1.x*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/submit-cancel-resp.txt' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/submit-cancel-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## {{cancel_n.next()}}.検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
## {{cancel_n.next()}}.最終結果の確認
|
||||
|
||||
トランザクションのステータスを確認するには、CheckCancelトランザクションの識別用ハッシュを指定した[txメソッド][]を使用します。トランザクションが成功したことを示す`"TransactionResult": "tesSUCCESS"`フィールドをトランザクションメタデータから検索し、またこの結果が最終結果であることを示す`"validated": true`フィールドを結果から検索します。
|
||||
|
||||
トランザクションによって[Checkレジャーオブジェクト](check.html)が削除されたことを示す`"LedgerEntryType": "Check"`を含む`DeletedNode`オブジェクトを、トランザクションメタデータから検索します。このオブジェクトの`LedgerIndex`はCheckのIDに一致している必要があります。
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*ripple-lib 1.x*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/getCancelTx.js' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/tx-cancel-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*ripple-lib 1.x*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/js/get-cancel-tx-resp.txt' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/tx-cancel-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,215 +0,0 @@
|
||||
---
|
||||
html: cash-a-check-for-a-flexible-amount.html
|
||||
parent: use-checks.html
|
||||
blurb: Checkから可能な限りの額を受領します。
|
||||
labels:
|
||||
- Checks
|
||||
---
|
||||
# Checkの変動金額での換金
|
||||
|
||||
_[Checks Amendment][]が必要です。_
|
||||
|
||||
Checkがレジャーに記録されており有効期限切れではない場合は、指定受取人は`DeliverMin`フィールドを指定した[CheckCashトランザクション][]を送信することで、Checkを変動金額で換金して受領できます。この方法でCheckを換金すると、受取人は送金を最大限受領でき、Checkの送金元からは、Checkの`SendMax`の全額が引き落とされるか、または可能な限りの額が引き落とされます。Checkの受取人に`DeliverMin`以上の額を送金できない場合は換金が失敗します。
|
||||
|
||||
Checkから可能な限りの額を受領したい場合には、変動金額でCheckを換金できます。
|
||||
|
||||
指定受取人は、[Checkを正確な金額で換金する](cash-a-check-for-a-flexible-amount.html)こともできます。
|
||||
|
||||
{% set cash_flex_n = cycler(* range(1,99)) %}
|
||||
|
||||
|
||||
## 前提条件
|
||||
|
||||
{% include '_snippets/checkcash-prereqs.ja.md' %}<!--#{ fix md highlighting_ #}-->
|
||||
|
||||
## {{cash_flex_n.next()}}.CheckCashトランザクションの準備
|
||||
|
||||
[CheckCashトランザクション][]のフィールドの値を決定します。Checkを変動金額で換金する場合、以下のフィールドは必要最小限です。それ以外のフィールドはオプションまたは署名時に[自動入力](transaction-common-fields.html#自動入力可能なフィールド)可能なフィールドです。
|
||||
|
||||
| フィールド | 値 | 説明 |
|
||||
|:------------------|:--------------------------|:-----------------------------|
|
||||
| `TransactionType` | 文字列 | 値が`CheckCash`の場合、これはCheckCashトランザクションです。 |
|
||||
| `Account` | 文字列(アドレス) | Checkを換金する送信者のアドレス。(あなたのアドレスです。) |
|
||||
| `CheckID` | 文字列 | レジャーで換金するCheckオブジェクトのID。この情報を確認するには、[txメソッド][]を使用してCheckCreateトランザクションのメタデータを調べるか、または[account_objectsメソッド][]を使用してCheckを探します。 |
|
||||
| `DeliverMin` | 文字列またはオブジェクト(額) | Checkから受領する最小額。この額を受領できない場合はCheckの換金が失敗し、Checkがレジャーに残るので、後で換金を再試行できます。XRPの場合、XRPのdrop数を示す文字列でなければなりません。発行済み通貨の場合、これは`currency`、`issuer`、および`value` フィールドを持つオブジェクトです。`currency`フィールドと`issuer`フィールドは、Checkオブジェクトの対応するフィールドに一致しており、`value`はCheckオブジェクトの額以下でなければなりません。詳細は、[通貨額の指定][]を参照してください。 |
|
||||
|
||||
### 変動金額で換金するCheckCashトランザクションの準備の例
|
||||
|
||||
Checkを変動金額で換金するためのトランザクションを準備する手順を以下の例に示します。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*JSON-RPC、WebSocket、またはコマンドライン*
|
||||
|
||||
```json
|
||||
{
|
||||
"Account": "rGPnRH1EBpHeTF2QG8DCAgM7z5pb75LAis",
|
||||
"TransactionType": "CheckCash",
|
||||
"DeliverMin": "95000000",
|
||||
"CheckID": "2E0AD0740B79BE0AAE5EDD1D5FC79E3C5C221D23C6A7F771D85569B5B91195C2"
|
||||
}
|
||||
```
|
||||
|
||||
*ripple-lib 1.x*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/prepareCashFlex.js' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## {{cash_flex_n.next()}}.CheckCashトランザクションの署名
|
||||
|
||||
{% include '_snippets/tutorial-sign-step.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/sign-cash-flex-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/sign-cash-flex-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
## {{cash_flex_n.next()}}.署名済みCheckCashトランザクションの送信
|
||||
|
||||
{% set step_1_link = "#1checkcashトランザクションの準備" %}
|
||||
{% include '_snippets/tutorial-submit-step.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/submit-cash-flex-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/submit-cash-flex-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## {{cash_flex_n.next()}}.検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
## {{cash_flex_n.next()}}.最終結果の確認
|
||||
|
||||
トランザクションのステータスを確認するには、CheckCashトランザクションの識別用ハッシュを指定した[txメソッド][]を使用します。トランザクションが成功したことを示す`"TransactionResult": "tesSUCCESS"`フィールドをトランザクションメタデータから検索し、またこの結果が最終結果であることを示す`"validated": true`フィールドを結果から検索します。
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/tx-cash-flex-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/tx-cash-flex-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
### エラー処理
|
||||
|
||||
[](transaction-results.html)Checkの換金が`tec`クラスコードで失敗した場合は、[すべてのトランザクション応答のリスト](transaction-results.html)でコードを確認し、適切に対処してください。CheckCashトランザクションでよく返される結果コードの一部を次に示します。
|
||||
|
||||
| 結果コード | 意味 | 対処 |
|
||||
|-------------|---------|----------------|
|
||||
| `tecEXPIRED` | Checkが有効期限切れです。 | Checkを取り消して、以前より長い有効期限を設定して新しいCheckを作成するように送金元に依頼します。 |
|
||||
| `tecNO_ENTRY` | Check IDが存在していません。 | CheckCashトランザクションの`CheckID`が正しいことを確認してください。Checkがまだ取り消されていないこと、または正常に換金されていないことを確認してください。 |
|
||||
| `tecNO_LINE` | 受取人がCheckの通貨のトラストラインを所有していません。 | このイシュアーからのこの通貨を保有するには、指定された通貨とイシュアーのトラストラインを作成し、[TrustSetトランザクション][]を使用してこのトラストラインに適切な限度額を設定してから、Checkの換金を再試行します。 |
|
||||
| `tecNO_PERMISSION` | CheckCashトランザクションの送信者はCheckの`Destination`ではありません。 | Checkの`Destination`を再度確認します。 |
|
||||
| `tecNO_AUTH` | このCheckの通貨のイシュアーは[Authorized Trust Line](authorized-trust-lines.html)を使用していますが、受取人からイシュアーへのトラストラインが承認されていません。 | このトラストラインを承認するようイシュアーに依頼し、承認されたらCheckの換金を再試行します。 |
|
||||
| `tecPATH_PARTIAL` | トラストラインの限度額、または送金元に送金通貨の残高(イシュアーの[送金手数料](transfer-fees.html)がある場合はこの手数料を含む)が十分になかったことが原因で、Checkでは十分な発行済み通貨を送金できませんでした。 | 原因がトラストラインの限度額である場合は、(希望する場合には)限度額を引き上げる[TrustSetトランザクション][]を送信するか、または通貨の一部を消費して残高を減らしてから、Checkの換金を再試行します。原因が送金元の残高である場合は、送金元にCheckの通貨が積み増しされるまで待つか、または以前よりも低い額でCheckの換金を再試行します。 |
|
||||
| `tecUNFUNDED_PAYMENT` | Checkで十分なXRPを送金できませんでした。 | 送金元にXRPが積み増しされるまで待つか、または以前よりも低い額でCheckの換金を再試行します。 |
|
||||
|
||||
## {{cash_flex_n.next()}}.送金された額の確認
|
||||
|
||||
Checkが変動する`DeliverMin`の額で換金された場合は、Checkは少なくとも`DeliverMin`の額で換金されたと想定できます。送金された額を正確に得るには、トランザクションメタデータを調べます。<!--{# TODO: Update if RIPD-1623 adds a delivered_amount field. #}-->メタデータの`AffectedNodes`配列には、通貨のタイプに応じて、Checkの換金による残高の変更を反映した1~2つのオブジェクトが含まれています。
|
||||
|
||||
- XRPの場合、Checkの送金元の`AccountRoot`オブジェクトのXRP `Balance` フィールドから引き落しが行われます。Checkの受取人(CheckCashトランザクションを送信したユーザー)の`AccountRoot`オブジェクトでは、最低でもCheckCashトランザクションの`DeliverMin`から、トランザクションの送信にかかる[トランザクションコスト](transaction-cost.html)を差し引いた額が、XRP `Balance`に入金されます。
|
||||
|
||||
たとえば以下の`ModifiedNode`は、アカウントrGPnRH1EBpHeTF2QG8DCAgM7z5pb75LAis(Checkの受取人でありこのCheckCashトランザクションの送信者)のXRP残高が`9999999970` dropから`10099999960` dropに変更されています。つまり、このトランザクションを処理した結果として、受取人に対し _正味_ 99.99999 XRPが入金されています。
|
||||
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rGPnRH1EBpHeTF2QG8DCAgM7z5pb75LAis",
|
||||
"Balance": "10099999960",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 2,
|
||||
"Sequence": 5
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "7939126A732EBBDEC715FD3CCB056EB31E65228CA17E3B2901E7D30B90FD03D3",
|
||||
"PreviousFields": {
|
||||
"Balance": "9999999970",
|
||||
"Sequence": 4
|
||||
},
|
||||
"PreviousTxnID": "0283465F0D21BE6B1E91ABDE17266C24C1B4915BAAA9A88CC098A98D5ECD3E9E",
|
||||
"PreviousTxnLgrSeq": 8005334
|
||||
}
|
||||
}
|
||||
|
||||
正味金額99.99999 XRPは、このCheckCashトランザクションを送信するにあたり、トランザクションコストを支払うために消却された額を差し引いた後の金額です。以下のトランザクション指示(抜粋)は、トランザクションコスト(`Fee`フィールド)がXRPの10 dropであることを示しています。これを正味残高の変更に追加することで、このCheckの換金のために受取人rGPnRH1EBpHeTF2QG8DCAgM7z5pb75LAisに _総額_ 100 XRPが入金されます。
|
||||
|
||||
"Account" : "rGPnRH1EBpHeTF2QG8DCAgM7z5pb75LAis",
|
||||
"TransactionType" : "CheckCash",
|
||||
"DeliverMin" : "95000000",
|
||||
"Fee" : "10",
|
||||
|
||||
- Checkの送金元または受取人がイシュアーである発行済み通貨の場合、これらのアカウント間のトラストラインを表す`RippleState`オブジェクトでは、`Balance`がCheckの受取人に有利な方法で調整されています。
|
||||
|
||||
<!-- {# TODO: example of single-RippleState balance changes #}-->
|
||||
|
||||
- イシュアーが第三者である発行済み通貨の場合、2つの`RippleState`(送金元からイシュアーへのトラストラインとイシュアーから受取人へのトラストライン)に対する変更があります。Checkの送金元とイシュアーの関係を表す`RippleState`オブジェクトではその`Balance`がイシュアーに有利に変更され、イシュアーと受取人の間の関係を表す`RippleState`オブジェクトではその`Balance`が受取人に有利に変更されます。
|
||||
|
||||
<!--{# TODO: example of double-RippleState balance changes #}-->
|
||||
|
||||
- 発行済み通貨に[送金手数料](transfer-fees.html)がある場合、受取人への入金額を上回る額がCheckの送金元から引き落とされます。(この差額が送金手数料であり、これがイシュアーに戻されることによりイシュアーの正味の債務は減少します。)
|
||||
|
||||
<!--{# common links #}-->
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
@@ -1,159 +0,0 @@
|
||||
---
|
||||
html: cash-a-check-for-an-exact-amount.html
|
||||
parent: use-checks.html
|
||||
blurb: Checkに指定されている額までの正確な額を受領します。
|
||||
labels:
|
||||
- Checks
|
||||
---
|
||||
# Checkの正確な金額での換金
|
||||
|
||||
_[Checks Amendment][]が必要です。_
|
||||
|
||||
Checkがレジャーに含まれており有効期限切れではない場合は、指定の受取人は`Amount`フィールドを指定した[CheckCashトランザクション][]を送信することで、Checkを換金し、Checkに指定されている額までの正確な額を受領できます。請求書の額面通りの金額を回収したい場合など、特定の金額の受領を希望する際には、この方法でCheckを換金できます。
|
||||
|
||||
指定の受取人は、[Checkを変動金額で換金する](cash-a-check-for-a-flexible-amount.html)こともできます。
|
||||
|
||||
{% set cash_exact_n = cycler(* range(1,99)) %}
|
||||
|
||||
## 前提条件
|
||||
|
||||
{% include '_snippets/checkcash-prereqs.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
## {{cash_exact_n.next()}}.CheckCashトランザクションの準備
|
||||
|
||||
[CheckCashトランザクション][]のフィールドの値を決定します。Checkを正確な金額で換金する場合、以下のフィールドが最低限必要です。それ以外のフィールドはオプションまたは署名時に[自動入力](transaction-common-fields.html#自動入力可能なフィールド)可能なフィールドです。
|
||||
|
||||
| フィールド | 値 | 説明 |
|
||||
|:------------------|:--------------------------|:-----------------------------|
|
||||
| `TransactionType` | 文字列 | 値が`CheckCash`の場合、これはCheckCashトランザクションです。 |
|
||||
| `Account` | 文字列(アドレス) | Checkを換金する送信者のアドレス。(あなたのアドレスです。) |
|
||||
| `CheckID` | 文字列 | レジャーで換金するCheckオブジェクトのID。この情報を確認するには、[txメソッド][]を使用してCheckCreateトランザクションのメタデータを調べるか、または[account_objectsメソッド][]を使用してCheckを探します。 |
|
||||
| `Amount` | 文字列またはオブジェクト(額) | Checkから精算する額。XRPの場合、XRPのdrop数を示す文字列でなければなりません。発行済み通貨の場合、これは`currency`、`issuer`、および`value` フィールドを持つオブジェクトです。`currency`フィールドと`issuer`フィールドは、Checkオブジェクトの対応するフィールドに一致しており、`value`はCheckオブジェクトの額以下でなければなりません。(送金手数料のかかる通貨の場合、`SendMax`で送金手数料を支払えるように、`SendMax`よりも低い額を換金する必要があります。)この額を受領できない場合はCheckの換金が失敗し、Checkがレジャーに残るので、後で換金を再試行できます。詳細は、[通貨額の指定][]を参照してください。 |
|
||||
|
||||
|
||||
### 正確な金額で換金するCheckCashトランザクションの準備の例
|
||||
|
||||
Checkを正確な金額で換金するためのトランザクションを準備する手順を以下の例に示します。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*JSON-RPC、WebSocket、またはコマンドライン*
|
||||
|
||||
```json
|
||||
{
|
||||
"Account": "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
|
||||
"TransactionType": "CheckCash",
|
||||
"Amount": "100000000",
|
||||
"CheckID": "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334",
|
||||
"Fee": "12"
|
||||
}
|
||||
```
|
||||
|
||||
*ripple-lib 1.x*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/prepareCashExact.js' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## {{cash_exact_n.next()}}.CheckCashトランザクションの署名
|
||||
|
||||
{% include '_snippets/tutorial-sign-step.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/sign-cash-exact-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/sign-cash-exact-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
## {{cash_exact_n.next()}}.署名済みCheckCashトランザクションの送信
|
||||
|
||||
{% set step_1_link = "#1checkcashトランザクションの準備" %}
|
||||
{% include '_snippets/tutorial-submit-step.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/submit-cash-exact-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/submit-cash-exact-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## {{cash_exact_n.next()}}.検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
## {{cash_exact_n.next()}}.最終結果の確認
|
||||
|
||||
トランザクションのステータスを確認するには、CheckCashトランザクションの識別用ハッシュを指定した[txメソッド][]を使用します。トランザクションが成功したことを示す`"TransactionResult": "tesSUCCESS"`フィールドをトランザクションメタデータから検索し、またこの結果が最終結果であることを示す`"validated": true`フィールドを結果から検索します。
|
||||
|
||||
Checkが正確な`Amount`で換金された場合は、受取人に対し正確な額が入金されたと想定できます(発行済み通貨の金額が極めて大きい場合や小さい場合は、金額が丸められることがあります)。
|
||||
|
||||
Checkを換金できない場合、Checkはレジャーに残るため、後日換金を再試行できます。代わりに[Checkを変動金額で換金する](cash-a-check-for-a-flexible-amount.html)ことができます。
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/tx-cash-exact-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/tx-cash-exact-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
<!--{# common links #}-->
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
html: look-up-checks-by-recipient.html
|
||||
parent: use-checks.html
|
||||
blurb: 特定のアドレスで受信されるすべてのCheckのリストを取得する。
|
||||
labels:
|
||||
- Checks
|
||||
---
|
||||
# 受取人に基づくCheckの検索
|
||||
|
||||
_[Checks Amendment][]が必要です。_
|
||||
|
||||
このチュートリアルでは、[Check](checks.html)をその受取人で検索する方法を説明します。[Checkを送金元で検索する](look-up-checks-by-sender.html)こともできます。
|
||||
|
||||
## 1. 特定のアドレスのすべてのCheckの検索
|
||||
|
||||
特定のアドレスで受信および送信されるすべてのCheckのリストを取得するには、受取人アカウントのアドレスを指定した`account_objects`コマンドを実行し、要求の`type` フィールドを`checks`に設定します。
|
||||
|
||||
**注記:**`account_objects`コマンドのコマンドラインインターフェイスでは`type`フィールドは受け入れられません。代わりに[jsonメソッド][]を使用してコマンドラインからJSON-RPCフォーマットの要求を送信できます。
|
||||
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*RippleAPI*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/getChecks.js' %}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/json-rpc/account_objects-req.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*RippleAPI*
|
||||
|
||||
```
|
||||
{% include '_code-samples/checks/js/get-checks-resp.txt' %}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
200 OK
|
||||
|
||||
{% include '_code-samples/checks/json-rpc/account_objects-resp.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
## 2. 受取人に基づく応答の絞り込み
|
||||
|
||||
応答には、要求のアカウントが送金元であるCheckと、アカウントが受取人であるCheckが含まれていることがあります。応答の`account_objects`配列の各メンバーは1つのCheckを表します。これらの各Checkオブジェクトでは、`Destination`のアドレスはそのCheckの受取人のアドレスです。
|
||||
|
||||
以下の疑似コードに、受取人で応答を絞り込む方法を示します。
|
||||
|
||||
```js
|
||||
recipient_address = "rBXsgNkPcDN2runsvWmwxk3Lh97zdgo9za"
|
||||
account_objects_response = get_account_objects({
|
||||
account: recipient_address,
|
||||
ledger_index: "validated",
|
||||
type: "check"
|
||||
})
|
||||
|
||||
for (i=0; i < account_objects_response.account_objects.length; i++) {
|
||||
check_object = account_objects_response.account_objects[i]
|
||||
if (check_object.Destination == recipient_address) {
|
||||
log("Check to recipient:", check_object)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!--{# common links #}-->
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
html: look-up-checks-by-sender.html
|
||||
parent: use-checks.html
|
||||
blurb: 特定のアドレスで送信されるすべてのCheckのリストを取得する。
|
||||
labels:
|
||||
- Checks
|
||||
---
|
||||
# 送金元に基づくCheckの検索
|
||||
|
||||
_[Checks Amendment][]が必要です。_
|
||||
|
||||
このチュートリアルでは、[Check](checks.html)をその送金元で検索する方法を説明します。[Checkを受取人で検索する](look-up-checks-by-recipient.html)こともできます。
|
||||
|
||||
## 1. 特定のアドレスのすべてのCheckの検索
|
||||
|
||||
<!--{# TODO: Update if https://github.com/XRPLF/rippled/issues/2443 gets done #}-->
|
||||
|
||||
特定のアドレスで受信および送信されるすべてのCheckのリストを取得するには、送金元アカウントのアドレスを指定した`account_objects`コマンドを実行し、要求の`type` フィールドを`checks`に設定します。
|
||||
|
||||
**注記:**`account_objects`コマンドのコマンドラインインターフェイスでは`type`フィールドは受け入れられません。代わりに[jsonメソッド][]を使用してコマンドラインからJSON-RPCフォーマットの要求を送信できます。
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*RippleAPI*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/getChecks.js' %}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/json-rpc/account_objects-req.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*RippleAPI*
|
||||
|
||||
```
|
||||
{% include '_code-samples/checks/js/get-checks-resp.txt' %}
|
||||
```
|
||||
|
||||
*JSON-RPC*
|
||||
|
||||
```json
|
||||
200 OK
|
||||
|
||||
{% include '_code-samples/checks/json-rpc/account_objects-resp.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## 2. 送金元に基づく応答の絞り込み
|
||||
|
||||
応答には、要求のアカウントが送金元であるCheckと、アカウントが受取人であるCheckが含まれていることがあります。応答の`account_objects`配列の各メンバーは1つのCheckを表します。これらの各Checkオブジェクトでは、`Account`のアドレスはそのCheckの送金元のアドレスです。
|
||||
|
||||
以下の疑似コードに、送金元で応答を絞り込む方法を示します。
|
||||
|
||||
```js
|
||||
sender_address = "rBXsgNkPcDN2runsvWmwxk3Lh97zdgo9za"
|
||||
account_objects_response = get_account_objects({
|
||||
account: sender_address,
|
||||
ledger_index: "validated",
|
||||
type: "check"
|
||||
})
|
||||
|
||||
for (i=0; i < account_objects_response.account_objects.length; i++) {
|
||||
check_object = account_objects_response.account_objects[i]
|
||||
if (check_object.Account == sender_address) {
|
||||
log("Check from sender:", check_object)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!--{# common links #}-->
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
@@ -1,241 +0,0 @@
|
||||
---
|
||||
html: send-a-check.html
|
||||
parent: use-checks.html
|
||||
blurb: 受取人が後で現金化できるCheckオブジェクトが作成されます。
|
||||
labels:
|
||||
- Checks
|
||||
---
|
||||
# Checkの送信
|
||||
|
||||
_[Checks Amendment][]が必要です。_
|
||||
|
||||
Checkの送信は、指定受取人にあなたからの支払いを引き出す許可を与えることに似ています。このプロセスの結果、受取人が後で現金化できる[レジャーのCheckオブジェクト](check.html)が作成されます。
|
||||
|
||||
多くの場合、Checkではなく[Payment][]が送信されます。これは、Paymentでは1つのステップで受取人に直接送金できるためです。ただし、指定受取人が[DepositAuth](depositauth.html)を使用している場合はPaymentを直接送信できないため、代替手段としてCheckが適切です。
|
||||
|
||||
このチュートリアルでは、架空の会社BoxSend SG(XRP LedgerアドレスはrBXsgNkPcDN2runsvWmwxk3Lh97zdgo9za)が架空の暗号資産コンサルタント会社Grand Payments(XRP LedgerアドレスはrGPnRH1EBpHeTF2QG8DCAgM7z5pb75LAis)に、コンサルティング料を支払う例を取り上げます。Grand PaymentsはXRPでの支払いを望んでいますが、税務処理と規制対応を簡素化するため、明示的に承認した支払いのみを受け入れます。
|
||||
|
||||
XRP Ledgerの外部でGrand PaymentsはBoxSend SGに請求書(IDは`46060241FABCF692D4D934BA2A6C4427CD4279083E38C77CBE642243E43BE291`)を送り、Grand PaymentsのXRP Ledgerアドレス(rGPnRH1EBpHeTF2QG8DCAgM7z5pb75LAis)宛てに100 XRPのCheckを送信するよう要求します。
|
||||
|
||||
{% set send_n = cycler(* range(1,99)) %}
|
||||
|
||||
## 前提条件
|
||||
|
||||
このチュートリアルでCheckを送信するには、以下が必要です。
|
||||
|
||||
- Checkの送信元である資金供給のあるアカウントの**アドレス**と**シークレットキー**。
|
||||
- [XRP Ledger Test Net Faucet](xrp-test-net-faucet.html)を使用して、10,000 Test Net XRPを保有する資金供給のあるアドレスおよびシークレットを取得できます。
|
||||
- Checkを受領する資金供給のあるアカウントの**アドレス**。
|
||||
- トランザクションに[安全に署名できる手段](secure-signing.html)。
|
||||
- [クライアントライブラリ](client-libraries.html)またはHTTPライブラリ、WebSocketライブラリなど。
|
||||
|
||||
## {{send_n.next()}}.CheckCreateトランザクションの準備
|
||||
|
||||
Checkの額と、Checkを現金化できる当事者を決定します。[CheckCreateトランザクション][]のフィールドの値を決定します。以下のフィールドは必要最小限のフィールドです。その他のフィールドはオプションまたは署名時に[自動入力](transaction-common-fields.html#自動入力可能なフィールド)できるフィールドです。
|
||||
|
||||
| フィールド | 値 | 説明 |
|
||||
|:------------------|:--------------------------|:-----------------------------|
|
||||
| `TransactionType` | 文字列 | このフィールドには文字列`CheckCreate`を使用します。 |
|
||||
| `Account` | 文字列(アドレス) | Checkを作成する送金元のアドレス。(あなたのアドレスです。) |
|
||||
| `Destination` | 文字列(アドレス) | Checkを換金できる指定受取人のアドレス。 |
|
||||
| `SendMax` | 文字列またはオブジェクト(額) | Checkが現金化されるときに送金元から引き出される最大額。XRPの場合、XRPのdrop数を示す文字列を使用します。発行済み通貨の場合、`currency`、`issuer`、および`value` フィールドを含むオブジェクトを使用します。詳細は、[通貨額の指定][]を参照してください。受取人がXRP以外の通貨で正確な額のCheckを換金できるようにし、かつ[送金手数料](transfer-fees.html)を含めるには、送金手数料分の追加パーセンテージを必ず指定してください。(たとえば受取人が送金手数料2%でCheckをイシュアーからの100 CADに現金化できるようにするには、`SendMax`をイシュアーからの102 CADに設定する必要があります。) |
|
||||
|
||||
### CheckCreateトランザクションの準備の例
|
||||
|
||||
以下の例は、BoxSend SG(rBXsgNkPcDN2runsvWmwxk3Lh97zdgo9za)がGrand Payments(rGPnRH1EBpHeTF2QG8DCAgM7z5pb75LAis)宛てに作成した100 XRPのCheckです。追加(オプション)のメタデータとして、BoxSend SGはGrand Paymentsの請求書のIDを追加しています。これによりGrand PaymentsはこのCheckがどの請求書に対する支払いかを確認できます。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*JSON-RPC、WebSocket、またはコマンドライン*
|
||||
|
||||
```
|
||||
{
|
||||
"TransactionType":"CheckCreate",
|
||||
"Account":"rBXsgNkPcDN2runsvWmwxk3Lh97zdgo9za",
|
||||
"Destination":"rGPnRH1EBpHeTF2QG8DCAgM7z5pb75LAis",
|
||||
"SendMax":"100000000",
|
||||
"InvoiceID":"46060241FABCF692D4D934BA2A6C4427CD4279083E38C77CBE642243E43BE291"
|
||||
}
|
||||
```
|
||||
|
||||
*ripple-lib 1.x*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/prepareCreate.js' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## {{send_n.next()}}.CheckCreateトランザクションへの署名
|
||||
|
||||
{% include '_snippets/tutorial-sign-step.ja.md' %}
|
||||
<!--{#_ #}-->
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*RippleAPI*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/signCreate.js' %}
|
||||
```
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/websocket/sign-create-req.json' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/sign-create-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
#### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*RippleAPI*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/sign-create-resp.txt' %}
|
||||
```
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/websocket/sign-create-resp.json' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/sign-create-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## {{send_n.next()}}.署名済みトランザクションの送信
|
||||
|
||||
{% set step_1_link = "#1checkcreateトランザクションの準備" %}
|
||||
{% include '_snippets/tutorial-submit-step.md' %}
|
||||
<!--{#_ #}-->
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*RippleAPI*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/submitCreate.js' %}
|
||||
```
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/websocket/submit-create-req.json' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/submit-create-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*RippleAPI*
|
||||
|
||||
```js
|
||||
{% include '_code-samples/checks/js/submit-create-resp.txt' %}
|
||||
```
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/websocket/submit-create-resp.json' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/submit-create-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
## {{send_n.next()}}.検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.ja.md' %}
|
||||
<!--{#_ #}-->
|
||||
|
||||
## {{send_n.next()}}.最終結果の確認
|
||||
|
||||
トランザクションのステータスを確認するには、CheckCreateトランザクションの識別用ハッシュを指定した[txメソッド][]を使用します。トランザクションメタデータで、トランザクションが成功したことを示す`"TransactionResult": "tesSUCCESS"`フィールドを探し、またこの結果が最終結果であることを示す`"validated": true`フィールドを結果で探します。
|
||||
|
||||
トランザクションのメタデータで、`LedgerEntryType`が `"Check"`の`CreatedNode`オブジェクトを探します。これは、トランザクションにより[Checkレジャーオブジェクト](check.html)が作成されたことを示します。このオブジェクトの`LedgerIndex` がCheckのIDです。以下の例ではCheckのIDは`84C61BE9B39B2C4A2267F67504404F1EC76678806C1B901EA781D1E3B4CE0CD9`です。
|
||||
|
||||
**注記:** RippleAPIでは、CheckCreateトランザクションの検索時にCheckのIDが報告されません。この回避策として、以下のRippleAPIコードの例に示すように[Check IDフォーマット](check.html#check-idのフォーマット)からCheckのIDを計算することができます。 <!--{# TODO: Remove this and update the code samples if ripple-lib #876 gets fixed. #}-->
|
||||
|
||||
### 要求の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*RippleAPI*
|
||||
|
||||
```
|
||||
{% include '_code-samples/checks/js/getCreateTx.js' %}
|
||||
```
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/websocket/tx-create-req.json' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```bash
|
||||
{% include '_code-samples/checks/cli/tx-create-req.sh' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
### 応答の例
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*RippleAPI*
|
||||
|
||||
```
|
||||
{% include '_code-samples/checks/js/get-create-tx-resp.txt' %}
|
||||
```
|
||||
|
||||
*WebSocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/websocket/tx-create-resp.json' %}
|
||||
```
|
||||
|
||||
*コマンドライン*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/checks/cli/tx-create-resp.txt' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
html: use-checks.html
|
||||
parent: use-specialized-payment-types.html
|
||||
blurb: XRP LedgerのCheckは、紙の小切手と同じように、別のアカウントに資金を振り込ませることができます。
|
||||
template: pagetype-category.html.jinja
|
||||
labels:
|
||||
- Checks
|
||||
---
|
||||
# Checkの使用
|
||||
|
||||
XRP LedgerのChecksでは、別のアカウントが後で支払いを請求することが認められていており、個人用の紙の小切手の仕組みと似ています。
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,138 +0,0 @@
|
||||
---
|
||||
html: cancel-an-expired-escrow.html
|
||||
parent: use-escrows.html
|
||||
blurb: 有効期限切れのEscrowを取り消します。
|
||||
labels:
|
||||
- Escrow
|
||||
- スマートコントラクト
|
||||
---
|
||||
# 有効期限切れEscrowの取消し
|
||||
|
||||
## 1.有効期限切れEscrowの確認
|
||||
|
||||
XRP LedgerのEscrowが有効期限切れとなるのは、その`CancelAfter`の時刻が検証済みレジャーの`close_time`よりも前である場合です。(Escrowに`CancelAfter`時刻が指定されていない場合は、Escrowが有効期限切れになることはありません。)最新の検証済みレジャーの閉鎖時刻は、[ledgerメソッド][]を使用して検索できます。
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/ledger-request-expiration.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/ledger-response-expiration.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
[account_objectsメソッド][]を使用してEscrowを検索し、`CancelAfter`の時刻と比較できます。
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/account_objects-request-expiration.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/account_objects-response-expiration.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## 2.EscrowCancelトランザクションの送信
|
||||
|
||||
XRP Ledgerでは、[EscrowCancelトランザクション][]に[署名して送信する](transactions.html#トランザクションへの署名とトランザクションの送信)ことで、***誰でも***有効期限切れのEscrowを取り消すことができます。トランザクションの`Owner`フィールドを、そのEscrowを作成した`EscrowCreate`トランザクションの`Account`に設定します。`OfferSequence`フィールドを、`EscrowCreate`トランザクションの`Sequence`に設定します。
|
||||
|
||||
{% include '_snippets/secret-key-warning.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/submit-request-escrowcancel.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/submit-response-escrowcancel.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
トランザクションの識別用`hash`値をメモしておきます。これにより、検証済みレジャーバージョンに記録されるときにその最終ステータスを確認できます。
|
||||
|
||||
## 3.検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
## 4.最終結果の確認
|
||||
|
||||
EscrowCancelトランザクションの識別用ハッシュを指定した[txメソッド][]を使用してトランザクションの最終ステータスを確認します。トランザクションのメタデータで`LedgerEntryType`が`Escrow`である`DeletedNode`を探します。また、エスクローに預託された支払いの送金元の`ModifiedNode`(タイプが`AccountRoot`)も探します。オブジェクトの`FinalFields`に、`Balance`フィールドのXRP返金額の増分が表示されている必要があります。
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/tx-request-escrowcancel.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/tx-response-escrowcancel.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
上記の例では、`r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT`がEscrowの送金元であり、`Balance`が99999**8**9990 dropから99999**9**9990 dropに増加していることから、エスクローに預託されていた10,000 XRP dropが返金されたことがわかります(drop = 0.01XRP) 。
|
||||
|
||||
**ヒント:** Escrowを実行する[EscrowFinishトランザクション][]で使用する`OfferSequence`が不明な場合は、Escrowの`PreviousTxnID`フィールドのトランザクションの識別用ハッシュを指定した[txメソッド][]を使用して、そのEscrowを作成したトランザクションを検索します。Escrowを終了するときには、そのトランザクションの`Sequence`の値を`OfferSequence`の値として使用します。
|
||||
|
||||
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
@@ -1,90 +0,0 @@
|
||||
---
|
||||
html: look-up-escrows.html
|
||||
parent: use-escrows.html
|
||||
blurb: 送金元または送金先のアドレスを使って保留中のEscrowを検索します。
|
||||
labels:
|
||||
- Escrow
|
||||
- スマートコントラクト
|
||||
---
|
||||
# Escrowの検索
|
||||
|
||||
保留中のEscrowはすべて[Escrowオブジェクト](escrow.html)としてレジャーに保管されます。
|
||||
|
||||
Escrowオブジェクトを検索するには、[account_objectsメソッド][]で[送金元のアドレス](#送金元のアドレスによるescrowの検索)または[送金先のアドレス](#送金先のアドレスによるescrowの検索)を使用して検索します。
|
||||
|
||||
## 送金元のアドレスによるEscrowの検索
|
||||
|
||||
[account_objectsメソッド][]を使用して、送金元アドレスからEscrowオブジェクトを検索できます。
|
||||
|
||||
たとえば、送金元アドレスが`rfztBskAVszuS3s5Kq7zDS74QtHrw893fm`である保留中のEscrowオブジェクトをすべて検索するとします。以下の要求の例に従ってこの検索を実行できます。この例では送金元アドレスは`account`の値です。
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/account_objects-request.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
応答は以下の例のようになります。この応答には、送金元アドレスまたは送金先アドレスが`rfztBskAVszuS3s5Kq7zDS74QtHrw893fm`である保留中のEscrowオブジェクトがすべて含まれています。送金元アドレスは`Account`の値であり、送金先アドレスは`Destination`の値です。
|
||||
|
||||
この例では、2番目と4番目のEscrowオブジェクトが検索条件に一致しています。これは、これらのオブジェクトの`Account`(送金元のアドレス)の値が`rfztBskAVszuS3s5Kq7zDS74QtHrw893fm`に設定されているためです。
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/account_objects-response.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## 送金先のアドレスによるEscrowの検索
|
||||
|
||||
[account_objectsメソッド][]を使用して、送金先アドレスからEscrowオブジェクトを検索できます。
|
||||
|
||||
**注記:** 送金先のアドレスによる保留中のEscrowオブジェクトの検索は、[fix1523 Amendment][]が2017/11/14に有効化された後に作成されたEscrowについてのみ行うことができます。
|
||||
|
||||
たとえば、送金先アドレスが`rfztBskAVszuS3s5Kq7zDS74QtHrw893fm`である保留中のEscrowオブジェクトをすべて検索するとします。以下の要求の例に従ってこの検索を実行できます。この例では送金先アドレスは`account`の値です。
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/account_objects-request.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
応答は以下の例のようになります。応答には送金先アドレスまたは送金元アドレスが`rfztBskAVszuS3s5Kq7zDS74QtHrw893fm`である保留中のEscrowオブジェクトがすべて含まれています。送金先アドレスは`Destination`の値であり、送金元アドレスは`Account`の値です。
|
||||
|
||||
この例では、1番目と3番目のEscrowオブジェクトが検索条件に一致しています。これは、これらのオブジェクトの`Destination`(送金先のアドレス)の値が`rfztBskAVszuS3s5Kq7zDS74QtHrw893fm`に設定されているためです。
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/account_objects-response.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
@@ -1,195 +0,0 @@
|
||||
---
|
||||
html: send-a-conditionally-held-escrow.html
|
||||
parent: use-escrows.html
|
||||
blurb: 満たされた条件に基づいてリリースとなるEscrowを作成します。
|
||||
labels:
|
||||
- Escrow
|
||||
- スマートコントラクト
|
||||
---
|
||||
# 条件に基づくEscrowの送信
|
||||
|
||||
## 1.条件とフルフィルメントの生成
|
||||
|
||||
XRP Ledger EscrowにはPREIMAGE-SHA-256 [Crypto-Conditions](https://tools.ietf.org/html/draft-thomas-crypto-conditions-03)が必要です。条件とフルフィルメントを適切なフォーマットで計算するには、[five-bells-condition](https://github.com/interledgerjs/five-bells-condition)などのCrypto-conditionsライブラリを使用する必要があります。フルフィルメントについては、以下のフルフィルメントを生成するためのメソッドのいずれかを使用することが推奨されます。
|
||||
|
||||
- 暗号論的に安全な乱数ソースを使用して、32バイト以上のランダムバイトを生成します。
|
||||
- Interledger Protocolの[PSK仕様](https://github.com/interledger/rfcs/blob/master/deprecated/0016-pre-shared-key/0016-pre-shared-key.md)に従い、ILPパケットのHMAC-SHA-256をフルフィルメントとして使用します。
|
||||
|
||||
ランダムなフルフィルメントと条件のJavaScriptコードの例:
|
||||
|
||||
```js
|
||||
const cc = require('five-bells-condition')
|
||||
const crypto = require('crypto')
|
||||
|
||||
const preimageData = crypto.randomBytes(32)
|
||||
const myFulfillment = new cc.PreimageSha256()
|
||||
myFulfillment.setPreimage(preimageData)
|
||||
|
||||
const condition = myFulfillment.getConditionBinary().toString('hex').toUpperCase()
|
||||
console.log('Condition:', condition)
|
||||
// (Random hexadecimal, 72 chars in length)
|
||||
|
||||
// keep secret until you want to finish executing the held payment:
|
||||
const fulfillment = myFulfillment.serializeBinary().toString('hex').toUpperCase()
|
||||
console.log('Fulfillment:', fulfillment)
|
||||
// (Random hexadecimal, 78 chars in length)
|
||||
```
|
||||
|
||||
後で使用できるように条件とフルフィルメントを保存します。保留中の支払いの実行が完了するまでは、フルフィルメントを公開しないでください。フルフィルメントを知っていれば誰でもEscrowを終了でき、保留中の資金を指定された送金先にリリースできます。
|
||||
|
||||
|
||||
## 2.リリース時刻または取消し時刻の計算
|
||||
|
||||
条件付き`Escrow`トランザクションには、`CancelAfter`フィールドと`FinishAfter`フィールドのいずれか、または両方が含まれている必要があります。`CancelAfter`フィールドを使用すると、指定の時刻までに条件を満たすことができなかった場合に送金元へXRPを返金できます。`FinishAfter`フィールドに指定される時刻より前の時間は、正しいフルフィルメントが送信されてもEscrowを実行できません。いずれのフィールドでも、将来の時刻を指定する必要があります。
|
||||
|
||||
`CancelAfter`の時刻を24時間先に設定する例:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_JavaScript_
|
||||
|
||||
```js
|
||||
const rippleOffset = 946684800
|
||||
const CancelAfter = Math.floor(Date.now() / 1000) + (24*60*60) - rippleOffset
|
||||
console.log(CancelAfter)
|
||||
// Example:556927412
|
||||
```
|
||||
|
||||
<!--{# Striking Python example for now since we don't have full examples
|
||||
_Python 2/3_
|
||||
|
||||
```python
|
||||
from time import time
|
||||
ripple_offset = 946684800
|
||||
cancel_after = int(time()) + (24*60*60) - 946684800
|
||||
print(cancel_after)
|
||||
# Example: 556927412
|
||||
```
|
||||
|
||||
#}-->
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
**警告:** XRP Ledgerでは、時刻を**Rippleエポック(2000-01-01T00:00:00Z)以降の経過秒数**として指定する必要があります。`CancelAfter`または`FinishAfter`フィールドで、UNIX時刻を同等のRipple時刻に変換せずに使用すると、ロック解除時刻が**30年**先に設定されることになります。
|
||||
|
||||
## 3.EscrowCreateトランザクションの送信
|
||||
|
||||
[EscrowCreateトランザクション][]に[署名して送信](transactions.html#トランザクションへの署名とトランザクションの送信)します。トランザクションの`Condition`フィールドを、保留中の支払いがリリースされる時刻に設定します。`Destination`を受取人に設定します。受取人と送金元のアドレスは同じでもかまいません。前の手順で算出した`CancelAfter`または`FinishAfter`の時刻も指定します。`Amount`を、Escrowする[XRP、drop単位][]の合計額に設定します。
|
||||
|
||||
{% include '_snippets/secret-key-warning.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/submit-request-escrowcreate-condition.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/submit-response-escrowcreate-condition.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## 4.検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
## 5.Escrowが作成されたことの確認
|
||||
|
||||
トランザクションの識別用ハッシュを指定した[txメソッド][]を使用して、トランザクションの最終ステータスを確認します。特に、[Escrowレジャーオブジェクト](escrow.html)が作成されたことを示す`CreatedNode`をトランザクションメタデータで探します。
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/tx-request-escrowcreate-condition.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/tx-response-escrowcreate-condition.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## 6.EscrowFinishトランザクションの送信
|
||||
|
||||
`FinishAfter`の時刻が経過した後で資金のリリースを実行する[EscrowFinishトランザクション][]に[署名して送信](transactions.html#トランザクションへの署名とトランザクションの送信)します。トランザクションの`Owner`フィールドにEscrowCreateトランザクションの`Account`アドレスを設定し、`OfferSequence` にEscrowCreateトランザクションの`Sequence`番号を設定します。`Condition`フィールドと`Fulfillment`フィールドに、ステップ1で生成した条件値とフルフィルメント値をそれぞれ16進数で設定します。フルフィルメントのサイズ(バイト数)に基づいて`Fee`([トランザクションコスト](transaction-cost.html))の値を設定します。条件付きEscrowFinishでは、少なくとも330 drop(XRP)と、フルフィルメントのサイズで16バイトごとに10 dropが必要です。
|
||||
|
||||
**注記:** EscrowCreateトランザクションに`FinishAfter`フィールドが含まれている場合、Escrowの条件として正しいフルフィルメントを指定しても、この時刻よりも前の時点ではこのトランザクションを実行できません。前に閉鎖されたレジャーの閉鎖時刻が`FinishAfter`の時刻よりも前である場合、EscrowFinishトランザクションは[結果コード](transaction-results.html)`tecNO_PERMISSION`で失敗します。
|
||||
|
||||
Escrowが有効期限切れの場合は、[Escrowの取消し](cancel-an-expired-escrow.html)だけが可能です。
|
||||
|
||||
{% include '_snippets/secret-key-warning.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/submit-request-escrowfinish-condition.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
_Websocket_
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/submit-response-escrowfinish-condition.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
トランザクションの識別用`hash`値をメモしておきます。これにより、検証済みレジャーバージョンに記録されるときにその最終ステータスを確認できます。
|
||||
|
||||
## 7.検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
## 8.最終結果の確認
|
||||
|
||||
EscrowFinishトランザクションの識別用ハッシュを指定した[txメソッド][]を使用して、トランザクションの最終ステータスを確認します。特にトランザクションメタデータ内で、エスクローに預託された支払いの送金先の`ModifiedNode`(タイプが`AccountRoot`)を確認します。オブジェクトの`FinalFields`に、`Balance`フィールドのXRP返金額の増分が表示されている必要があります。
|
||||
|
||||
要求:
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/tx-request-escrowfinish-condition.json' %}
|
||||
```
|
||||
|
||||
応答:
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/tx-response-escrowfinish-condition.json' %}
|
||||
```
|
||||
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -1,215 +0,0 @@
|
||||
---
|
||||
html: send-a-time-held-escrow.html
|
||||
parent: use-escrows.html
|
||||
blurb: 指定した時間が経過することがリリースの唯一の条件であるEscrowを作成します。
|
||||
labels:
|
||||
- Escrow
|
||||
- スマートコントラクト
|
||||
---
|
||||
# 時間に基づくEscrowの送信
|
||||
|
||||
[EscrowCreateトランザクション][]タイプでは、リリースの唯一の条件が特定時刻を経過することであるEscrowを作成できます。このためには、`FinishAfter`フィールドを使用し、`Condition`フィールドを省略します。
|
||||
|
||||
## 1.リリース時刻の計算
|
||||
|
||||
時刻を **[Rippleエポック以降の経過秒数][]** として指定する必要があります。Rippleエポックは、UNIXエポックの946684800秒後です。たとえば、2017年11月13日の午前0時(UTC)に資金をリリースする場合、以下のようになります。
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*JavaScript*
|
||||
|
||||
```js
|
||||
// JavaScript Date() is natively expressed in milliseconds; convert to seconds
|
||||
const release_date_unix = Math.floor( new Date("2017-11-13T00:00:00Z") / 1000 );
|
||||
const release_date_ripple = release_date_unix - 946684800;
|
||||
console.log(release_date_ripple);
|
||||
// 563846400
|
||||
```
|
||||
|
||||
<!--{# //Python code works OK but we don't have full examples, so hiding it
|
||||
*Python 3*
|
||||
|
||||
```python
|
||||
import datetime
|
||||
release_date_utc = datetime.datetime(2017,11,13,0,0,0,tzinfo=datetime.timezone.utc)
|
||||
release_date_ripple = int(release_date_utc.timestamp()) - 946684800
|
||||
print(release_date_ripple)
|
||||
# 563846400
|
||||
```
|
||||
|
||||
#}-->
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
**警告:** `FinishAfter`フィールドで、UNIX時刻を同等のRipple時刻に変換せずに使用すると、ロック解除時刻が30年先に設定されることになります。
|
||||
|
||||
## 2.EscrowCreateトランザクションの送信
|
||||
|
||||
[EscrowCreateトランザクション][]に[署名して送信](transactions.html#トランザクションへの署名とトランザクションの送信)します。トランザクションの`FinishAfter`フィールドを、保留中の支払いがリリースされる時刻に設定します。`Condition`フィールドを省略して、時刻を保留中の支払いをリリースする唯一の条件とします。`Destination`を受取人に設定します。受取人と送金元のアドレスは同じでもかまいません。`Amount`を、Escrowする[XRP、drop単位][]の合計額に設定します。
|
||||
|
||||
{% include '_snippets/secret-key-warning.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/submit-request-escrowcreate-time.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/submit-response-escrowcreate-time.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
トランザクションの識別用`hash`値をメモしておきます。これにより、検証済みレジャーバージョンに記録されるときにその最終ステータスを確認できます。
|
||||
|
||||
## 3.検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
## 4.Escrowが作成されたことの確認
|
||||
|
||||
トランザクションの識別用ハッシュを指定した[txメソッド][]を使用して、トランザクションの最終ステータスを確認します。[Escrowレジャーオブジェクト](escrow.html)が作成されたことを示す`CreatedNode`をトランザクションメタデータで探します。
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/tx-request-escrowcreate-time.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/tx-response-escrowcreate-time.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
## 5.リリース時刻までの待機
|
||||
|
||||
`FinishAfter`時刻が指定されている保留中の支払いは、Escrowノードの`FinishAfter`時刻よりも後の[`close_time`ヘッダーフィールド](ledger-header.html)の時刻でレジャーが閉鎖するまでは完了できません。
|
||||
|
||||
最新の検証済みレジャーの閉鎖時刻は、[ledgerメソッド][]を使用して検索できます。
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/ledger-request.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/ledger-response.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
## 6.EscrowFinishトランザクションの送信
|
||||
|
||||
`FinishAfter`の時刻が経過した後で資金のリリースを実行する[EscrowFinishトランザクション][]に[署名して送信](transactions.html#トランザクションへの署名とトランザクションの送信)します。トランザクションの`Owner`フィールドにEscrowCreateトランザクションの`Account`アドレスを設定し、`OfferSequence` にEscrowCreateトランザクションの`Sequence`番号を設定します。時刻のみに基づいて保留されているEscrowの場合は、`Condition`フィールドと`Fulfillment`フィールドを省略します。
|
||||
|
||||
**ヒント:** XRP Ledgerの状態はトランザクションでしか変更できないため、EscrowFinishトランザクションが必要です。このトランザクションの送信者は、Escrowの受取人、Escrowの元としての送金人、またはその他のXRP Ledgerアドレスのいずれかです。
|
||||
|
||||
Escrowが有効期限切れの場合は、[Escrowの取消し](cancel-an-expired-escrow.html)だけが可能です。
|
||||
|
||||
{% include '_snippets/secret-key-warning.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/submit-request-escrowfinish-time.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/submit-response-escrowfinish-time.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
トランザクションの識別用`hash`値をメモしておきます。これにより、検証済みレジャーバージョンに記録されるときにその最終ステータスを確認できます。
|
||||
|
||||
## 7.検証の待機
|
||||
|
||||
{% include '_snippets/wait-for-validation.ja.md' %} <!--#{ fix md highlighting_ #}-->
|
||||
|
||||
## 8.最終結果の確認
|
||||
|
||||
EscrowFinishトランザクションの識別用ハッシュを指定した[txメソッド][]を使用して、トランザクションの最終ステータスを確認します。特にトランザクションメタデータ内で、エスクローに預託された支払いの送金先の`ModifiedNode`(タイプが`AccountRoot`)を確認します。オブジェクトの`FinalFields`に、`Balance`フィールドのXRP返金額の増分が表示されている必要があります。
|
||||
|
||||
要求:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/tx-request-escrowfinish-time.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
応答:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*Websocket*
|
||||
|
||||
```json
|
||||
{% include '_code-samples/escrow/websocket/tx-response-escrowfinish-time.json' %}
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -228,6 +228,6 @@ Response:
|
||||
- [Escrow ledger object](escrow-object.html)
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
|
||||
@@ -1,615 +0,0 @@
|
||||
---
|
||||
html: use-payment-channels.html
|
||||
parent: use-specialized-payment-types.html
|
||||
blurb: Payment Channelは、少額の単位に分割可能な「非同期」のXRPペイメントを送信し、後日決済する高度な機能です。このチュートリアルでは、全体的なPayment Channelの使用方法を、ローカルのrippledサーバーのJSON-RPC APIを使用する例を使って説明します。
|
||||
labels:
|
||||
- Payment Channel
|
||||
- スマートコントラクト
|
||||
---
|
||||
# Payment Channelの使用
|
||||
|
||||
Payment Channelは、少額の単位に分割可能な「非同期」のXRPペイメントを送信し、後日決済する高度な機能です。このチュートリアルでは、全体的な[Payment Channel](payment-channels.html)の使用方法を、ローカル`rippled`サーバーの[JSON-RPC API](http-websocket-apis.html)を使用する例を使って説明します。
|
||||
|
||||
このチュートリアルを進めるにあたって[資金供給されているXRP Ledgerアカウント](accounts.html)を所有するユーザーが2名いれば理想的です。ただし、2つのXRP Ledgerアドレスを管理する1名のユーザーとしてこのチュートリアルを進めることもできます。
|
||||
|
||||
## サンプルの値
|
||||
|
||||
このチュートリアルでは、例として以下のアドレスを使用します。
|
||||
|
||||
| | |
|
||||
|--|--|
|
||||
| **支払人のアドレス** | rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH |
|
||||
| **Channelに使用する公開鍵(XRP Ledgerの[base58][]エンコード文字列フォーマット)** | aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3
|
||||
| **Channelに使用する公開鍵(16進数)** | 023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6 |
|
||||
| **受取人のアドレス** | rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn |
|
||||
|
||||
**ヒント:** この例では、Channelの公開鍵は支払人のマスターキーペアの公開鍵です。これは完全に安全であり有効です。また、支払人のみが異なるキーペアの公開鍵と秘密鍵を把握している場合に限り、そのキーペアを使用することも完全に安全であり有効です。 <!-- Editor's note: We don't have a good page to link to explain key pairs as of time of this writing. -->
|
||||
|
||||
また、トランザクションの送信先`rippled`サーバーも必要です。このチュートリアルの例では、`rippled`サーバーがテストマシン(`localhost`)で稼働しており、このテストマシンはポート**5005**で非暗号化JSON-RPC APIエンドポイントに接続しています。
|
||||
|
||||
実際のXRPを送金せずにテストを実施するには、Test Net XRPを保有する[XRP Ledger Testnet](xrp-testnet-faucet.html)のアドレスを使用できます。XRP Ledger Test Netを使用する場合、`http://localhost:5005/`ではなく`https://api.altnet.rippletest.net:51234`に接続することで、Test NetサーバーのJSON-RPC APIを使用できます。
|
||||
|
||||
Payment Channelに使用できるXRPの額に制限はありません。このチュートリアルで使用されているサンプルの値では、Payment Channelで100 XRP(`100000000` drop)が少なくとも1日間は確保されます。
|
||||
|
||||
## フローチャート
|
||||
[フローチャート]: #フローチャート
|
||||
|
||||
次の図は、Payment Channelのライフサイクルの概要を示します。
|
||||
|
||||
[](img/paychan-flow.ja.png)
|
||||
|
||||
この図のステップの番号は、このチュートリアルのステップの番号に対応しています。
|
||||
|
||||
1. [支払人: Channelの作成](#1-支払人が特定の受取人へのpayment-channelを作成します)
|
||||
2. [受取人: Channelの確認](#2-受取人がpayment-channelの特性を確認します)
|
||||
3. [支払人: クレームへの署名](#3-支払人がchannelのxrpに対して1つ以上の署名付き-クレーム-を作成します)
|
||||
4. [支払人: 受取人へのクレームの送信](#4-支払人が商品またはサービスに対する支払いとしてクレームを受取人に送信します)
|
||||
5. [受取人: クレームの検証](#5-受取人がクレームを検証します)
|
||||
6. [受取人: 商品またはサービスの提供](#6-受取人が商品またはサービスを提供します)
|
||||
7. [必要に応じてステップ3~6を繰り返す](#7-必要に応じてステップ36を繰り返します)
|
||||
8. [受取人: クレームの清算](#8-準備が完了すれば受取人は承認された額のクレームを清算します)
|
||||
9. [支払人: Channel閉鎖の要求](#9-支払人と受取人の取引完了後支払人はchannelの閉鎖を要求します)
|
||||
10. [支払人(またはその他の担当者): 有効期限切れChannelの閉鎖](#10-有効期限切れのchannelは誰でも閉鎖できます)
|
||||
|
||||
## 1. 支払人が特定の受取人へのPayment Channelを作成します。
|
||||
|
||||
これは[PaymentChannelCreateトランザクション][]です。このプロセスでは、支払人がChannelの特定の特性(有効期限、決済遅延など、Channelのクレームに関する保証に影響する特性)を設定します。支払人は、Channelに対するクレームの検証に使用する公開鍵も設定します。 <!-- STYLE_OVERRIDE: will -->
|
||||
|
||||
**ヒント:** 「決済遅延」の設定だけが決済を遅延するわけでわありません。レジャーバージョンが閉鎖すると即時に決済が遅延されます(3~5秒)。「決済遅延」とは、Channel閉鎖の強制的な遅延です。これにより、受取人が決済を完了できるようになります。
|
||||
|
||||
以下の例は、JSON-RPC APIを使用してローカル`rippled`サーバーへ[送信](submit.html#署名と送信モード)することでPayment Channelを作成する方法を示しています。Payment Channelは、決済を1日遅らせて[サンプルの支払人](#サンプルの値)(rN7n7...)から[サンプルの受取人](#サンプルの値)(rf1Bi...)に100 XRPを割り当てます。公開鍵はサンプルの支払人のマスター公開鍵(16進数)です。
|
||||
|
||||
**注記:** Payment Channelは1つのオブジェクトとして支払人の[所有者準備金](reserves.html#所有者準備金)に反映されます。所有者は少なくとも、Payment Channelに割り当てられたXRPを差引き後に、準備金を維持するのに十分なXRPを保有している必要があります。
|
||||
|
||||
要求:
|
||||
|
||||
POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [{
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"TransactionType": "PaymentChannelCreate",
|
||||
"Amount": "100000000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"SettleDelay": 86400,
|
||||
"PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"DestinationTag": 20170428
|
||||
},
|
||||
"fee_mult_max": 1000
|
||||
}]
|
||||
}
|
||||
|
||||
応答:
|
||||
|
||||
200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied.Only final in a validated ledger.",
|
||||
...
|
||||
"tx_json": {
|
||||
...
|
||||
"TransactionType": "PaymentChannelCreate",
|
||||
"hash": "3F93C482C0BC2A1387D9E67DF60BECBB76CC2160AE98522C77AF0074D548F67D"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
`submit`要求に対する直接の応答には、トランザクションを識別する`hash`値を含む _暫定的な_ 結果が含まれています。支払人は、検証済みレジャーでトランザクションの _最終_ 結果を確認し、メタデータからChannel IDを取得する必要があります。この処理は`tx`コマンドを使用して実行できます。
|
||||
|
||||
要求:
|
||||
|
||||
POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "tx",
|
||||
"params": [{
|
||||
"transaction": "3F93C482C0BC2A1387D9E67DF60BECBB76CC2160AE98522C77AF0074D548F67D"
|
||||
}]
|
||||
}
|
||||
|
||||
応答:
|
||||
|
||||
200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"Amount": "100000000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
...
|
||||
"TransactionType": "PaymentChannelCreate",
|
||||
...
|
||||
"hash": "3F93C482C0BC2A1387D9E67DF60BECBB76CC2160AE98522C77AF0074D548F67D",
|
||||
"inLedger": 29380080,
|
||||
"ledger_index": 29380080,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
...
|
||||
{
|
||||
"CreatedNode": {
|
||||
"LedgerEntryType": "PayChannel",
|
||||
"LedgerIndex": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"NewFields": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"Amount": "100000000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"DestinationTag": 20170428,
|
||||
"PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"SettleDelay": 86400
|
||||
}
|
||||
}
|
||||
},
|
||||
...
|
||||
],
|
||||
"TransactionIndex": 16,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"status": "success",
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
|
||||
支払人はJSON-RPCからの応答で以下を確認する必要があります。
|
||||
|
||||
- トランザクションの`meta`フィールドで、`TransactionResult`が`tesSUCCESS`であることを確認します。
|
||||
- データが検証済みレジャーのデータであることを示す`"validated":true`が応答に含まれていることを確認します。(結果`tesSUCCESS`は、検証済みレジャーバージョンに記録されている場合にのみ[最終的な](finality-of-results.html)結果です。)
|
||||
- トランザクションの`meta`フィールドの`AffectedNodes`配列で、`LedgerEntryType`が`PayChannel`である`CreatedNode`オブジェクトを検索します。`CreatedNode`オブジェクトの`LedgerIndex`フィールドはChannel IDを示します。(上記の例では、これは「5DB0...」で始まる16進文字列です。)Channel IDは、後でクレームに署名する際に必要です。
|
||||
PayChannelレジャーオブジェクトタイプの詳細については、[PayChannelレジャーオブジェクト](paychannel.html)を参照してください。
|
||||
|
||||
|
||||
## 2. 受取人がPayment Channelの特性を確認します。
|
||||
|
||||
Payment Channelを見つけるには、以下の例(JSON-RPC APIを使用)に示すようにChannelの支払人を指定した[account_channelsメソッド][]を使用します。
|
||||
|
||||
要求:
|
||||
|
||||
POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "account_channels",
|
||||
"params": [{
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}]
|
||||
}
|
||||
|
||||
応答:
|
||||
|
||||
200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"channels": [{
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"amount": "100000000",
|
||||
"balance": "0",
|
||||
"channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"destination_tag": 20170428,
|
||||
"public_key": "aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3",
|
||||
"public_key_hex": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"settle_delay": 86400
|
||||
}],
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
|
||||
受取人は、以下のすべての点を含め、Payment Channelのパラメーターが特定のユースケースに適していることを確認します。
|
||||
|
||||
- `destination_account`フィールドに受取人の正しいアドレスが指定されていることを確認します。
|
||||
- `settle_delay`フィールドに、受取人が未処理のクレームを清算するのに十分な決済遅延期間が秒単位で指定されていることを確認します。
|
||||
- `cancel_after`(変更できない有効期限)フィールドと`expiration`(変更できる有効期限)フィールドが含まれている場合は、これらのフィールドの値が早過ぎないことを確認します。受取人はこれらの時刻をメモして、それらの時刻より前にクレームを清算できるようにします。
|
||||
- `public_key`フィールドと`channel_id`フィールドをメモします。これらのフィールドは、後でクレームを検証、清算する際に必要です。
|
||||
- _(省略可)_`destination_tag`フィールドが存在しており、必要な宛先タグが指定されていることを確認します。
|
||||
|
||||
2名の当事者間に複数のChannelが存在している可能性があるため、受取人が正しいChannelのクオリティを確認することが重要です。混乱する場合は、使用するChannelのChannel ID(`channel_id`)を支払人が明確にする必要があります。
|
||||
|
||||
|
||||
## 3. 支払人がChannelのXRPに対して1つ以上の署名付き _クレーム_ を作成します。
|
||||
|
||||
これらのクレームの額は、支払人が購入する具体的な商品またはサービスに応じて異なります。
|
||||
|
||||
各クレームの額は累計額でなければなりません。つまり、2つのアイテムをそれぞれ10 XRPで購入する場合、1番目のクレームの額は10 XRPで、2番目のクレームの額は20 XRPである必要があります。クレームは、Channelに割り当てられているXRPの合計額を超えることはありません。([PaymentChannelFund][]トランザクションでは、Channelに割り当てられるXRPの合計額を増加できます。)
|
||||
|
||||
[channel_authorizeメソッド][]を使用してクレームを作成できます。以下の例では、Channelから1 XRPが承認されます。
|
||||
|
||||
要求:
|
||||
|
||||
POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "channel_authorize",
|
||||
"params": [{
|
||||
"channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"secret": "s████████████████████████████",
|
||||
"amount": "1000000"
|
||||
}]
|
||||
}
|
||||
|
||||
応答:
|
||||
|
||||
{
|
||||
"result": {
|
||||
"signature": "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
## 4. 支払人が、商品またはサービスに対する支払いとしてクレームを受取人に送信します。
|
||||
|
||||
この通信は、支払人と受取人が合意できる通信システムで「レジャー外」で行われます。これには安全な通信を使用する必要がありますが、必須ではありません。Channelの支払人または受取人がそのChannelに対するクレームを清算できます。
|
||||
|
||||
クレームで以下の情報が伝達される限り、クレームの厳密なフォーマットは重要ではありません。
|
||||
|
||||
| フィールド | 例 |
|
||||
|:------------------------|:---------------------------------------------------|
|
||||
| Channel ID | `5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3` |
|
||||
| XRPの額(drop単位) | `1000000` |
|
||||
| 署名 | `304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A` <br/> `400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064` _(注記: この長い文字列は1行に収まるように改行されています)_ |
|
||||
|
||||
受取人は、Channelに関連付けられている公開鍵も把握する必要があります。この鍵は、Channelの存続期間中変更されることはありません。
|
||||
|
||||
## 5. 受取人がクレームを検証します。
|
||||
|
||||
[channel_verifyメソッド][]を使用してクレームを検証できます。受取人は、クレームの額が提供した商品およびサービスの合計価格以上であることを確認する必要があります。(金額は累計額であるため、これまでに購入されたすべての商品およびサービスの合計価格です。)
|
||||
|
||||
JSON-RPC APIで`channel_verify`を使用する例:
|
||||
|
||||
要求:
|
||||
|
||||
POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "channel_verify",
|
||||
"params": [{
|
||||
"channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"signature": "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
|
||||
"public_key": "aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3",
|
||||
"amount": "1000000"
|
||||
}]
|
||||
}
|
||||
|
||||
応答:
|
||||
|
||||
200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"signature_verified":true,
|
||||
"status":"success"
|
||||
}
|
||||
}
|
||||
|
||||
応答に`"signature_verified": true`が含まれている場合、クレームの署名は真正です。受取人は、クレームを換金できる十分なXRPがChannelにあること**も**確認する必要があります。このためには、受取人は[account_channelsメソッド][]を使用して、Payment Channelの最新の検証済み状態を確認します。
|
||||
|
||||
要求:
|
||||
|
||||
POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "account_channels",
|
||||
"params": [{
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}]
|
||||
}
|
||||
|
||||
応答:
|
||||
|
||||
200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"channels": [{
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"amount": "100000000",
|
||||
"balance": "0",
|
||||
"channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"destination_tag": 20170428,
|
||||
"public_key": "aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3",
|
||||
"public_key_hex": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"settle_delay": 86400
|
||||
}],
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
|
||||
受取人は以下の点を確認する必要があります:
|
||||
|
||||
- `channel_id`がクレームのChannel IDと一致する`channels`配列のオブジェクトを見つけます。同一の当事者間であっても複数のPayment Channelが存在していることがありますが、クレームはIDが一致するChannelでのみ清算できます。
|
||||
- Channelの`expiration`(変更可能な有効期限)がある場合は、この期限が早過ぎないことを確認します。受取人はこの期限の前にクレームを清算する必要があります。
|
||||
- クレームの`amount`がChannelの`amount`以下であることを確認します。クレームの`amount`の方が大きい場合、支払人が[PaymentChannelFundトランザクション][]を使用してChannelで使用可能なXRPの合計額を増加しない限り、クレームを清算できません。
|
||||
- Channelの`balance`が、受取人がすでにChannelから受領していると予測している額と一致していることを確認します。これらの金額が一致しない場合、受取人はChannelのトランザクション履歴を再度確認する必要があります。不一致の原因として以下のものが考えられます。
|
||||
- 支払人が[PaymentChannelClaim][]トランザクションを使用してChannelから受取人にXRPを送金したところ、受取人がこれに気付かず、着信トランザクションを記録していなかった。
|
||||
- 受取人のレコードに、「処理中」のトランザクションや、最新の検証済みレジャーバージョンにはまだ記録されていないトランザクションが含まれていた。受取人は[txメソッド][]を使用して個々のトランザクションの状態を調べ、この点を確認できます。
|
||||
- `account_channels`要求に正しいレジャーバージョンが指定されていなかった。(最新の検証済みバージョンを確認するには、`"ledger_index":"validated”`を使用します)
|
||||
- 受取人は以前にXRPを清算したものの、記録し忘れていた。
|
||||
- 受取人がXRPの清算を試行し、暫定的な結果を記録したが、トランザクションの最終的な検証済みの結果がこれとは異なり、受取人はこの最終検証済み結果を記録し忘れていた。
|
||||
- 受取人が照会した`rippled`サーバーが、ネットワークの他の部分と同期していない状態であったか、または不明なバグが発生した。サーバーの状態を確認するには、[server_infoメソッド][]を使用します。(この状況を再現できる場合は、[問題を報告してください](https://github.com/XRPLF/rippled/issues/)。)
|
||||
|
||||
受取人がPayment Channelの署名と現行状態の両方を確認した後で、XRPをまだ受領していない場合、XRPを清算するトランザクションがChannelの有効期限より前に処理される限り、XRPを確実に清算 _できます_ 。
|
||||
|
||||
|
||||
## 6. 受取人が商品またはサービスを提供します。
|
||||
|
||||
この時点で受取人は支払がすでに保証されていることを把握しているので、商品またはサービスを支払人に提供できます。
|
||||
|
||||
このチュートリアルに関して、受取人は支払人に「商品およびサービス」としてハイタッチまたは同等のオンラインメッセージを送信できます。
|
||||
|
||||
|
||||
## 7. 必要に応じてステップ3~6を繰り返します。
|
||||
|
||||
支払人と受取人はXRP Ledger自体を待つことなく、ステップ3~6(商品およびサービスと交換するクレームの作成、送信、検証)を必要な回数と間隔で繰り返すことができます。この処理に関する2つの主な制限を以下に示します。
|
||||
|
||||
- Payment ChannelのXRPの額。(支払人は必要に応じて[PaymentChannelFundトランザクション][]を送信し、Channelで使用可能なXRPの合計額を増加できます。)
|
||||
|
||||
- Payment Channelの変更可能な有効期限(設定されている場合)。(これは[account_channelsメソッド][]に対する応答の`cancel_after`フィールドに表示されます。)
|
||||
|
||||
|
||||
## 8. 準備が完了すれば、受取人は承認された額のクレームを清算します。
|
||||
|
||||
この時点で受取人は最終的にChannelからXRPを受領します。
|
||||
|
||||
これは、`Balance`、`Amount`、`Signature`、および`PublicKey`フィールドが指定された[PaymentChannelClaimトランザクション][]です。クレームの値は累計額であるため、受取人は最も高額な(最新の)クレームを清算するだけで全額を受領できます。受取人は、承認済みの額全額をクレームで清算する必要はありません。
|
||||
|
||||
受取人は必要に応じて、取引継続中にこの手順を繰り返し実行して、一部の額を決済することができます。
|
||||
|
||||
ChannelからXRPを清算する例:
|
||||
|
||||
要求:
|
||||
|
||||
POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [{
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"TransactionType": "PaymentChannelClaim",
|
||||
"Amount": "1000000",
|
||||
"Balance": "1000000",
|
||||
"Channel": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"Signature": "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064"
|
||||
},
|
||||
"fee_mult_max": 1000
|
||||
}]
|
||||
}
|
||||
|
||||
応答:
|
||||
|
||||
200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied.Only final in a validated ledger.",
|
||||
"status": "success",
|
||||
"tx_blob": "12000F2280000000240000017450165DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB36140000000000F42406240000000000F424068400000000000000A7121023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7447304502210096B933BC24DA77D8C4057B4780B282BA66C668DFE1ACF4EEC063AD6661725797022037C8823669CE91AACA8CC754C9F041359F85B0B32384AEA141EBC3603798A24C7646304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF5029006481144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Amount": "1000000",
|
||||
"Balance": "1000000",
|
||||
"Channel": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"Fee": "10",
|
||||
"Flags": 2147483648,
|
||||
"PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"Sequence": 372,
|
||||
"Signature": "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
|
||||
"SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType": "PaymentChannelClaim",
|
||||
"TxnSignature": "304502210096B933BC24DA77D8C4057B4780B282BA66C668DFE1ACF4EEC063AD6661725797022037C8823669CE91AACA8CC754C9F041359F85B0B32384AEA141EBC3603798A24C",
|
||||
"hash": "C9FE08FC88CF76C3B06622ADAA47AE99CABB3380E4D195E7751274CFD87910EB"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
受取人は検証済みレジャーでこのトランザクションが正常に処理されたことを確認します。詳細は、[確実なトランザクションの送信](reliable-transaction-submission.html)を参照してください。
|
||||
|
||||
## 9. 支払人と受取人の取引完了後、支払人はChannelの閉鎖を要求します。
|
||||
|
||||
これは、`tfClose`フラグを設定した[PaymentChannelClaimトランザクション][]、または`Expiration`フィールドを設定した[PaymentChannelFundトランザクション][]です。_([フローチャート][]の9a)_。
|
||||
|
||||
支払人がChannelの閉鎖を要求した時点でChannelにXRPが残っていない場合は、Channelは即時に閉鎖されます。
|
||||
|
||||
ChannelにXRPが _残っている_ 場合は、このChannelの閉鎖要求は、受取人に対し未処理のクレームを速やかに清算することを求める最終警告となります。Channelの閉鎖までに、少なくとも決済遅延期間相当の時間が受取人に残されています。正確な秒数は、レジャーの閉鎖時刻に応じて多少異なります。
|
||||
|
||||
また、受取人はクレームの処理完了直後にPayment Channelを閉鎖できます _([フローチャート][]の9b)_。
|
||||
|
||||
Channelの閉鎖を要求する[トランザクションを送信する](submit.html#署名と送信モード)例:
|
||||
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [{
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"TransactionType": "PaymentChannelClaim",
|
||||
"Channel": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"Flags": 2147614720
|
||||
},
|
||||
"fee_mult_max": 1000
|
||||
}]
|
||||
}
|
||||
|
||||
トランザクションが検証済みレジャーに記録されたら、いずれの当事者も[account_channelsメソッド][]を使用して現在スケジュールされているChannelの有効期限を確認できます。最新の検証済みレジャーバージョンからデータを取得するには、`"ledger_index": "validated"`を必ず指定してください。
|
||||
|
||||
`account_channels`応答の例:
|
||||
|
||||
{
|
||||
"result": {
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"channels": [
|
||||
{
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"amount": "100000000",
|
||||
"balance": "1000000",
|
||||
"channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"destination_tag": 20170428,
|
||||
"expiration": 547073182,
|
||||
"public_key": "aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3",
|
||||
"public_key_hex": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"settle_delay": 86400
|
||||
}
|
||||
],
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
|
||||
この例に示されている`expiration`の値547073182([Rippleエポック以降の経過秒数][]) は2017-05-02T20:46:22Zに対応しています。このため、この時刻までに決済されなかったクレームはすべて無効になります。
|
||||
|
||||
## 10. 有効期限切れのChannelは誰でも閉鎖できます。
|
||||
|
||||
決済遅延が経過するか、またはChannelが予定されている有効期限に達したら、Channelは有効期限切れになります。それ以降に行われるこのChannelに影響するトランザクションはすべて、Channelを閉鎖するだけであり、未請求のXRPは支払人に返金されます。
|
||||
|
||||
Channelは期限切れ状態で永久にレジャーに残ることがあります。これは、レジャーはトランザクションの結果によってのみ変わるので、_誰かが_ 有効期限切れのChannelを閉鎖するトランザクションを送信する必要があるためです。Channelがレジャーに残っている限り、そのChannelは[所有者準備金](reserves.html#所有者準備金)の点から支払人が所有するオブジェクトと見なされます。
|
||||
|
||||
このため、支払人には`tfClose`フラグを指定した2番目の[PaymentChannelClaimトランザクション][]を送信することが推奨されます。ただしその他のアカウント(Payment Channelに関与するアカウントを含む)は有効期限切れのChannelを閉鎖できません。
|
||||
|
||||
このトランザクションを送信するコマンドは、Channelの有効期限切れを要求する前述の例と同じです。(ただしコマンドの実行結果である[自動入力](transaction-common-fields.html#自動入力可能なフィールド) `Sequence`番号、署名、識別用ハッシュは一意です。)
|
||||
|
||||
有効期限切れのChannelを閉鎖するトランザクションを[送信する](submit.html#署名と送信モード)例:
|
||||
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [{
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"TransactionType": "PaymentChannelClaim",
|
||||
"Channel": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"Flags": 2147614720
|
||||
},
|
||||
"fee_mult_max": 1000
|
||||
}]
|
||||
}
|
||||
|
||||
トランザクションが検証済みレジャーに記録されたら、そのトランザクションのメタデータを調べて、Channelが削除され、XRPが送金元に返金されたことを確認できます。
|
||||
|
||||
このステップのトランザクションを検索する[txメソッド][]を使用した場合の応答の例:
|
||||
|
||||
{
|
||||
"result": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"Channel": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"Fee": "5606",
|
||||
"Flags": 2147614720,
|
||||
"Sequence": 41,
|
||||
"SigningPubKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"TransactionType": "PaymentChannelClaim",
|
||||
"TxnSignature": "3044022008922FEB6F7D35D42006685BCBB007103D2A40AFAA69A7CFC10DF529F94BB6A402205D67816F50BBAEE0A2709AA3A93707304EC21133550FD2FF7436AD0C3CA6CE27",
|
||||
"date": 547091262,
|
||||
"hash": "9C0CAAC3DD1A74461132DA4451F9E53BDF4C93DFDBEFCE1B10021EC569013B33",
|
||||
"inLedger": 29480670,
|
||||
"ledger_index": 29480670,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"PreviousTxnID": "C9FE08FC88CF76C3B06622ADAA47AE99CABB3380E4D195E7751274CFD87910EB",
|
||||
"PreviousTxnLgrSeq": 29385089
|
||||
}
|
||||
},
|
||||
{
|
||||
"DeletedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"Amount": "100000000",
|
||||
"Balance": "1000000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"DestinationTag": 20170428,
|
||||
"Expiration": 547073182,
|
||||
"Flags": 0,
|
||||
"OwnerNode": "0000000000000000",
|
||||
"PreviousTxnID": "C5C70B2BCC515165B7F62ACC8126F8F8B655EB6E1D949A49B2358262BDA986B4",
|
||||
"PreviousTxnLgrSeq": 29451256,
|
||||
"PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"SettleDelay": 86400
|
||||
},
|
||||
"LedgerEntryType": "PayChannel",
|
||||
"LedgerIndex": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"Balance": "1041862844",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 2,
|
||||
"Sequence": 42
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "B1CB040A17F9469BC00376EC8719535655824AD16CB5F539DD5765FEA88FDBE3",
|
||||
"PreviousFields": {
|
||||
"Balance": "942868450",
|
||||
"OwnerCount": 3,
|
||||
"Sequence": 41
|
||||
},
|
||||
"PreviousTxnID": "C5C70B2BCC515165B7F62ACC8126F8F8B655EB6E1D949A49B2358262BDA986B4",
|
||||
"PreviousTxnLgrSeq": 29451256
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Flags": 0,
|
||||
"Owner": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"RootIndex": "E590FC40B4F24D18341569BD3702A2D4E07E7BC04D11CE63608B67979E67030C"
|
||||
},
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "E590FC40B4F24D18341569BD3702A2D4E07E7BC04D11CE63608B67979E67030C"
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 7,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"status": "success",
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
|
||||
トランザクションメタデータで以下のエントリを検索します。
|
||||
|
||||
- `"LedgerEntryType": "PayChannel"`が指定された`DeletedNode`。`LedgerIndex`フィールドはChannel IDと一致している必要があります。これはChannelが削除されたことを示します。
|
||||
- `"LedgerEntryType": "AccountRoot"`が指定された`ModifiedNode`。`PreviousFields`と`FinalFields`の`Balance`フィールドの変化は、支払人に返金される未使用のXRPを反映しています。
|
||||
|
||||
これらのフィールドは、Payment Channelが閉鎖したことを示しています。
|
||||
|
||||
|
||||
## 結論
|
||||
|
||||
これでPayment Channelの使用法のチュートリアルを終了します。ユーザーが、Payment Channelのスピードと利便性を最大限に活用できる独特で興味深い用途を考えることが推奨されます。
|
||||
|
||||
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -11,6 +11,7 @@ labels:
|
||||
- AMM
|
||||
---
|
||||
# Create an Automated Market Maker
|
||||
|
||||
_(Requires the [AMM amendment][] :not_enabled:)_
|
||||
|
||||
An [Automated Market Maker (AMM)](automated-market-makers.html) can be an efficient way to facilitate exchanges between two assets while earning its liquidity providers passive income. This tutorial shows how to create an AMM for a given asset pair.
|
||||
@@ -76,7 +77,7 @@ _JavaScript_
|
||||
|
||||
As the creator of an AMM, you are also the first liquidity provider and you have to supply it with a starting pool of assets. Other users of the XRP Ledger can also become liquidity providers by supplying assets after the AMM exists. It's crucial to choose assets carefully because, as a liquidity provider for an AMM, you are supplying some amounts of both for users to swap between. If one of the AMM's assets becomes worthless, other users can use the AMM to trade for the other asset, leaving the AMM (and thus, its liquidity providers including you) holding only the worthless one. Technically, the AMM always holds some positive amount of both assets, but the amounts can be very small.
|
||||
|
||||
You can choose any pair of fungible assets in the XRP Ledger, including XRP or tokens, including LP Tokens from another AMM. If you use a token, you must hold some amount of that token. (If a token's issuer uses, [authorized trust lines](authorized-trust-lines.html), that means you have to be authorized first.)
|
||||
You can choose any pair of fungible assets in the XRP Ledger, including XRP or tokens, as long as they meet the [restrictions on AMM assets](automated-market-makers.html#restrictions-on-assets).
|
||||
|
||||
For each of the two assets, you need to know its currency code and issuer; as an exception, XRP has no issuer. For each of the assets, you must hold a balance of the asset (or _be_ the issuer). The following sample code acquires two assets, "TST" (which it buys using XRP) and "FOO" (which it receives from the issuer).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user