diff --git a/@l10n/ja/docs/_snippets/common-links.md b/@l10n/ja/docs/_snippets/common-links.md index b937ba1b82..56cc71bf76 100644 --- a/@l10n/ja/docs/_snippets/common-links.md +++ b/@l10n/ja/docs/_snippets/common-links.md @@ -4,6 +4,7 @@ [AMMオブジェクト]: /@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/amm.md [AMMBid]: /@l10n/ja/docs/references/protocol/transactions/types/ammbid.md [AMMBidトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/ammbid.md +[AMMClawbackトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/ammclawback.md [AMMCreate]: /@l10n/ja/docs/references/protocol/transactions/types/ammcreate.md [AMMCreateトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/ammcreate.md [AMMDelete]: /@l10n/ja/docs/references/protocol/transactions/types/ammdelete.md @@ -148,6 +149,7 @@ [PermissionDelegation amendment]: /@l10n/ja/resources/known-amendments.md#permissiondelegation [PermissionedDEX amendment]: /@l10n/ja/resources/known-amendments.md#permissioneddex [PermissionedDomains amendment]: /@l10n/ja/resources/known-amendments.md#permissioneddomains +[PermissionedDomainSetトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/permissioneddomainset.md [許可型ドメイン]: /@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-domains.md [PriceOracle amendment]: /@l10n/ja/resources/known-amendments.md#priceoracle [MPTokensV1_1 amendment]: /@l10n/ja/resources/known-amendments.md#priceoracle @@ -173,7 +175,7 @@ [通貨額の指定]: /@l10n/ja/docs/references/protocol/data-types/basic-data-types.md#通貨額の指定 [レジャーの指定]: /@l10n/ja/docs/references/protocol/data-types/basic-data-types.md#レジャーの指定 [時間の指定]: /@l10n/ja/docs/references/protocol/data-types/basic-data-types.md#時間の指定 -[Specifying Without Amounts]: /@l10n/ja/docs/references/protocol/data-types/currency-formats.md#specifying-without-amounts +[金額なしの指定]: /@l10n/ja/docs/references/protocol/data-types/currency-formats.md#金額なしでの通貨の指定 [SusPay amendment]: /@l10n/ja/resources/known-amendments.md#suspay [TickSize amendment]: /@l10n/ja/resources/known-amendments.md#ticksize [Ticketエントリ]: /@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/ticket.md diff --git a/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-dex-roles.svg b/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-dex-roles.svg new file mode 100644 index 0000000000..a0cd94d164 --- /dev/null +++ b/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-dex-roles.svg @@ -0,0 +1,160 @@ + + +Tracy(許可型DEXのトレーダー)オーダーブックUSD.Acme:FOO.WayGateDomainID: ドメインA10 FOO : 10 USD – Marko9 FOO : 15 USD – Tracy...ドメインA所有者: Owen承認された資格情報:- "認可済" by Isabel- "認可済" by OwenOwen(資格情報の発行者かつドメインの所有者)資格情報タイプ: "認可済"発行者: Owen対象: Tracy保有アクセス許可発行 diff --git a/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-dex-structure.svg b/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-dex-structure.svg new file mode 100644 index 0000000000..b77524fb23 --- /dev/null +++ b/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-dex-structure.svg @@ -0,0 +1,164 @@ + + +オーダーブックEUR:JPYDomainID: BオーダーブックJPY:EURDomainID: B許可型DEX AオーダーブックUSD:FOOオーダーブックBAR:BAZオーダーブックFOO:USDオーダーブックFOO:XRPオーダーブックXRP:FOOオープンDEXオーダーブックEUR:JPYDomainID: AオーダーブックUSD:FOODomainID: AオーダーブックFOO:XRPDomainID: A許可型DEX B diff --git a/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-dexes.md b/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-dexes.md new file mode 100644 index 0000000000..d4e665820b --- /dev/null +++ b/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-dexes.md @@ -0,0 +1,113 @@ +--- +seo: + description: 許可型メインインスタンスの定義と詳細について +labels: + - コンプライアンス + - 分散型取引所 +--- +# 許可型DEX + +許可型DEXは、XRP Ledgerの[分散型取引所(DEX)](./index.md)内での取引を制御する環境です。許可型DEXでの取引は、オープンDEXと同様ですが、[_許可型ドメイン_](./permissioned-domains.md)によって誰がオファーを置くことができるか、またはオファーを受け入れることができるかを制御します。許可型DEXを利用することで、規制下にある企業はXRP Ledgerでの取引に参加し、取引先のすべての相手方が適切に検証されていることを確認することができます。 + +XRP Ledgerブロックチェーン内には、複数の許可型DEXが存在することができます。それぞれは、許可型ドメインと関連付けられており、そのDEXへのアクセスを許可するリストとして機能します。許可型DEX内に置かれた取引は、同じ許可型DEX内の他の取引にのみ実行できます。各許可型DEXは、必要に応じて、任意の数の通貨ペアの注文帳を持つことができます。 + + +## 背景: 許可型DEXの必要性 + +XRP Ledgerは、ローンチ以来、単一の、_オープンDEX_ を持っています。XRPLアカウントを持っていれば誰でもこのDEXで取引することができ、システムは誰がオファーを作成したに関係なく、マッチングする注文、もしくはオファーを自動的に約定します。注文はまた、クロスカレンシー支払いに流動性を提供し、潜在的に1つのアトミック取引の一部として複数の取引を実行することができます。 + +システムは、アカウントの背後にある人々や組織について何も知らないため、ある取引の相手方が誰かは確実ではありません。しかし、経済制裁や金融規制は、犯罪者、テロリスト、または特定の国との取引に対して厳格なルールを課しています。これらの制限により、規制下にある金融機関は、オープンDEXでの取引に対するリスクを負うことを望んでいないかもしれません。 + +さらなる背景情報: + +- [分散型取引所](./index.md) +- [オファー](./offers.md) +- [許可型ドメイン](./permissioned-domains.md) + + +## 許可型DEXの重要な役割 + +許可型DEXを使用するには、以下の役割と責任を持つ参加者が必要です。 + +- 少なくとも2人のトレーダーがマッチングするオファーを置く必要があります。例えば、1人がXRPをUSDに交換し、もう1人がUSDをXRPに交換します。 +- 許可型ドメインの所有者。許可型ドメインへのアクセスを許可する資格情報を制御します。 +- 資格情報(Credentials)の発行者。許可型ドメインへのアクセスを許可する資格情報を発行します。 + +1つのアカウントがこれらの役割のいずれかを複数回果たすことができます。例えば、許可型ドメインの所有者、資格情報の発行者、およびトレーダーの3つの役割を同時に果たすことができます。唯一の制限は、トレーダーが異なるアカウントである必要があることです。 + +{% inline-svg file="./permissioned-dex-roles.svg" /%} + +_図: 許可型オーダーブック。Owenは許可型ドメインの所有者であり、許可型ドメインの承認された資格情報の1つの発行者です。TracyはOwenが発行した適切な資格情報を保有しているため、許可型オーダーブックで取引することができます。_ + + +## 許可型DEXの構造を理解する: オファーの種類と相互作用 + +許可型DEX機能を使用すると、取引オファーは _オープン_、_許可型_、または _ハイブリッド_ のいずれかになります。 + +### オープンオファー + +オープンオファーはオープンDEXを使用し、他のオープンなオファー、ハイブリッドなオファー、[自動マーケットメーカー(AMM)](./automated-market-makers.md)、またはオファーとAMMの組み合わせによってマッチングすることができます。_オープンオファー_ は、許可型DEXがない場合のXRPLのDEXの動作と変わりません。 + +### 許可型オファー + +許可型オファーはドメインIDを指定し、そのドメインIDに一致する許可型ドメインが存在し、オファーを置いたアカウントがそのドメインにアクセスできる場合にのみ有効です。許可型オファーは、指定されたドメインと通貨ペアのオーダーブックに配置され、オープンDEXのオーダーブックとは別です。 + +許可型オファーは、同じドメインIDを指定する許可型オファーとのみマッチングすることができます。[クロスカレンシー支払い](../../payment-types/cross-currency-payments.md)もドメインIDを指定することができ、その場合は、対応する許可型DEXからのみオファーを約定するように制限されます。許可型DEX内の取引は、必要な注文がすべて同じ許可型DEX内に存在する限り、[オートブリッジング](./autobridging.md)を使用することができます。 + +### ハイブリッドオファー + +ハイブリッドオファーはドメインIDを指定し、ハイブリッドフラグを付けます。許可型オファーと同様に、指定された許可型ドメインが存在し、オファーを置いたアカウントがそのドメインにアクセスできる場合にのみ有効です。ただし、ハイブリッドオファーは、指定されたDEXとオープンDEXの両方でオファーをマッチングすることができます。 + +ハイブリッドオファーは、オープンDEXのオーダーブックと、その通貨ペアの許可型ドメイン固有のオーダーブックの両方で追跡され、どちらかのオファーとマッチングすることができます。配置された場合、許可型DEXのオファーと優先的にマッチングします。 + + +### オープン、ハイブリッド、許可型オファーのマッチング方法 + +要約すると、以下の表に、どのオファーがマッチングできるかをまとめています: + +| オファー/支払いタイプ | オープンオファー | ハイブリッドオファー | 許可型オファー | AMM | +|-----------------------|------------------|----------------------|-------------------|-----| +| オープン | ✅ | ✅ | ❌ | ✅ | +| ハイブリッド | ✅ | ✅ | ✅ (同じドメイン) | ✅ | +| 許可型 | ❌ | ❌ | ✅ (同じドメイン) | ❌ | + +許可型DEXを表すための単一のレジャーエントリはありません。 それは暗黙的に、同じドメインIDを持つすべてのオーダーブックとして存在します。指定されたドメインIDを使用して有効なオファーが配置されると、そのオーダーブックが作成され、空になると自動的に削除されます。 + +1つのトランザクションは、同じドメインIDを持つ複数のオーダーブックを使用できます。つまり、同じ許可型DEX内の異なる通貨ペアです。それは、長い[クロスカレンシー支払い](../../payment-types/cross-currency-payments.md)の一部として、またはオートブリッジングを介して使用することができます。ハイブリッドオファーは、許可型オファーとオープンオファーの混合をマッチングすることができますが、トランザクションは複数の異なるドメインを使用することはできません。 + +どのDEXでも利用可能な流動性の量と最良の交換レートは、そのDEXに配置されたオファーによって異なる場合があります。一部のトレーダーは、価格差を利用するために複数の許可型DEXとオープンDEXで取引することを選択するかもしれませんが、他のトレーダーは、そのコンプライアンス要件に応じて、1つのドメインで厳密に取引するかもしれません。 + +{% inline-svg file="./permissioned-dex-structure.svg" /%} + +_図: オープンDEXと2つの異なる許可型DEX。それぞれが、可能な通貨ペアのサブセットの注文帳を含んでいます。_ + + +### 無効な許可型オファー + +オープンDEXでオファーが資金不足になる方法に加えて、許可型DEXでのオファーは _無効_ になる可能性があります。無効なオファーは、資金不足のオファーと同じ方法で処理され、トランザクションがそれらを含むオーダーブックを変更するたびに自動的に削除されます。トランザクションがそれらを削除するまで、レジャーデータ内に無期限に残ることができますが、無効な場合は約定できません。 + +許可型オファーが無効になる理由には、以下のようなものがあります。 + +- オファーを置いたアカウントが保有する資格情報が期限切れまたは削除された。 +- 許可型ドメインが更新され、アクセスを許可する資格情報のセットが変更され、オファーを置いたアカウントが新しい資格情報を保有していない。 +- 許可型ドメインが削除された。 + +資金不足のオファーと同様に、オファーが一時的に無効になり、再度有効になる可能性があります。例えば、トレーダーの資格情報が許可型ドメインへのアクセスを許可する資格情報が期限切れになった場合、そのトレーダーの許可型DEXでのオファーは無効になります。しかし、資格情報が更新された場合、すでに削除されていないオファーは自動的に有効になります。 + +### 許可型DEXの制限 + +許可型DEX機能は、**PermissionedDEX** Amendmentによって有効になり、[Credentials](../../decentralized-storage/credentials.md)と[Permissioned Domains](./permissioned-domains.md) Amendmentに依存しているため、それらのAmendmentが _すべて_ 有効になるまで利用できません。 + +#### AMMとの互換性なし + +許可型DEXは、[自動マーケットメーカー(AMM)](../../tokens/decentralized-exchange/automated-market-makers.md)と互換性がありません。許可型オファーと許可型支払いはAMMで約定できません。また、許可型ドメインによってAMMへのアクセスを制限することはできません。オープンDEXを使用する取引は、場合によってはハイブリッドオファーを消費し、同じトランザクションでAMMを使用することができますが、ドメインを指定するトランザクションではAMMを使用することはできません。 + +**許可型DEXは独立しています** + +許可型DEXは独立しており、それぞれが独自のオーダーブックとオファーを持っています。1つのトランザクションは、複数の許可型DEXで取引することはできません。また、複数の許可型DEXから流動性を集約することはできません。ハイブリッドオファーは、1つの許可型DEXとオープンDEXの両方を使用することができますが、複数の異なる許可型DEXを使用することはできません。 + +#### 許可型DEXのセキュリティに関する考慮事項 + +許可型DEXのセキュリティと公平性は、許可型ドメインの所有者と、そのドメインへのアクセスを許可する資格情報の発行者に依存します。基本的に、各資格情報の定義とその資格情報を取得するための要件は、資格情報の発行者によって定義され、適用されているため、許可型ドメインの存在は、実際に誰がそれを使用できるかについて、本質的に何も意味しません。 + +資格情報の発行者は、資格情報を発行または取り消すことができます。もし、それらが信頼できないか、侵害されている場合、それらの資格情報を受け入れる許可型ドメインも同様です。同様に、ドメインの所有者は、ドメインの承認された資格情報のリストを変更して、ドメインへのアクセスを許可または拒否することができるため、もし、それらが信頼できないか、侵害されている場合、ドメインも同様です。 diff --git a/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-domains.md b/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-domains.md index 11b23aabe3..d793e47a7e 100644 --- a/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-domains.md +++ b/@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-domains.md @@ -36,4 +36,4 @@ _([PermissionedDomains amendment][]が必要です {% not-enabled /%})_ - 単一資産Vaultと貸付プロトコル - 許可型DEX -{% raw-partial file="/docs/_snippets/common-links.md" /%} +{% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} diff --git a/@l10n/ja/docs/infrastructure/configuration/server-modes/run-rippled-as-a-validator.md b/@l10n/ja/docs/infrastructure/configuration/server-modes/run-rippled-as-a-validator.md index 7de419a947..6d2203b082 100644 --- a/@l10n/ja/docs/infrastructure/configuration/server-modes/run-rippled-as-a-validator.md +++ b/@l10n/ja/docs/infrastructure/configuration/server-modes/run-rippled-as-a-validator.md @@ -313,9 +313,6 @@ _**公開ハブを使用してバリデータをネットワークに接続す 4. 記入したGoogleフォームを送信すると、ドメイン検証の成否を通知するメールがXRP Chartsから送信されます。ドメイン検証が成功した場合は、XRP Chartsの[バリデータレジストリー](https://xrpcharts.ripple.com/#/validators)にバリデータとドメインが表示されます。 - - - ## バリデータキーの破棄 diff --git a/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/ledger-methods/ledger_entry.md b/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/ledger-methods/ledger_entry.md index 97014d77c9..c3515fb583 100644 --- a/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/ledger-methods/ledger_entry.md +++ b/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/ledger-methods/ledger_entry.md @@ -119,7 +119,7 @@ rippled json ledger_entry '{ "index": "7DB0788C020F02780A673DC74757F23823FA3014C アドレスから[AccountRootエントリ](../../../protocol/ledger-data/ledger-entry-types/accountroot.md)を取得します。これは[account_infoメソッド][]とほぼ同じです。 | フィールド | 型 | 説明 | -|:----------- ---|:--------------------|:----------------------| +|:---------------|:--------------------|:----------------------| | `account_root` | 文字列 - [アドレス][] | 取得する[AccountRootエントリ](../../../protocol/ledger-data/ledger-entry-types/accountroot.md)の標準アドレス。 | {% tabs %} diff --git a/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/book_offers.md b/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/book_offers.md index 710e53b911..78b2c45bd3 100644 --- a/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/book_offers.md +++ b/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/book_offers.md @@ -1,6 +1,4 @@ --- -html: book_offers.html -parent: path-and-order-book-methods.html seo: description: オーダーブックと呼ばれる、2つの通貨間のオファーのリストを取得します。 labels: @@ -10,7 +8,7 @@ labels: # book_offers [[ソース]](https://github.com/XRPLF/rippled/blob/master/src/ripple/rpc/handlers/BookOffers.cpp "Source") -`book_offers`メソッドは、[オーダーブック](http://www.investopedia.com/terms/o/order-book.asp)と呼ばれる、2つの通貨間のオファーのリストを取得します。結果が非常に大きい場合、結果の一部がマーカー付きで返されます。これにより、その後のリクエストは前回のリクエストで終わった箇所から再開できます。 +`book_offers`メソッドは、2つの通貨間の[オファー](../../../../concepts/tokens/decentralized-exchange/offers.md)のリストを取得します。これは、_オーダーブック_ とも呼ばれます。レスポンスは、[資金供給のないオファー](../../../../concepts/tokens/decentralized-exchange/offers.md#オファーのライフサイクル)を省略し、残りの各オファーの合計に対して資金供給されている割合を報告します。 ## リクエストのフォーマット リクエストのフォーマットの例: @@ -69,15 +67,16 @@ rippled book_offers 'USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' 'EUR/rvYAfWj5gh67oV6 リクエストには以下のパラメーターが含まれます。 -| `Field` | 型 | 説明 | -|:---------------|:-------------------------------------------|:-------------------------------| -| `ledger_hash` | 文字列 | _(省略可)_ 使用するレジャーバージョンの20バイトの16進文字列。([レジャーの指定][]をご覧ください) | -| `ledger_index` | 文字列または符号なし整数 | _(省略可)_ 使用するレジャーの[レジャーインデックス][]、またはレジャーを自動的に選択するためのショートカット文字列。([レジャーの指定][]をご覧ください) | -| `limit` | 符号なし整数 | _(省略可)_ 指定されている場合、サーバはこの制限を超える数のオファーを結果に含めません。資金供給のないオファーはサーバにより省略されるため、返される結果の総数はこの制限よりも少ないことがあります。 | -| `marker` | [マーカー][] | _(省略可)_ 以前にページネーションされたレスポンスの値。そのレスポンスを停止した箇所からデータの取得を再開します。 | -| `taker` | 文字列 | _(省略可)_ パースペクティブとして使用するアカウントの[アドレス][]。このアカウントが発行した[資金供給のないオファー](../../../../concepts/tokens/decentralized-exchange/offers.md#オファーのライフサイクル)は常にレスポンスに含まれます。(これを使用して、キャンセルしたい各自のオーダーを検索できます。) | -| `taker_gets` | オブジェクト | オファーを受諾するアカウントが受け取る通貨を、[通貨額][通貨額]と同様に、`currency`フィールドと`issuer`フィールドを持つオブジェクトとして指定します(XRPの場合はissuerを省略)。 | -| `taker_pays` | オブジェクト | オファーを受諾するアカウントが支払う通貨を、[通貨額][通貨額]と同様に、`currency`フィールドと`issuer`フィールドを持つオブジェクトとして指定します(XRPの場合はissuerを省略)。 | +| フィールド | 型 | 必須? | 説明 | +|:---------------|:-------------------------|:-------|:-------------------------------| +| `taker_gets` | オブジェクト | はい | オファーを受諾するアカウントが受け取る通貨を、[通貨額][通貨額]と同様に、`currency`フィールドと`issuer`フィールドを持つオブジェクトとして指定します(XRPの場合はissuerを省略)。 | +| `taker_pays` | オブジェクト | はい | オファーを受諾するアカウントが支払う通貨を、[通貨額][通貨額]と同様に、`currency`フィールドと`issuer`フィールドを持つオブジェクトとして指定します(XRPの場合はissuerを省略)。 | +| `domain` | [ハッシュ][] | いいえ | 許可型ドメインのレジャーエントリID。指定された場合、オープンDEXの代わりに、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)からオファーを返します。 _([PermissionedDEX amendment][]が必要です。 {% not-enabled /%})_ | +| `ledger_hash` | [ハッシュ][] | いいえ | 使用するレジャーバージョンの20バイトの16進文字列。([レジャーの指定][]をご覧ください) | +| `ledger_index` | [レジャーインデックス][] | いいえ | 使用するレジャーの[レジャーインデックス][]、またはレジャーを自動的に選択するためのショートカット文字列。([レジャーの指定][]をご覧ください) | +| `limit` | 整数 | いいえ | 指定されている場合、サーバはこの制限を超える数のオファーを結果に含めません。資金供給のないオファーはサーバにより省略されるため、返される結果の総数はこの制限よりも少ないことがあります。 | +| `taker` | 文字列 | いいえ | パースペクティブとして使用するアカウントの[アドレス][]。このアカウントが発行した[資金供給のないオファー](../../../../concepts/tokens/decentralized-exchange/offers.md#オファーのライフサイクル)は常にレスポンスに含まれます。(これを使用して、キャンセルしたい各自のオーダーを検索できます。) | + ## レスポンスのフォーマット @@ -161,26 +160,97 @@ rippled book_offers 'USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' 'EUR/rvYAfWj5gh67oV6 ``` {% /tab %} +{% tab label="Commandline" %} +```json +{ + "result" : { + "ledger_current_index" : 56867201, + "offers" : [ + { + "Account" : "rnixnrMHHvR7ejMpJMRCWkaNrq3qREwMDu", + "BookDirectory" : "7E5F614417C2D0A7CEFEB73C4AA773ED5B078DE2B5771F6D56038D7EA4C68000", + "BookNode" : "0000000000000000", + "Flags" : 131072, + "LedgerEntryType" : "Offer", + "OwnerNode" : "0000000000000000", + "PreviousTxnID" : "E43ADD1BD4AC2049E0D9DE6BC279B7FD95A99C8DE2C4694A4A7623F6D9AAAE29", + "PreviousTxnLgrSeq" : 47926685, + "Sequence" : 219, + "TakerGets" : { + "currency" : "EUR", + "issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value" : "2.459108753792364" + }, + "TakerPays" : { + "currency" : "USD", + "issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value" : "24.59108753792364" + }, + "index" : "3087B4828C6B5D8595EA325D69C0F396C57452893647799493A38F2C164990AB", + "owner_funds" : "2.872409153061363", + "quality" : "10" + }, + { + "Account" : "rKwjWCKBaASEvtHCxtvReNd2i9n8DxSihk", + "BookDirectory" : "7E5F614417C2D0A7CEFEB73C4AA773ED5B078DE2B5771F6D56038D7EA4C68000", + "BookNode" : "0000000000000000", + "Flags" : 131072, + "LedgerEntryType" : "Offer", + "OwnerNode" : "0000000000000000", + "PreviousTxnID" : "B63B2ECD124FE6B02BC2998929517266BD221A02FEE51DDE4992C1BCB7E86CD3", + "PreviousTxnLgrSeq" : 43166305, + "Sequence" : 19, + "TakerGets" : { + "currency" : "EUR", + "issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value" : "3.52" + }, + "TakerPays" : { + "currency" : "USD", + "issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value" : "35.2" + }, + "index" : "89865F2C70D1140796D9D249AC2ED765AE2D007A52DEC6D6D64CCB1A77A6EB7F", + "owner_funds" : "3.523192614770459", + "quality" : "10", + "taker_gets_funded" : { + "currency" : "EUR", + "issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value" : "3.516160294182094" + }, + "taker_pays_funded" : { + "currency" : "USD", + "issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value" : "35.16160294182094" + } + } + ], + "status" : "success", + "validated" : false + } +} +``` +{% /tab %} + {% /tabs %} このレスポンスは[標準フォーマット][]に従っており、正常に完了した場合は結果に次のフィールドが含まれます。 -| `Field` | 型 | 説明 | -|:-----------------------|:--------------------------|:------------------------| -| `ledger_current_index` | 数値 - [レジャーインデックス][] | _(`ledger_current_index`が指定されている場合は省略)_ この情報の取得時に使用した、現在処理中のレジャーバージョンの[レジャーインデックス][]。 | -| `ledger_index` | 数値 - [レジャーインデックス][] | _(`ledger_current_index`が指定されている場合は省略可)_ リクエストに従って、このデータの取得時に使用されたレジャーバージョンのレジャーインデックス。 | -| `ledger_hash` | 文字列 - [ハッシュ][] | _(省略される場合があります)_ リクエストに従って、このデータの取得時に使用されたレジャーバージョンの識別用ハッシュ。 | -| `marker` | [マーカー][] | _(省略される場合があります)_ レスポンスがページネーションされていることを示す、サーバが定義した値。この値を次のコールに渡して、このコールで終わった箇所から再開します。この後に情報ページがない場合は省略されます。 | -| `offers` | 配列 | Offerオブジェクトの配列。各オブジェクトには[Offer オブジェクト](../../../protocol/ledger-data/ledger-entry-types/offer.md)のフィールドが含まれています。 | +| フィールド | 型 | 説明 | +|:-----------------------|:-------------------------|:------------------------| +| `ledger_current_index` | [レジャーインデックス][] | _(`ledger_current_index`が指定されている場合は省略)_ この情報の取得時に使用した、現在処理中のレジャーバージョンの[レジャーインデックス][]。 | +| `ledger_index` | [レジャーインデックス][] | _(`ledger_current_index`が指定されている場合は省略)_ リクエストに従って、このデータの取得時に使用されたレジャーバージョンのレジャーインデックス。 | +| `ledger_hash` | [ハッシュ][] | _(省略される場合があります)_ リクエストに従って、このデータの取得時に使用されたレジャーバージョンの識別用ハッシュ。 | +| `offers` | 配列 | Offerオブジェクトの配列。詳細は下記にて。 | -`offers`配列の要素には、Offerの標準フィールドの他に以下のフィールドが含まれます。 +`offers`配列の各要素には、[Offerエントリ][]の標準フィールドの他に、以下の追加フィールドが含まれます。 -| `Field` | 型 | 説明 | -|:--------------------|:---------------------------------|:--------------------| -| `owner_funds` | 文字列 | オファーの発行元が保有する取引可能なTakerGets通貨の金額。(XRPはdrop単位で表されます。その他のすべての通貨は10進数値として表されます。)1人のトレーダーの複数のオファーが同一のブックに含まれている場合、このフィールドは最高順位のオファーにのみ含まれます。 | -| `taker_gets_funded` | 文字列(XRP)またはオブジェクト(XRP以外) | (部分的に資金供給されているオファーのみに含まれます)オファーの資金供給ステータスが指定されている場合に、受取人が受領できる最大通貨額。 | -| `taker_pays_funded` | 文字列(XRP)またはオブジェクト(XRP以外) | (部分的に資金供給されているオファーのみに含まれます)オファーの資金供給ステータスが指定されている場合に、受取人が支払う最大通貨額。 | -| `quality` | 文字列 | 為替レート(`taker_pays`を`taker_gets`で割った比率)。公正を期すため、同じクオリティのオファーは先入れ先出しで自動的に受諾されます。(つまり、複数の人々が通貨を同じレートで取引するオファーを出した場合、最も古いオファーが最初に受諾されます。) | +| フィールド | 型 | 説明 | +|:--------------------|:-----------|:--------------------| +| `owner_funds` | 文字列 | オファーの発行元が保有する取引可能なTakerGets通貨の金額。(XRPはdrop単位で表されます。その他のすべての通貨は10進数値として表されます。)1人のトレーダーの複数のオファーが同一のブックに含まれている場合、このフィールドは最高順位のオファーにのみ含まれます。 | +| `taker_gets_funded` | [通貨額][] | (部分的に資金供給されているオファーのみに含まれます) オファーの資金供給ステータスが指定されている場合に、受取人が受領できる最大通貨額。 | +| `taker_pays_funded` | [通貨額][] | (部分的に資金供給されているオファーのみに含まれます) オファーの資金供給ステータスが指定されている場合に、受取人が支払う最大通貨額。 | +| `quality` | 文字列 | 為替レート(`taker_pays`を`taker_gets`で割った比率)。公正を期すため、同じクオリティのオファーは先入れ先出しで自動的に約定されます。(つまり、複数の人々が通貨を同じレートで取引するオファーを出した場合、最も古いオファーが最初に受諾されます。) | ## 考えられるエラー diff --git a/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/path_find.md b/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/path_find.md index 3d8b2546c8..fb9e803200 100644 --- a/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/path_find.md +++ b/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/path_find.md @@ -55,14 +55,15 @@ path_findコマンドには3種類のモード(サブコマンド)があり リクエストには以下のパラメーターが含まれます。 -| `Field` | 型 | 説明 | -|:----------------------|:-----------------|:----------------------------------| -| `subcommand` | 文字列 | `"create"`を使用してcreateサブコマンドを送信します。 | -| `source_account` | 文字列 | 探索するパスの送金元アカウントの一意のアドレス。(つまり、支払いを送金するアカウントです。) | -| `destination_account` | 文字列 | 探索するパスの送金先アカウントの一意のアドレス。(つまり、支払いを受領するアカウントです。) | -| `destination_amount` | 文字列またはオブジェクト | 送金先アカウントがトランザクションで受領する[通貨額][]。**特殊なケース:**{% badge href="https://github.com/XRPLF/rippled/releases/tag/0.30.0" %}新規: rippled 0.30.0{% /badge %}`value`フィールドには`"-1"`(XRPの場合)または-1(XRP以外の通貨の場合)を指定できます。これにより、最大限の額を送金できるパスがリクエストされます。ただし`send_max`が指定されている場合は、指定額を上回る額が支払われることはありません。 | -| `send_max` | 文字列またはオブジェクト | _(省略可)_ トランザクションに使用する[通貨額][]。`source_currencies`と同時に指定することはできません。{% badge href="https://github.com/XRPLF/rippled/releases/tag/0.30.0" %}新規: rippled 0.30.0{% /badge %} | -| `paths` | 配列 | _(省略可)_ チェックする[ペイメントパス](../../../../concepts/tokens/fungible-tokens/paths.md)を表すオブジェクトの配列。すでに判明している特定パスの変更内容を常に把握する場合や、特定パスに沿った支払いにかかる総コストを確認する場合にこのフィールドを使用できます。 | +| フィールド | 型 | 必須? | 説明 | +|:----------------------|:-------------------------|:-------|:---------------------------| +| `subcommand` | 文字列 | はい | `"create"`を使用してcreateサブコマンドを送信します。 | +| `source_account` | 文字列 - [アドレス][] | はい | 検索するパスの送金元アカウントのドレス。(つまり、支払いを送金するアカウント) | +| `destination_account` | 文字列 - [アドレス][] | はい | 検索するパスの送金先アカウントのアドレス。(つまり、支払いを受領するアカウント) | +| `destination_amount` | [通貨額][] | はい | 送金先アカウントが受け取る金額。 **特殊ケース:** XRPの場合、`"-1"`を指定するか、トークンの場合、`value`フィールドの内容として-1を指定できます。これにより、`send_max`で指定された金額を超えない範囲で、可能な限り多くの送金先への送金を要求します。 | +| `domain` | 文字列 - [ハッシュ][] | いいえ | 許可型ドメインのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。 _([PermissionedDEX amendment][]が必要です。 {% not-enabled /%})_ | +| `paths` | 配列 | いいえ | チェックする[支払いパス](../../../../concepts/tokens/fungible-tokens/paths.md)を表すオブジェクトの配列。すでに判明している特定パスの変更内容を常に把握する場合や、特定パスに沿った支払いにかかる総コストを確認する場合にこのフィールドを使用できます。 | +| `send_max` | [通貨額][] | いいえ | トランザクションに使用する[通貨額][]。`source_currencies`と同時に指定することはできません。| サーバは`source_currencies`および`bridges`フィールドも認識しますが、これらのフィールドを使用した場合の結果は保証されません。これらのフィールドは将来のために予約されているものと考えてください。 @@ -444,8 +445,8 @@ path_findコマンドには3種類のモード(サブコマンド)があり この初期レスポンスは[標準フォーマット](../../api-conventions/response-formatting.md)に従っており、正常に完了した場合は次のフィールドが含まれています。 -| `Field` | 型 | 説明 | -|:----------------------|:-----------------|:----------------------------------| +| フィールド | 型 | 説明 | +|:----------------------|:-----------------|:---------------------------| | `alternatives` | 配列 | 以下に説明する、提案される[パス](../../../../concepts/tokens/fungible-tokens/paths.md)のオブジェクトの配列。空の場合、送金元アカウントと送金先アカウントを結ぶパスが見つかりませんでした。 | | `destination_account` | 文字列 | トランザクションを受信するアカウントの一意のアドレス。 | | `destination_amount` | 文字列またはオブジェクト | 送金先がトランザクションで受領する[通貨額][]。 | @@ -455,8 +456,8 @@ path_findコマンドには3種類のモード(サブコマンド)があり `alternatives`配列の各要素は、1つの送金元通貨(開始アカウントが保有)から送金先アカウントへのパスと通貨を表すオブジェクトです。このオブジェクトのフィールドを次に示します。 -| `Field` | 型 | 説明 | -|:-----------------|:-----------------|:---------------------------------------| +| フィールド | 型 | 説明 | +|:-----------------|:-----------------|:--------------------------------| | `paths_computed` | 配列 | [ペイメントパス](../../../../concepts/tokens/fungible-tokens/paths.md)を定義するオブジェクトの配列。 | | `source_amount` | 文字列またはオブジェクト | 送金先が必要な額を受領するために、送金元がこのパスで送金する必要がある[通貨額][]。 | @@ -521,17 +522,17 @@ path_find createリクエストからの非同期フォローアップの例を リクエストには以下のパラメーターが含まれます。 -| `Field` | 型 | 説明 | -|:-------------|:-------|:-------------------------------------------| +| フィールド | 型 | 説明 | +|:-------------|:-------|:------------------------------------| | `subcommand` | 文字列 | closeサブコマンドを送信するため`"close"`を使用します。 | ### レスポンスのフォーマット Pathfindingリクエストが正常にクローズされた場合、レスポンスは[`path_find create`](#path_find-create)に対する初期レスポンスと同じフォーマットであり、されに以下のフィールドが含まれます。 -| `Field` | 型 | 説明 | -|:---------|:--------|:--------------------------------------------------------| -| `closed` | ブール値 | 値が`true`の場合、これは`path_find close`コマンドに対するレスポンスです。 | +| フィールド | 型 | 説明 | +|:-----------|:--------|:-------------------------------------------------| +| `closed` | ブール値 | 値が`true`の場合、これは`path_find close`コマンドに対するレスポンスです。 | 未処理のPathfindingリクエストがない場合はエラーが返されます。 @@ -566,17 +567,17 @@ Pathfindingリクエストが正常にクローズされた場合、レスポン リクエストには以下のパラメーターが含まれます。 -| `Field` | 型 | 説明 | -|:-------------|:-------|:---------------------------------------------| +| フィールド | 型 | 説明 | +|:-------------|:-------|:--------------------------------------| | `subcommand` | 文字列 | `"status"`を使用して、statusサブコマンドを送信します。 | ### レスポンスのフォーマット Pathfindingリクエストが実行中の場合、レスポンスは[`path_find create`](#path_find-create)に対する初期レスポンスと同じフォーマットであるのに加えて、以下のフィールドがあります。 -| `Field` | 型 | 説明 | -|:---------|:--------|:--------------------------------------------------------| -| `status` | ブール値 | 値が`true`の場合、これは`path_find status`コマンドに対するレスポンスです。 | +| フィールド | 型 | 説明 | +|:-----------|:--------|:-------------------------------------------------| +| `status` | ブール値 | 値が`true`の場合、これは`path_find status`コマンドに対するレスポンスです。 | 未処理のPathfindingリクエストがない場合はエラーが返されます。 diff --git a/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/ripple_path_find.md b/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/ripple_path_find.md index a4f2c8d056..758693b7a0 100644 --- a/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/ripple_path_find.md +++ b/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/ripple_path_find.md @@ -85,15 +85,16 @@ rippled ripple_path_find '{"source_account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59" リクエストには以下のパラメーターが含まれます。 -| `Field` | 型 | 説明 | -|:----------------------|:---------------------------|:------------------------| -| `source_account` | 文字列 | トランザクションで資金を送金するアカウントの一意のアドレス。 | -| `destination_account` | 文字列 | トランザクションで資金を受領するアカウントの一意のアドレス。 | -| `destination_amount` | 文字列またはオブジェクト | 送金先アカウントがトランザクションで受領する[通貨額][]。**特殊なケース:** {% badge href="https://github.com/XRPLF/rippled/releases/tag/0.30.0" %}新規: rippled 0.30.0{% /badge %}`value`フィールドには`"-1"`(XRPの場合)または-1(XRP以外の通貨の場合)を指定できます。これにより、最大限の額を送金できるパスがリクエストされます。ただし`send_max`が指定されている場合は、指定されている額を上回る額が支払われることはありません。 | -| `send_max` | 文字列またはオブジェクト | _(省略可)_ トランザクションで使用する[通貨額][]。`source_currencies`と同時に使用することはできません。{% badge href="https://github.com/XRPLF/rippled/releases/tag/0.30.0" %}新規: rippled 0.30.0{% /badge %} | -| `source_currencies` | 配列 | _(省略可)_ 送信元アカウントが使用する通貨の配列。この配列の各エントリは、必須の`currency`フィールドとオプションの`issuer`フィールドを有するJSONオブジェクトです([通貨額][]の指定方法と同様)。指定できる送金元通貨は**18**種類以下です。デフォルトでは、あらゆる送金元通貨を使用し、最大で**88**の異なる通貨/イシュアーペアに使用できます。 | -| `ledger_hash` | 文字列 | _(省略可)_ 使用するレジャーバージョンの20バイトの16進文字列。([レジャーの指定][]をご覧ください) | -| `ledger_index` | 文字列または符号なし整数 | _(省略可)_ 使用するレジャーのシーケンス番号、またはレジャーを自動的に選択するためのショートカット文字列。([レジャーの指定][]をご覧ください) | +| フィールド | 型 | 必須? | 説明 | +|:----------------------|:-------------------------|:-------|:-----------------| +| `source_account` | 文字列 - [アドレス][] | はい | トランザクションで資金を送金するアカウントのアドレス。 | +| `destination_account` | 文字列 - [アドレス][] | はい | トランザクションで資金を受領するアカウントのアドレス。 | +| `destination_amount` | [通貨額][] | はい | 送金先アカウントがトランザクションで受領する[通貨額][]。**特殊なケース:** `value`フィールドには`"-1"`(XRPの場合)または-1(XRP以外の通貨の場合)を指定できます。これにより、最大限の額を送金できるパスがリクエストされます。ただし`send_max`が指定されている場合は、指定されている額を上回る額が支払われることはありません。 | +| `domain` | 文字列 - [ハッシュ][] | いいえ | 許可型DEXのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です) | +| `ledger_hash` | 文字列 - [ハッシュ][] | いいえ | 使用するレジャーバージョンの20バイトの16進文字列。([レジャーの指定][]をご覧ください) | +| `ledger_index` | [レジャーインデックス][] | いいえ | 使用するレジャーのシーケンス番号、またはレジャーを自動的に選択するためのショートカット文字列。([レジャーの指定][]をご覧ください) | +| `send_max` | [通貨額][] | いいえ | トランザクションで使用する[通貨額][]。`source_currencies`と同時に使用することはできません。 | +| `source_currencies` | 配列 | いいえ | 送信元アカウントが使用する通貨の配列。この配列の各エントリは、必須の`currency`フィールドとオプションの`issuer`フィールドを有するJSONオブジェクトです([通貨額][]の指定方法と同様)。指定できる送金元通貨は**18**種類以下です。デフォルトでは、あらゆる送金元通貨を使用し、最大で**88**の異なる通貨/イシュアーペアに使用できます。 | ## レスポンスのフォーマット @@ -323,7 +324,7 @@ rippled ripple_path_find '{"source_account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59" このレスポンスは[標準フォーマット][]に従っており、正常に完了した場合は結果に次のフィールドが含まれます。 -| `Field` | 型 | 説明 | +| フィールド | 型 | 説明 | |:-------------------------|:-------|:-----------------------------------------| | `alternatives` | 配列 | 使用可能なパスを持つオブジェクトの配列。以下に説明します。空の場合、送金元アカウントと送金先アカウントを結ぶパスがありません。 | | `destination_account` | 文字列 | 支払トランザクションを受信するアカウントの一意のアドレス。 | @@ -331,7 +332,7 @@ rippled ripple_path_find '{"source_account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59" `alternatives`配列の各要素は、1つの送金元通貨(開始アカウントが保有)から送金先アカウントへのパスと通貨を表すオブジェクトです。このオブジェクトのフィールドを次に示します。 -| `Field` | 型 | 説明 | +| フィールド | 型 | 説明 | |:-----------------|:-----------------|:---------------------------------------| | `paths_computed` | 配列 | (省略可)[ペイメントパス](../../../../concepts/tokens/fungible-tokens/paths.md)を定義するオブジェクトの配列。 | | `source_amount` | 文字列またはオブジェクト | 送金先が希望額を受領できるよう、送金元がこのパスで送金する必要のある[通貨額][]。 | diff --git a/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/subscription-methods/subscribe.md b/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/subscription-methods/subscribe.md index 1a36a9f0f2..a99ad90237 100644 --- a/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/subscription-methods/subscribe.md +++ b/@l10n/ja/docs/references/http-websocket-apis/public-api-methods/subscription-methods/subscribe.md @@ -10,7 +10,7 @@ labels: - スマートコントラクト --- # subscribe -[[ソース]](https://github.com/XRPLF/rippled/blob/master/src/ripple/rpc/handlers/Subscribe.cpp "Source") +[[ソース]](https://github.com/XRPLF/rippled/blob/master/src/xrpld/rpc/handlers/Subscribe.cpp "Source") `subscribe`メソッドは、特定のイベントが発生した場合に、定期的に通知するようサーバにリクエストします。 @@ -66,42 +66,47 @@ labels: リクエストには以下のパラメーターが含まれます。 -| `Field` | 型 | 説明 | -| :------------------ | :----- | ---- | -| `streams` | 配列 | _(省略可)_ 以下に説明する、サブスクライブする汎用ストリームの文字列名の配列。 | -| `accounts` | 配列 | _(省略可)_ 検証済みトランザクションを監視するアカウントの一意のアドレスを持つ配列。これらのアドレスはXRP Ledgerの[base58][]フォーマットで記述されている必要があります。サーバは、1つ以上のアカウントに影響するすべてのトランザクションについて通知を送信します。 | -| `accounts_proposed` | 配列 | _(省略可)_ `accounts`と同様ですが、まだファイナライズされていないトランザクションを含みます。 | -| `books` | 配列 | _(省略可)_ 以下に説明するとおり、更新の監視のために[オーダーブック](http://www.investopedia.com/terms/o/order-book.asp)を定義するオブジェクトの配列。 | -| `url` | 文字列 | (Websocketでは省略可、それ以外では必須)サーバが各イベントのJSON-RPCコールバックを送信するURL。*管理者専用。* | -| `url_username` | 文字列 | _(省略可)_ コールバックURLで基本認証を行うためのユーザ名。 | -| `url_password` | 文字列 | _(省略可)_ コールバックURLで基本認証を行うためのパスワード。 | +| フィールド | 型 | 必須? | 説明 | +|:--------------------|:-------|:-------|:-----| +| `streams` | 配列 | いいえ | 以下で説明するストリームにサブスクライブします。配列の各要素は、ストリームの文字列名でなければなりません。 | +| `accounts` | 配列 | いいえ | 検証済みトランザクションを監視するアカウントの一意の[アドレス][]を持つ配列。サーバは、少なくともこれらのアカウントのいずれかに影響を与えるトランザクションが発生するたびに、`transaction`タイプのメッセージを送信します。 | +| `accounts_proposed` | 配列 | いいえ | `accounts`と同様ですが、まだファイナライズされていないトランザクションを含みます。 | +| `books` | 配列 | いいえ | 更新を監視するオーダーブック。配列の各要素は、以下で定義される[book object](#book-objects)でなければなりません。サーバは、トランザクションがこのアカウントに影響を与えるたびに、`transaction`タイプのメッセージを送信します。 | +| `url` | 文字列 | いいえ | (Websocketでは省略可、それ以外では必須)サーバが各イベントのJSON-RPCコールバックを送信するURL。*管理者専用。* | +| `url_username` | 文字列 | いいえ | コールバックURLで基本認証を行うためのユーザ名。 | +| `url_password` | 文字列 | いいえ | コールバックURLで基本認証を行うためのパスワード。 | -以下のパラメーターは廃止予定で、今後予告なしに削除される可能性があります。`user`、`password`、`rt_accounts`。 +以下のパラメータは廃止予定で、今後予告なしに削除される可能性があります。`user`、`password`、`rt_accounts`。 -`streams`パラメーターは、以下のデフォルトの情報ストリームへのアクセスを可能にします。 +`streams`パラメータは、以下のデフォルトの情報ストリームへのアクセスを可能にします。 -- `book_changes` - コンセンサスプロセスが新しい有効なレジャーを作成するたびに、オーダーブックの変更をメッセージで送信します。 -- `consensus` - サーバがコンセンサスサイクルのフェーズを変更するたびにメッセージを送信します。 -- `ledger` - コンセンサスプロセスで新しい検証済みレジャーが宣言されるたびにメッセージを送信します。 -- `manifests` - バリデータのephemeral署名鍵の更新を受け取るたびにメッセージを送信します。 -- `peer_status` - **(管理者専用)** 接続している`rippled`のピアサーバに関する情報(特にコンセンサスプロセスに関する情報)。 -- `transactions` - 閉鎖済みレジャーにトランザクションが追加されるたびにメッセージを送信します。 -- `transactions_proposed` - 閉鎖済みレジャーにトランザクションが追加される場合や、検証済みレジャーにまだ追加されておらず、今後も追加される見込みのない一部のトランザクションが検証済みレジャーに追加される場合に、メッセージを送信します。提案されたすべてのトランザクションが検証前に表示されるわけではありません。 - {% admonition type="info" name="注記" %}[成功しなかったトランザクション](../../../protocol/transactions/transaction-results/index.md) 成功しなかったトランザクションも、スパム対策取引手数料を取るため、検証済みレジャーに含まれます。{% /admonition %} -- `server` - `rippled`サーバのステータス(ネットワーク接続など)が変更されるたびにメッセージを送信します。 -- `validations` - サーバがバリデータを信頼しているか否かにかかわらず、サーバが検証メッセージを受信するたびに、メッセージを送信します。(個々の`rippled`は、サーバが少なくとも定数の信頼できるバリデータから検証メッセージを受信した時点で、レジャーが検証済みであると宣言します。) +| ストリーム名 | メッセージタイプ | 説明 | +|:------------------------|:---------------------|:------------| +| `book_changes` | `bookChanges` | コンセンサスプロセスが新しい検証済みレジャーを宣言するたびに、オーダーブックの変更をメッセージで送信します。 | +| `consensus` | `consensusPhase` | サーバがコンセンサスサイクルのフェーズを変更するたびにメッセージを送信します。 | +| `ledger` | `ledgerClosed` | コンセンサスプロセスで新しい検証済みレジャーが宣言されるたびにメッセージを送信します。 | +| `manifests` | `manifestReceived` | バリデータのephemeral署名鍵の更新を受け取るたびにメッセージを送信します。 | +| `peer_status` | `peerStatusChange` | **(管理者専用)** 接続している`rippled`のピアサーバに関する情報(特にコンセンサスプロセスに関する情報)。 | +| `transactions` | `transaction` | 閉鎖済みレジャーにトランザクションが追加されるたびにメッセージを送信します。 | +| `transactions_proposed` | `transaction` | 閉鎖済みレジャーにトランザクションが追加される場合や、検証済みレジャーにまだ追加されておらず、今後も追加される見込みのない一部のトランザクションが検証済みレジャーに追加される場合に、メッセージを送信します。提案されたすべてのトランザクションが検証前に表示されるわけではありません。 {% admonition type="info" name="注記" %}[成功しなかったトランザクション](../../../protocol/transactions/transaction-results/index.md) 成功しなかったトランザクションも、スパム対策取引手数料を取るため、検証済みレジャーに含まれます。{% /admonition %} | +| `server` | `serverStatus` | `rippled`サーバのステータス(ネットワーク接続など)が変更されるたびにメッセージを送信します。 | +| `validations` | `validationReceived` | サーバがバリデータを信頼しているか否かにかかわらず、サーバが検証メッセージを受信するたびに、メッセージを送信します。(個々の`rippled`は、サーバが少なくとも定数の信頼できるバリデータから検証メッセージを受信した時点で、レジャーが検証済みであると宣言します。) | {% admonition type="info" name="注記" %}以下のストリームは Clioおよび[レポートモード][]の`rippled`サーバからは利用できません: `server`、`peer_status`、`consensus`。これらのストリームを要求すると、どちらも`reportingUnsupported`エラーを返します。 {% badge href="https://github.com/XRPLF/rippled/releases/tag/1.8.1" %}更新: rippled 1.8.1{% /badge %} {% badge href="https://github.com/XRPLF/clio/releases/tag/2.0.0" %}新規: Clio v2.0{% /badge %}{% /admonition %} +### Bookオブジェクト + `books`配列が指定されている場合、この配列の各要素は、以下のフィールドを持つオブジェクトです。 -| `Field` | 型 | 説明 | -| :----------- | :----------- | ---- | -| `taker_gets` | オブジェクト | オファーを受諾するアカウントが受け取る通貨を[金額なしの通貨オブジェクト](../../../protocol/data-types/currency-formats.md#金額なしでの通貨の指定)として指定します。 | -| `taker_pays` | オブジェクト | オファーを受諾するアカウントが支払う通貨を[金額なしの通貨オブジェクト](../../../protocol/data-types/currency-formats.md#金額なしでの通貨の指定)として指定します。 | -| `taker` | 文字列 | オファーを表示するパースペクティブとして使用する一意のアカウントアドレス(XRP Ledgerの[base58][]フォーマット)。(これはオファーの資金提供ステータスと手数料に影響します。) | -| `snapshot` | ブール値 | (省略可)`true`の場合は、更新の送信前にサブスクライブした時点でオーダーブックの現在の状態を一度返します。デフォルトは`false` | -| `both` | ブール値 | (省略可)`true`の場合は、オーダーブックの両サイドを返します。デフォルトは`false` | +| フィールド | 型 | 必須? | 説明 | +| :----------- | :-------------------- | :----- | ---- | +| `taker_gets` | オブジェクト | はい | オファーを受諾するアカウントが受け取る通貨を[金額なしの通貨オブジェクト](../../../protocol/data-types/currency-formats.md#金額なしでの通貨の指定)として指定します。 | +| `taker_pays` | オブジェクト | はい | オファーを受諾するアカウントが支払う通貨を[金額なしの通貨オブジェクト](../../../protocol/data-types/currency-formats.md#金額なしでの通貨の指定)として指定します。 | +| `both` | ブール値 | いいえ | `true`の場合は、オーダーブックの両サイドを返します。デフォルトは`false` | +| `domain` | 文字列 - [ハッシュ][] | いいえ | 許可型DEXのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です) | +| `snapshot` | ブール値 | いいえ | `true`の場合は、更新の送信前にサブスクライブした時点でオーダーブックの現在の状態を一度返します。デフォルトは`false` | +| `taker` | 文字列 | いいえ | オファーを表示するパースペクティブとして使用する一意のアカウントアドレス(XRP Ledgerの[base58][]フォーマット)。(これはオファーの資金提供ステータスと手数料に影響します。) | + ## レスポンスのフォーマット @@ -167,7 +172,7 @@ labels: レジャーストリームメッセージのフィールドは次のとおりです。 -| `Field` | 型 | 説明 | +| フィールド | 型 | 説明 | | :------------------ | :------------------------------ | ---- | | `type` | 文字列 | `ledgerClosed`は、このメッセージがレジャーストリームからのものであることを示します。 | | `fee_base` | 数値 | このレジャーバージョン時点の[Referenceトランザクションコスト](../../../../concepts/transactions/transaction-cost.md#referenceトランザクションコスト)([XRPのdrop数][])。このレジャーバージョンに[SetFee疑似トランザクション](../../../protocol/transactions/pseudo-transaction-types/setfee.md)が含まれている場合は、次のレジャーバージョンから新しいトランザクションコストが適用されます。 | @@ -212,7 +217,7 @@ labels: 検証ストリームメッセージのフィールドは次のとおりです。 -| `Field` | 型 | 説明 | +| フィールド | 型 | 説明 | | :---------------------- | :------------ | ---- | | `type` | 文字列 | 値`validationReceived`は、このメッセージが検証ストリームからであることを示します。 | | `amendments` | 文字列の配列 | (省略される場合があります)このサーバがプロトコルへの追加を求める[Amendment](../../../../concepts/networks-and-servers/amendments.md)。 | @@ -333,7 +338,7 @@ labels: {% tab label="API v2" %} -| `Field` | 型 | 説明 | +| フィールド | 型 | 説明 | |:------------------------|:--------------------------|:-----| | `close_time_iso` | 文字列 | レジャーの終了時刻をISO 8601の時刻形式で表します。 | | `type` | 文字列 | `transaction`は、複数の可能なストリームからのトランザクションの通知であることを示します。 | @@ -352,7 +357,7 @@ labels: {% tab label="API v1" %} -| `Field` | 型 | 説明 | +| フィールド | 型 | 説明 | | :---------------------- | :------------------------------ | ---- | | `type` | 文字列 | `transaction`は、トランザクションの通知であることを示します。この通知はさまざまなストリームから送信される可能性があります。 | | `engine_result` | 文字列 | 文字列の[トランザクション結果コード](../../../protocol/transactions/transaction-results/index.md) | @@ -389,7 +394,7 @@ labels: ピアステータスストリームメッセージは、`rippled`ピアサーバのステータスが変化したイベントを表します。これらのメッセージは、次のフィールドを持つJSONオブジェクトです。 -| `Field` | 値 | 説明 | +| フィールド | 値 | 説明 | | :----------------- | :----- | ---- | | `type` | 文字列 | `peerStatusChange`は、ピアステータスストリームからのメッセージであることを示します。 | | `action` | 文字列 | このメッセージが送信される原因となったイベントのタイプ。有効な値については、[ピアステータスイベント](#ピアステータスイベント)をご覧ください。 | @@ -561,7 +566,7 @@ labels: オーダーブックストリームメッセージの形式は、[トランザクションストリームメッセージ](#トランザクションストリーム)と同様ですが、`OfferCreate`トランザクションに以下のフィールドも含まれている点が異なります。 -| `Field` | 値 | 説明 | +| フィールド | 値 | 説明 | | :------------------------ | :----- | ---- | | `transaction.owner_funds` | 文字列 | このOfferCreateトランザクションを送信する`Account`が、このトランザクション実行後に有する`TakerGets`通貨の金額。この通貨額が[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているかどうかはチェックされません。
[API v2][]では`tx_json.owner_funds`に変更されました。 | @@ -695,7 +700,7 @@ labels: [Book Changes]ストリームメッセージのフィールドは以下のとおりです: -| Field | 値 | 説明 | +| フィールド | 値 | 説明 | |:---------------|:-------------------------|:-----| | `type` | 文字列 | 値`bookChanges`は、これがBook Changesストリームからのものであることを示します。 | | `ledger_index` | [レジャーインデックス][] | これらの変更を含むレジャーのレジャーインデックス。 | @@ -717,7 +722,7 @@ labels: コンセンサスストリームメッセージのフィールドは次のとおりです。 -| `Field` | 型 | 説明 | +| フィールド | 型 | 説明 | | :---------- | :----- | ---- | | `type` | 文字列 | `consensusPhase`は、このメッセージがコンセンサスストリームからのものであることを示します。 | | `consensus` | 文字列 | サーバで実行されている新しいコンセンサスフェーズ。値には、`open`、`establish`、`accepted`などがあります。 | diff --git a/@l10n/ja/docs/references/protocol/data-types/currency-formats.md b/@l10n/ja/docs/references/protocol/data-types/currency-formats.md index 0a3b5dc240..dd05545839 100644 --- a/@l10n/ja/docs/references/protocol/data-types/currency-formats.md +++ b/@l10n/ja/docs/references/protocol/data-types/currency-formats.md @@ -73,7 +73,7 @@ XRPの金額は負になることはありません。 } ``` -#### 金額なしでの通貨の指定 +### 金額なしでの通貨の指定 場合によっては、[分散型取引所](../../../concepts/tokens/decentralized-exchange/index.md)でオーダーブックを指定するときなど、特定の金額なしで資産(XRPやトークン)を定義する必要があります。 diff --git a/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/directorynode.md b/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/directorynode.md index bddb2f991b..2568ff2410 100644 --- a/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/directorynode.md +++ b/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/directorynode.md @@ -6,7 +6,7 @@ labels: - 分散型取引所 --- # DirectoryNode -[[ソース]](https://github.com/XRPLF/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L44 "Source") +[[ソース]](https://github.com/XRPLF/rippled/blob/7e24adbdd0b61fb50967c4c6d4b27cc6d81b33f3/include/xrpl/protocol/detail/ledger_entries.macro#L177-L192 "Source") `DirectoryNode`オブジェクトタイプは、レジャーの状態ツリー内の他オブジェクトへのリンクのリストを提供します。概念上の1つの _ディレクトリ_ は、1つ以上の各DirectoryNodeオブジェクトが含まれる二重リンクリストの形式になっています。各DirectoryNodeオブジェクトには、他オブジェクトの[ID](../common-fields.md)が最大32個まで含まれています。1番目のオブジェクトはディレクトリのルートと呼ばれ、ルートオブジェクト以外のオブジェクトはすべて必要に応じて自由に追加または削除できます。 @@ -95,6 +95,7 @@ labels: | 名前 | JSONの型 | [内部の型][] | 必須? | 説明 | |---------------------|-----------|--------------|:-------|-------------| +| `DomainID` | 文字列 | Hash256 | いいえ | (オファーディレクトリのみ) 許可型DEXのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です。) | | `ExchangeRate` | 数値 | UInt64 | いいえ | (オファーディレクトリのみ)**廃止予定**。使用しないでください。 | | `Flags` | 数値 | UInt32 | はい | このディレクトリに対して有効になっているブール値フラグのビットマップ。現在、プロトコルではDirectoryNodeオブジェクトのフラグは定義されていません。 | | `Indexes` | 配列 | Vector256 | はい | このディレクトリの内容: 他のオブジェクトのIDの配列。 | @@ -135,6 +136,7 @@ DirectoryNodeのIDを作成するときには、DirectoryNodeが以下のどの * 所有者ディレクトリまたはNFTオファーディレクトリの1番目のページ(ルートとも呼ばれます) * オファーディレクトリの1番目のページ +* オファーディレクトリの最初のページ。オープンDEXと認可型DEX用のバージョンが含まれます。 _([PermissionedDEX amendment][]が必要です。 {% not-enabled /%})_ * いずれかのディレクトリの以降のページ **所有者ディレクトリまたはNFTオファーディレクトリの1番目のページ**のIDは、以下の値がこの順序で連結されている[SHA-512Half][]です。 @@ -149,6 +151,7 @@ DirectoryNodeのIDを作成するときには、DirectoryNodeが以下のどの * `TakerGetsCurrency`の160ビットの通貨コード * `TakerPaysIssuer`のAccountID * `TakerGetsIssuer`のAccountID +* このオーダーブックが属する許可型DEXの許可型ドメインの`DomainID`。許可型DEXのオーダーブックの場合。オープンDEXのオーダーブックの場合は省略。 オファーディレクトリのIDの下位64ビットは、そのディレクトリ内のオファーのTakerPaysの額をTakerGetsの額で割った結果を、XRP Ledgerの内部金額フォーマットの64ビット数値で表したものです。 diff --git a/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/offer.md b/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/offer.md index 31c2c7d0df..f92a46423b 100644 --- a/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/offer.md +++ b/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/offer.md @@ -7,9 +7,9 @@ labels: - 分散型取引所 --- # Offer -[[ソース]](https://github.com/XRPLF/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L57 "Source") +[[ソース]](https://github.com/XRPLF/rippled/blob/7e24adbdd0b61fb50967c4c6d4b27cc6d81b33f3/include/xrpl/protocol/detail/ledger_entries.macro#L242-L255 "ソース") -台帳の`Offer`エントリは、XRP Ledgerの[分散型取引所](../../../../concepts/tokens/decentralized-exchange/index.md)で通貨を交換する[オファー](../../../../concepts/tokens/decentralized-exchange/offers.md)を表しています。(金融ではより伝統的に _オーダー_ として知られています)。[OfferCreateトランザクション][]は台帳にある他のOfferを全額約定できない場合、台帳に`Offer`エントリを作成します。 +`Offer`レジャーエントリは、XRP Ledgerの[分散型取引所](../../../../concepts/tokens/decentralized-exchange/index.md)で通貨を交換する[オファー](../../../../concepts/tokens/decentralized-exchange/offers.md)を表しています。(金融ではより伝統的に _オーダー_ として知られています)。[OfferCreateトランザクション][]は他のOfferを全額約定できない場合、Offerエントリを作成します。 オファーがネットワーク上の他の活動によって資金不足になることはありますが、元帳には残ります。トランザクションを処理する際、ネットワークはトランザクションが見つけた資金不足のオファーを自動的に削除します。( _トランザクションのみ_ が台帳の状態を変更できるため、削除が行われないと資金不足のオファーが残ってしまいます。) @@ -40,29 +40,32 @@ labels: [共通フィールド][]に加えて、{% $frontmatter.seo.title %}エントリは以下のフィールドを使用します。 -| 名前 | JSONの型 | [内部の型][] | 必須? | 説明 | -|-------------------|-----------|-----------|------|-------| -| `Account` | 文字列 | AccountID | はい | このオファーを所有するアカウントのアドレス。 | -| `BookDirectory` | 文字列 | UInt256 | はい | このオファーにリンクしている[オファーディレクトリー](directorynode.md)のID。 | -| `BookNode` | 文字列 | UInt64 | はい | Offerディレクトリが複数ページで構成されている場合に、このオブジェクトにリンクしているページを示すヒント。 | -| `Expiration` | 数値 | UInt32 | いいえ | (省略可)このオファーが資金不足とみなされる時刻。詳細は、[時間の指定][]をご覧ください。 | -| `Flags` | 数値 | UInt32 | はい | このオファーに対して有効になっているブール値フラグのビットマップ。 | -| `LedgerEntryType` | 文字列 | UInt16 | はい | 値が`0x006F`(文字列`Offer`にマッピング)の場合は、このオブジェクトが通貨取引オーダーを記述することを示す。 | -| `OwnerNode` | 文字列 | UInt64 | はい | 所有者ディレクトリーが複数ページで構成されている場合に、このオブジェクトにリンクしているページを示すヒント。**注記:** このオファーには、オファーを含む所有者ディレクトリーへの直接リンクは含まれていません。これは、その値を`Account`から取得できるためです。 | -| `PreviousTxnID` | 文字列 | UInt256 | はい | 最後にこのオブジェクトを変更したトランザクションの識別用ハッシュ。 | -| `Sequence` | 数値 | UInt32 | はい | `Offer`オブジェクトを作成した[OfferCreate][]トランザクションの`Sequence`値。`Account`とこのフィールドの組み合わせによってこのオファーが識別されます。 | +| 名前 | JSONの型 | [内部の型][] | 必須? | 説明 | +|---------------------|-----------------------|--------------|-------|-------| +| `Account` | 文字列 | AccountID | はい | このオファーを所有するアカウントのアドレス。 | +| `AdditionalBooks` | 配列 | Array | いいえ| 追加のオファーディレクトリーのリスト。このフィールドは、このオファーが[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)でハイブリッドオファーの場合にのみ存在します。配列には常に1つのエントリが含まれます。([PermissionedDEX amendment][] {% not-enabled /%}が必要です。) | +| `BookDirectory` | 文字列 - [ハッシュ][] | UInt256 | はい | このオファーにリンクしている[オファーディレクトリー](directorynode.md)のID。 | +| `BookNode` | 文字列 | UInt64 | はい | Offerディレクトリが複数ページで構成されている場合に、このオブジェクトにリンクしているページを示すヒント。 | +| `DomainID` | 文字列 - [ハッシュ][] | Hash256 | いいえ | 許可型DEXのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です。) | +| `Expiration` | 数値 | UInt32 | いいえ | (省略可)このオファーが資金不足とみなされる時刻。詳細は、[時間の指定][]をご覧ください。 | +| `Flags` | 数値 | UInt32 | はい | このオファーに対して有効になっているブール値フラグのビットマップ。 | +| `LedgerEntryType` | 文字列 | UInt16 | はい | 値が`0x006F`(文字列`Offer`にマッピング)の場合は、このオブジェクトが通貨取引オーダーを記述することを示す。 | +| `OwnerNode` | 文字列 | UInt64 | はい | 所有者ディレクトリーが複数ページで構成されている場合に、このオブジェクトにリンクしているページを示すヒント。**注記:** このオファーには、オファーを含む所有者ディレクトリーへの直接リンクは含まれていません。これは、その値を`Account`から取得できるためです。 | +| `PreviousTxnID` | 文字列 - [ハッシュ][] | UInt256 | はい | 最後にこのオブジェクトを変更したトランザクションの識別用ハッシュ。 | +| `Sequence` | 数値 | UInt32 | はい | `Offer`オブジェクトを作成した[OfferCreate][]トランザクションの`Sequence`値。`Account`とこのフィールドの組み合わせによってこのオファーが識別されます。 | | `PreviousTxnLgrSeq` | 数値 | UInt32 | はい | 最後にこのオブジェクトを変更したトランザクションが記録された[レジャーインデックス][]。 | -| `TakerPays` | 文字列またはオブジェクト | Amount | はい | オファー作成者がリクエストする残額と通貨の種類。 | -| `TakerGets` | 文字列またはオブジェクト | Amount | はい | オファー作成者が提供する残額と通貨の種類。 | +| `TakerPays` | [通貨額][] | Amount | はい | オファー作成者がリクエストする残額と通貨の種類。 | +| `TakerGets` | [通貨額][] | Amount | はい | オファー作成者が提供する残額と通貨の種類。 | ## Offerのフラグ `Offer`エントリは以下のフラグを`Flags`フィールドに指定することができます。 -| フラグ名 | 16進数値 | 10進数値 | 対応する[OfferCreateフラグ](../../transactions/types/offercreate.md#offercreateフラグ) | 説明 | -|-----------|-----------|---------------|-------------|------------------------| -| `lsfPassive` | `0x00010000` | 65536 | `tfPassive` | オブジェクトはパッシブオファーとして発注されています。レジャー内のオブジェクトには影響しません。 | -| `lsfSell` | `0x00020000` | 131072 | `tfSell` | オブジェクトは売却オファーとして発注されています。これは台帳にあるオブジェクトには何の影響もありません (`tfSell`は指定したレートよりも良いレートが存在する場合にのみ意味を持ち、台帳にこのフラグを持ったオブジェクトが入ることはありません。)。 | +| フラグ名 | 16進数値 | 10進数値 | 対応する[OfferCreateフラグ](../../transactions/types/offercreate.md#offercreateフラグ) | 説明 | +|--------------|--------------|----------|-------------|------------------------| +| `lsfPassive` | `0x00010000` | 65536 | `tfPassive` | オブジェクトはパッシブオファーとして発注されています。レジャー内のオブジェクトには影響しません。 | +| `lsfSell` | `0x00020000` | 131072 | `tfSell` | オブジェクトは売却オファーとして発注されています。これは台帳にあるオブジェクトには何の影響もありません (`tfSell`は指定したレートよりも良いレートが存在する場合にのみ意味を持ち、台帳にこのフラグを持ったオブジェクトが入ることはありません。)。 | +| `lsfHybrid` | `0x00040000` | 262144 | `tfHybrid` | ハイブリッドオファーとして作成されています。これは、[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)と公開DEXの両方にリストされていることを意味します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です。) | ## {% $frontmatter.seo.title %}の準備金 @@ -78,6 +81,6 @@ labels: * オファーを行うアカウントのAccountID * オファーを作成した[OfferCreateトランザクション][]のシーケンス番号 - OfferCreateトランザクションが[Ticket](../../../../concepts/accounts/tickets.md)を使用した場合、代わりに`TicketSequence`値を使用します。 + OfferCreateトランザクションが[チケット](../../../../concepts/accounts/tickets.md)を使用した場合、代わりに`TicketSequence`値を使用します。 {% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} diff --git a/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/permissioneddomain.md b/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/permissioneddomain.md index 9f4b7b1495..a3929fa08c 100644 --- a/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/permissioneddomain.md +++ b/@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/permissioneddomain.md @@ -100,4 +100,4 @@ _([PermissionedDomains amendment][]が必要です {% not-enabled /%})_ 3. 作成した{% code-page-name /%}トランザクションのシーケンス番号 -{% raw-partial file="/docs/_snippets/common-links.md" /%} +{% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} diff --git a/@l10n/ja/docs/references/protocol/transactions/types/ammbid.md b/@l10n/ja/docs/references/protocol/transactions/types/ammbid.md index e261814356..a289deddec 100644 --- a/@l10n/ja/docs/references/protocol/transactions/types/ammbid.md +++ b/@l10n/ja/docs/references/protocol/transactions/types/ammbid.md @@ -55,7 +55,7 @@ AMMのLPトークンを使って落札すると、落札に利用したLPトー {% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%} | フィールド | JSONの型 | [内部の型][] | 必須? | 説明 | -|:---------------|:-----------|:- ----------|:----- |:------------| +|:---------------|:-----------|:------------|:------|:------------| | `Asset` | オブジェクト | STIssue | はい | AMMのプールにある資産の一つを定義します。JSONでは、`currency`と`issuer`フィールドを持つオブジェクトになります(XRPの場合は`issuer`を省略します)。 | | `Asset2` | オブジェクト | STIssue | はい | AMMのプールにあるもう一つのアセットの定義です。JSONでは、`currency`と`issuer`フィールドを持つオブジェクトになります(XRPの場合は`issuer`を省略します)。 | | `BidMin` | [通貨額][] | Amount | いいえ | スロットに支払う最小の金額。この値を高く設定すると、他の人から競り落とされにくくなります。省略された場合は、落札に必要な最低額を支払います。 | diff --git a/@l10n/ja/docs/references/protocol/transactions/types/ammclawback.md b/@l10n/ja/docs/references/protocol/transactions/types/ammclawback.md new file mode 100644 index 0000000000..c7ab1d26b6 --- /dev/null +++ b/@l10n/ja/docs/references/protocol/transactions/types/ammclawback.md @@ -0,0 +1,81 @@ +--- +seo: + description: 自動マーケットメーカープールに発行済みトークンを預け入れた保有者から、トークンを回収する。 +labels: + - AMM + - Tokens +--- +# AMMClawback + +[[ソース]](https://github.com/XRPLF/rippled/blob/master/src/xrpld/app/tx/detail/AMMClawback.cpp "ソース") + +発行したトークンをAMMプールに預け入れた保有者からトークンを回収します。 + +Clawbackはデフォルトで無効です。Clawbackを使用するには、[AccountSetトランザクション][]を送信して、**Allow Trust Line Clawback**設定を有効にする必要があります。すでにトークンが発行済みである発行者はClawbackを有効にできません。**Allow Trust Line Clawback**を有効にするには、トラストライン、オファー、エスクロー、ペイメントチャネル、チェック、署名者リストを設定する前に、所有者ディレクトリを完全に空にする必要があります。Clawbackを有効にした後は、元に戻すことはできません。つまり発行者アカウントは、トラストラインの発行済みトークンを回収できる権利を永続的に得ます。 + + +_([AMMClawback amendment][]により追加されました。)_ + + +## {% $frontmatter.seo.title %} JSONの例 + +```json +{ + "TransactionType": "AMMClawback", + "Account": "rPdYxU9dNkbzC5Y2h4jLbVJ3rMRrk7WVRL", + "Holder": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "Asset": { + "currency" : "FOO", + "issuer" : "rPdYxU9dNkbzC5Y2h4jLbVJ3rMRrk7WVRL" + }, + "Asset2" : { + "currency" : "BAR", + "issuer" : "rHtptZx1yHf6Yv43s1RWffM3XnEYv3XhRg" + }, + "Amount": { + "currency" : "FOO", + "issuer" : "rPdYxU9dNkbzC5Y2h4jLbVJ3rMRrk7WVRL", + "value" : "1000" + } +} +``` + + +{% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%} + + +| フィールド | JSONの型 | [内部の型][] | 必須? | 説明 | +|:-----------|:----------------------|:-------------|:-------|:------------------| +| `Account` | 文字列 - [アドレス][] | AccountID | はい | 回収する資産の発行者。このトランザクションは、発行者のみが送信できます。 | +| `Asset` | オブジェクト | Issue | はい | AMMプールから回収したい資産を指定します。資産はXRP、トークン、またはMPT([金額なしの指定][]を参照)です。`issuer`フィールドは`Account`と一致していなければなりません。 | +| `Asset2` | オブジェクト | Issue | はい | AMMのプール内のもう一方の資産を指定します。資産はXRP、トークン、またはMPT([金額なしの指定][]を参照)です。 | +| `Amount` | [通貨額][] | Amount | いいえ | AMMアカウントから回収する最大額を指定します。`currency`と`issuer`サブフィールドは`Asset`サブフィールドと一致していなければなりません。このフィールドが指定されていない場合、または`value`サブフィールドがAMMの保有者の利用可能なトークンを超えている場合、保有者のすべてのトークンが回収されます。 | +| `Holder` | 文字列 - [アドレス][] | AccountID | はい | 回収する資産を保有しているアカウント。 | + + +## AMMClawbackのフラグ + +| フラグ名 | Hex値 | 10進数値 | 説明 | +|-------------------|--------------|----------|-------------| +| `tfClawTwoAssets` | `0x00000001` | 1 | `Asset`の指定額を回収し、AMMプールの資産比率に基づいて`Asset2`の対応する額を回収します。両方の資産は`Account`フィールドの発行者によって発行されなければなりません。このフラグが有効でない場合、発行者は`Asset`の指定された額を回収しますが、`Asset2`の対応する比率は`Holder`に返されます。 | + + +## エラーのケース + +すべてのトランザクションで発生する可能性のあるエラーに加えて、`AMMClawback`トランザクションは以下の[トランザクション結果コード](../transaction-results/index.md)をもたらすことがあります。 + +| エラーコード | 説明 | +|:-------------------|:------------| +| `tecNO_PERMISSION` | `lsfAllowTrustlineClawback` フラグが有効になっていない状態で AMM からトークンを回収しようとした場合、または AMM で両方の資産を発行していない状態で `tfClawTwoAssets` フラグが有効になっている場合に発生します。また、`Asset` の発行者が `Account` と一致しない場合にも発生します。 | +| `tecAMM_BALANCE` | `Holder`がAMMプールのLPトークンを保有していない場合に発生します。 | +| `temDISABLED` | [AMMClawback amendment][]が有効になっていない場合に発生します。 | +| `temBAD_AMOUNT` | `AMMClawback`トランザクションの`Amount`フィールドが0以下の場合、または`currency`と`issuer`サブフィールドが`Amount`と`Asset`の間で一致しない場合に発生します。 | +| `temINVALID_FLAG` | `tfClawTwoAssets`以外のフラグを有効にしようとした場合に発生します。 | +| `temMALFORMED` | `issuer`サブフィールドが`Asset`と`Account`の間で一致しない場合、`Account`が`Holder`と同じ場合、または`Asset`がXRPの場合に発生します。 | +| `terNO_AMM` | `Asset`と`Asset2`で指定されたAMMプールが存在しない場合に発生します。 | + +## 関連項目 + +- [AMMエントリ][] + +{% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} diff --git a/@l10n/ja/docs/references/protocol/transactions/types/ammcreate.md b/@l10n/ja/docs/references/protocol/transactions/types/ammcreate.md index 6cb1ef5cfc..588bc35e6a 100644 --- a/@l10n/ja/docs/references/protocol/transactions/types/ammcreate.md +++ b/@l10n/ja/docs/references/protocol/transactions/types/ammcreate.md @@ -39,12 +39,12 @@ AMMを表す[AMMエントリ][]と[特殊なAccountRootエントリ](../../ledge {% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%} | フィールド | JSONの型 | [内部の型][] | 必須? | 説明 | -|:-------------|:---- -----|:-----------|:------|:------------| +|:-------------|:----------|:-----------|:------|:------------| | `Amount` | [通貨額][] | Amount | はい | このAMMの最初の資金となる2つの資産のうち、1つ目の資産です。これは正数である必要があります。 | | `Amount2` | [通貨額][] | Amount | はい | このAMMの最初の資金となる2つの資産のうち、2つ目の資産です。これは正数である必要があります。 | | `TradingFee` | 数値 | UInt16 | はい | このAMMインスタンスに対する取引に課される手数料を1/100,000単位で指定します(値1は0.001%に相当)。最大値は`1000`で、1%の手数料を意味します。最小値は `0`です。 | -`Amount`と`Amount2`の一方または両方は[トークン](../../../../concepts/tokens/index.md)であり、最大でどちらか一方を[XRP](../../../../introduction/what-is-xrp.md)にすることが可能です。通貨コードと発行者が同じものは使用できません。AMMのLPトークンは、別のAMMの資産の1つとして使用することができます。トークンの発行者は[Default Ripple](../../../../concepts/tokens/fungible-tokens/rippling.md#defaultrippleフラグ)を有効にしていなければなりません。[Clawback Amendment][] が有効になっている場合、それらの発行者はAllow Clawbackフラグを有効にしていてはいけません。AMMのLPトークンは、別のAMMの資産の一つとして使用することはできません。 +`Amount`と`Amount2`の一方または両方は[トークン](../../../../concepts/tokens/index.md)であり、最大でどちらか一方を[XRP](../../../../introduction/what-is-xrp.md)にすることが可能です。通貨コードと発行者が同じものは使用できません。AMMのLPトークンは、別のAMMの資産の1つとして使用することができます。トークンの発行者は[Default Ripple](../../../../concepts/tokens/fungible-tokens/rippling.md#defaultrippleフラグ)を有効にしていなければなりません。AMMのLPトークンは、別のAMMの資産の一つとして使用することはできません。 ## 特殊なトランザクションコスト @@ -54,17 +54,19 @@ AMMを表す[AMMエントリ][]と[特殊なAccountRootエントリ](../../ledge すべてのトランザクションで発生する可能性のあるエラーに加えて、{% $frontmatter.seo.title %}トランザクションでは、次の[トランザクション結果コード](../transaction-results/index.md)が発生する可能性があります。 -| エラーコード | 説明 | +| エラーコード | 説明 | |:--------------------|:---------------------------------------------| -| `temDISABLED` | このネットワークでは、AMM機能 | -| `temINVALID_FLAG` | トランザクションに無効な`Flags`値が指定されています。現在、このトランザクションタイプに定義されたフラグはないので、[グローバルフラグ](../common-fields.md#グローバルフラグ)のみが許可されます。 | -| `temBAD_AMM_TOKENS` | `Amount`と`Amount2`値が正しくありません。例えば、両方とも同じトークンを参照している場合です。 | -| `temBAD_FEE` | `TradingFee`の値が不正です。ゼロまたは正の整数でなければならず、1000を超えることはできません。 | -| `terNO_ACCOUNT` | リクエストで参照されたいずれかのアカウントが存在しません。| -| `tecNO_AUTH` | 送信者は資産(`Amount`または`Amount2`)のいずれかを保有する権限がありません。 | -| `tecNO_LINE` | 送信者は資産(`Amount`または`Amount2`)のうちいずれか1つに対するトラストラインを保有していません。 | -| `tecFROZEN` | 資産(`Amount`または`Amount2`)の少なくとも1つが現在[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。 | +| `tecAMM_INVALID_TOKENS` | `Amount`または`Amount2`が、このAMMのLPトークンと同じ通貨コードを使用しています。(これが起こることは稀です。) | +| `tecDUPLICATE` | この通貨ペアを扱っているAMMが既に存在しています。 | +| `tecFROZEN` | 資産(`Amount`または`Amount2`)の少なくとも1つが現在[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。 | +| `tecINSUF_RESERVE_LINE` | 送信者は、このトランザクションを処理するための[準備金要件](../../../../concepts/accounts/reserves.md)を満たしていません。おそらく、LPトークンを保持するための新しいトラストラインが必要で、新しいトラストラインの所有者準備金を満たす十分なXRPを持っていないためです。 | +| `tecNO_AUTH` | 送信者は資産(`Amount`または`Amount2`)のいずれかを保有する権限がありません。 | +| `tecNO_LINE` | 送信者は資産(`Amount`または`Amount2`)のうちいずれか1つに対するトラストラインを保有していません。 | +| `tecNO_PERMISSION` | 少なくとも1つの入金資産はAMMで使用できません。 | | `tecUNFUNDED_AMM` | 送信者は`Amount`と`Amount2`で指定された金額をAMMに入金するための十分な資金を保有していません。 | -| `tecAMM_EXISTS` | この通貨ペアを扱っているAMMが既に存在しています。 | +| `terNO_RIPPLE` | 少なくとも1つの資産の発行者が[Default Rippleフラグ](../../../../concepts/tokens/fungible-tokens/rippling.md#defaultrippleフラグ)を有効にしていません。 | +| `temAMM_BAD_TOKENS` | `Amount`と`Amount2`値が正しくありません。例えば、両方とも同じトークンを参照している場合です。 | +| `temBAD_FEE` | `TradingFee`の値が不正です。ゼロまたは正の整数でなければならず、1000を超えることはできません。 | +| `temDISABLED` | このネットワークでは、AMM機能が無効になっています。 | {% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} diff --git a/@l10n/ja/docs/references/protocol/transactions/types/ammdeposit.md b/@l10n/ja/docs/references/protocol/transactions/types/ammdeposit.md index d8a973d567..db70878999 100644 --- a/@l10n/ja/docs/references/protocol/transactions/types/ammdeposit.md +++ b/@l10n/ja/docs/references/protocol/transactions/types/ammdeposit.md @@ -137,7 +137,7 @@ AMMDepositトランザクションは、以下のような[`Flags`フィール | `tecAMM_EMPTY` | 現在、AMM は資産を保有していないため、通常の入金はできません。代わりに、空のAMMの場合の特殊な入金を行う必要があります。 | | `tecAMM_NOT_EMPTY` | トランザクションで`tfTwoAssetIfEmpty`が指定されましたが、AMMは空ではありませんでした。 | | `tecAMM_FAILED` | 預け入れの条件が成立しませんでした。例えば、`EPrice`フィールドに指定された実効価格が低すぎる場合など。 | -| `tecFROZEN` | トランザクションは[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているトークンを預けようとしました。 | +| `tecFROZEN` | トランザクションは[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているトークンを預けようとした、またはプール内の資産の少なくとも1つがフリーズされています。 | | `tecINSUF_RESERVE_LINE` | このトランザクションの送信者は、この処理による[準備金要件](../../../../concepts/accounts/reserves.md)の増加の対象であり、LPトークンを保持するための新しいトラストラインが必要で、そのための追加の所有者準備金分のXRPを保有していないためと思われます。 | | `tecUNFUNDED_AMM` | 送信者の残高が、指定された預け入れを行うのに十分な量ではありません。 | | `temBAD_AMM_TOKENS` | トランザクションでLPトークンを指定しましたが、`issuer`がAMMに紐づくAccountアドレスではない、または`currency`がこのAMMのLPトークンの通貨コードではない、またはトランザクションでこのAMMのLPトークンをAssetフィールドのいずれかに指定しました。 | diff --git a/@l10n/ja/docs/references/protocol/transactions/types/batch.md b/@l10n/ja/docs/references/protocol/transactions/types/batch.md index 678956260e..320967f0aa 100644 --- a/@l10n/ja/docs/references/protocol/transactions/types/batch.md +++ b/@l10n/ja/docs/references/protocol/transactions/types/batch.md @@ -170,4 +170,4 @@ status: not_enabled | `temINVALID_INNER_BATCH` | 内部トランザクションの形式が不正です。 | | `temSEQ_AND_TICKET` | トランザクションに`TicketSequence`フィールドと、0以外の`Sequence`フィールドの両方が含まれています。両方を同時に指定することはできませんが、いずれか一方は必須です。 | -{% raw-partial file="/docs/_snippets/common-links.md" /%} +{% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} diff --git a/@l10n/ja/docs/references/protocol/transactions/types/offercreate.md b/@l10n/ja/docs/references/protocol/transactions/types/offercreate.md index 2701fef680..f59b8c24c1 100644 --- a/@l10n/ja/docs/references/protocol/transactions/types/offercreate.md +++ b/@l10n/ja/docs/references/protocol/transactions/types/offercreate.md @@ -34,43 +34,46 @@ OfferCreateトランザクションは[分散型取引所](../../../../concepts/ {% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%} -| フィールド | JSONの型 | [内部の型][] | 説明 | -|:-----------------|:----------|:------------|:-----------| -| [Expiration](../../../../concepts/tokens/decentralized-exchange/offers.md#オファーの有効期限) | 数字 | UInt32 | _(省略可)_ オファーがアクティブでなくなるまでの時間([Rippleエポック以降の経過秒数][])。 | -| `OfferSequence` | 数字 | UInt32 | _(省略可)_ 最初に削除されるオファー([OfferCancel][]と同様に指定されます)。 | -| `TakerGets` | [通貨額][] | Amount | オファーの作成者によって作成される金額および通貨の種類。 | -| `TakerPays` | [通貨額][] | Amount | オファーの作成者によってリクエストされる金額および通貨の種類。 | +| フィールド | JSONの型 | [内部の型][] | 必須? | 説明 | +|:-----------------|:----------------------|:-------------|:---------|:-----------| +| `DomainID` | 文字列 - [ハッシュ][] | Hash256 | いいえ | 許可型DEXのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です。) | +| [`Expiration`](../../../../concepts/tokens/decentralized-exchange/offers.md#オファーの有効期限) | 整数 | UInt32 | いいえ | オファーがアクティブでなくなるまでの時間([Rippleエポック以降の経過秒数][])。 | +| `OfferSequence` | 整数 | UInt32 | いいえ | 最初に削除されるオファー([OfferCancel][]と同様に指定されます)。 | +| `TakerGets` | [通貨額][] | Amount | はい | オファーの作成者によって作成される金額および通貨の種類。 | +| `TakerPays` | [通貨額][] | Amount | はい | オファーの作成者によってリクエストされる金額および通貨の種類。 | ## OfferCreateフラグ OfferCreate型のトランザクションについては、[`Flags`フィールド](../common-fields.md#flagsフィールド)で以下の値が追加でサポートされます。 -| フラグ名 | 16進数 | 10進数 | 説明 | +| フラグ名 | 16進数 | 10進数 | 説明 | |:----------------------|:-------------|:--------------|:-------------------| -| `tfPassive` | `0x00010000` | 65536 | 有効な場合、オファーはオファーが完全に約定するオファーを消費せず、代わりにレジャーのOfferオブジェクトになります。それはまだクロスしたオファーを消費します。 | -| `tfImmediateOrCancel` | `0x00020000` | 131072 | オファーを[IOC注文](http://en.wikipedia.org/wiki/Immediate_or_cancel)として扱います。有効な場合、オファーはレジャーオブジェクトにはなりません。レジャー内の既存のオファーと約定させようとするだけです。即時にオファーがどのオファーとも約定しない場合、どの通貨とも取引せずに「正常に」実行します。この場合、トランザクションは`tesSUCCESS`の[結果コード](../transaction-results/index.md)を返しますが、レジャー内には、[Offerオブジェクト](../../ledger-data/ledger-entry-types/offer.md)を作成しません。 | -| `tfFillOrKill` | `0x00040000` | 262144 | オファーを[FOK注文](http://en.wikipedia.org/wiki/Fill_or_kill)として扱います。レジャー内の既存のオファーのみを約定しようとします。またこれは、全`TakerPays`の数量が取得できる場合に限られます。[fix1578 amendment][]が有効な場合でオファーを配置した時に実行できない場合、トランザクションは`tecKILLED`の[結果コード](../transaction-results/index.md)を返します。そうでない場合は、トランザクションは、どの通貨とも取り引きせずにキャンセルされた場合でも`tesSUCCESS`の結果コードを返します。 | -| `tfSell` | `0x00080000` | 524288 | 取引所で`TakerPays`Amountよりも多く取得することになっても、`TakerGets` Amountを交換します。 | +| `tfPassive` | `0x00010000` | 65536 | このオファーと完全に一致するオファーを約定しません。これにより、特定の値で交換レートを固定するオファーを台帳に設定できます。 | +| `tfImmediateOrCancel` | `0x00020000` | 131072 | オファーを[即時またはキャンセル注文](http://en.wikipedia.org/wiki/Immediate_or_cancel)として扱い、[Offerエントリ][]をオーダーブックに配置しません。トランザクションは、処理時に既存のオファーを約定し、可能な限り多くの取引を行います。 | +| `tfFillOrKill` | `0x00040000` | 262144 | オファーを[即時またはキャンセル注文](http://en.wikipedia.org/wiki/Fill_or_kill)として扱い、[Offerエントリ][]をオーダーブックに配置しません。実行時に完全に約定できない場合、オファーをキャンセルします。デフォルトでは、所有者は完全な`TakerPays`の金額を受け取る必要があります。`tfSell`フラグが有効な場合、所有者は代わりに完全な`TakerGets`の金額を約定できる必要があります。 | +| `tfSell` | `0x00080000` | 524288 | 取引所で`TakerPays`の金額よりも多く取得することになっても、`TakerGets`の金額を約定します。 | +| `tfHybrid` | `0x00100000` | 1048576 | 許可型DEXとオープンDEXの両方を使用できるハイブリッドオファーにします。このフラグを使用する場合、`DomainID`フィールドを指定する必要があります。 | ## エラーケース -| エラーコード | 説明 | +| エラーコード | 説明 | |:-------------------------|:--------------------------------------------------| -| `temINVALID_FLAG` | トランザクションが`tfImmediateOrCancel`と`tfFillOrKill`両方を指定した場合に発生します。| -| `tecEXPIRED` | トランザクションが指定した`Expiration`の時間が既に経過している場合に発生します。 | -| `tecKILLED` | トランザクションが`tfFillOrKill`を指定し、全額を約定できない場合に発生します。_[ImmediateOfferKilled amendment][]_ が有効な場合、この結果コードは、トランザクションが`tfImmediateOrCancel`を指定して資金が移動せずに実行された場合にも発生します(これまでは、これは`tesSUCCESS`を返していました)。 | -| `temBAD_EXPIRATION` | トランザクションの`Expiration`フィールドの値が無効なフォーマットの場合に発生します。 | -| `temBAD_SEQUENCE` | トランザクションの`OfferSequence`フィールドの値が無効なフォーマットであるか、トランザクション自身の`Sequence`番号より大きい場合に発生します。 | -| `temBAD_OFFER` | OfferがXRPとXRPを交換しようとした場合、またはトークンの無効な量やマイナスの量を交換しようとした場合に発生します。 | -| `temREDUNDANT` | トランザクションが同じトークン(同じ発行者、通貨コード)を指定した場合に発生します。 | -| `temBAD_CURRENCY` | トランザクションで通貨コードが"XRP"のトークンが指定された場合に発生します。 | -| `temBAD_ISSUER` | トランザクションが無効な`issuer`値を持つトークンを指定した場合に発生します。 | -| `tecNO_ISSUER` | トランザクションで、`issuer`の値が台帳の有効化されたアカウントでないトークンを指定した場合に発生します。| -| `tecFROZEN` | [フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されたトラストライン(ローカルおよびグローバルのフリーズを含む)上のトークンを含むトランザクションの場合に発生します。`TakerPays`(購入額)トークンが発行者によってディープフリーズされている場合に発生します。 | -| `tecUNFUNDED_OFFER` | トランザクションの送信者が`TakerGets`の通貨を正の値で保有していない場合に発生する。(例外: `TakerGets`にトランザクションの送信者が発行するトークンを指定した場合、トランザクションは成功します)。 | -| `tecNO_LINE` | 発行者が[Authorized Trust Lines](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)を使用しているトークンを含むトランザクションで、必要なトラストラインが存在しない場合に発生します。 | -| `tecNO_AUTH` | 発行者が[Authorized Trust Lines](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)を使用しているトークンを含むトランザクションで、トークンを受け取るトラストラインが存在するが認証されていない場合に発生します。 | -| `tecINSUF_RESERVE_OFFER` | 所有者が台帳に新しいOfferオブジェクトを追加するための準備要件を満たすのに十分なXRPを持っておらず、トランザクションがどの通貨も変換しなかった場合に発生します。(トランザクションが何らかの金額のトレードに成功した場合、トランザクションは結果コード`tesSUCCESS`で成功しますが、残りは台帳にOfferオブジェクトを作成しません)。 | | `tecDIR_FULL` | トランザクションの送信者が台帳で多くのアイテムを所有している場合、またはオーダーブックに同じ取引レートのオファーがすでに多く含まれている場合に発生します。 | +| `tecEXPIRED` | トランザクションが指定した`Expiration`の時間が既に経過している場合に発生します。 | +| `tecFROZEN` | [フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されたトラストライン(ローカルおよびグローバルのフリーズを含む)上のトークンを含むトランザクションの場合に発生します。`TakerPays`(購入額)トークンが発行者によってディープフリーズされている場合に発生します。 | +| `tecINSUF_RESERVE_OFFER` | 所有者が台帳に新しいOfferオブジェクトを追加するための準備要件を満たすのに十分なXRPを持っておらず、トランザクションがどの通貨も変換しなかった場合に発生します。(トランザクションが何らかの金額のトレードに成功した場合、トランザクションは結果コード`tesSUCCESS`で成功しますが、残りは台帳にOfferオブジェクトを作成しません)。 | +| `tecKILLED` | トランザクションが`tfFillOrKill`を指定し、全額を約定できない場合に発生します。_[ImmediateOfferKilled amendment][]_ が有効な場合、この結果コードは、トランザクションが`tfImmediateOrCancel`を指定して資金が移動せずに実行された場合にも発生します(これまでは、これは`tesSUCCESS`を返していました)。 | +| `tecNO_AUTH` | 発行者が[Authorized Trust Lines](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)を使用しているトークンを含むトランザクションで、トークンを受け取るトラストラインが存在するが認証されていない場合に発生します。 | +| `tecNO_ISSUER` | トランザクションで、`issuer`の値が台帳の有効化されたアカウントでないトークンを指定した場合に発生します。| +| `tecNO_LINE` | 発行者が[Authorized Trust Lines](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)を使用しているトークンを含むトランザクションで、必要なトラストラインが存在しない場合に発生します。 | +| `tecNO_PERMISSION` | トランザクションが`DomainID`を使用しているが、送信者がそのドメインのメンバーではない場合に発生します。([PermissionedDEX amendment][] {% not-enabled /%}) | +| `tecUNFUNDED_OFFER` | トランザクションの送信者が`TakerGets`の通貨を正の値で保有していない場合に発生する。(例外: `TakerGets`にトランザクションの送信者が発行するトークンを指定した場合、トランザクションは成功します)。 | +| `temBAD_CURRENCY` | トランザクションで通貨コードが"XRP"のトークンが指定された場合に発生します。 | +| `temBAD_EXPIRATION` | トランザクションの`Expiration`フィールドの値が無効なフォーマットの場合に発生します。 | +| `temBAD_ISSUER` | トランザクションが無効な`issuer`値を持つトークンを指定した場合に発生します。 | +| `temBAD_OFFER` | OfferがXRPとXRPを交換しようとした場合、またはトークンの無効な量やマイナスの量を交換しようとした場合に発生します。 | +| `temBAD_SEQUENCE` | トランザクションの`OfferSequence`フィールドの値が無効なフォーマットであるか、トランザクション自身の`Sequence`番号より大きい場合に発生します。 | +| `temINVALID_FLAG` | トランザクションが`tfImmediateOrCancel`と`tfFillOrKill`両方を指定した場合に発生します。| +| `temREDUNDANT` | トランザクションが同じトークン(同じ発行者、通貨コード)を指定した場合に発生します。 | {% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} diff --git a/@l10n/ja/docs/references/protocol/transactions/types/payment.md b/@l10n/ja/docs/references/protocol/transactions/types/payment.md index 78443ece27..09e58a94d3 100644 --- a/@l10n/ja/docs/references/protocol/transactions/types/payment.md +++ b/@l10n/ja/docs/references/protocol/transactions/types/payment.md @@ -8,7 +8,7 @@ labels: - トークン --- # Payment -[[ソース]](https://github.com/XRPLF/rippled/blob/5425a90f160711e46b2c1f1c93d68e5941e4bfb6/src/ripple/app/transactors/Payment.cpp "ソース") +[[ソース]](https://github.com/XRPLF/rippled/blob/master/src/xrpld/app/tx/detail/Payment.cpp "ソース") Paymentトランザクションは、アカウント間での価値の移動を表現するものです(通過するパスによっては、非可分的に発生する追加的な価値交換を伴うことがあります)。このトランザクションタイプはいくつかの[支払いの種類](#paymentの種類)に使用することがでできます。 @@ -37,17 +37,18 @@ Paymentは、[アカウントを作成](#アカウントの作成)する唯一 {% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%} -| フィールド | JSONの型 | [内部の型][] | 説明 | -| :--------------- | :------------------ | :----------- | ---- | -| `Amount` | [通貨額][] | Amount | `DeliverMax`のエイリアス | -| `CredentialIDs` | 文字列の配列 | Vector256 | このトランザクションによって作成される入金を承認するための、受取人によって事前承認された資格証明のセット。配列の各メンバは、レジャーのCredentialエントリのレジャーエントリIDでなければなりません。(_[**Credentials** amendment](../../../../../resources/known-amendments.md#credentials)が必要です。_ {% not-enabled /%}) | -| `DeliverMax` | [Currency Amount][] | Amount | [API v2][]: 送金する通貨額。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。[**tfPartialPayment**フラグ](#paymentのフラグ)が設定されている場合は、この金額を _上限_ とする金額を送金します。 {% badge href="https://github.com/XRPLF/rippled/releases/tag/2.0.0" %}新規: rippled 2.0.0{% /badge %} | -| `DeliverMin` | [通貨額][] | Amount | _(省略可)_ このトランザクションで送金する、宛先通貨での最少金額。[Partial Payments](../../../../concepts/payment-types/partial-payments.md)の場合のみ有効になります。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。 | -| `Destination` | 文字列 | AccountID | 支払いを受取るアカウントの一意アドレス。 | -| `DestinationTag` | 数値 | UInt32 | _(省略可)_ 宛先(支払先となる、ホスティングされている受取人)への支払い理由を明確にするための任意のタグ。 | -| `InvoiceID` | 文字列 | UInt256 | _(省略可)_ この支払いの具体的な理由または識別子を表現する任意の256ビットハッシュ。 | -| `Paths` | パス配列の配列 | PathSet | (省略可。自動入力可能)このトランザクションに使用される[支払いパス](../../../../concepts/tokens/fungible-tokens/paths.md)の配列。XRP間のトランザクションでは省略する必要があります。 | -| `SendMax` | [通貨額][] | Amount | _(省略可)_ [送金手数料](../../../../concepts/tokens/transfer-fees.md)、為替レート、[スリッページ](http://en.wikipedia.org/wiki/Slippage_%28finance%29)を含め、このトランザクションに関して支払い元通貨での負担を許容する上限額。[トランザクションの送信コストとしてバーンされるXRP](../../../../concepts/transactions/transaction-cost.md)は含めないでください。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。クロスカレンシー支払いまたは複数のトークンを伴う支払いについては、このフィールドを入力する必要があります。XRP間の支払いでは省略する必要があります。 | +| フィールド | JSONの型 | [内部の型][] | 必須? | 説明 | +| :--------------- | :-------------------- | :----------- | :---------- | :---- | +| `Amount` | [通貨額][] | Amount | APIv1: はい | `DeliverMax`のエイリアス | +| `CredentialIDs` | 文字列の配列 | Vector256 | いいえ | このトランザクションによって作成される入金を承認するための、受取人によって事前承認された資格証明のセット。配列の各メンバは、レジャーのCredentialエントリのレジャーエントリIDでなければなりません。(_[**Credentials** amendment](../../../../../resources/known-amendments.md#credentials)が必要です。_ {% not-enabled /%}) | +| `DeliverMax` | [通貨額][] | Amount | はい | [API v2][]: 送金する通貨額。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。[**tfPartialPayment**フラグ](#paymentのフラグ)が設定されている場合は、この金額を _上限_ とする金額を送金します。 {% badge href="https://github.com/XRPLF/rippled/releases/tag/2.0.0" %}新規: rippled 2.0.0{% /badge %} | +| `DeliverMin` | [通貨額][] | Amount | いいえ | _(省略可)_ このトランザクションで送金する、宛先通貨での最少金額。[Partial Payments](#partial-payments)の場合のみ有効になります。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。 | +| `Destination` | 文字列 - [アドレス][] | AccountID | はい | 支払いを受取るアカウントの一意アドレス。 | +| `DestinationTag` | 数値 | UInt32 | いいえ | 宛先(支払先となる、ホスティングされている受取人)への支払い理由を明確にするための任意のタグ。 | +| `DomainID` | String - [Hash][] | Hash256 | いいえ | 許可されたドメインのレジャーエントリID。クロスカレンシー支払いの場合は、通貨を変換するために、対応する[許可されたDEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用してください。送信者と受取人の両方が、指定されたドメインへのアクセスを許可する有効な資格証明を持っている必要があります。このフィールドは、クロスカレンシー支払いではない場合は効果がありません。(_[**PermissionedDEX** amendment][]が必要です。_ {% not-enabled /%}) | +| `InvoiceID` | 文字列 - 16進文字 | UInt256 | いいえ | この支払いの具体的な理由または識別子を表現する任意の256ビットハッシュ。 | +| `Paths` | パス配列の配列 | PathSet | いいえ | _(自動入力可能)_ このトランザクションに使用される[支払いパス](../../../../concepts/tokens/fungible-tokens/paths.md)の配列。XRP間のトランザクションでは省略する必要があります。 | +| `SendMax` | [通貨額][] | Amount | いいえ | [送金手数料](../../../../concepts/tokens/transfer-fees.md)、為替レート、[スリッページ](http://en.wikipedia.org/wiki/Slippage_%28finance%29)を含め、このトランザクションに関して支払い元通貨での負担を許容する上限額。[トランザクションの送信コストとしてバーンされるXRP](../../../../concepts/transactions/transaction-cost.md)は含めないでください。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。クロスカレンシー支払いまたは複数のトークンを伴う支払いについては、このフィールドを入力する必要があります。XRP間の支払いでは省略する必要があります。 | トランザクションを指定する際は、`Amount`または`DeliverMax`のいずれかを指定する必要がありますが、両方を指定することはできません。JSONでトランザクションを表示する場合、API v1では常に`Amount`を使用し、API v2(以降)では常に`DeliverMax`を使用します。 @@ -62,7 +63,7 @@ Paymentトランザクションタイプは、いくつかの異なるタイプ | [クロスカレンシー(通貨間)決済][] | オブジェクト (非XRP) / 文字列 (XRP) | オブジェクト (非XRP) / 文字列 (XRP) | 通常は必須 | いいえ | 発行された通貨を保有者から別の保有者に送信します。`Amount`と`SendMax`の両方をXRPにすることはできません。これらの支払いは、発行者を介して[リップリング](../../../../concepts/tokens/fungible-tokens/rippling.md)し、トランザクションがパスセットを指定した場合、複数の仲介者を介してより長い[パス](../../../../concepts/tokens/fungible-tokens/paths.md)を取ることができます。トランザクション形式には、発行者が設定した[送金手数料](../../../../concepts/tokens/transfer-fees.md) が適用されます。これらのトランザクションは、異なる通貨間や、場合によっては同じ通貨コードで異なる発行者の通貨間を接続するために、[分散型取引所](../../../../concepts/tokens/decentralized-exchange/index.md)のオファーを利用します。 | | [Partial payment][] | オブジェクト (非XRP) / 文字列 (XRP) | オブジェクト (非XRP) / 文字列 (XRP) | 通常は必須 | いいえ | 任意の通貨を特定の金額まで送ります。[`tfPartialPayment` フラグ](#paymentのフラグ)を使用します。トランザクションが成功するための最小値を指定する `DeliverMin` 値を含めることができます。トランザクションが `DeliverMin` を指定しない場合、_任意の正の値_ を指定して成功させることができる。 | | 通貨変換 | オブジェクト (非XRP) / 文字列 (XRP) | オブジェクト (非XRP) / 文字列 (XRP) | 必須 | はい | [分散型取引所](../../../../concepts/tokens/decentralized-exchange/index.md)のオファーを消費して、ある通貨を別の通貨に交換し、[裁定取引](https://ja.wikipedia.org/wiki/%E8%A3%81%E5%AE%9A%E5%8F%96%E5%BC%95)の機会を得ることが出来ます。`Amount`と `SendMax` の両方を XRP にすることはできません。[Data API](../../../data-api.md) は、このタイプの取引を "payment" ではなく、"exchange" として追跡しています。 | -| MPTの支払い | オブジェクト | 省略 | 省略 | はい | MPTを保有者に送信します。[MPTの支払い](#mpt-payments)をご覧ください。 | +| MPTの支払い | オブジェクト | 省略 | 省略 | いいえ | MPTを保有者に送信します。[MPTの支払い](#mpt-payments)をご覧ください。 | [XRP同士の直接支払い]: ../../../../concepts/payment-types/direct-xrp-payments.md [発行通貨の作成・償還]: ../../../../concepts/tokens/index.md @@ -74,11 +75,11 @@ Paymentトランザクションタイプは、いくつかの異なるタイプ -ほとんどの場合、XRP以外の[通貨額][]の`issuer`フィールドは、金融機関の[発行アドレス](../../../../concepts/accounts/account-types.md)を示しています。ただし、支払いを記述するにあたって、支払いの`Amount`フィールドと`SendMax`フィールドにある`issuer`フィールドについては、特殊なルールが存在します。 +ほとんどの場合、XRP以外の[通貨額][]の`issuer`フィールドは、金融機関の[発行アドレス](../../../../concepts/accounts/account-types.md)を示しています。ただし、支払いを記述するにあたって、支払いの`DeliverMax`(または`Amount`)フィールドと`SendMax`フィールドにある`issuer`フィールドについては、特殊なルールが存在します。 * 2つのアドレス間で、同一の通貨に関して存在する残高は常に1つです。つまり、金額の`issuer`フィールドが実際に表しているのは、イシュアンスを作成したアドレスではなく、イシュアンスを換金する相手方であることがあります。 -* 宛先`Amount`フィールドの`issuer`フィールドが`Destination`アドレスと一致している場合、「宛先が受け入れるあらゆるイシュアー」を意味する特殊なケースとして取り扱われます。これには、他のトラストラインで保持されている宛先によって作成されたイシュアンスに加え、宛先が当該アドレスまでトラストラインを延長しているすべてのアドレスが含まれます。 -* `SendMax`フィールドの`issuer`フィールドが送信元アカウントのアドレスと一致している場合、「送信元が使用できるあらゆるイシュアー」を意味する特殊なケースとして取り扱われます。これには、他のアカウントが送信元アカウントまで延長しているトラストラインで新しいイシュアンスを作成すること、送信元アカウントが保持しているイシュアンスを他のイシュアーから送信することが含まれます。 +* 宛先`DeliverMax`フィールドの`issuer`フィールドが`Destination`アドレスと一致している場合、「宛先が受け入れるあらゆるイシュアー」を意味する特殊なケースとして取り扱われます。これには、他のトラストラインで保持されている宛先によって作成されたイシュアンスに加え、宛先が当該アドレスまでトラストラインを延長しているすべてのアドレスが含まれます。 +* `SendMax`フィールドの`issuer`フィールドが送信元アカウントのアドレスと一致している場合、「送信元が使用できるあらゆるイシュアー」を意味する特殊なケースとして取り扱われます。送信元アカウントが既に保有しているトークンを送信するか、送信元アカウントと信頼関係にある他のユーザーに対して新しいトークンを発行することができます。 ## アカウントの作成 @@ -108,7 +109,7 @@ Payment型のトランザクションについては、[`Flags`フィールド]( | フラグの名前 | 16進値 | 10進値 | 説明 | | :----------------- | :----------- | :----- | ---- | | `tfNoRippleDirect` | `0x00010000` | 65536 | デフォルトパスを使用せず、`Paths`フィールドに含まれているパスのみ使用します。これによりトランザクションは強制的に裁定機会を活用することになります。ほとんどのクライアントでは、これは必要ありません。 | -| `tfPartialPayment` | `0x00020000` | 131072 | `SendMax`を超えていないのに指定された`Amount`を送金できない場合、即座に失敗とするのではなく、受取られる額を減額します。詳細は、[Partial Payments](../../../../concepts/payment-types/partial-payments.md)をご覧ください。 | +| `tfPartialPayment` | `0x00020000` | 131072 | `SendMax`を超えていないのに指定された`Amount`を送金できない場合、即座に失敗とするのではなく、受取られる額を減額します。詳細は、[Partial Payments](#partial-payments)をご覧ください。 | | `tfLimitQuality` | `0x00040000` | 262144 | すべての変換で、入力と出力との比率が`Amount`と`SendMax`との比率と同一であるか、さらに有利となるパスのみを採用します。詳細は、[クオリティの制限](#クオリティの制限)をご覧ください。 | ## Partial Payments @@ -184,6 +185,10 @@ _([Credentials amendment][]が必要です。 {% not-enabled /%})_ 提供された資格証明が、Deposit Authorizationを使用していないアカウントに対して提供されている場合、資格証明は不要ですが、有効性は依然としてチェックされます。 +{% admonition type="info" name="注記" %} +`CredentialIDs`フィールドは、デポジットの承認処理にのみ使用され、[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)での取引には使用されません。ただし、許可型DEXでもアクセス権限を付与するために認証情報が使用されます。許可型DEXで取引を行うには、`DomainID`フィールドを使用して、有効な資格情報を保持しているドメインを指定する必要があります。 +{% /admonition %} + ## 準備金を下回るアカウントに対する特別な送金のケース diff --git a/@l10n/ja/docs/references/protocol/transactions/types/permissioneddomaindelete.md b/@l10n/ja/docs/references/protocol/transactions/types/permissioneddomaindelete.md index d8475365dd..6522c36832 100644 --- a/@l10n/ja/docs/references/protocol/transactions/types/permissioneddomaindelete.md +++ b/@l10n/ja/docs/references/protocol/transactions/types/permissioneddomaindelete.md @@ -45,4 +45,4 @@ _([PermissionedDomains amendment][]が必要です {% not-enabled /%})_ | `tecNO_ENTRY` | `DomainID`フィールドで指定された許可型ドメインがレジャーに存在しません。 | | `temDISABLED` | `PermissionedDomains` amendmentが有効ではありません。 | -{% raw-partial file="/docs/_snippets/common-links.md" /%} +{% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} diff --git a/@l10n/ja/docs/references/protocol/transactions/types/xchainmodifybridge.md b/@l10n/ja/docs/references/protocol/transactions/types/xchainmodifybridge.md index e07fc63804..86574fa60f 100644 --- a/@l10n/ja/docs/references/protocol/transactions/types/xchainmodifybridge.md +++ b/@l10n/ja/docs/references/protocol/transactions/types/xchainmodifybridge.md @@ -44,7 +44,7 @@ _([XChainBridge Amendment][] {% not-enabled /%} が必要です)_ ## XChainModifyBridgeのフィールド | フィールド | JSONの型 | [内部の型][] | 必須? | 説明 | -|:-------------------------|:-------------|:-------- -----|:------|-----| +|:-------------------------|:-------------|:--------------|:------|-----| | `Flags` | 数値 | UInt32 | はい | このトランザクションのフラグを指定します。 | | `MinAccountCreateAmount` | [通貨額][] | Amount | いいえ | `XChainAccountCreateCommit`トランザクションに必要な最小金額。このフィールドが存在しない場合、`XChainAccountCreateCommit`トランザクションは失敗します。このフィールドはXRP-XRPブリッジにのみ存在できます。 | | `SignatureReward` | [通貨額][] | Amount | いいえ | Witnessサーバに支払う署名の報酬の合計額。この金額は署名者の間で分配されます。 | diff --git a/@l10n/ja/translations.yaml b/@l10n/ja/translations.yaml index e49cc10f32..cc2d730f83 100644 --- a/@l10n/ja/translations.yaml +++ b/@l10n/ja/translations.yaml @@ -829,6 +829,9 @@ resources.dev-tools.websocket-api.curl.modal.desc.part2: を使用してこれ API Methods: APIメソッド Methods: メソッド Examples: の例 +# resources/dev-tools/websocket-api/ClioOnly.tsx +resources.dev-tools.websocket-api.clio-only-badge: Clioのみ +resources.dev-tools.websocket-api.clio-only-tooltip: このメソッドはClioサーバーからのみ利用可能です。 # resources/dev-tools/xrp-ledger-toml-checker.page.tsx resources.dev-tools.toml-checker.p.part1: もしあなたがXRP Ledgerバリデータを運営していたり、XRP Ledgerをビジネスで利用しているのであれば、XRP Ledgerの利用状況に関する情報を、機械読み取り可能な diff --git a/@theme/styles.css b/@theme/styles.css index b958e9f130..90b191b92d 100644 --- a/@theme/styles.css +++ b/@theme/styles.css @@ -11,145 +11,155 @@ ul.nav.navbar-nav { flex-grow: 1; } -:root { +.clio-only-notice { + background-color: var(--admonition-info-bg-color); + margin-left: var(--spacing-sm); + padding: var(--spacing-xs); + border-radius: var(--border-radius); +} + +:root, :root.dark { + --navbar-height: 80px; + /* XRPL color palette; match to styles/_colors.scss Some colors don't have a 10 equivalent so 9 is repeated. - Note, at present these variables are mostly overridden by - styled-components variables which are in reverse order, so - we can't actually use these variables as-is. + These are in reverse order of the ones in styles/_colors.scss + so that they correspond to the same-named variables provided by + styled-components as part of Redocly. */ + /* Redocly doesn't have vars for grays by default */ - --color-gray-1: #F5F5F7; - --color-gray-2: #E0E0E1; - --color-gray-3: #C1C1C2; - --color-gray-4: #A2A2A4; + --color-gray-1: #111112; + --color-gray-2: #232325; + --color-gray-3: #343437; + --color-gray-4: #454549; --color-gray-5: #838386; - --color-gray-6: #454549; - --color-gray-7: #343437; - --color-gray-8: #232325; - --color-gray-9: #111112; + --color-gray-6: #A2A2A4; + --color-gray-7: #C1C1C2; + --color-gray-8: #E0E0E1; + --color-gray-9: #F5F5F7; --color-gray-10: var(--color-gray-9); /* color-red = XRPL $magenta */ - --color-red-1: #FFE5F2; - --color-red-2: #FFB2D8; - --color-red-3: #FF80BF; - --color-red-4: #FF4BA4; - --color-red-5: #FF198B; - --color-red-6: #E50071; - --color-red-7: #B20058; - --color-red-8: #80003F; - --color-red-9: #4C0026; - --color-red-10: #4C0026; - + --color-red-1: #4C0026; + --color-red-2: #4C0026; + --color-red-3: #80003F; + --color-red-4: #B20058; + --color-red-5: #E50071; + --color-red-6: #FF198B; + --color-red-7: #FF4BA4; + --color-red-8: #FF80BF; + --color-red-9: #FFB2D8; + --color-red-10: #FFE5F2; + /* color-green = XRPL $green */ - --color-green-1: #D6FAE7; - --color-green-2: #ADF5CE; - --color-green-3: #84F0B6; - --color-green-4: #5BEB9D; - --color-green-5: #32E685; - --color-green-6: #2DCF78; - --color-green-7: #28B86A; - --color-green-8: #1E8A50; - --color-green-9: #145C35; - --color-green-10: #0A2E1B; - + --color-green-1: #0A2E1B; + --color-green-2: #145C35; + --color-green-3: #1E8A50; + --color-green-4: #28B86A; + --color-green-5: #2DCF78; + --color-green-6: #32E685; + --color-green-7: #5BEB9D; + --color-green-8: #84F0B6; + --color-green-9: #ADF5CE; + --color-green-10: #D6FAE7; + /* color-gold = XRPL $yellow */ - --color-gold-1: #FEFFE5; - --color-gold-2: #FDFFB2; - --color-gold-3: #FCFF80; - --color-gold-4: #FBFF4C; - --color-gold-5: #FAFF19; - --color-gold-6: #E0E500; - --color-gold-7: #AEB200; - --color-gold-8: #7D8000; - --color-gold-9: #4B4C00; - --color-gold-10: #4B4C00; - + --color-gold-1: #4B4C00; + --color-gold-2: #4B4C00; + --color-gold-3: #7D8000; + --color-gold-4: #AEB200; + --color-gold-5: #E0E500; + --color-gold-6: #FAFF19; + --color-gold-7: #FBFF4C; + --color-gold-8: #FCFF80; + --color-gold-9: #FDFFB2; + --color-gold-10: #FEFFE5; + /* color-blue = XRPL $blue */ - --color-blue-1: #E5F5FF; - --color-blue-2: #B2E0FF; - --color-blue-3: #80CCFF; - --color-blue-4: #4BB7FF; - --color-blue-5: #19A3FF; - --color-blue-6: #008AE5; - --color-blue-7: #006BB2; - --color-blue-8: #004D80; - --color-blue-9: #002E4C; - --color-blue-10: #001133; - + --color-blue-1: #001133; + --color-blue-2: #002E4C; + --color-blue-3: #004D80; + --color-blue-4: #006BB2; + --color-blue-5: #008AE5; + --color-blue-6: #19A3FF; + --color-blue-7: #4BB7FF; + --color-blue-8: #80CCFF; + --color-blue-9: #B2E0FF; + --color-blue-10: #E5F5FF; + /* color purple = XRPL $blue-purple */ - --color-purple-1: #F0E5FF; - --color-purple-2: #D2B2FF; - --color-purple-3: #B480FF; - --color-purple-4: #9A52FF; - --color-purple-5: #7919FF; - --color-purple-6: #5F00E5; - --color-purple-7: #4A00B2; - --color-purple-8: #350080; - --color-purple-9: #20004C; - --color-purple-10: #20004C; - + --color-purple-1: #20004C; + --color-purple-2: #20004C; + --color-purple-3: #350080; + --color-purple-4: #4A00B2; + --color-purple-5: #5F00E5; + --color-purple-6: #7919FF; + --color-purple-7: #9A52FF; + --color-purple-8: #B480FF; + --color-purple-9: #D2B2FF; + --color-purple-10: #F0E5FF; + /* color-magenta = XRPL $red-purple */ - --color-magenta-1: #FBE5FF; - --color-magenta-2: #F2B2FF; - --color-magenta-3: #EA80FF; - --color-magenta-4: #E24CFF; - --color-magenta-5: #D919FF; - --color-magenta-6: #C000E5; - --color-magenta-7: #9500B2; - --color-magenta-8: #6B0080; - --color-magenta-9: #40004C; - --color-magenta-10: #40004C; - - /* XRPL doesn't have a color-cyan equivalent - --color-cyan-1: #e6fffb; - --color-cyan-2: #b5f5ec; - --color-cyan-3: #87e8de; - --color-cyan-4: #5cdbd3; - --color-cyan-5: #36cfc9; - --color-cyan-6: #13c2c2; - --color-cyan-7: #08979c; - --color-cyan-8: #006d75; - --color-cyan-9: #00474f; - --color-cyan-10: #002329; */ - + --color-magenta-1: #40004C; + --color-magenta-2: #40004C; + --color-magenta-3: #6B0080; + --color-magenta-4: #9500B2; + --color-magenta-5: #C000E5; + --color-magenta-6: #D919FF; + --color-magenta-7: #E24CFF; + --color-magenta-8: #EA80FF; + --color-magenta-9: #F2B2FF; + --color-magenta-10: #FBE5FF; + + /* XRPL doesn't have a color-cyan equivalent* + --color-cyan-1: #002329;* + --color-cyan-2: #00474f;* + --color-cyan-3: #006d75;* + --color-cyan-4: #08979c;* + --color-cyan-5: #13c2c2;* + --color-cyan-6: #36cfc9;* + --color-cyan-7: #5cdbd3;* + --color-cyan-8: #87e8de;* + --color-cyan-9: #b5f5ec;* + --color-cyan-10: #e6fffb; */ + /* color-yellow = XRPL $yellow */ - --color-yellow-1: #FEFFE5; - --color-yellow-2: #FDFFB2; - --color-yellow-3: #FCFF80; - --color-yellow-4: #FBFF4C; - --color-yellow-5: #FAFF19; - --color-yellow-6: #E0E500; - --color-yellow-7: #AEB200; - --color-yellow-8: #7D8000; - --color-yellow-9: #4B4C00; - --color-yellow-10: #4B4C00; - - /* XRPL doesn't have a color-lime equivalent - --color-lime-1: #fcffe6; - --color-lime-2: #f4ffb8; - --color-lime-3: #eaff8f; - --color-lime-4: #d3f261; - --color-lime-5: #bae637; - --color-lime-6: #a0d911; - --color-lime-7: #7cb305; - --color-lime-8: #5b8c00; - --color-lime-9: #3f6600; - --color-lime-10: #254000; */ - - /* XRPL doesn't have a color-geekblue equivalent - --color-geekblue-1: #f0f5ff; - --color-geekblue-2: #d6e4ff; - --color-geekblue-3: #adc6ff; - --color-geekblue-4: #85a5ff; - --color-geekblue-5: #597ef7; - --color-geekblue-6: #2f54eb; - --color-geekblue-7: #1d39c4; - --color-geekblue-8: #10239e; - --color-geekblue-9: #061178; - --color-geekblue-10: #030852; */ + --color-yellow-1: #4B4C00; + --color-yellow-2: #4B4C00; + --color-yellow-3: #7D8000; + --color-yellow-4: #AEB200; + --color-yellow-5: #E0E500; + --color-yellow-6: #FAFF19; + --color-yellow-7: #FBFF4C; + --color-yellow-8: #FCFF80; + --color-yellow-9: #FDFFB2; + --color-yellow-10: #FEFFE5; + + /* XRPL doesn't have a color-lime equivalent* + --color-lime-1: #254000;* + --color-lime-2: #3f6600;* + --color-lime-3: #5b8c00;* + --color-lime-4: #7cb305;* + --color-lime-5: #a0d911;* + --color-lime-6: #bae637;* + --color-lime-7: #d3f261;* + --color-lime-8: #eaff8f;* + --color-lime-9: #f4ffb8;* + --color-lime-10: #fcffe6; */ + + /* XRPL doesn't have a color-geekblue equivalent* + --color-geekblue-1: #030852;* + --color-geekblue-2: #061178;* + --color-geekblue-3: #10239e;* + --color-geekblue-4: #1d39c4;* + --color-geekblue-5: #2f54eb;* + --color-geekblue-6: #597ef7;* + --color-geekblue-7: #85a5ff;* + --color-geekblue-8: #adc6ff;* + --color-geekblue-9: #d6e4ff;* + --color-geekblue-10: #f0f5ff; */ /* Dark mode colors by default */ --color-primary-bg: var(--color-gray-10); @@ -162,30 +172,30 @@ ul.nav.navbar-nav { --color-primary-text-hover: #201dad; --color-primary-text: #161087; --color-primary-text-active: #0d086e;*/ - - --link-color-primary: #fff; + + --link-color-primary: white; --link-decoration: underline; --link-font-weight: var(--font-weight-regular); - --link-color-primary-hover: #9a52ff; + --link-color-primary-hover: var(--color-purple-7) --link-decoration-hover: underline; - --link-color-visited: #fff; + --link-color-visited: white; --link-visited-decoration: underline; --bg-color: var(--color-gray-10); - --bg-color-raised: var(--color-gray-8); + --bg-color-raised: var(--color-gray-2); --background-color: var(--bg-color); --font-family-base: 'Work Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; --heading-font-family: var(--font-family-base); --inline-code-font-family: "Space Mono", monospace; - --inline-code-text-color: #5beb9d; /* $green-400 */ - --inline-code-bg-color: #0a2e1b; /* $green-1000 */ + --inline-code-text-color: var(--color-green-7); + --inline-code-bg-color: var(--color-green-1); --inline-code-border-radius: 0; - --heading-anchor-color: #9a52ff; + --heading-anchor-color: var(--color-purple-7); --h1-font-size: 3rem; --h2-font-size: 2.5rem; --h3-font-size: 2.125rem; @@ -195,14 +205,18 @@ ul.nav.navbar-nav { --h5-font-size: 1.25rem; --h5-line-height: 1.5rem; + --menu-container-padding-top: 0; + --md-content-padding: 4px 0; + --toc-offset-top: 2px; + --sidebar-border-color: transparent; --sidebar-bg-color: transparent; --sidebar-margin-horizontal: 32px; --border-radius-md: 4px; - --code-block-bg-color: #232325; - --code-block-controls-bg-color: #232325; + --code-block-bg-color: var(--color-gray-2); + --code-block-controls-bg-color: var(--color-gray-2); --code-block-controls-border: none; --code-block-padding: 0 2rem 1.5rem 2rem; @@ -216,62 +230,111 @@ ul.nav.navbar-nav { --footer-border-color: transparent; --footer-title-font-weight: 600; --footer-title-font-size: 1rem; - --footer-title-text-color: #A2A2A4; + --footer-title-text-color: var(--color-gray-6); --menu-item-padding-horizontal: 0px; - + --md-list-left-padding: 40px; - --md-table-header-bg-color: #32343E; - --md-table-border-color: #32343E; - + --md-list-margin: 0 0 20px 0; + --md-table-header-bg-color: var(--color-gray-3); + --md-table-border-color: var(--color-gray-3); + --md-tabs-content-padding: 0; + --md-tabs-tab-wrapper-padding: 0; + + --text-color-helper: var(--color-gray-6); + --color-text-primary: white; + --button-color-hover: white; + + --text-color-secondary: var(--color-gray-9); /* inherited for adominition text color */ + --admonition-success-bg-color: var(--color-green-2); + --admonition-info-bg-color: var(--color-blue-4); + /* none of the yellow shades in the XRPL palette work well with "warning" + admonitions, so leave it the default */ + --admonition-danger-bg-color: var(--color-red-3); } :root.light { - --link-color-primary-hover: #4A00B2; - --link-color-visited: #000; - --text-color-secondary: #000; - --code-block-bg-color: #E0E0E1; - --code-block-controls-bg-color: #E0E0E1; + --link-color-primary-hover: var(--color-purple-4); + --link-color-visited: black; + --text-color-secondary: black; + --code-block-bg-color: var(--color-gray-8); + --code-block-controls-bg-color: var(--color-gray-8); --code-block-controls-border: none; - --md-tabs-active-tab-bg-color: #C1C1C2; - - --code-block-tokens-function-color: #B23C00; - --code-block-tokens-operator-color: #000; - --code-block-tokens-comment-color: #343437; - --code-block-tokens-string-color: #145C35; - --inline-code-bg-color: #E0E0E1; + --md-tabs-active-tab-bg-color: var(--color-gray-7); - --search-trigger-bg-color: #E0E0E1; - --search-trigger-color: #838386; + --inline-code-bg-color: var(--color-gray-8); - --language-picker-border-color: #C1C1C2; - --language-picker-background-color: #E0E0E1; - --select-list-bg-color: #E0E0E1; + --search-trigger-bg-color: var(--color-gray-8); + --search-trigger-color: var(--color-gray-5); + --modal-bg-color: var(--color-gray-9); - --footer-title-text-color: #000; - --bg-color: var(--color-gray-1); - --bg-color-raised: var(--color-gray-2); - --button-content-color-link: #000; + --language-picker-border-color: var(--color-gray-7); + --language-picker-background-color: var(--color-gray-8); + --select-list-bg-color: var(--color-gray-8); - --md-table-header-bg-color: var(--color-gray-2); - --md-table-border-color: var(--color-gray-2); + --footer-title-text-color: black; + --bg-color: var(--color-gray-9); + --bg-color-raised: var(--color-gray-8); + --button-content-color-link: black; + + --md-table-header-bg-color: var(--color-gray-8); + --md-table-border-color: var(--color-gray-8); + + --bg-color: var(--color-gray-8); + --code-panel-bg-color: var(--color-blue-7); + --layer-color-hover: var(--color-gray-9); + + --code-block-text-color: var(--color-gray-1); + --code-block-tokens-comment-color: var(--color-gray-4); + --code-block-tokens-constant-color: var(--color-gray-1); + --code-block-tokens-function-color: var(--color-red-4); + --code-block-tokens-keyword-color: var(--color-magenta-5); + --code-block-tokens-operator-color: black; + --code-block-tokens-string-color: var(--color-green-3); + + --bg-raised-gradient: ""; + --text-color-helper: var(--color-gray-4); + --button-color-hover: black; + + --admonition-success-bg-color: var(--color-green-9); + --admonition-info-bg-color: var(--color-blue-9); + --admonition-warning-bg-color: var(--color-yellow-9); + --admonition-danger-bg-color: var(--color-red-9); } :root.dark { - --link-color-primary: #fff; - --link-color-visited: #fff; - --link-color-primary-hover: #9a52ff; - - --search-highlight-text-color: #4BB7FF; /* color-blue-4 */ - - --code-block-tokens-comment-color: #C1C1C2; /* color-gray-3 */ + --link-color-primary: white; + --link-color-visited: white; + --link-color-primary-hover: var(--color-purple-7); + + --navbar-bg-color: var(--color-gray-2); /* controls search box bg */ + --modal-bg-color: var(--color-gray-2); /* controls search modal bg */ + --search-highlight-text-color: var(--color-blue-7); + + --code-block-text-color: var(--color-gray-9); + --code-block-tokens-comment-color: var(--color-gray-7); + --code-block-tokens-constant-color: var(--color-gray-9); + --code-block-tokens-keyword-color: var(--color-magenta-8); + --code-block-tokens-string-color: var(--color-blue-8); + + --code-panel-bg-color: var(--color-blue-3); + --layer-color-hover: var(--color-gray-3); + --bg-raised-gradient: ""; } :root .form-control-plaintext { color: var(--text-color); } +/* Fix unnecessary horizontal scrolling of tables in Japanese */ +[lang="ja"] table.md { + word-break: break-word; +} +[lang="ja"] table.md th { + min-width: 7em; +} + [data-component-name="Search/SearchTrigger"] > div { justify-content: start; width: 100%; diff --git a/_code-samples/batch/README.md b/_code-samples/batch/README.md new file mode 100644 index 0000000000..c0852466c2 --- /dev/null +++ b/_code-samples/batch/README.md @@ -0,0 +1,4 @@ +# Batch + +Code samples showing how to create and submit a [Batch transaction](../../docs/concepts/transactions/batch-transactions.md). +Both for simple and multi account batch transactions. diff --git a/_code-samples/batch/go/go.mod b/_code-samples/batch/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/batch/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/batch/go/go.sum b/_code-samples/batch/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/batch/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/batch/go/rpc/main.go b/_code-samples/batch/go/rpc/main.go new file mode 100644 index 0000000000..33740c43ec --- /dev/null +++ b/_code-samples/batch/go/rpc/main.go @@ -0,0 +1,198 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/rpc/types" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +var ( + CreatePaymentTx = func(sender, receiver *wallet.Wallet, amount txnTypes.CurrencyAmount) *transaction.Payment { + return &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: sender.GetAddress(), + TransactionType: transaction.PaymentTx, + Flags: txnTypes.TfInnerBatchTxn, + }, + Amount: amount, + Destination: receiver.GetAddress(), + } + } +) + +func main() { + // Configure the client + cfg, err := rpc.NewClientConfig( + "https://s.devnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + client := rpc.NewClient(cfg) + + // Create and fund wallets + userWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + user2Wallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + receiverWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Funding wallets...") + if err := client.FundWallet(&userWallet); err != nil { + panic(err) + } + if err := client.FundWallet(&user2Wallet); err != nil { + panic(err) + } + fmt.Println("Wallets funded") + + // Check initial balances + userBalance, err := client.GetXrpBalance(userWallet.ClassicAddress) + if err != nil { + userBalance = "0" + } + user2Balance, err := client.GetXrpBalance(user2Wallet.ClassicAddress) + if err != nil { + user2Balance = "0" + } + + receiverBalance, err := client.GetXrpBalance(receiverWallet.ClassicAddress) + if err != nil { + receiverBalance = "0" + } + + fmt.Printf("User initial balance: %s XRP\n", userBalance) + fmt.Printf("User2 initial balance: %s XRP\n", user2Balance) + fmt.Printf("Receiver initial balance: %s XRP\n", receiverBalance) + fmt.Println() + + fmt.Printf("Batch transaction test\n") + + // Create test batch transaction + batchTx := &transaction.Batch{ + BaseTx: transaction.BaseTx{ + Account: txnTypes.Address(userWallet.ClassicAddress), + TransactionType: transaction.BatchTx, + }, + RawTransactions: []txnTypes.RawTransaction{ + {RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()}, + {RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()}, + }, + } + batchTx.SetAllOrNothingFlag() + + flattenedBatchTx := batchTx.Flatten() + fmt.Println("Autofilling flattened batch transaction...") + if err := client.Autofill(&flattenedBatchTx); err != nil { + panic(err) + } + + fmt.Println("Signing batch transaction...") + response, err := client.SubmitTxAndWait(flattenedBatchTx, &types.SubmitOptions{ + Autofill: false, + Wallet: &userWallet, + }) + if err != nil { + panic(err) + } + + fmt.Println("Batch transaction submitted") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Printf("Validated: %t\n", response.Validated) + fmt.Println() + + // Check final balances + finalUserBalance, err := client.GetXrpBalance(userWallet.ClassicAddress) + if err != nil { + finalUserBalance = "0" + } + finalReceiverBalance, err := client.GetXrpBalance(receiverWallet.ClassicAddress) + if err != nil { + finalReceiverBalance = "0" + } + + fmt.Printf("User final balance: %s XRP\n", finalUserBalance) + + fmt.Printf("Receiver final balance: %s XRP\n", finalReceiverBalance) + + fmt.Println() + fmt.Printf("Multisig Batch transaction test\n") + + // Create test batch transaction + multiBatchTx := &transaction.Batch{ + BaseTx: transaction.BaseTx{ + Account: txnTypes.Address(userWallet.ClassicAddress), + TransactionType: transaction.BatchTx, + }, + RawTransactions: []txnTypes.RawTransaction{ + {RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()}, + {RawTransaction: CreatePaymentTx(&user2Wallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()}, + }, + BatchSigners: []txnTypes.BatchSigner{ + { + BatchSigner: txnTypes.BatchSignerData{ + Account: txnTypes.Address(user2Wallet.ClassicAddress), + SigningPubKey: user2Wallet.PublicKey, + }, + }, + }, + } + multiBatchTx.SetAllOrNothingFlag() + + flattenedMultiBatchTx := multiBatchTx.Flatten() + fmt.Println("Autofilling flattened multi batch transaction...") + if err := client.AutofillMultisigned(&flattenedMultiBatchTx, 1); err != nil { + panic(err) + } + + fmt.Println("Signing multi batch transaction...") + if err := wallet.SignMultiBatch(user2Wallet, &flattenedMultiBatchTx, nil); err != nil { + panic(err) + } + + response, err = client.SubmitTxAndWait(flattenedMultiBatchTx, &types.SubmitOptions{ + Autofill: false, + Wallet: &userWallet, + }) + if err != nil { + panic(err) + } + + fmt.Println("Multisig Batch transaction submitted") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Printf("Validated: %t\n", response.Validated) + fmt.Println() + + // Check final balances + finalUser2Balance, err := client.GetXrpBalance(user2Wallet.ClassicAddress) + if err != nil { + finalUser2Balance = "0" + } + finalUserBalance, err = client.GetXrpBalance(userWallet.ClassicAddress) + if err != nil { + finalUserBalance = "0" + } + finalReceiverBalance, err = client.GetXrpBalance(receiverWallet.ClassicAddress) + if err != nil { + finalReceiverBalance = "0" + } + fmt.Printf("User final balance: %s XRP\n", finalUserBalance) + fmt.Printf("User2 final balance: %s XRP\n", finalUser2Balance) + fmt.Printf("Receiver final balance: %s XRP\n", finalReceiverBalance) +} diff --git a/_code-samples/batch/go/ws/main.go b/_code-samples/batch/go/ws/main.go new file mode 100644 index 0000000000..027e066480 --- /dev/null +++ b/_code-samples/batch/go/ws/main.go @@ -0,0 +1,199 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" + "github.com/Peersyst/xrpl-go/xrpl/websocket/types" +) + +var ( + CreatePaymentTx = func(sender, receiver *wallet.Wallet, amount txnTypes.CurrencyAmount) *transaction.Payment { + return &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: sender.GetAddress(), + TransactionType: transaction.PaymentTx, + Flags: txnTypes.TfInnerBatchTxn, + }, + Amount: amount, + Destination: receiver.GetAddress(), + } + } +) + +func main() { + // Connect to testnet + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.devnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + // Create and fund wallets + userWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + user2Wallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + receiverWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Funding wallets...") + if err := client.FundWallet(&userWallet); err != nil { + panic(err) + } + if err := client.FundWallet(&user2Wallet); err != nil { + panic(err) + } + fmt.Println("Wallets funded") + + // Check initial balances + userBalance, err := client.GetXrpBalance(userWallet.ClassicAddress) + if err != nil { + userBalance = "0" + } + user2Balance, err := client.GetXrpBalance(user2Wallet.ClassicAddress) + if err != nil { + user2Balance = "0" + } + + receiverBalance, err := client.GetXrpBalance(receiverWallet.ClassicAddress) + if err != nil { + receiverBalance = "0" + } + + fmt.Printf("User initial balance: %s XRP\n", userBalance) + fmt.Printf("User2 initial balance: %s XRP\n", user2Balance) + fmt.Printf("Receiver initial balance: %s XRP\n", receiverBalance) + fmt.Println() + + fmt.Printf("Batch transaction test\n") + + // Create test batch transaction + batchTx := &transaction.Batch{ + BaseTx: transaction.BaseTx{ + Account: txnTypes.Address(userWallet.ClassicAddress), + TransactionType: transaction.BatchTx, + }, + RawTransactions: []txnTypes.RawTransaction{ + {RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()}, + {RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()}, + }, + } + batchTx.SetAllOrNothingFlag() + + flattenedBatchTx := batchTx.Flatten() + fmt.Println("Autofilling flattened batch transaction...") + if err := client.Autofill(&flattenedBatchTx); err != nil { + panic(err) + } + + fmt.Println("Signing batch transaction...") + response, err := client.SubmitTxAndWait(flattenedBatchTx, &types.SubmitOptions{ + Autofill: false, + Wallet: &userWallet, + }) + if err != nil { + panic(err) + } + + fmt.Println("Batch transaction submitted") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Printf("Validated: %t\n", response.Validated) + fmt.Println() + + // Check final balances + finalUserBalance, err := client.GetXrpBalance(userWallet.ClassicAddress) + if err != nil { + finalUserBalance = "0" + } + finalReceiverBalance, err := client.GetXrpBalance(receiverWallet.ClassicAddress) + if err != nil { + finalReceiverBalance = "0" + } + + fmt.Printf("User final balance: %s XRP\n", finalUserBalance) + + fmt.Printf("Receiver final balance: %s XRP\n", finalReceiverBalance) + + fmt.Println() + fmt.Printf("Multisig Batch transaction test\n") + + // Create test batch transaction + multiBatchTx := &transaction.Batch{ + BaseTx: transaction.BaseTx{ + Account: txnTypes.Address(userWallet.ClassicAddress), + TransactionType: transaction.BatchTx, + }, + RawTransactions: []txnTypes.RawTransaction{ + {RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()}, + {RawTransaction: CreatePaymentTx(&user2Wallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()}, + }, + BatchSigners: []txnTypes.BatchSigner{ + { + BatchSigner: txnTypes.BatchSignerData{ + Account: txnTypes.Address(user2Wallet.ClassicAddress), + SigningPubKey: user2Wallet.PublicKey, + }, + }, + }, + } + multiBatchTx.SetAllOrNothingFlag() + + flattenedMultiBatchTx := multiBatchTx.Flatten() + fmt.Println("Autofilling flattened multi batch transaction...") + if err := client.AutofillMultisigned(&flattenedMultiBatchTx, 1); err != nil { + panic(err) + } + + fmt.Println("Signing multi batch transaction...") + if err := wallet.SignMultiBatch(user2Wallet, &flattenedMultiBatchTx, nil); err != nil { + panic(err) + } + + response, err = client.SubmitTxAndWait(flattenedMultiBatchTx, &types.SubmitOptions{ + Autofill: false, + Wallet: &userWallet, + }) + if err != nil { + panic(err) + } + + fmt.Println("Multisig Batch transaction submitted") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Printf("Validated: %t\n", response.Validated) + fmt.Println() + + // Check final balances + finalUser2Balance, err := client.GetXrpBalance(user2Wallet.ClassicAddress) + if err != nil { + finalUser2Balance = "0" + } + finalUserBalance, err = client.GetXrpBalance(userWallet.ClassicAddress) + if err != nil { + finalUserBalance = "0" + } + finalReceiverBalance, err = client.GetXrpBalance(receiverWallet.ClassicAddress) + if err != nil { + finalReceiverBalance = "0" + } + fmt.Printf("User final balance: %s XRP\n", finalUserBalance) + fmt.Printf("User2 final balance: %s XRP\n", finalUser2Balance) + fmt.Printf("Receiver final balance: %s XRP\n", finalReceiverBalance) +} diff --git a/_code-samples/checks/go/go.mod b/_code-samples/checks/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/checks/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/checks/go/go.sum b/_code-samples/checks/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/checks/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/checks/go/rpc/main.go b/_code-samples/checks/go/rpc/main.go new file mode 100644 index 0000000000..7c8dcf1299 --- /dev/null +++ b/_code-samples/checks/go/rpc/main.go @@ -0,0 +1,152 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/ledger-entry-types" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + + w, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + receiverWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Setting up wallets...") + if err := client.FundWallet(&w); err != nil { + panic(err) + } + fmt.Println("Sender wallet funded!") + + if err := client.FundWallet(&receiverWallet); err != nil { + panic(err) + } + + fmt.Println("Receiver wallet funded!") + fmt.Println() + + fmt.Println("Wallets setup complete!") + fmt.Println("Sender wallet:", w.ClassicAddress) + fmt.Println("Receiver wallet:", receiverWallet.ClassicAddress) + fmt.Println() + + fmt.Println("Creating check...") + cc := &transaction.CheckCreate{ + BaseTx: transaction.BaseTx{ + Account: w.GetAddress(), + }, + Destination: receiverWallet.GetAddress(), + SendMax: types.XRPCurrencyAmount(1000000), + InvoiceID: "46060241FABCF692D4D934BA2A6C4427CD4279083E38C77CBE642243E43BE291", + } + + flatCc := cc.Flatten() + + if err := client.Autofill(&flatCc); err != nil { + panic(err) + } + + blob, _, err := w.Sign(flatCc) + if err != nil { + panic(err) + } + + res, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + if !res.Validated { + fmt.Println("Check creation failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Check created!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Println() + + meta, ok := res.Meta.(map[string]interface{}) + if !ok { + fmt.Println("Meta is not of type TxObjMeta") + return + } + + var checkID string + + affectedNodes := meta["AffectedNodes"].([]interface{}) + + for _, node := range affectedNodes { + affectedNode, ok := node.(map[string]interface{}) + if !ok { + fmt.Println("Node is not of type map[string]interface{}") + return + } + + createdNode, ok := affectedNode["CreatedNode"].(map[string]interface{}) + if !ok { + continue + } + + if createdNode["LedgerEntryType"] == string(ledger.CheckEntry) { + + checkID = createdNode["LedgerIndex"].(string) + } + } + + if checkID == "" { + fmt.Println("Check not found") + return + } + + fmt.Println("Cashing out check...") + checkCash := &transaction.CheckCash{ + BaseTx: transaction.BaseTx{ + Account: receiverWallet.GetAddress(), + }, + CheckID: types.Hash256(checkID), + Amount: types.XRPCurrencyAmount(1000000), + } + + flatCheckCash := checkCash.Flatten() + + if err := client.Autofill(&flatCheckCash); err != nil { + panic(err) + } + + blob, _, err = receiverWallet.Sign(flatCheckCash) + if err != nil { + panic(err) + } + + res, err = client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Check cashed out!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Println() +} diff --git a/_code-samples/checks/go/ws/main.go b/_code-samples/checks/go/ws/main.go new file mode 100644 index 0000000000..65eede1300 --- /dev/null +++ b/_code-samples/checks/go/ws/main.go @@ -0,0 +1,163 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/ledger-entry-types" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +func main() { + fmt.Println("Connecting to testnet...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + if !client.IsConnected() { + fmt.Println("Failed to connect to testnet") + return + } + + fmt.Println("Connected to testnet") + fmt.Println() + + w, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + receiverWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Setting up wallets...") + if err := client.FundWallet(&w); err != nil { + panic(err) + } + fmt.Println("Sender wallet funded!") + + if err := client.FundWallet(&receiverWallet); err != nil { + panic(err) + } + + fmt.Println("Receiver wallet funded!") + fmt.Println() + + fmt.Println("Wallets setup complete!") + fmt.Println("Sender wallet:", w.ClassicAddress) + fmt.Println("Receiver wallet:", receiverWallet.ClassicAddress) + fmt.Println() + + fmt.Println("Creating check...") + cc := &transaction.CheckCreate{ + BaseTx: transaction.BaseTx{ + Account: w.GetAddress(), + }, + Destination: receiverWallet.GetAddress(), + SendMax: types.XRPCurrencyAmount(1000000), + InvoiceID: "46060241FABCF692D4D934BA2A6C4427CD4279083E38C77CBE642243E43BE291", + } + + flatCc := cc.Flatten() + + if err := client.Autofill(&flatCc); err != nil { + panic(err) + } + + + blob, _, err := w.Sign(flatCc) + if err != nil { + panic(err) + } + + res, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + if !res.Validated { + fmt.Println("Check creation failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Check created!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Println() + + meta, ok := res.Meta.(map[string]interface{}) + if !ok { + fmt.Println("Meta is not of type TxObjMeta") + return + } + + var checkID string + + affectedNodes := meta["AffectedNodes"].([]interface{}) + + for _, node := range affectedNodes { + affectedNode, ok := node.(map[string]interface{}) + if !ok { + fmt.Println("Node is not of type map[string]interface{}") + return + } + + createdNode, ok := affectedNode["CreatedNode"].(map[string]interface{}) + if !ok { + continue + } + + if createdNode["LedgerEntryType"] == string(ledger.CheckEntry) { + + checkID = createdNode["LedgerIndex"].(string) + } + } + + if checkID == "" { + fmt.Println("Check not found") + return + } + + fmt.Println("Cashing out check...") + checkCash := &transaction.CheckCash{ + BaseTx: transaction.BaseTx{ + Account: receiverWallet.GetAddress(), + }, + CheckID: types.Hash256(checkID), + Amount: types.XRPCurrencyAmount(1000000), + } + + flatCheckCash := checkCash.Flatten() + + if err := client.Autofill(&flatCheckCash); err != nil { + panic(err) + } + + blob, _, err = receiverWallet.Sign(flatCheckCash) + if err != nil { + panic(err) + } + + res, err = client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Check cashed out!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Println() +} diff --git a/_code-samples/clawback/README.md b/_code-samples/clawback/README.md new file mode 100644 index 0000000000..3a6a54c8d0 --- /dev/null +++ b/_code-samples/clawback/README.md @@ -0,0 +1,3 @@ +# Clawback + +Create, configure, and execute a Clawback transaction to reclaim issued tokens from a trust line on the XRPL. diff --git a/_code-samples/clawback/go/go.mod b/_code-samples/clawback/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/clawback/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/clawback/go/go.sum b/_code-samples/clawback/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/clawback/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/clawback/go/rpc/main.go b/_code-samples/clawback/go/rpc/main.go new file mode 100644 index 0000000000..0d83713b20 --- /dev/null +++ b/_code-samples/clawback/go/rpc/main.go @@ -0,0 +1,235 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + transactions "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +const ( + currencyCode = "FOO" +) + +func main() { + // + // Configure client + // + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + + // + // Configure wallets + // + fmt.Println("Setting up wallets...") + coldWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + err = client.FundWallet(&coldWallet) + if err != nil { + panic(err) + } + fmt.Println("Cold wallet funded!") + + hotWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + err = client.FundWallet(&hotWallet) + if err != nil { + panic(err) + } + fmt.Println("Hot wallet funded!") + fmt.Println() + + fmt.Println("Wallets setup complete!") + fmt.Println("Cold wallet:", coldWallet.ClassicAddress) + fmt.Println("Hot wallet:", hotWallet.ClassicAddress) + fmt.Println() + + // + // Configure cold address settings + // + fmt.Println("Configuring cold address settings...") + coldWalletAccountSet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + TickSize: types.TickSize(5), + TransferRate: types.TransferRate(0), + Domain: types.Domain("6578616D706C652E636F6D"), // example.com + } + + coldWalletAccountSet.SetAsfAllowTrustLineClawback() + coldWalletAccountSet.SetDisallowXRP() + + coldWalletAccountSet.SetRequireDestTag() + + flattenedTx := coldWalletAccountSet.Flatten() + + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err := coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err := client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Cold wallet unfreezing failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Cold address settings configured!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Create trust line from hot to cold address + // + fmt.Println("Creating trust line from hot to cold address...") + hotColdTrustSet := &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(hotWallet.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100000000000000", + }, + } + + flattenedTx = hotColdTrustSet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = hotWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Trust line from hot to cold address creation failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Trust line from hot to cold address created!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Send tokens from cold wallet to hot wallet + // + fmt.Println("Sending tokens from cold wallet to hot wallet...") + coldToHotPayment := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "3800", + }, + Destination: types.Address(hotWallet.ClassicAddress), + DestinationTag: types.DestinationTag(1), + } + + flattenedTx = coldToHotPayment.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Tokens not sent from cold wallet to hot wallet!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Tokens sent from cold wallet to hot wallet!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Claw back tokens from customer one + // + fmt.Println("Clawing back tokens from hot wallet...") + + coldWalletClawback := &transactions.Clawback{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(hotWallet.ClassicAddress), + Value: "50", + }, + } + + flattenedTx = coldWalletClawback.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Tokens not clawed back from customer one!") + fmt.Println("Try again!") + return + } + + fmt.Println("Tokens clawed back from customer one!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() +} diff --git a/_code-samples/clawback/go/ws/main.go b/_code-samples/clawback/go/ws/main.go new file mode 100644 index 0000000000..88119fac61 --- /dev/null +++ b/_code-samples/clawback/go/ws/main.go @@ -0,0 +1,241 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + transactions "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +const ( + currencyCode = "FOO" +) + +func main() { + // + // Configure client + // + fmt.Println("Setting up client...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + fmt.Println("Client configured!") + fmt.Println() + + fmt.Println("Connecting to server...") + if err := client.Connect(); err != nil { + panic(err) + } + + fmt.Println("Connection: ", client.IsConnected()) + + // + // Configure wallets + // + fmt.Println("Setting up wallets...") + coldWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + err = client.FundWallet(&coldWallet) + if err != nil { + panic(err) + } + fmt.Println("Cold wallet funded!") + + hotWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + err = client.FundWallet(&hotWallet) + if err != nil { + panic(err) + } + fmt.Println("Hot wallet funded!") + fmt.Println() + + fmt.Println("Wallets setup complete!") + fmt.Println("Cold wallet:", coldWallet.ClassicAddress) + fmt.Println("Hot wallet:", hotWallet.ClassicAddress) + fmt.Println() + + // + // Configure cold address settings + // + fmt.Println("Configuring cold address settings...") + coldWalletAccountSet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + TickSize: types.TickSize(5), + TransferRate: types.TransferRate(0), + Domain: types.Domain("6578616D706C652E636F6D"), // example.com + } + + coldWalletAccountSet.SetAsfAllowTrustLineClawback() + coldWalletAccountSet.SetDisallowXRP() + + coldWalletAccountSet.SetRequireDestTag() + + flattenedTx := coldWalletAccountSet.Flatten() + + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err := coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err := client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Cold wallet unfreezing failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Cold address settings configured!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Create trust line from hot to cold address + // + fmt.Println("Creating trust line from hot to cold address...") + hotColdTrustSet := &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(hotWallet.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100000000000000", + }, + } + + flattenedTx = hotColdTrustSet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = hotWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Trust line from hot to cold address creation failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Trust line from hot to cold address created!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Send tokens from cold wallet to hot wallet + // + fmt.Println("Sending tokens from cold wallet to hot wallet...") + coldToHotPayment := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "3800", + }, + Destination: types.Address(hotWallet.ClassicAddress), + DestinationTag: types.DestinationTag(1), + } + + flattenedTx = coldToHotPayment.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Tokens not sent from cold wallet to hot wallet!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Tokens sent from cold wallet to hot wallet!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Claw back tokens from customer one + // + fmt.Println("Clawing back tokens from hot wallet...") + + coldWalletClawback := &transactions.Clawback{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(hotWallet.ClassicAddress), + Value: "50", + }, + } + + flattenedTx = coldWalletClawback.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Tokens not clawed back from customer one!") + fmt.Println("Try again!") + return + } + + fmt.Println("Tokens clawed back from customer one!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() +} diff --git a/_code-samples/credential/README.md b/_code-samples/credential/README.md new file mode 100644 index 0000000000..751fa22c5f --- /dev/null +++ b/_code-samples/credential/README.md @@ -0,0 +1,3 @@ +# Credential + +Create, accept, and delete a credential on the XRPL using dedicated transactions between issuer and subject wallets. diff --git a/_code-samples/credential/go/go.mod b/_code-samples/credential/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/credential/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/credential/go/go.sum b/_code-samples/credential/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/credential/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/credential/go/rpc/main.go b/_code-samples/credential/go/rpc/main.go new file mode 100644 index 0000000000..0473667466 --- /dev/null +++ b/_code-samples/credential/go/rpc/main.go @@ -0,0 +1,104 @@ +package main + +import ( + "encoding/hex" + "fmt" + "time" + + "github.com/Peersyst/xrpl-go/examples/clients" + "github.com/Peersyst/xrpl-go/pkg/crypto" + rippleTime "github.com/Peersyst/xrpl-go/xrpl/time" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + // As of February 2025, Credential is only available on Devnet. + client := clients.GetDevnetRpcClient() + + // Configure wallets + + // Issuer + fmt.Println("Setting up credential issuer wallet...") + issuer, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&issuer) + if err != nil { + panic(err) + } + fmt.Printf("Issuer wallet funded: %s\n", issuer.ClassicAddress) + + // ----------------------------------------------------- + + // Subject (destination) + fmt.Println("Setting up Subject wallet...") + subjectWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&subjectWallet) + if err != nil { + panic(err) + } + fmt.Printf("Subject wallet funded: %s\n", subjectWallet.ClassicAddress) + + // ----------------------------------------------------- + + // Creating the CredentialCreate transaction + fmt.Println("Creating CredentialCreate transaction...") + + expiration, err := rippleTime.IsoTimeToRippleTime(time.Now().Add(time.Hour * 24).Format(time.RFC3339)) + credentialType := types.CredentialType("6D795F63726564656E7469616C") + + if err != nil { + panic(err) + } + + txn := &transaction.CredentialCreate{ + BaseTx: transaction.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + CredentialType: credentialType, + Subject: types.Address(subjectWallet.ClassicAddress), + Expiration: uint32(expiration), + URI: hex.EncodeToString([]byte("https://example.com")), + } + + clients.SubmitTxBlobAndWait(client, txn, issuer) + + // ----------------------------------------------------- + + // Creating the CredentialAccept transaction + fmt.Println("Creating CredentialAccept transaction...") + + acceptTxn := &transaction.CredentialAccept{ + BaseTx: transaction.BaseTx{ + Account: types.Address(subjectWallet.ClassicAddress), + }, + CredentialType: credentialType, + Issuer: types.Address(issuer.ClassicAddress), + } + + clients.SubmitTxBlobAndWait(client, acceptTxn, subjectWallet) + + // ----------------------------------------------------- + + // Creating the CredentialDelete transaction + fmt.Println("Creating CredentialDelete transaction...") + + deleteTxn := &transaction.CredentialDelete{ + BaseTx: transaction.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + CredentialType: credentialType, + Issuer: types.Address(issuer.ClassicAddress), + Subject: types.Address(subjectWallet.ClassicAddress), + } + + clients.SubmitTxBlobAndWait(client, deleteTxn, issuer) +} diff --git a/_code-samples/credential/go/ws/main.go b/_code-samples/credential/go/ws/main.go new file mode 100644 index 0000000000..1093d6d462 --- /dev/null +++ b/_code-samples/credential/go/ws/main.go @@ -0,0 +1,116 @@ +package main + +import ( + "encoding/hex" + "fmt" + "time" + + "github.com/Peersyst/xrpl-go/examples/clients" + "github.com/Peersyst/xrpl-go/pkg/crypto" + rippleTime "github.com/Peersyst/xrpl-go/xrpl/time" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + + fmt.Println("Setting up client...") + + client := clients.GetDevnetWebsocketClient() + fmt.Println("Connecting to server...") + if err := client.Connect(); err != nil { + panic(err) + } + + fmt.Println("Client configured!") + fmt.Println() + + fmt.Printf("Connection: %t", client.IsConnected()) + fmt.Println() + + // Configure wallets + + // Issuer + fmt.Println("Setting up credential issuer wallet...") + issuer, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&issuer) + if err != nil { + panic(err) + } + fmt.Printf("Issuer wallet funded: %s\n", issuer.ClassicAddress) + + // ----------------------------------------------------- + + // Subject (destination) + fmt.Println("Setting up Subject wallet...") + subjectWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&subjectWallet) + if err != nil { + panic(err) + } + fmt.Printf("Subject wallet funded: %s\n", subjectWallet.ClassicAddress) + + // ----------------------------------------------------- + + // Creating the CredentialCreate transaction + fmt.Println("Creating CredentialCreate transaction...") + + expiration, err := rippleTime.IsoTimeToRippleTime(time.Now().Add(time.Hour * 24).Format(time.RFC3339)) + credentialType := types.CredentialType("6D795F63726564656E7469616C") + + if err != nil { + panic(err) + } + + txn := &transaction.CredentialCreate{ + BaseTx: transaction.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + CredentialType: credentialType, + Subject: types.Address(subjectWallet.ClassicAddress), + Expiration: uint32(expiration), + URI: hex.EncodeToString([]byte("https://example.com")), + } + + clients.SubmitTxBlobAndWait(client, txn, issuer) + + // ----------------------------------------------------- + + // Creating the CredentialAccept transaction + fmt.Println("Creating CredentialAccept transaction...") + + acceptTxn := &transaction.CredentialAccept{ + BaseTx: transaction.BaseTx{ + Account: types.Address(subjectWallet.ClassicAddress), + }, + CredentialType: credentialType, + Issuer: types.Address(issuer.ClassicAddress), + } + + clients.SubmitTxBlobAndWait(client, acceptTxn, subjectWallet) + + // ----------------------------------------------------- + + // Creating the CredentialDelete transaction + fmt.Println("Creating CredentialDelete transaction...") + + deleteTxn := &transaction.CredentialDelete{ + BaseTx: transaction.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + CredentialType: credentialType, + Issuer: types.Address(issuer.ClassicAddress), + Subject: types.Address(subjectWallet.ClassicAddress), + } + + clients.SubmitTxBlobAndWait(client, deleteTxn, issuer) +} diff --git a/_code-samples/delegate-set/README.md b/_code-samples/delegate-set/README.md new file mode 100644 index 0000000000..2d8736f4e4 --- /dev/null +++ b/_code-samples/delegate-set/README.md @@ -0,0 +1,3 @@ +# Delegate + +Example delegating payment permission to an account and executing on behalf the delegator. diff --git a/_code-samples/delegate-set/go/go.mod b/_code-samples/delegate-set/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/delegate-set/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/delegate-set/go/go.sum b/_code-samples/delegate-set/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/delegate-set/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/delegate-set/go/rpc/main.go b/_code-samples/delegate-set/go/rpc/main.go new file mode 100644 index 0000000000..a2314cef67 --- /dev/null +++ b/_code-samples/delegate-set/go/rpc/main.go @@ -0,0 +1,125 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/rpc/types" + transactions "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + // Configure the client + cfg, err := rpc.NewClientConfig( + "https://s.devnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + client := rpc.NewClient(cfg) + + // Create and fund wallets + delegatorWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + delegateeWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Funding wallets...") + if err := client.FundWallet(&delegatorWallet); err != nil { + panic(err) + } + if err := client.FundWallet(&delegateeWallet); err != nil { + panic(err) + } + fmt.Println("Wallets funded") + + // Check initial balances + delegatorBalance, err := client.GetXrpBalance(delegatorWallet.ClassicAddress) + if err != nil { + delegatorBalance = "0" + } + delegateeBalance, err := client.GetXrpBalance(delegateeWallet.ClassicAddress) + if err != nil { + delegateeBalance = "0" + } + + fmt.Printf("Delegator initial balance: %s XRP\n", delegatorBalance) + fmt.Printf("Delegatee initial balance: %s XRP\n", delegateeBalance) + fmt.Println() + + // Create DelegateSet transaction + delegateSetTx := &transactions.DelegateSet{ + BaseTx: transactions.BaseTx{ + Account: txnTypes.Address(delegatorWallet.ClassicAddress), + }, + Authorize: txnTypes.Address(delegateeWallet.ClassicAddress), + Permissions: []txnTypes.Permission{ + { + Permission: txnTypes.PermissionValue{ + PermissionValue: "Payment", + }, + }, + }, + } + + // Submit DelegateSet transaction + response, err := client.SubmitTxAndWait(delegateSetTx.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &delegatorWallet, + }) + if err != nil { + panic(err) + } + + fmt.Println("DelegateSet transaction submitted") + fmt.Printf("Hash: %s\n", response.Hash) + fmt.Printf("Validated: %t\n", response.Validated) + fmt.Println() + + // Create delegated payment transaction + delegatedPaymentTx := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: txnTypes.Address(delegatorWallet.ClassicAddress), + Delegate: txnTypes.Address(delegateeWallet.ClassicAddress), + }, + Destination: txnTypes.Address(delegateeWallet.ClassicAddress), + Amount: txnTypes.XRPCurrencyAmount(1000000), // 1 XRP + } + + // Submit delegated payment + response2, err := client.SubmitTxAndWait(delegatedPaymentTx.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &delegateeWallet, + }) + if err != nil { + panic(err) + } + + fmt.Println("Delegated payment submitted") + fmt.Printf("Hash: %s\n", response2.Hash) + fmt.Printf("Validated: %t\n", response2.Validated) + fmt.Println() + + // Check final balances + finalDelegatorBalance, err := client.GetXrpBalance(delegatorWallet.ClassicAddress) + if err != nil { + finalDelegatorBalance = "0" + } + finalDelegateeBalance, err := client.GetXrpBalance(delegateeWallet.ClassicAddress) + if err != nil { + finalDelegateeBalance = "0" + } + + fmt.Printf("Delegator final balance: %s XRP\n", finalDelegatorBalance) + fmt.Printf("Delegatee final balance: %s XRP\n", finalDelegateeBalance) +} diff --git a/_code-samples/delegate-set/go/ws/main.go b/_code-samples/delegate-set/go/ws/main.go new file mode 100644 index 0000000000..6b303c4c04 --- /dev/null +++ b/_code-samples/delegate-set/go/ws/main.go @@ -0,0 +1,140 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + transactions "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +func main() { + // Connect to testnet + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.devnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + // Create and fund wallets + delegatorWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + delegateeWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Funding wallets...") + if err := client.FundWallet(&delegatorWallet); err != nil { + panic(err) + } + if err := client.FundWallet(&delegateeWallet); err != nil { + panic(err) + } + fmt.Println("Wallets funded") + + // Check initial balances + delegatorBalance, err := client.GetXrpBalance(delegatorWallet.ClassicAddress) + if err != nil { + delegatorBalance = "0" + } + delegateeBalance, err := client.GetXrpBalance(delegateeWallet.ClassicAddress) + if err != nil { + delegateeBalance = "0" + } + + fmt.Printf("Delegator initial balance: %s XRP\n", delegatorBalance) + fmt.Printf("Delegatee initial balance: %s XRP\n", delegateeBalance) + fmt.Println() + + // Create DelegateSet transaction + delegateSetTx := &transactions.DelegateSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(delegatorWallet.ClassicAddress), + }, + Authorize: types.Address(delegateeWallet.ClassicAddress), + Permissions: []types.Permission{ + { + Permission: types.PermissionValue{ + PermissionValue: "Payment", + }, + }, + }, + } + + // Submit DelegateSet transaction + flattenedTx := delegateSetTx.Flatten() + if err := client.Autofill(&flattenedTx); err != nil { + panic(err) + } + + txBlob, _, err := delegatorWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err := client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + fmt.Println("DelegateSet transaction submitted") + fmt.Printf("Hash: %s\n", response.Hash) + fmt.Printf("Validated: %t\n", response.Validated) + fmt.Println() + + // Create delegated payment transaction + delegatedPaymentTx := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(delegatorWallet.ClassicAddress), + Delegate: types.Address(delegateeWallet.ClassicAddress), + }, + Destination: types.Address(delegateeWallet.ClassicAddress), + Amount: types.XRPCurrencyAmount(1000000), // 1 XRP + } + + // Submit delegated payment + flatDelegatedPayment := delegatedPaymentTx.Flatten() + if err := client.Autofill(&flatDelegatedPayment); err != nil { + panic(err) + } + + txBlob2, _, err := delegateeWallet.Sign(flatDelegatedPayment) + if err != nil { + panic(err) + } + + response2, err := client.SubmitTxBlobAndWait(txBlob2, false) + if err != nil { + panic(err) + } + + fmt.Println("Delegated payment submitted") + fmt.Printf("Hash: %s\n", response2.Hash) + fmt.Printf("Validated: %t\n", response2.Validated) + fmt.Println() + + // Check final balances + finalDelegatorBalance, err := client.GetXrpBalance(delegatorWallet.ClassicAddress) + if err != nil { + finalDelegatorBalance = "0" + } + finalDelegateeBalance, err := client.GetXrpBalance(delegateeWallet.ClassicAddress) + if err != nil { + finalDelegateeBalance = "0" + } + + fmt.Printf("Delegator final balance: %s XRP\n", finalDelegatorBalance) + fmt.Printf("Delegatee final balance: %s XRP\n", finalDelegateeBalance) +} diff --git a/_code-samples/deposit-preauth/README.md b/_code-samples/deposit-preauth/README.md new file mode 100644 index 0000000000..16b546d7eb --- /dev/null +++ b/_code-samples/deposit-preauth/README.md @@ -0,0 +1,3 @@ +# DepositPreauth + +Example of DepositPreauth transaction demonstrating how deposit permissions can be managed. diff --git a/_code-samples/deposit-preauth/go/go.mod b/_code-samples/deposit-preauth/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/deposit-preauth/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/deposit-preauth/go/go.sum b/_code-samples/deposit-preauth/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/deposit-preauth/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/deposit-preauth/go/rpc/main.go b/_code-samples/deposit-preauth/go/rpc/main.go new file mode 100644 index 0000000000..54eef31f91 --- /dev/null +++ b/_code-samples/deposit-preauth/go/rpc/main.go @@ -0,0 +1,214 @@ +package main + +import ( + "encoding/hex" + "fmt" + "time" + + "github.com/Peersyst/xrpl-go/examples/clients" + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/queries/account" + "github.com/Peersyst/xrpl-go/xrpl/queries/common" + rippletime "github.com/Peersyst/xrpl-go/xrpl/time" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + client := clients.GetDevnetRpcClient() + + // Configure wallets + + // Issuer + fmt.Println("Setting up credential issuer wallet...") + issuer, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&issuer) + if err != nil { + panic(err) + } + fmt.Printf("Credential issuer wallet funded: %s\n", issuer.ClassicAddress) + + // ----------------------------------------------------- + + // Holder 1 + fmt.Println("Setting up holder 1 wallet...") + holderWallet1, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&holderWallet1) + if err != nil { + panic(err) + } + fmt.Printf("Holder 1 wallet funded: %s\n", holderWallet1.ClassicAddress) + + // ----------------------------------------------------- + + // Enabling DepositAuth on the issuer account with an AccountSet transaction + fmt.Println("Enabling DepositAuth on the issuer account...") + accountSetTx := &transaction.AccountSet{ + BaseTx: transaction.BaseTx{ + Account: issuer.ClassicAddress, + TransactionType: transaction.AccountSetTx, + }, + } + accountSetTx.SetAsfDepositAuth() + + clients.SubmitTxBlobAndWait(client, accountSetTx, issuer) + + // ----------------------------------------------------- + + // Creating the CredentialCreate transaction + fmt.Println("Creating the CredentialCreate transaction...") + + expiration, err := rippletime.IsoTimeToRippleTime(time.Now().Add(time.Hour * 24).Format(time.RFC3339)) + if err != nil { + panic(err) + } + credentialType := types.CredentialType("6D795F63726564656E7469616C") // my_credential + + credentialCreateTx := &transaction.CredentialCreate{ + BaseTx: transaction.BaseTx{ + Account: issuer.ClassicAddress, + TransactionType: transaction.CredentialCreateTx, + }, + Expiration: uint32(expiration), + CredentialType: credentialType, + Subject: types.Address(holderWallet1.ClassicAddress), + URI: hex.EncodeToString([]byte("https://example.com")), + } + + clients.SubmitTxBlobAndWait(client, credentialCreateTx, issuer) + + // ----------------------------------------------------- + + // Creating the CredentialAccept transaction + fmt.Println("Creating the CredentialAccept transaction...") + + credentialAcceptTx := &transaction.CredentialAccept{ + BaseTx: transaction.BaseTx{ + Account: holderWallet1.ClassicAddress, + TransactionType: transaction.CredentialAcceptTx, + }, + CredentialType: credentialType, + Issuer: types.Address(issuer.ClassicAddress), + } + + clients.SubmitTxBlobAndWait(client, credentialAcceptTx, holderWallet1) + + // ----------------------------------------------------- + + // Creating the DepositPreauth transaction + fmt.Println("Creating the DepositPreauth transaction using AuthorizeCredentials...") + + depositPreauthTx := &transaction.DepositPreauth{ + BaseTx: transaction.BaseTx{ + Account: issuer.ClassicAddress, + TransactionType: transaction.DepositPreauthTx, + }, + AuthorizeCredentials: []types.AuthorizeCredentialsWrapper{ + { + Credential: types.AuthorizeCredentials{ + Issuer: issuer.ClassicAddress, + CredentialType: credentialType, + }, + }, + }, + } + + clients.SubmitTxBlobAndWait(client, depositPreauthTx, issuer) + + // ----------------------------------------------------- + + // Get the credential ID + fmt.Println("Getting the credential ID from the holder 1 account...") + + objectsRequest := &account.ObjectsRequest{ + Account: holderWallet1.ClassicAddress, + Type: account.CredentialObject, + LedgerIndex: common.Validated, + } + + objectsResponse, err := client.GetAccountObjects(objectsRequest) + if err != nil { + panic(err) + } + + // Check if we have any credential objects + if len(objectsResponse.AccountObjects) == 0 { + fmt.Println("No credential objects found") + return + } + + // Extract the credential ID + credentialID, ok := objectsResponse.AccountObjects[0]["index"].(string) + if !ok { + fmt.Println("Could not extract credential ID from response") + return + } + + fmt.Printf("Credential ID: %s\n", credentialID) + fmt.Println() + + // ----------------------------------------------------- + + // Sending XRP to the holder 1 account + fmt.Println("Sending XRP to the issuer account, should succeed...") + + sendTx := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: holderWallet1.ClassicAddress, + TransactionType: transaction.PaymentTx, + }, + Amount: types.XRPCurrencyAmount(1000000), + Destination: issuer.ClassicAddress, + CredentialIDs: types.CredentialIDs{credentialID}, + } + + clients.SubmitTxBlobAndWait(client, sendTx, holderWallet1) + + // ----------------------------------------------------- + + // Unauthorizing the holder 1 account + fmt.Println("Unauthorizing the holder 1 account with the DepositPreauth transaction and the UnauthorizeCredentials field...") + + unauthorizeTx := &transaction.DepositPreauth{ + BaseTx: transaction.BaseTx{ + Account: issuer.ClassicAddress, + TransactionType: transaction.DepositPreauthTx, + }, + UnauthorizeCredentials: []types.AuthorizeCredentialsWrapper{ + { + Credential: types.AuthorizeCredentials{ + Issuer: issuer.ClassicAddress, + CredentialType: credentialType, + }, + }, + }, + } + + clients.SubmitTxBlobAndWait(client, unauthorizeTx, issuer) + + // ----------------------------------------------------- + + // Sending XRP to the holder 1 account again (which should fail) + fmt.Println("Sending XRP to the issuer account again (which should fail)...") + + sendTx2 := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: holderWallet1.ClassicAddress, + TransactionType: transaction.PaymentTx, + }, + Amount: types.XRPCurrencyAmount(1000000), + Destination: issuer.ClassicAddress, + CredentialIDs: types.CredentialIDs{credentialID}, + } + + clients.SubmitTxBlobAndWait(client, sendTx2, holderWallet1) +} diff --git a/_code-samples/deposit-preauth/go/ws/main.go b/_code-samples/deposit-preauth/go/ws/main.go new file mode 100644 index 0000000000..95d9842b7d --- /dev/null +++ b/_code-samples/deposit-preauth/go/ws/main.go @@ -0,0 +1,227 @@ +package main + +import ( + "encoding/hex" + "fmt" + "time" + + "github.com/Peersyst/xrpl-go/examples/clients" + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/queries/account" + "github.com/Peersyst/xrpl-go/xrpl/queries/common" + rippletime "github.com/Peersyst/xrpl-go/xrpl/time" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + + fmt.Println("Setting up client...") + + client := clients.GetDevnetWebsocketClient() + fmt.Println("Connecting to server...") + if err := client.Connect(); err != nil { + panic(err) + } + + fmt.Println("Client configured!") + fmt.Println() + + fmt.Printf("Connection: %t", client.IsConnected()) + fmt.Println() + + // Configure wallets + + // Issuer + fmt.Println("Setting up credential issuer wallet...") + issuer, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&issuer) + if err != nil { + panic(err) + } + fmt.Printf("Credential issuer wallet funded: %s\n", issuer.ClassicAddress) + + // ----------------------------------------------------- + + // Holder 1 + fmt.Println("Setting up holder 1 wallet...") + holderWallet1, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&holderWallet1) + if err != nil { + panic(err) + } + fmt.Printf("Holder 1 wallet funded: %s\n", holderWallet1.ClassicAddress) + + // ----------------------------------------------------- + + // Enabling DepositAuth on the issuer account with an AccountSet transaction + fmt.Println("Enabling DepositAuth on the issuer account...") + accountSetTx := &transaction.AccountSet{ + BaseTx: transaction.BaseTx{ + Account: issuer.ClassicAddress, + TransactionType: transaction.AccountSetTx, + }, + } + accountSetTx.SetAsfDepositAuth() + + clients.SubmitTxBlobAndWait(client, accountSetTx, issuer) + + // ----------------------------------------------------- + + // Creating the CredentialCreate transaction + fmt.Println("Creating the CredentialCreate transaction...") + + expiration, err := rippletime.IsoTimeToRippleTime(time.Now().Add(time.Hour * 24).Format(time.RFC3339)) + if err != nil { + panic(err) + } + credentialType := types.CredentialType("6D795F63726564656E7469616C") // my_credential + + credentialCreateTx := &transaction.CredentialCreate{ + BaseTx: transaction.BaseTx{ + Account: issuer.ClassicAddress, + TransactionType: transaction.CredentialCreateTx, + }, + Expiration: uint32(expiration), + CredentialType: credentialType, + Subject: types.Address(holderWallet1.ClassicAddress), + URI: hex.EncodeToString([]byte("https://example.com")), + } + + clients.SubmitTxBlobAndWait(client, credentialCreateTx, issuer) + + // ----------------------------------------------------- + + // Creating the CredentialAccept transaction + fmt.Println("Creating the CredentialAccept transaction...") + + credentialAcceptTx := &transaction.CredentialAccept{ + BaseTx: transaction.BaseTx{ + Account: holderWallet1.ClassicAddress, + TransactionType: transaction.CredentialAcceptTx, + }, + CredentialType: credentialType, + Issuer: types.Address(issuer.ClassicAddress), + } + + clients.SubmitTxBlobAndWait(client, credentialAcceptTx, holderWallet1) + + // ----------------------------------------------------- + + // Creating the DepositPreauth transaction + fmt.Println("Creating the DepositPreauth transaction using AuthorizeCredentials...") + + depositPreauthTx := &transaction.DepositPreauth{ + BaseTx: transaction.BaseTx{ + Account: issuer.ClassicAddress, + TransactionType: transaction.DepositPreauthTx, + }, + AuthorizeCredentials: []types.AuthorizeCredentialsWrapper{ + { + Credential: types.AuthorizeCredentials{ + Issuer: issuer.ClassicAddress, + CredentialType: credentialType, + }, + }, + }, + } + + clients.SubmitTxBlobAndWait(client, depositPreauthTx, issuer) + + // ----------------------------------------------------- + + // Get the credential ID + fmt.Println("Getting the credential ID from the holder 1 account...") + + objectsRequest := &account.ObjectsRequest{ + Account: holderWallet1.ClassicAddress, + Type: account.CredentialObject, + LedgerIndex: common.Validated, + } + + objectsResponse, err := client.GetAccountObjects(objectsRequest) + if err != nil { + panic(err) + } + + // Check if we have any credential objects + if len(objectsResponse.AccountObjects) == 0 { + fmt.Println("No credential objects found") + return + } + + // Extract the credential ID + credentialID, ok := objectsResponse.AccountObjects[0]["index"].(string) + if !ok { + fmt.Println("Could not extract credential ID from response") + return + } + + fmt.Printf("Credential ID: %s\n", credentialID) + fmt.Println() + + // ----------------------------------------------------- + + // Sending XRP to the holder 1 account + fmt.Println("Sending XRP to the issuer account, should succeed...") + + sendTx := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: holderWallet1.ClassicAddress, + TransactionType: transaction.PaymentTx, + }, + Amount: types.XRPCurrencyAmount(1000000), + Destination: issuer.ClassicAddress, + CredentialIDs: types.CredentialIDs{credentialID}, + } + + clients.SubmitTxBlobAndWait(client, sendTx, holderWallet1) + + // ----------------------------------------------------- + + // Unauthorize the holder 1 account + fmt.Println("Unauthorize the holder 1 account with the DepositPreauth transaction and the UnauthorizeCredentials field...") + + unauthorizeTx := &transaction.DepositPreauth{ + BaseTx: transaction.BaseTx{ + Account: issuer.ClassicAddress, + TransactionType: transaction.DepositPreauthTx, + }, + UnauthorizeCredentials: []types.AuthorizeCredentialsWrapper{ + { + Credential: types.AuthorizeCredentials{ + Issuer: issuer.ClassicAddress, + CredentialType: credentialType, + }, + }, + }, + } + + clients.SubmitTxBlobAndWait(client, unauthorizeTx, issuer) + + // ----------------------------------------------------- + + // Sending XRP to the holder 1 account again (which should fail) + fmt.Println("Sending XRP to the issuer account again (which should fail)...") + + sendTx2 := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: holderWallet1.ClassicAddress, + TransactionType: transaction.PaymentTx, + }, + Amount: types.XRPCurrencyAmount(1000000), + Destination: issuer.ClassicAddress, + CredentialIDs: types.CredentialIDs{credentialID}, + } + + clients.SubmitTxBlobAndWait(client, sendTx2, holderWallet1) +} diff --git a/_code-samples/freeze/go/go.mod b/_code-samples/freeze/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/freeze/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/freeze/go/go.sum b/_code-samples/freeze/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/freeze/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/freeze/go/rpc/main.go b/_code-samples/freeze/go/rpc/main.go new file mode 100644 index 0000000000..c8b72e6527 --- /dev/null +++ b/_code-samples/freeze/go/rpc/main.go @@ -0,0 +1,335 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/currency" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + transactions "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +const ( + currencyCode = "USDA" +) + +type SubmittableTransaction interface { + TxType() transactions.TxType + Flatten() transactions.FlatTransaction // Ensures all transactions can be flattened +} + +func main() { + client := getRpcClient() + + // Configure wallets + + // Issuer + fmt.Println("Setting up issuer wallet...") + issuer, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&issuer) + if err != nil { + panic(err) + } + fmt.Printf("Issuer wallet funded: %s\n", issuer.ClassicAddress) + + // ----------------------------------------------------- + + // Holder 1 + fmt.Println("Setting up holder 1 wallet...") + holderWallet1, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&holderWallet1) + if err != nil { + panic(err) + } + fmt.Printf("Holder wallet 1 funded: %s\n", holderWallet1.ClassicAddress) + + // ----------------------------------------------------- + + // Holder 2 + fmt.Println("Setting up holder 2 wallet...") + holderWallet2, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&holderWallet2) + if err != nil { + panic(err) + } + fmt.Printf("Holder wallet 2 funded: %s\n", holderWallet2.ClassicAddress) + fmt.Println() + + fmt.Println("Wallets setup complete!") + fmt.Println() + + // ----------------------------------------------------- + + // Configuring Issuing account + fmt.Println("Configuring issuer address settings...") + accountSet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + Domain: types.Domain("697373756572"), // issuer + } + + accountSet.SetAsfDefaultRipple() + submitAndWait(client, accountSet, issuer) + + // ----------------------------------------------------- + + // Trustline from the holder 1 to the issuer + fmt.Println("Setting up trustline from holder 1 to the issuer...") + trustSet := &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet1.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "1000000000", + }} + trustSet.SetSetNoRippleFlag() + submitAndWait(client, trustSet, holderWallet1) + + // ----------------------------------------------------- + + // Trustline from the holder 2 to the issuer + fmt.Println("Setting up trustline from holder 2 to the issuer...") + trustSet = &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet2.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "1000000000", + }, + } + trustSet.SetSetNoRippleFlag() + submitAndWait(client, trustSet, holderWallet2) + + // ----------------------------------------------------- + + // Minting to Holder 1 + fmt.Println("Minting to Holder 1...") + payment := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + Destination: types.Address(holderWallet1.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "50000", + }, + } + submitAndWait(client, payment, issuer) + + // ----------------------------------------------------- + + // Minting to Holder 2 + fmt.Println("Minting to Holder 2...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + Destination: types.Address(holderWallet2.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "40000", + }, + } + submitAndWait(client, payment, issuer) + + // ----------------------------------------------------- + + // Sending payment from Holder 1 to Holder 2 + fmt.Println("Sending payment from Holder 1 to Holder 2...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet1.ClassicAddress), + }, + Destination: types.Address(holderWallet2.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "20", + }, + } + submitAndWait(client, payment, holderWallet1) + + // ----------------------------------------------------- + + // Freezing and Deep Freezing holder1 + fmt.Println("Freezing and Deep Freezing holder 1 trustline...") + trustSet = &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(holderWallet1.ClassicAddress), + Value: "0", + }, + } + trustSet.SetSetFreezeFlag() + trustSet.SetSetDeepFreezeFlag() + + submitAndWait(client, trustSet, issuer) + + // ------------------- SHOULD FAIL ------------------ + + // Sending payment from Holder 1 to Holder 2 (which should fail), Holder 1 can't decrease its balance + fmt.Println("Sending payment from Holder 1 to Holder 2 (which should fail). Holder 1 can't decrease its balance...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet1.ClassicAddress), + }, + Destination: types.Address(holderWallet2.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "10", + }, + } + submitAndWait(client, payment, holderWallet1) + + // ------------------- SHOULD FAIL ------------------ + + // Sending payment from Holder 2 to Holder 1 (which should fail), Holder 1 can't increase its balance + fmt.Println("Sending payment from Holder 2 to Holder 1 (which should fail). Holder 1 can't increase its balance...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet2.ClassicAddress), + }, + Destination: types.Address(holderWallet1.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "10", + }, + } + submitAndWait(client, payment, holderWallet2) + + // ------------------- SHOULD FAIL ------------------ + + // Creating OfferCreate transaction (which should fail), Holder 1 can't create an offer + fmt.Println("Creating OfferCreate transaction (which should fail). Holder 1 can't create an offer...") + offerCreate := &transactions.OfferCreate{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet1.ClassicAddress), + }, + TakerPays: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "10", + }, + TakerGets: types.XRPCurrencyAmount(10), + } + submitAndWait(client, offerCreate, holderWallet1) + + // ----------------------------------------------------- + + // Unfreezing and Deep Unfreezing holder 1 + fmt.Println("Unfreezing and Deep Unfreezing holder 1 trustline...") + trustSet = &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(holderWallet1.ClassicAddress), + Value: "0", + }, + } + trustSet.SetClearFreezeFlag() + trustSet.SetClearDeepFreezeFlag() + submitAndWait(client, trustSet, issuer) + + // ----------------------------------------------------- + + // Sending payment from Holder 1 to Holder 2 (which should succeed), Holder 1 can decrease its balance + fmt.Println("Sending payment from Holder 1 to Holder 2 (which should succeed). Holder 1 can decrease its balance...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet1.ClassicAddress), + }, + Destination: types.Address(holderWallet2.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "10", + }, + } + submitAndWait(client, payment, holderWallet1) + + // ----------------------------------------------------- + + // Sending payment from Holder 2 to Holder 1 (which should succeed), Holder 1 can increase its balance + fmt.Println("Sending payment from Holder 2 to Holder 1 (which should succeed). Holder 1 can increase its balance...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet2.ClassicAddress), + }, + Destination: types.Address(holderWallet1.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "10", + }, + } + submitAndWait(client, payment, holderWallet2) +} + +// getRpcClient returns a new rpc client +func getRpcClient() *rpc.Client { + cfg, err := rpc.NewClientConfig( + // DeepFreeze only available on Devnet as of February 2025, change to testnet/mainnet once the amendment passes. + "https://s.devnet.rippletest.net:51234", + rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + return rpc.NewClient(cfg) +} + +// submitAndWait submits a transaction and waits for it to be included in a validated ledger +func submitAndWait(client *rpc.Client, txn SubmittableTransaction, wallet wallet.Wallet) { + fmt.Printf("Submitting %s transaction...\n", txn.TxType()) + + flattenedTx := txn.Flatten() + + err := client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err := wallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err := client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + fmt.Printf("%s transaction submitted\n", txn.TxType()) + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() +} diff --git a/_code-samples/freeze/go/ws/main.go b/_code-samples/freeze/go/ws/main.go new file mode 100644 index 0000000000..5ea6c2a780 --- /dev/null +++ b/_code-samples/freeze/go/ws/main.go @@ -0,0 +1,344 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/currency" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + transactions "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +const ( + currencyCode = "USDA" +) + +type SubmittableTransaction interface { + TxType() transactions.TxType + Flatten() transactions.FlatTransaction // Ensures all transactions can be flattened +} + +func main() { + fmt.Println("Setting up client...") + + client := getClient() + fmt.Println("Connecting to server...") + if err := client.Connect(); err != nil { + panic(err) + } + + fmt.Println("Client configured!") + fmt.Println() + + fmt.Printf("Connection: %t", client.IsConnected()) + fmt.Println() + + // Configure wallets + + // Issuer + fmt.Println("Setting up issuer wallet...") + issuer, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&issuer) + if err != nil { + panic(err) + } + fmt.Printf("Issuer wallet funded: %s\n", issuer.ClassicAddress) + + // ----------------------------------------------------- + + // Holder 1 + fmt.Println("Setting up holder 1 wallet...") + holderWallet1, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&holderWallet1) + if err != nil { + panic(err) + } + fmt.Printf("Holder wallet 1 funded: %s\n", holderWallet1.ClassicAddress) + + // ----------------------------------------------------- + + // Holder 2 + fmt.Println("Setting up holder 2 wallet...") + holderWallet2, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + err = client.FundWallet(&holderWallet2) + if err != nil { + panic(err) + } + fmt.Printf("Holder wallet 2 funded: %s\n", holderWallet2.ClassicAddress) + fmt.Println() + + fmt.Println("Wallets setup complete!") + fmt.Println() + + // ----------------------------------------------------- + + // Configuring Issuing account + fmt.Println("Configuring issuer address settings...") + accountSet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + Domain: types.Domain("697373756572"), // issuer + } + + accountSet.SetAsfDefaultRipple() + submitAndWait(client, accountSet, issuer) + + // ----------------------------------------------------- + + // Trustline from the holder 1 to the issuer + fmt.Println("Setting up trustline from holder 1 to the issuer...") + trustSet := &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet1.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "1000000000", + }} + trustSet.SetSetNoRippleFlag() + submitAndWait(client, trustSet, holderWallet1) + + // ----------------------------------------------------- + + // Trustline from the holder 2 to the issuer + fmt.Println("Setting up trustline from holder 2 to the issuer...") + trustSet = &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet2.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "1000000000", + }, + } + trustSet.SetSetNoRippleFlag() + submitAndWait(client, trustSet, holderWallet2) + + // ----------------------------------------------------- + + // Minting to Holder 1 + fmt.Println("Minting to Holder 1...") + payment := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + Destination: types.Address(holderWallet1.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "50000", + }, + } + submitAndWait(client, payment, issuer) + + // ----------------------------------------------------- + + // Minting to Holder 2 + fmt.Println("Minting to Holder 2...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + Destination: types.Address(holderWallet2.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "40000", + }, + } + submitAndWait(client, payment, issuer) + + // ----------------------------------------------------- + + // Sending payment from Holder 1 to Holder 2 + fmt.Println("Sending payment from Holder 1 to Holder 2...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet1.ClassicAddress), + }, + Destination: types.Address(holderWallet2.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "20", + }, + } + submitAndWait(client, payment, holderWallet1) + + // ----------------------------------------------------- + + // Freezing and Deep Freezing holder1 + fmt.Println("Freezing and Deep Freezing holder 1 trustline...") + trustSet = &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(holderWallet1.ClassicAddress), + Value: "0", + }, + } + trustSet.SetSetFreezeFlag() + trustSet.SetSetDeepFreezeFlag() + + submitAndWait(client, trustSet, issuer) + + // ------------------- SHOULD FAIL ------------------ + + // Sending payment from Holder 1 to Holder 2 (which should fail), Holder 1 can't decrease its balance + fmt.Println("Sending payment from Holder 1 to Holder 2 (which should fail). Holder 1 can't decrease its balance...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet1.ClassicAddress), + }, + Destination: types.Address(holderWallet2.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "10", + }, + } + submitAndWait(client, payment, holderWallet1) + + // ------------------- SHOULD FAIL ------------------ + + // Sending payment from Holder 2 to Holder 1 (which should fail), Holder 1 can't increase its balance + fmt.Println("Sending payment from Holder 2 to Holder 1 (which should fail). Holder 1 can't increase its balance...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet2.ClassicAddress), + }, + Destination: types.Address(holderWallet1.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "10", + }, + } + submitAndWait(client, payment, holderWallet2) + + // ------------------- SHOULD FAIL ------------------ + + // Creating OfferCreate transaction (which should fail), Holder 1 can't create an offer + fmt.Println("Creating OfferCreate transaction (which should fail). Holder 1 can't create an offer...") + offerCreate := &transactions.OfferCreate{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet1.ClassicAddress), + }, + TakerPays: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "10", + }, + TakerGets: types.XRPCurrencyAmount(10), + } + submitAndWait(client, offerCreate, holderWallet1) + + // ----------------------------------------------------- + + // Unfreezing and Deep Unfreezing holder 1 + fmt.Println("Unfreezing and Deep Unfreezing holder 1 trustline...") + trustSet = &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(issuer.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(holderWallet1.ClassicAddress), + Value: "0", + }, + } + trustSet.SetClearFreezeFlag() + trustSet.SetClearDeepFreezeFlag() + submitAndWait(client, trustSet, issuer) + + // ----------------------------------------------------- + + // Sending payment from Holder 1 to Holder 2 (which should succeed), Holder 1 can decrease its balance + fmt.Println("Sending payment from Holder 1 to Holder 2 (which should succeed). Holder 1 can decrease its balance...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet1.ClassicAddress), + }, + Destination: types.Address(holderWallet2.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "10", + }, + } + submitAndWait(client, payment, holderWallet1) + + // ----------------------------------------------------- + + // Sending payment from Holder 2 to Holder 1 (which should succeed), Holder 1 can increase its balance + fmt.Println("Sending payment from Holder 2 to Holder 1 (which should succeed). Holder 1 can increase its balance...") + payment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(holderWallet2.ClassicAddress), + }, + Destination: types.Address(holderWallet1.ClassicAddress), + Amount: types.IssuedCurrencyAmount{ + Currency: currency.ConvertStringToHex(currencyCode), + Issuer: types.Address(issuer.ClassicAddress), + Value: "10", + }, + } + submitAndWait(client, payment, holderWallet2) +} + +// getRpcClient returns a new rpc client +func getClient() *websocket.Client { + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.devnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + + return client +} + +// submitAndWait submits a transaction and waits for it to be included in a validated ledger +func submitAndWait(client *websocket.Client, txn SubmittableTransaction, wallet wallet.Wallet) { + fmt.Printf("Submitting %s transaction...\n", txn.TxType()) + + flattenedTx := txn.Flatten() + + err := client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err := wallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err := client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + fmt.Printf("%s transaction submitted\n", txn.TxType()) + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() +} diff --git a/_code-samples/get-started/README.md b/_code-samples/get-started/README.md index b953a5d5b5..ef6de058b4 100644 --- a/_code-samples/get-started/README.md +++ b/_code-samples/get-started/README.md @@ -8,3 +8,4 @@ For more context, see the Get Started tutorial for your preferred language: - [Java](https://xrpl.org/get-started-using-java.html) - [JavaScript](https://xrpl.org/get-started-using-javascript.html) - [PHP](https://xrpl.org/get-started-using-php.html) +- [Go](https://xrpl.org/get-started-using-go.html) diff --git a/_code-samples/get-started/go/base/rpc/main.go b/_code-samples/get-started/go/base/rpc/main.go new file mode 100644 index 0000000000..c25428ad88 --- /dev/null +++ b/_code-samples/get-started/go/base/rpc/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/queries/utility" + "github.com/Peersyst/xrpl-go/xrpl/rpc" +) + +func main() { + // Define the network client configuration + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + // Initiate the network client + client := rpc.NewClient(cfg) + + // Ping the network (used to avoid Go unused variable error, but useful to check connectivity) + _, err = client.Ping(&utility.PingRequest{}) + if err != nil { + panic(err) + } + + // ... custom code goes here + +} diff --git a/_code-samples/get-started/go/base/ws/main.go b/_code-samples/get-started/go/base/ws/main.go new file mode 100644 index 0000000000..ddfe3f3ecf --- /dev/null +++ b/_code-samples/get-started/go/base/ws/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +func main() { + + // Define the network client + client := websocket.NewClient(websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + + // Disconnect the client when done. (Defer executes at the end of the function) + defer client.Disconnect() + + // Connect to the network + if err := client.Connect(); err != nil { + panic(err) + } + + // ... custom code goes here +} diff --git a/_code-samples/get-started/go/get-acc-info/rpc/main.go b/_code-samples/get-started/go/get-acc-info/rpc/main.go new file mode 100644 index 0000000000..dbc0bd50e2 --- /dev/null +++ b/_code-samples/get-started/go/get-acc-info/rpc/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/queries/account" + "github.com/Peersyst/xrpl-go/xrpl/queries/common" + "github.com/Peersyst/xrpl-go/xrpl/queries/ledger" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + // Define the network client with a faucet provider + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + client := rpc.NewClient(cfg) + + // Create a new wallet + w, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + fmt.Println("New wallet created:") + fmt.Println("Address:", w.ClassicAddress) + + // Fund the wallet with testnet XRP + if err := client.FundWallet(&w); err != nil { + panic(err) + } + + // Get info from the ledger about the address we just funded + acc_info, err := client.GetAccountInfo(&account.InfoRequest{ + Account: w.GetAddress(), + }) + if err != nil { + panic(err) + } + fmt.Println("Account Balance:", acc_info.AccountData.Balance) + fmt.Println("Account Sequence:", acc_info.AccountData.Sequence) + + // Get info about the ledger + ledger, err := client.GetLedger(&ledger.Request{LedgerIndex: common.Current}) + if err != nil { + panic(err) + } + fmt.Println("Ledger Index:", ledger.Ledger.LedgerIndex) +} diff --git a/_code-samples/get-started/go/get-acc-info/ws/main.go b/_code-samples/get-started/go/get-acc-info/ws/main.go new file mode 100644 index 0000000000..ae15744308 --- /dev/null +++ b/_code-samples/get-started/go/get-acc-info/ws/main.go @@ -0,0 +1,69 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/queries/account" + "github.com/Peersyst/xrpl-go/xrpl/queries/common" + "github.com/Peersyst/xrpl-go/xrpl/queries/ledger" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +func main() { + + // Define the network client with a faucet provider + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + + // Disconnect the client when done. (Defer executes at the end of the function) + defer client.Disconnect() + + // Connect to the network + if err := client.Connect(); err != nil { + panic(err) + } + + if !client.IsConnected() { + fmt.Println("Failed to connect to testnet") + return + } + + fmt.Println("Connected to testnet") + fmt.Println() + + // Create a new wallet + w, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + fmt.Println("New wallet created:") + fmt.Println("Address:", w.ClassicAddress) + + // Fund the wallet with testnet XRP + if err := client.FundWallet(&w); err != nil { + panic(err) + } + + // Get info from the ledger about the address we just funded + acc_info, err := client.GetAccountInfo(&account.InfoRequest{ + Account: w.GetAddress(), + }) + if err != nil { + panic(err) + } + fmt.Println("Account Balance:", acc_info.AccountData.Balance) + fmt.Println("Account Sequence:", acc_info.AccountData.Sequence) + + // Get info about the ledger + ledger, err := client.GetLedger(&ledger.Request{LedgerIndex: common.Current}) + if err != nil { + panic(err) + } + fmt.Println("Ledger Index:", ledger.Ledger.LedgerIndex) +} diff --git a/_code-samples/get-started/go/go.mod b/_code-samples/get-started/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/get-started/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/get-started/go/go.sum b/_code-samples/get-started/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/get-started/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/get-started/js/README.md b/_code-samples/get-started/js/README.md new file mode 100644 index 0000000000..f96921f960 --- /dev/null +++ b/_code-samples/get-started/js/README.md @@ -0,0 +1,135 @@ +# Get Started Using JavaScript Library + +Connects to the XRP Ledger, gets account information, and subscribes to ledger events using JavaScript. + +To download the source code, see [Get Started Using JavaScript Library](http://xrpl.org/docs/tutorials/javascript/build-apps/get-started). + +## Run the Code + +**Node.js** + +Quick setup and usage: + +```sh +npm install +node ./get-acct-info.js +``` + +You should see output similar to the following: + +```sh +Connected to Testnet + +Creating a new wallet and funding it with Testnet XRP... +Wallet: rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i +Balance: 10 + +Account Testnet Explorer URL: +https://testnet.xrpl.org/accounts/rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i + +Getting account info... +{ + "api_version": 2, + "id": 4, + "result": { + "account_data": { + "Account": "rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i", + "Balance": "10000000", + "Flags": 0, + "LedgerEntryType": "AccountRoot", + "OwnerCount": 0, + "PreviousTxnID": "0FF9DB2FE141DD0DF82566A171B6AF70BB2C6EB6A53D496E65D42FC062C91A78", + "PreviousTxnLgrSeq": 9949268, + "Sequence": 9949268, + "index": "4A9C9220AE778DC38C004B2B17A08E218416D90E01456AFCF844C18838B36D01" + }, + "account_flags": { + "allowTrustLineClawback": false, + "defaultRipple": false, + "depositAuth": false, + "disableMasterKey": false, + "disallowIncomingCheck": false, + "disallowIncomingNFTokenOffer": false, + "disallowIncomingPayChan": false, + "disallowIncomingTrustline": false, + "disallowIncomingXRP": false, + "globalFreeze": false, + "noFreeze": false, + "passwordSpent": false, + "requireAuthorization": false, + "requireDestinationTag": false + }, + "ledger_hash": "304C7CC2A33B712BE43EB398B399E290C191A71FCB71784F584544DFB7C441B0", + "ledger_index": 9949268, + "validated": true + }, + "type": "response" +} + +Listening for ledger close events... +Ledger #9949269 validated with 0 transactions! +Ledger #9949270 validated with 0 transactions! +Ledger #9949271 validated with 0 transactions! + +Disconnected +``` + +**Web** + +To run the web example, open `index.html` in a web browser and wait for the results to appear on the page. + +You should see output similar to the following: + +```text +Connected to Testnet +Creating a new wallet and funding it with Testnet XRP... +Wallet: rf7CWJdNssSzQk2GtypYLVhyvGe8oHS3S +Balance: 10 +View account on XRPL Testnet Explorer: rf7CWJdNssSzQk2GtypYLVhyvGe8oHS3S + +Getting account info... +{ + "api_version": 2, + "id": 5, + "result": { + "account_data": { + "Account": "rf7CWJdNssSzQk2GtypYLVhyvGe8oHS3S", + "Balance": "10000000", + "Flags": 0, + "LedgerEntryType": "AccountRoot", + "OwnerCount": 0, + "PreviousTxnID": "96E4B44F93EC0399B7ADD75489630C6A8DCFC922F20F6810D25490CC0D3AA12E", + "PreviousTxnLgrSeq": 9949610, + "Sequence": 9949610, + "index": "B5D2865DD4BF8EEDFEE2FD95DE37FC28D624548E9BBC42F9FBF61B618E98FAC8" + }, + "account_flags": { + "allowTrustLineClawback": false, + "defaultRipple": false, + "depositAuth": false, + "disableMasterKey": false, + "disallowIncomingCheck": false, + "disallowIncomingNFTokenOffer": false, + "disallowIncomingPayChan": false, + "disallowIncomingTrustline": false, + "disallowIncomingXRP": false, + "globalFreeze": false, + "noFreeze": false, + "passwordSpent": false, + "requireAuthorization": false, + "requireDestinationTag": false + }, + "ledger_hash": "7692673B8091899C3EEE6807F66B65851D3563F483A49A5F03A83608658473D6", + "ledger_index": 9949610, + "validated": true + }, + "type": "response" +} + +Listening for ledger close events... +Ledger #9949611 validated with 0 transactions +Ledger #9949612 validated with 1 transactions +Ledger #9949613 validated with 0 transactions + +Disconnected +``` diff --git a/_code-samples/get-started/js/base.js b/_code-samples/get-started/js/base.js index 8b5238234f..9c02b161d3 100644 --- a/_code-samples/get-started/js/base.js +++ b/_code-samples/get-started/js/base.js @@ -1,17 +1,11 @@ -// In browsers, use a + + + +

XRPL.js Get Started

+
+ + + + diff --git a/_code-samples/get-started/js/package.json b/_code-samples/get-started/js/package.json index 58e2ddda32..43c89bf1e0 100644 --- a/_code-samples/get-started/js/package.json +++ b/_code-samples/get-started/js/package.json @@ -1,5 +1,6 @@ { "dependencies": { - "xrpl": "^4.0.0" - } + "xrpl": "^4.4.0" + }, + "type": "module" } diff --git a/_code-samples/get-tx/go/go.mod b/_code-samples/get-tx/go/go.mod new file mode 100644 index 0000000000..4643f9f714 --- /dev/null +++ b/_code-samples/get-tx/go/go.mod @@ -0,0 +1,23 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/get-tx/go/go.sum b/_code-samples/get-tx/go/go.sum new file mode 100644 index 0000000000..44302b3a35 --- /dev/null +++ b/_code-samples/get-tx/go/go.sum @@ -0,0 +1,56 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/get-tx/go/main.go b/_code-samples/get-tx/go/main.go new file mode 100644 index 0000000000..dfac0b27d0 --- /dev/null +++ b/_code-samples/get-tx/go/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/xrpl/queries/common" + "github.com/Peersyst/xrpl-go/xrpl/queries/ledger" + "github.com/Peersyst/xrpl-go/xrpl/queries/transactions" + "github.com/Peersyst/xrpl-go/xrpl/rpc" +) + +func main() { + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + + // Get the latest validated ledger + led, err := client.GetLedger(&ledger.Request{ + Transactions: true, + LedgerIndex: common.Validated, + }) + if err != nil { + panic(err) + } + fmt.Println("Latest validated ledger:", led) + + // Get the first transaction hash from the ledger + if len(led.Ledger.Transactions) > 0 { + txHash := led.Ledger.Transactions[0].(string) // type assertion may be needed + + // Query the transaction details + txResp, err := client.Request(&transactions.TxRequest{ + Transaction: txHash, + }) + if err != nil { + panic(err) + } + fmt.Println("First transaction in the ledger:") + fmt.Println(txResp) + } +} diff --git a/_code-samples/issue-a-token/go/go.mod b/_code-samples/issue-a-token/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/issue-a-token/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/issue-a-token/go/go.sum b/_code-samples/issue-a-token/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/issue-a-token/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/issue-a-token/go/rpc/main.go b/_code-samples/issue-a-token/go/rpc/main.go new file mode 100644 index 0000000000..c9ae903a82 --- /dev/null +++ b/_code-samples/issue-a-token/go/rpc/main.go @@ -0,0 +1,488 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + transactions "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +const ( + currencyCode = "FOO" +) + +func main() { + // + // Configure client + // + fmt.Println("Setting up client...") + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + fmt.Println("Client configured!") + fmt.Println() + + // + // Configure wallets + // + fmt.Println("Setting up wallets...") + coldWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + err = client.FundWallet(&coldWallet) + if err != nil { + panic(err) + } + fmt.Println("Cold wallet funded!") + + hotWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + err = client.FundWallet(&hotWallet) + if err != nil { + panic(err) + } + fmt.Println("Hot wallet funded!") + + customerOneWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + err = client.FundWallet(&customerOneWallet) + if err != nil { + panic(err) + } + fmt.Println("Customer one wallet funded!") + fmt.Println() + + fmt.Println("Wallets setup complete!") + fmt.Println("Cold wallet:", coldWallet.ClassicAddress) + fmt.Println("Hot wallet:", hotWallet.ClassicAddress) + fmt.Println("Customer one wallet:", customerOneWallet.ClassicAddress) + fmt.Println() + + // + // Configure cold address settings + // + fmt.Println("Configuring cold address settings...") + coldWalletAccountSet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + TickSize: types.TickSize(5), + TransferRate: types.TransferRate(0), + Domain: types.Domain("6578616D706C652E636F6D"), // example.com + } + + coldWalletAccountSet.SetAsfDefaultRipple() + coldWalletAccountSet.SetDisallowXRP() + + coldWalletAccountSet.SetRequireDestTag() + + flattenedTx := coldWalletAccountSet.Flatten() + + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err := coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err := client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Cold address settings configuration failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Cold address settings configured!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Configure hot address settings + // + fmt.Println("Configuring hot address settings...") + hotWalletAccountSet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(hotWallet.ClassicAddress), + }, + Domain: types.Domain("6578616D706C652E636F6D"), // example.com + } + + hotWalletAccountSet.SetAsfRequireAuth() + hotWalletAccountSet.SetDisallowXRP() + hotWalletAccountSet.SetRequireDestTag() + + flattenedTx = hotWalletAccountSet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = hotWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Hot address settings configuration failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Hot address settings configured!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Create trust line from hot to cold address + // + fmt.Println("Creating trust line from hot to cold address...") + hotColdTrustSet := &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(hotWallet.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100000000000000", + }, + } + + flattenedTx = hotColdTrustSet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = hotWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Trust line from hot to cold address creation failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Trust line from hot to cold address created!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Create trust line from costumer one to cold address + // + fmt.Println("Creating trust line from customer one to cold address...") + customerOneColdTrustSet := &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(customerOneWallet.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100000000000000", + }, + } + + flattenedTx = customerOneColdTrustSet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = customerOneWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Trust line from customer one to cold address creation failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Trust line from customer one to cold address created!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Send tokens from cold wallet to hot wallet + // + fmt.Println("Sending tokens from cold wallet to hot wallet...") + coldToHotPayment := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "3800", + }, + Destination: types.Address(hotWallet.ClassicAddress), + DestinationTag: types.DestinationTag(1), + } + + flattenedTx = coldToHotPayment.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Tokens not sent from cold wallet to hot wallet!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Tokens sent from cold wallet to hot wallet!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Send tokens from hot wallet to customer one + // + fmt.Println("Sending tokens from cold wallet to customer one...") + coldToCustomerOnePayment := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100", + }, + Destination: types.Address(customerOneWallet.ClassicAddress), + } + + flattenedTx = coldToCustomerOnePayment.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Tokens not sent from cold wallet to customer one!") + fmt.Println() + return + } + + fmt.Println("Tokens sent from cold wallet to customer one!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Freeze cold wallet + // + fmt.Println("Freezing cold wallet...") + freezeColdWallet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + } + + freezeColdWallet.SetAsfGlobalFreeze() + + flattenedTx = freezeColdWallet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Cold wallet freezing failed!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + return + } + + fmt.Println("Cold wallet frozen!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Try to send tokens from hot wallet to customer one + // + fmt.Println("Trying to send tokens from hot wallet to customer one...") + hotToCustomerOnePayment := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(hotWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100", + }, + Destination: types.Address(customerOneWallet.ClassicAddress), + } + + flattenedTx = hotToCustomerOnePayment.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = hotWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + _, err = client.SubmitTxBlobAndWait(txBlob, false) + if err == nil { + return + } + + fmt.Println("Tokens not sent from hot wallet to customer one!") + fmt.Println() + + // // + // // Unfreeze cold wallet + // // + fmt.Println("Unfreezing cold wallet...") + unfreezeColdWallet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + } + + unfreezeColdWallet.ClearAsfGlobalFreeze() + + flattenedTx = unfreezeColdWallet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Cold wallet unfreezing failed!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + return + } + + fmt.Println("Cold wallet unfrozen!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Try to send tokens from hot wallet to customer one + // + fmt.Println("Trying to send tokens from hot wallet to customer one...") + hotToCustomerOnePayment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(hotWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100", + }, + Destination: types.Address(customerOneWallet.ClassicAddress), + } + + flattenedTx = hotToCustomerOnePayment.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = hotWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Tokens not sent from hot wallet to customer one!") + fmt.Println("Try again!") + return + } + + fmt.Println("Tokens sent from hot wallet to customer one!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() +} diff --git a/_code-samples/issue-a-token/go/ws/main.go b/_code-samples/issue-a-token/go/ws/main.go new file mode 100644 index 0000000000..99dd464013 --- /dev/null +++ b/_code-samples/issue-a-token/go/ws/main.go @@ -0,0 +1,493 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + transactions "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +const ( + currencyCode = "FOO" +) + +func main() { + // + // Configure client + // + fmt.Println("Setting up client...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + defer client.Disconnect() + fmt.Println("Client configured!") + fmt.Println() + + fmt.Println("Connecting to server...") + if err := client.Connect(); err != nil { + panic(err) + } + + fmt.Println("Connection: ", client.IsConnected()) + fmt.Println() + + // + // Configure wallets + // + fmt.Println("Setting up wallets...") + coldWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + err = client.FundWallet(&coldWallet) + if err != nil { + panic(err) + } + fmt.Println("Cold wallet funded!") + + hotWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + err = client.FundWallet(&hotWallet) + if err != nil { + panic(err) + } + fmt.Println("Hot wallet funded!") + + customerOneWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + err = client.FundWallet(&customerOneWallet) + if err != nil { + panic(err) + } + fmt.Println("Customer one wallet funded!") + fmt.Println() + + fmt.Println("Wallets setup complete!") + fmt.Println("Cold wallet:", coldWallet.ClassicAddress) + fmt.Println("Hot wallet:", hotWallet.ClassicAddress) + fmt.Println("Customer one wallet:", customerOneWallet.ClassicAddress) + fmt.Println() + + // + // Configure cold address settings + // + fmt.Println("Configuring cold address settings...") + coldWalletAccountSet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + TickSize: types.TickSize(5), + TransferRate: types.TransferRate(0), + Domain: types.Domain("6578616D706C652E636F6D"), // example.com + } + + coldWalletAccountSet.SetAsfDefaultRipple() + coldWalletAccountSet.SetDisallowXRP() + + coldWalletAccountSet.SetRequireDestTag() + + flattenedTx := coldWalletAccountSet.Flatten() + + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err := coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err := client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Cold address settings configuration failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Cold address settings configured!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Configure hot address settings + // + fmt.Println("Configuring hot address settings...") + hotWalletAccountSet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(hotWallet.ClassicAddress), + }, + Domain: types.Domain("6578616D706C652E636F6D"), // example.com + } + + hotWalletAccountSet.SetAsfRequireAuth() + hotWalletAccountSet.SetDisallowXRP() + hotWalletAccountSet.SetRequireDestTag() + + flattenedTx = hotWalletAccountSet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = hotWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Hot address settings configuration failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Hot address settings configured!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Create trust line from hot to cold address + // + fmt.Println("Creating trust line from hot to cold address...") + hotColdTrustSet := &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(hotWallet.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100000000000000", + }, + } + + flattenedTx = hotColdTrustSet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = hotWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Trust line from hot to cold address creation failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Trust line from hot to cold address created!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Create trust line from costumer one to cold address + // + fmt.Println("Creating trust line from customer one to cold address...") + customerOneColdTrustSet := &transactions.TrustSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(customerOneWallet.ClassicAddress), + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100000000000000", + }, + } + + flattenedTx = customerOneColdTrustSet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = customerOneWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Trust line from customer one to cold address creation failed!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Trust line from customer one to cold address created!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Send tokens from cold wallet to hot wallet + // + fmt.Println("Sending tokens from cold wallet to hot wallet...") + coldToHotPayment := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "3800", + }, + Destination: types.Address(hotWallet.ClassicAddress), + DestinationTag: types.DestinationTag(1), + } + + flattenedTx = coldToHotPayment.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Tokens not sent from cold wallet to hot wallet!") + fmt.Println("Try again!") + fmt.Println() + return + } + + fmt.Println("Tokens sent from cold wallet to hot wallet!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Send tokens from hot wallet to customer one + // + fmt.Println("Sending tokens from cold wallet to customer one...") + coldToCustomerOnePayment := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100", + }, + Destination: types.Address(customerOneWallet.ClassicAddress), + } + + flattenedTx = coldToCustomerOnePayment.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Tokens not sent from cold wallet to customer one!") + fmt.Println() + return + } + + fmt.Println("Tokens sent from cold wallet to customer one!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Freeze cold wallet + // + fmt.Println("Freezing cold wallet...") + freezeColdWallet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + } + + freezeColdWallet.SetAsfGlobalFreeze() + + flattenedTx = freezeColdWallet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Cold wallet freezing failed!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + return + } + + fmt.Println("Cold wallet frozen!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Try to send tokens from hot wallet to customer one + // + fmt.Println("Trying to send tokens from hot wallet to customer one...") + hotToCustomerOnePayment := &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(hotWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100", + }, + Destination: types.Address(customerOneWallet.ClassicAddress), + } + + flattenedTx = hotToCustomerOnePayment.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = hotWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + _, err = client.SubmitTxBlobAndWait(txBlob, false) + if err == nil { + return + } + + fmt.Println("Tokens not sent from hot wallet to customer one!") + fmt.Println() + + // // + // // Unfreeze cold wallet + // // + fmt.Println("Unfreezing cold wallet...") + unfreezeColdWallet := &transactions.AccountSet{ + BaseTx: transactions.BaseTx{ + Account: types.Address(coldWallet.ClassicAddress), + }, + } + + unfreezeColdWallet.ClearAsfGlobalFreeze() + + flattenedTx = unfreezeColdWallet.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = coldWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Cold wallet unfreezing failed!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + return + } + + fmt.Println("Cold wallet unfrozen!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() + + // + // Try to send tokens from hot wallet to customer one + // + fmt.Println("Trying to send tokens from hot wallet to customer one...") + hotToCustomerOnePayment = &transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(hotWallet.ClassicAddress), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: currencyCode, + Issuer: types.Address(coldWallet.ClassicAddress), + Value: "100", + }, + Destination: types.Address(customerOneWallet.ClassicAddress), + } + + flattenedTx = hotToCustomerOnePayment.Flatten() + err = client.Autofill(&flattenedTx) + if err != nil { + panic(err) + } + + txBlob, _, err = hotWallet.Sign(flattenedTx) + if err != nil { + panic(err) + } + + response, err = client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + if !response.Validated { + fmt.Println("Tokens not sent from hot wallet to customer one!") + fmt.Println("Try again!") + return + } + + fmt.Println("Tokens sent from hot wallet to customer one!") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Println() +} diff --git a/_code-samples/issue-mpt-with-metadata/README.md b/_code-samples/issue-mpt-with-metadata/README.md new file mode 100644 index 0000000000..bc09fac266 --- /dev/null +++ b/_code-samples/issue-mpt-with-metadata/README.md @@ -0,0 +1,3 @@ +# Issue an MPT with Metadata + +Shows how to issue a Multi-Purpose Token (MPT) with metadata encoded according to the XLS-89 schema. diff --git a/_code-samples/issue-mpt-with-metadata/js/README.md b/_code-samples/issue-mpt-with-metadata/js/README.md new file mode 100644 index 0000000000..5e73cd1a0b --- /dev/null +++ b/_code-samples/issue-mpt-with-metadata/js/README.md @@ -0,0 +1,16 @@ +# Issue MPT with Metadata (JavaScript) + +Creates a sample MPT issuance with metadata encoded as JSON according to the [XLS-89 standard](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0089-multi-purpose-token-metadata-schema). + +Quick setup and usage: + +```sh +npm i +node issue-mpt-with-metadata.js +``` + +The script should output a validated transaction and end with a line such as the following: + +```text +MPToken created successfully with issuance ID 005073C721E14A7613BAAF5E0B1A253459832FF8D0D81278. +``` diff --git a/_code-samples/issue-mpt-with-metadata/js/issue-mpt-with-metadata.js b/_code-samples/issue-mpt-with-metadata/js/issue-mpt-with-metadata.js new file mode 100644 index 0000000000..0d693b42ce --- /dev/null +++ b/_code-samples/issue-mpt-with-metadata/js/issue-mpt-with-metadata.js @@ -0,0 +1,85 @@ +import { stringToHex, hexToString } from '@xrplf/isomorphic/dist/utils/index.js' +import { MPTokenIssuanceCreateFlags, Client } from 'xrpl' + +// Connect to network and get a wallet +const client = new Client('wss://s.devnet.rippletest.net:51233') +await client.connect() + +console.log('Funding new wallet from faucet...') +const { wallet } = await client.fundWallet() + +// Define metadata as JSON +const mpt_metadata = { + ticker: 'TBILL', + name: 'T-Bill Yield Token', + desc: 'A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.', + icon: 'https://example.org/tbill-icon.png', + asset_class: 'rwa', + asset_subclass: 'treasury', + issuer_name: 'Example Yield Co.', + urls: [ + { + url: 'https://exampleyield.co/tbill', + type: 'website', + title: 'Product Page' + }, + { + url: 'https://exampleyield.co/docs', + type: 'docs', + title: 'Yield Token Docs' + } + ], + additional_info: { + interest_rate: '5.00%', + interest_type: 'variable', + yield_source: 'U.S. Treasury Bills', + maturity_date: '2045-06-30', + cusip: '912796RX0' + } +} + +// Convert JSON to a string (without excess whitespace), then string to hex +const mpt_metadata_hex = stringToHex(JSON.stringify(mpt_metadata)) + +// Define the transaction, including other MPT parameters +const mpt_issuance_create = { + TransactionType: 'MPTokenIssuanceCreate', + Account: wallet.address, + AssetScale: 4, + MaximumAmount: '50000000', + TransferFee: 0, + Flags: MPTokenIssuanceCreateFlags.tfMPTCanTransfer | + MPTokenIssuanceCreateFlags.tfMPTCanTrade, + MPTokenMetadata: mpt_metadata_hex +} + +// Prepare, sign, and submit the transaction +console.log('Sending MPTokenIssuanceCreate transaction...') +const submit_response = await client.submitAndWait(mpt_issuance_create, { wallet, autofill: true }) + +// Check transaction results and disconnect +console.log(JSON.stringify(submit_response, null, 2)) +if (submit_response.result.meta.TransactionResult !== 'tesSUCCESS') { + const result_code = response.result.meta.TransactionResult + console.warn(`Transaction failed with result code ${result_code}.`) + process.exit(1) +} + +const issuance_id = submit_response.result.meta.mpt_issuance_id +console.log(`MPToken created successfully with issuance ID ${issuance_id}.`) + +// Look up MPT Issuance entry in the validated ledger +console.log('Confirming MPT Issuance metadata in the validated ledger.') +const ledger_entry_response = await client.request({ + "command": "ledger_entry", + "mpt_issuance": issuance_id, + "ledger_index": "validated" +}) + +// Decode the metadata +const metadata_blob = ledger_entry_response.result.node.MPTokenMetadata +const decoded_metadata = JSON.parse(hexToString(metadata_blob)) +console.log('Decoded metadata:', decoded_metadata) + + +client.disconnect() diff --git a/_code-samples/issue-mpt-with-metadata/js/package.json b/_code-samples/issue-mpt-with-metadata/js/package.json new file mode 100644 index 0000000000..43c89bf1e0 --- /dev/null +++ b/_code-samples/issue-mpt-with-metadata/js/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "xrpl": "^4.4.0" + }, + "type": "module" +} diff --git a/_code-samples/issue-mpt-with-metadata/py/README.md b/_code-samples/issue-mpt-with-metadata/py/README.md new file mode 100644 index 0000000000..1e3f4e0f4f --- /dev/null +++ b/_code-samples/issue-mpt-with-metadata/py/README.md @@ -0,0 +1,18 @@ +# Issue MPT with Metadata (Python) + +Creates a sample MPT issuance with metadata encoded as JSON according to the [XLS-89 standard](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0089-multi-purpose-token-metadata-schema). + +Quick setup and usage: + +```sh +python -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt +python issue-mpt-with-metadata.py +``` + +The script should output a validated transaction and end with a line such as the following: + +```text +MPToken created successfully with issuance ID 0050773D6B8DF8C6BEA497016C8679728A217DE1C4D50AC5. +``` diff --git a/_code-samples/issue-mpt-with-metadata/py/issue-mpt-with-metadata.py b/_code-samples/issue-mpt-with-metadata/py/issue-mpt-with-metadata.py new file mode 100644 index 0000000000..52f0d16139 --- /dev/null +++ b/_code-samples/issue-mpt-with-metadata/py/issue-mpt-with-metadata.py @@ -0,0 +1,82 @@ +import json +from xrpl.utils import str_to_hex, hex_to_str +from xrpl.clients import JsonRpcClient +from xrpl.wallet import generate_faucet_wallet +from xrpl.transaction import submit_and_wait +from xrpl.models import LedgerEntry, MPTokenIssuanceCreate, MPTokenIssuanceCreateFlag + +# Set up client and get a wallet +client = JsonRpcClient("https://s.devnet.rippletest.net:51234") +print("Funding new wallet from faucet...") +wallet = generate_faucet_wallet(client, debug=True) + +# Define metadata as JSON +mpt_metadata = { + "ticker": "TBILL", + "name": "T-Bill Yield Token", + "desc": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.", + "icon": "https://example.org/tbill-icon.png", + "asset_class": "rwa", + "asset_subclass": "treasury", + "issuer_name": "Example Yield Co.", + "urls": [ + { + "url": "https://exampleyield.co/tbill", + "type": "website", + "title": "Product Page" + }, + { + "url": "https://exampleyield.co/docs", + "type": "docs", + "title": "Yield Token Docs" + } + ], + "additional_info": { + "interest_rate": "5.00%", + "interest_type": "variable", + "yield_source": "U.S. Treasury Bills", + "maturity_date": "2045-06-30", + "cusip": "912796RX0" + } +} + +# Convert JSON to a string (without excess whitespace), then string to hex +mpt_metadata_string = json.dumps(mpt_metadata, separators=(',', ':')) +mpt_metadata_hex = str_to_hex(mpt_metadata_string) + +# Define the transaction, including other MPT parameters +mpt_issuance_create = MPTokenIssuanceCreate( + account=wallet.address, + asset_scale=4, + maximum_amount="50000000", + transfer_fee=0, + flags=MPTokenIssuanceCreateFlag.TF_MPT_CAN_TRANSFER | + MPTokenIssuanceCreateFlag.TF_MPT_CAN_TRADE, + mptoken_metadata=mpt_metadata_hex +) + +# Prepare, sign, and submit the transaction +print("Sending MPTokenIssuanceCreate transaction...") +response = submit_and_wait(mpt_issuance_create, client, wallet, autofill=True) +print(json.dumps(response.result, indent=2)) + +# Check transaction results +result_code = response.result["meta"]["TransactionResult"] +if result_code != "tesSUCCESS": + print(f"Transaction failed with result code {result_code}") + exit(1) + +issuance_id = response.result["meta"]["mpt_issuance_id"] +print(f"MPToken successfully created with issuance ID {issuance_id}") + +# Look up MPT Issuance entry in the validated ledger +print("Confirming MPT Issuance metadata in the validated ledger.") +ledger_entry_response = client.request(LedgerEntry( + mpt_issuance=issuance_id, + ledger_index="validated" +)) + +# Decode the metadata +metadata_blob = ledger_entry_response.result["node"]["MPTokenMetadata"] +decoded_metadata = json.loads(hex_to_str(metadata_blob)) +print("Decoded metadata:", decoded_metadata) diff --git a/_code-samples/issue-mpt-with-metadata/py/requirements.txt b/_code-samples/issue-mpt-with-metadata/py/requirements.txt new file mode 100644 index 0000000000..a566e000a8 --- /dev/null +++ b/_code-samples/issue-mpt-with-metadata/py/requirements.txt @@ -0,0 +1 @@ +xrpl-py==4.3.0 diff --git a/_code-samples/monitor-payments-websocket/go/monitor-incoming-payments.go b/_code-samples/monitor-payments-websocket/go/monitor-incoming-payments.go index 1096a6f576..f0bcf93331 100644 --- a/_code-samples/monitor-payments-websocket/go/monitor-incoming-payments.go +++ b/_code-samples/monitor-payments-websocket/go/monitor-incoming-payments.go @@ -7,15 +7,15 @@ package main // install: go get github.com/gorilla/websocket import ( - "encoding/json" - "flag" - "log" - "net/url" - "os" - "os/signal" - "time" + "encoding/json" + "flag" + "log" + "net/url" + "os" + "os/signal" + "time" - "github.com/gorilla/websocket" + "github.com/gorilla/websocket" ) // websocket address @@ -23,75 +23,72 @@ var addr = flag.String("addr", "s.altnet.rippletest.net:51233", "http service ad // Payload object type message struct { - Command string `json:"command"` - Accounts []string `json:"accounts"` + Command string `json:"command"` + Accounts []string `json:"accounts"` } func main() { - flag.Parse() - log.SetFlags(0) + flag.Parse() + log.SetFlags(0) - var m message + var m message - // check for interrupts and cleanly close the connection - interrupt := make(chan os.Signal, 1) - signal.Notify(interrupt, os.Interrupt) + // check for interrupts and cleanly close the connection + interrupt := make(chan os.Signal, 1) + signal.Notify(interrupt, os.Interrupt) - u := url.URL{Scheme: "ws", Host: *addr, Path: "/"} - log.Printf("connecting to %s", u.String()) + u := url.URL{Scheme: "ws", Host: *addr, Path: "/"} + log.Printf("connecting to %s", u.String()) - // make the connection - c, _, err := websocket.DefaultDialer.Dial(u.String(), nil) - if err != nil { - log.Fatal("dial:", err) - } - // on exit close - defer c.Close() + // make the connection + c, _, err := websocket.DefaultDialer.Dial(u.String(), nil) + if err != nil { + panic(err) + } + // on exit close + defer c.Close() - done := make(chan struct{}) + done := make(chan struct{}) - // send a subscribe command and a target XRPL account - m.Command = "subscribe" - m.Accounts = append(m.Accounts, "rUCzEr6jrEyMpjhs4wSdQdz4g8Y382NxfM") + // send a subscribe command and a target XRPL account + m.Command = "subscribe" + m.Accounts = append(m.Accounts, "rUCzEr6jrEyMpjhs4wSdQdz4g8Y382NxfM") - // struct to JSON marshalling - msg, _ := json.Marshal(m) - // write to the websocket - err = c.WriteMessage(websocket.TextMessage, []byte(string(msg))) - if err != nil { - log.Println("write:", err) - return - } + // struct to JSON marshalling + msg, _ := json.Marshal(m) + // write to the websocket + err = c.WriteMessage(websocket.TextMessage, []byte(string(msg))) + if err != nil { + panic(err) + } - // read from the websocket - _, message, err := c.ReadMessage() - if err != nil { - log.Println("read:", err) - return - } - // print the response from the XRP Ledger - log.Printf("recv: %s", message) + // read from the websocket + _, message, err := c.ReadMessage() + if err != nil { + panic(err) + } + // print the response from the XRP Ledger + log.Printf("recv: %s", message) - // handle interrupt - for { - select { - case <-done: - return - case <-interrupt: - log.Println("interrupt") + // handle interrupt + for { + select { + case <-done: + return + case <-interrupt: + log.Println("interrupt") - // Cleanly close the connection by sending a close message and then - // waiting (with timeout) for the server to close the connection. - err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) - if err != nil { - log.Println("write close:", err) - return - } - select { - case <-done: - case <-time.After(time.Second): - } - return - } - } + // Cleanly close the connection by sending a close message and then + // waiting (with timeout) for the server to close the connection. + err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) + if err != nil { + panic(err) + } + select { + case <-done: + case <-time.After(time.Second): + } + return + } + } } diff --git a/_code-samples/multisigning/go/go.mod b/_code-samples/multisigning/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/multisigning/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/multisigning/go/go.sum b/_code-samples/multisigning/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/multisigning/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/multisigning/go/rpc/main.go b/_code-samples/multisigning/go/rpc/main.go new file mode 100644 index 0000000000..62a889a392 --- /dev/null +++ b/_code-samples/multisigning/go/rpc/main.go @@ -0,0 +1,152 @@ +package main + +import ( + "encoding/hex" + "fmt" + "maps" + "strings" + + "github.com/Peersyst/xrpl-go/xrpl" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/ledger-entry-types" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + + w1, err := wallet.FromSeed("sEdTtvLmJmrb7GaivhWoXRkvU4NDjVf", "") + if err != nil { + panic(err) + } + + w2, err := wallet.FromSeed("sEdSFiKMQp7RvYLgH7t7FEpwNRWv2Gr", "") + if err != nil { + panic(err) + } + + master, err := wallet.FromSeed("sEdTMm2yv8c8Rg8YHFHQA9TxVMFy1ze", "") + if err != nil { + panic(err) + } + + fmt.Println("Funding wallets...") + + if err := client.FundWallet(&w1); err != nil { + panic(err) + } + fmt.Println("Wallet 1 funded") + + if err := client.FundWallet(&w2); err != nil { + panic(err) + } + + fmt.Println("Wallet 2 funded") + + if err := client.FundWallet(&master); err != nil { + panic(err) + } + fmt.Println("Master wallet funded") + fmt.Println() + fmt.Println("Setting up signer list...") + + ss := &transaction.SignerListSet{ + BaseTx: transaction.BaseTx{ + Account: master.GetAddress(), + }, + SignerQuorum: uint32(2), + SignerEntries: []ledger.SignerEntryWrapper{ + { + SignerEntry: ledger.SignerEntry{ + Account: w1.GetAddress(), + SignerWeight: 1, + }, + }, + { + SignerEntry: ledger.SignerEntry{ + Account: w2.GetAddress(), + SignerWeight: 1, + }, + }, + { + SignerEntry: ledger.SignerEntry{ + Account: "XVYRdEocC28DRx94ZFGP3qNJ1D5Ln7ecXFMd3vREB5Pesju", + SignerWeight: 1, + }, + }, + }, + } + + flatSs := ss.Flatten() + + if err := client.Autofill(&flatSs); err != nil { + panic(err) + } + + blob, _, err := master.Sign(flatSs) + if err != nil { + panic(err) + } + + res, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("SignerListSet transaction submitted!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Println() + + fmt.Println("Setting up AccountSet multisign transaction...") + + as := &transaction.AccountSet{ + BaseTx: transaction.BaseTx{ + Account: master.GetAddress(), + }, + Domain: types.Domain(strings.ToUpper(hex.EncodeToString([]byte("example.com")))), + } + + flatAs := as.Flatten() + + if err := client.AutofillMultisigned(&flatAs, 2); err != nil { + panic(err) + } + + w1As := maps.Clone(flatAs) + + blob1, _, err := w1.Multisign(w1As) + if err != nil { + panic(err) + } + + w2As := maps.Clone(flatAs) + + blob2, _, err := w2.Multisign(w2As) + if err != nil { + panic(err) + } + + blob, err = xrpl.Multisign(blob1, blob2) + if err != nil { + panic(err) + } + + mRes, err := client.SubmitMultisigned(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Multisigned transaction submitted!") + fmt.Printf("Result: %s\n", mRes.EngineResult) +} diff --git a/_code-samples/multisigning/go/ws/main.go b/_code-samples/multisigning/go/ws/main.go new file mode 100644 index 0000000000..05e8665cf9 --- /dev/null +++ b/_code-samples/multisigning/go/ws/main.go @@ -0,0 +1,166 @@ +package main + +import ( + "encoding/hex" + "fmt" + "maps" + "strings" + + "github.com/Peersyst/xrpl-go/xrpl" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/ledger-entry-types" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +func main() { + fmt.Println("Connecting to testnet...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + if !client.IsConnected() { + fmt.Println("Failed to connect to testnet") + return + } + + fmt.Println("Connected to testnet") + fmt.Println() + + w1, err := wallet.FromSeed("sEdTtvLmJmrb7GaivhWoXRkvU4NDjVf", "") + if err != nil { + panic(err) + } + + w2, err := wallet.FromSeed("sEdSFiKMQp7RvYLgH7t7FEpwNRWv2Gr", "") + if err != nil { + panic(err) + } + + master, err := wallet.FromSeed("sEdTMm2yv8c8Rg8YHFHQA9TxVMFy1ze", "") + if err != nil { + panic(err) + } + + fmt.Println("Funding wallets...") + + if err := client.FundWallet(&w1); err != nil { + panic(err) + } + fmt.Println("Wallet 1 funded") + + if err := client.FundWallet(&w2); err != nil { + panic(err) + } + + fmt.Println("Wallet 2 funded") + + if err := client.FundWallet(&master); err != nil { + panic(err) + } + fmt.Println("Master wallet funded") + fmt.Println() + fmt.Println("Setting up signer list...") + + ss := &transaction.SignerListSet{ + BaseTx: transaction.BaseTx{ + Account: master.GetAddress(), + }, + SignerQuorum: uint32(2), + SignerEntries: []ledger.SignerEntryWrapper{ + { + SignerEntry: ledger.SignerEntry{ + Account: w1.GetAddress(), + SignerWeight: 1, + }, + }, + { + SignerEntry: ledger.SignerEntry{ + Account: w2.GetAddress(), + SignerWeight: 1, + }, + }, + { + SignerEntry: ledger.SignerEntry{ + Account: "XVYRdEocC28DRx94ZFGP3qNJ1D5Ln7ecXFMd3vREB5Pesju", + SignerWeight: 1, + }, + }, + }, + } + + fmt.Println("Flattening transaction...") + flatSs := ss.Flatten() + + fmt.Println("Autofilling transaction...") + if err := client.Autofill(&flatSs); err != nil { + panic(err) + } + + fmt.Println("Signing transaction...") + blob, _, err := master.Sign(flatSs) + if err != nil { + panic(err) + } + + fmt.Println("Submitting transaction...") + res, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("SignerListSet transaction submitted!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Println() + + fmt.Println("Setting up AccountSet multisign transaction...") + + as := &transaction.AccountSet{ + BaseTx: transaction.BaseTx{ + Account: master.GetAddress(), + }, + Domain: types.Domain(strings.ToUpper(hex.EncodeToString([]byte("example.com")))), + } + + flatAs := as.Flatten() + + if err := client.AutofillMultisigned(&flatAs, 2); err != nil { + panic(err) + } + + w1As := maps.Clone(flatAs) + + blob1, _, err := w1.Multisign(w1As) + if err != nil { + panic(err) + } + + w2As := maps.Clone(flatAs) + + blob2, _, err := w2.Multisign(w2As) + if err != nil { + panic(err) + } + + blob, err = xrpl.Multisign(blob1, blob2) + if err != nil { + panic(err) + } + + mRes, err := client.SubmitMultisigned(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Multisigned transaction submitted!") + fmt.Printf("Result: %s\n", mRes.EngineResult) +} diff --git a/_code-samples/non-fungible-token/go/go.mod b/_code-samples/non-fungible-token/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/non-fungible-token/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/non-fungible-token/go/go.sum b/_code-samples/non-fungible-token/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/non-fungible-token/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/non-fungible-token/go/nft-accept/rpc/main.go b/_code-samples/non-fungible-token/go/nft-accept/rpc/main.go new file mode 100644 index 0000000000..93d92d0ce8 --- /dev/null +++ b/_code-samples/non-fungible-token/go/nft-accept/rpc/main.go @@ -0,0 +1,122 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/rpc/types" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + // Initialize the RPC client configuration + cfg, err := rpc.NewClientConfig( + "https://s.devnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + // Create the RPC client + client := rpc.NewClient(cfg) + + // Step 1: Fund wallets + fmt.Println("Funding wallets...") + + // Create and fund the NFT minter wallet + nftMinter, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&nftMinter); err != nil { + panic(err) + } + fmt.Println("NFT minter wallet funded!") + + // Create and fund the NFT buyer wallet + nftBuyer, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&nftBuyer); err != nil { + panic(err) + } + fmt.Println("NFT buyer wallet funded!") + fmt.Println() + + // Step 2: Mint an NFT + fmt.Println("Minting NFT...") + + nftMint := transaction.NFTokenMint{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenMintTx, + }, + Destination: nftBuyer.ClassicAddress, + Amount: txnTypes.XRPCurrencyAmount(1000000), // 1 XRP + NFTokenTaxon: 0, + URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com + } + nftMint.SetTransferableFlag() + + responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !responseMint.Validated { + fmt.Println("NFTokenMint txn is not in a validated ledger", responseMint) + return + } + fmt.Println("NFT minted successfully! - Hash: ", responseMint.Hash) + fmt.Println() + + // Step 3: Retrieve the NFT token offer ID + fmt.Println("Retrieving NFT offer ID...") + + metaMap, ok := responseMint.Meta.(map[string]any) + if !ok { + fmt.Println("Meta is not a map[string]any") + return + } + + offerID, ok := metaMap["offer_id"].(string) + if !ok { + fmt.Println("offer_id not found or not a string") + return + } + + fmt.Println("offer_id:", offerID) + fmt.Println() + + // Step 4: Accept the NFT offer + fmt.Println("Accepting NFT offer...") + + nftAccept := transaction.NFTokenAcceptOffer{ + BaseTx: transaction.BaseTx{ + Account: nftBuyer.ClassicAddress, + TransactionType: transaction.NFTokenAcceptOfferTx, + }, + NFTokenSellOffer: txnTypes.Hash256(offerID), + } + + response, err := client.SubmitTxAndWait(nftAccept.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftBuyer, + }) + if err != nil { + panic(err) + } + if !response.Validated { + fmt.Println("NFTokenAcceptOffer txn is not in a validated ledger", response) + return + } + fmt.Println("NFT offer accepted successfully! - Hash: ", response.Hash) +} diff --git a/_code-samples/non-fungible-token/go/nft-accept/ws/main.go b/_code-samples/non-fungible-token/go/nft-accept/ws/main.go new file mode 100644 index 0000000000..c9424a56ee --- /dev/null +++ b/_code-samples/non-fungible-token/go/nft-accept/ws/main.go @@ -0,0 +1,126 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" + "github.com/Peersyst/xrpl-go/xrpl/websocket/types" +) + +func main() { + // Connect to the XRPL devnet + fmt.Println("Connecting to devnet...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.devnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + if !client.IsConnected() { + fmt.Println("Failed to connect to devnet") + return + } + fmt.Println("Connected to devnet") + fmt.Println() + + // Fund wallets + fmt.Println("Funding wallets...") + + // Create and fund the NFT minter wallet + nftMinter, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&nftMinter); err != nil { + panic(err) + } + fmt.Println("NFT minter wallet funded!") + + // Create and fund the NFT buyer wallet + nftBuyer, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&nftBuyer); err != nil { + panic(err) + } + fmt.Println("NFT buyer wallet funded!") + fmt.Println() + + // Mint an NFT + fmt.Println("Minting NFT...") + nftMint := transaction.NFTokenMint{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenMintTx, + }, + Destination: nftBuyer.ClassicAddress, + Amount: txnTypes.XRPCurrencyAmount(1000000), // 1 XRP + NFTokenTaxon: 0, + URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com + } + nftMint.SetTransferableFlag() + + responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !responseMint.Validated { + fmt.Println("NFTokenMint transaction is not in a validated ledger:", responseMint) + return + } + fmt.Println("NFT minted successfully! - Hash:", responseMint.Hash) + fmt.Println() + + // Extract the NFT token offer ID from the transaction metadata + fmt.Println("Extracting offer ID...") + metaMap, ok := responseMint.Meta.(map[string]any) + if !ok { + fmt.Println("Meta is not a map[string]any") + return + } + + offerID, ok := metaMap["offer_id"].(string) + if !ok { + fmt.Println("offer_id not found or not a string") + return + } + fmt.Println("offer_id:", offerID) + fmt.Println() + + // Accept the NFT offer + fmt.Println("Accepting NFT offer...") + nftAccept := transaction.NFTokenAcceptOffer{ + BaseTx: transaction.BaseTx{ + Account: nftBuyer.ClassicAddress, + TransactionType: transaction.NFTokenAcceptOfferTx, + }, + NFTokenSellOffer: txnTypes.Hash256(offerID), + } + + response, err := client.SubmitTxAndWait(nftAccept.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftBuyer, + }) + if err != nil { + panic(err) + } + if !response.Validated { + fmt.Println("NFTokenAcceptOffer transaction is not in a validated ledger:", response) + return + } + fmt.Println("NFT offer accepted successfully! - Hash:", response.Hash) +} diff --git a/_code-samples/non-fungible-token/go/nft-burn/rpc/main.go b/_code-samples/non-fungible-token/go/nft-burn/rpc/main.go new file mode 100644 index 0000000000..18a158613c --- /dev/null +++ b/_code-samples/non-fungible-token/go/nft-burn/rpc/main.go @@ -0,0 +1,110 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/rpc/types" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + // Initialize the RPC client configuration + cfg, err := rpc.NewClientConfig( + "https://s.devnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + // Create the RPC client + client := rpc.NewClient(cfg) + + // Step 1: Fund wallets + fmt.Println("Funding wallets...") + + // Create and fund the NFT minter wallet + nftMinter, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&nftMinter); err != nil { + panic(err) + } + fmt.Println("NFT minter wallet funded!") + fmt.Println() + + // Step 2: Mint an NFT + fmt.Println("Minting NFT...") + + nftMint := transaction.NFTokenMint{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenMintTx, + }, + NFTokenTaxon: 0, + URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com + } + nftMint.SetTransferableFlag() + + responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !responseMint.Validated { + fmt.Println("NFTokenMint txn is not in a validated ledger", responseMint) + return + } + fmt.Println("NFT minted successfully! - Hash: ", responseMint.Hash) + fmt.Println() + + // Step 3: Retrieve the token ID + fmt.Println("Retrieving NFT ID...") + + metaMap, ok := responseMint.Meta.(map[string]any) + if !ok { + fmt.Println("Meta is not a map[string]any") + return + } + + nftokenID, ok := metaMap["nftoken_id"].(string) + if !ok { + fmt.Println("nftoken_id not found or not a string") + return + } + + fmt.Println("nftoken_id:", nftokenID) + fmt.Println() + + // Step 4: Burn the NFT + fmt.Println("Burn the NFT...") + + nftBurn := transaction.NFTokenBurn{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenAcceptOfferTx, + }, + NFTokenID: txnTypes.NFTokenID(nftokenID), + } + + responseBurn, err := client.SubmitTxAndWait(nftBurn.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !responseBurn.Validated { + fmt.Println("NFTokenBurn transactiob is not in a validated ledger", responseBurn) + return + } + fmt.Println("NFT burned successfully! - Hash: ", responseBurn.Hash) +} diff --git a/_code-samples/non-fungible-token/go/nft-burn/ws/main.go b/_code-samples/non-fungible-token/go/nft-burn/ws/main.go new file mode 100644 index 0000000000..7fce1576da --- /dev/null +++ b/_code-samples/non-fungible-token/go/nft-burn/ws/main.go @@ -0,0 +1,118 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" + "github.com/Peersyst/xrpl-go/xrpl/websocket/types" +) + +func main() { + // Connect to the XRPL devnet + fmt.Println("Connecting to devnet...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.devnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + if !client.IsConnected() { + fmt.Println("Failed to connect to devnet") + return + } + fmt.Println("Connected to devnet") + fmt.Println() + + // Step 1: Fund wallets + fmt.Println("Funding wallets...") + + // Create and fund the NFT minter wallet + nftMinter, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&nftMinter); err != nil { + panic(err) + } + fmt.Println("NFT minter wallet funded!") + fmt.Println() + + // Step 2: Mint an NFT + fmt.Println("Minting NFT...") + + nftMint := transaction.NFTokenMint{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenMintTx, + }, + NFTokenTaxon: 0, + URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com + } + nftMint.SetTransferableFlag() + + responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !responseMint.Validated { + fmt.Println("NFTokenMint txn is not in a validated ledger", responseMint) + return + } + fmt.Println("NFT minted successfully! - Hash: ", responseMint.Hash) + fmt.Println() + + // Step 3: Retrieve the token ID + fmt.Println("Retrieving NFT ID...") + + metaMap, ok := responseMint.Meta.(map[string]any) + if !ok { + fmt.Println("Meta is not a map[string]any") + return + } + + nftokenID, ok := metaMap["nftoken_id"].(string) + if !ok { + fmt.Println("nftoken_id not found or not a string") + return + } + + fmt.Println("nftoken_id:", nftokenID) + fmt.Println() + + // Step 4: Burn the NFT + fmt.Println("Burn the NFT...") + + nftBurn := transaction.NFTokenBurn{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenAcceptOfferTx, + }, + NFTokenID: txnTypes.NFTokenID(nftokenID), + } + + responseBurn, err := client.SubmitTxAndWait(nftBurn.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !responseBurn.Validated { + fmt.Println("NFTokenBurn transactiob is not in a validated ledger", responseBurn) + return + } + fmt.Println("NFT burned successfully! - Hash: ", responseBurn.Hash) +} diff --git a/_code-samples/non-fungible-token/go/nft-cancel/rpc/main.go b/_code-samples/non-fungible-token/go/nft-cancel/rpc/main.go new file mode 100644 index 0000000000..fb66131653 --- /dev/null +++ b/_code-samples/non-fungible-token/go/nft-cancel/rpc/main.go @@ -0,0 +1,158 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/rpc/types" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + // Initialize the RPC client configuration + cfg, err := rpc.NewClientConfig( + "https://s.devnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + // Create the RPC client + client := rpc.NewClient(cfg) + + // Step 1: Fund wallet + fmt.Println("Funding wallet...") + + // Create and fund the NFT minter wallet + nftMinter, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&nftMinter); err != nil { + panic(err) + } + fmt.Println("NFT minter wallet funded!") + + // Step 2: Mint two NFTs + fmt.Println("Minting first NFT...") + + nftMint := transaction.NFTokenMint{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenMintTx, + }, + NFTokenTaxon: 0, + URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com + } + nftMint.SetTransferableFlag() + + responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !responseMint.Validated { + fmt.Println("First NFTokenMint transaction is not in a validated ledger", responseMint) + return + } + fmt.Println("First NFT minted successfully! - Hash: ", responseMint.Hash) + fmt.Println() + + // Step 3: Retrieve the NFT token ID + fmt.Println("Retrieving NFT ID...") + + metaMap, ok := responseMint.Meta.(map[string]any) + if !ok { + fmt.Println("Meta is not a map[string]any") + return + } + + nftokenID1, ok := metaMap["nftoken_id"].(string) + if !ok { + fmt.Println("nftoken_id not found or not a string") + return + } + + fmt.Println("nftoken_id:", nftokenID1) + fmt.Println() + + // ------ + + fmt.Println("Minting second NFT...") + + nftMint2 := transaction.NFTokenMint{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenMintTx, + }, + NFTokenTaxon: 0, + URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com + } + nftMint2.SetTransferableFlag() + + responseMint2, err := client.SubmitTxAndWait(nftMint2.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !responseMint.Validated { + fmt.Println("Second NFTokenMint transaction is not in a validated ledger", responseMint) + return + } + fmt.Println("Second NFT minted successfully! - Hash: ", responseMint.Hash) + fmt.Println() + + // Step 3: Retrieve the second NFT token ID + fmt.Println("Retrieving second NFT ID...") + + metaMap2, ok := responseMint2.Meta.(map[string]any) + if !ok { + fmt.Println("Meta is not a map[string]any") + return + } + + nftokenID2, ok := metaMap2["nftoken_id"].(string) + if !ok { + fmt.Println("nftoken_id not found or not a string") + return + } + + fmt.Println("nftoken_id:", nftokenID2) + fmt.Println() + + // Step 4: Cancel the NFT offers + fmt.Println("Canceling NFT offers...") + + nftCancel := transaction.NFTokenCancelOffer{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenAcceptOfferTx, + }, + NFTokenOffers: []txnTypes.NFTokenID{ + txnTypes.NFTokenID(nftokenID1), + txnTypes.NFTokenID(nftokenID2), + }, + } + + response, err := client.SubmitTxAndWait(nftCancel.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !response.Validated { + fmt.Println("NFTokenCancelOffer transaction is not in a validated ledger", response) + return + } + fmt.Println("NFT offers canceled successfully! - Hash: ", response.Hash) +} diff --git a/_code-samples/non-fungible-token/go/nft-cancel/ws/main.go b/_code-samples/non-fungible-token/go/nft-cancel/ws/main.go new file mode 100644 index 0000000000..410bb22195 --- /dev/null +++ b/_code-samples/non-fungible-token/go/nft-cancel/ws/main.go @@ -0,0 +1,166 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" + "github.com/Peersyst/xrpl-go/xrpl/websocket/types" +) + +func main() { + // Connect to the XRPL devnet + fmt.Println("Connecting to devnet...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.devnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + if !client.IsConnected() { + fmt.Println("Failed to connect to devnet") + return + } + fmt.Println("Connected to devnet") + fmt.Println() + + // Step 1: Fund wallet + fmt.Println("Funding wallet...") + + // Create and fund the NFT minter wallet + nftMinter, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&nftMinter); err != nil { + panic(err) + } + fmt.Println("NFT minter wallet funded!") + + // Step 2: Mint two NFTs + fmt.Println("Minting first NFT...") + + nftMint := transaction.NFTokenMint{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenMintTx, + }, + NFTokenTaxon: 0, + URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com + } + nftMint.SetTransferableFlag() + + responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !responseMint.Validated { + fmt.Println("First NFTokenMint transaction is not in a validated ledger", responseMint) + return + } + fmt.Println("First NFT minted successfully! - Hash: ", responseMint.Hash) + fmt.Println() + + // Step 3: Retrieve the NFT token ID + fmt.Println("Retrieving NFT ID...") + + metaMap, ok := responseMint.Meta.(map[string]any) + if !ok { + fmt.Println("Meta is not a map[string]any") + return + } + + nftokenID1, ok := metaMap["nftoken_id"].(string) + if !ok { + fmt.Println("nftoken_id not found or not a string") + return + } + + fmt.Println("nftoken_id:", nftokenID1) + fmt.Println() + + // ------ + + fmt.Println("Minting second NFT...") + + nftMint2 := transaction.NFTokenMint{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenMintTx, + }, + NFTokenTaxon: 0, + URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com + } + nftMint2.SetTransferableFlag() + + responseMint2, err := client.SubmitTxAndWait(nftMint2.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !responseMint.Validated { + fmt.Println("Second NFTokenMint transaction is not in a validated ledger", responseMint) + return + } + fmt.Println("Second NFT minted successfully! - Hash: ", responseMint.Hash) + fmt.Println() + + // Step 3: Retrieve the second NFT token ID + fmt.Println("Retrieving second NFT ID...") + + metaMap2, ok := responseMint2.Meta.(map[string]any) + if !ok { + fmt.Println("Meta is not a map[string]any") + return + } + + nftokenID2, ok := metaMap2["nftoken_id"].(string) + if !ok { + fmt.Println("nftoken_id not found or not a string") + return + } + + fmt.Println("nftoken_id:", nftokenID2) + fmt.Println() + + // Step 4: Cancel the NFT offers + fmt.Println("Canceling NFT offers...") + + nftCancel := transaction.NFTokenCancelOffer{ + BaseTx: transaction.BaseTx{ + Account: nftMinter.ClassicAddress, + TransactionType: transaction.NFTokenAcceptOfferTx, + }, + NFTokenOffers: []txnTypes.NFTokenID{ + txnTypes.NFTokenID(nftokenID1), + txnTypes.NFTokenID(nftokenID2), + }, + } + + response, err := client.SubmitTxAndWait(nftCancel.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftMinter, + }) + if err != nil { + panic(err) + } + if !response.Validated { + fmt.Println("NFTokenCancelOffer transaction is not in a validated ledger", response) + return + } + fmt.Println("NFT offers canceled successfully! - Hash: ", response.Hash) +} diff --git a/_code-samples/non-fungible-token/go/nft-modify/rpc/main.go b/_code-samples/non-fungible-token/go/nft-modify/rpc/main.go new file mode 100644 index 0000000000..f0783ffd32 --- /dev/null +++ b/_code-samples/non-fungible-token/go/nft-modify/rpc/main.go @@ -0,0 +1,103 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/rpc/types" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + cfg, err := rpc.NewClientConfig( + "https://s.devnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + fmt.Println() + + fmt.Println("Funding wallet...") + + // Create and fund the nft wallet + nftWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&nftWallet); err != nil { + panic(err) + } + fmt.Println("NFT wallet funded: ", nftWallet.ClassicAddress) + fmt.Println() + + // Mint NFT + nftMint := transaction.NFTokenMint{ + BaseTx: transaction.BaseTx{ + Account: nftWallet.ClassicAddress, + TransactionType: transaction.NFTokenMintTx, + }, + NFTokenTaxon: 0, + URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com + } + nftMint.SetMutableFlag() + nftMint.SetTransferableFlag() + + responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftWallet, + }) + if err != nil { + panic(err) + } + if !responseMint.Validated { + fmt.Println("NFTokenMint txn is not in a validated ledger", responseMint) + return + } + fmt.Println("NFT minted successfully! - Hash: ", responseMint.Hash) + fmt.Println() + + metaMap, ok := responseMint.Meta.(map[string]any) + if !ok { + fmt.Println("Meta is not a map[string]any") + return + } + + nftokenID, ok := metaMap["nftoken_id"].(string) + if !ok { + fmt.Println("nftoken_id not found or not a string") + return + } + + fmt.Println("nftoken_id:", nftokenID) + fmt.Println() + + // Update NFT + nftModify := transaction.NFTokenModify{ + BaseTx: transaction.BaseTx{ + Account: nftWallet.ClassicAddress, + TransactionType: transaction.NFTokenModifyTx, + }, + URI: "68747470733A2F2F7961686F6F2E636F6D", // https://yahoo.com + NFTokenID: txnTypes.NFTokenID(nftokenID), + } + // nftoken_id + responseModify, err := client.SubmitTxAndWait(nftModify.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftWallet, + }) + if err != nil { + panic(err) + } + if !responseModify.Validated { + fmt.Println("NFTokenModify txn is not in a validated ledger", responseModify) + return + } + fmt.Println("NFT URI modified successfully! - Hash: ", responseModify.Hash) +} diff --git a/_code-samples/non-fungible-token/go/nft-modify/ws/main.go b/_code-samples/non-fungible-token/go/nft-modify/ws/main.go new file mode 100644 index 0000000000..5f65893dd8 --- /dev/null +++ b/_code-samples/non-fungible-token/go/nft-modify/ws/main.go @@ -0,0 +1,112 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" + "github.com/Peersyst/xrpl-go/xrpl/websocket/types" +) + +func main() { + fmt.Println("Connecting to devnet...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.devnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewDevnetFaucetProvider()), + ) + + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + if !client.IsConnected() { + fmt.Println("Failed to connect to devnet") + return + } + + fmt.Println("Connected to devnet") + fmt.Println() + + // Create and fund the nft wallet + fmt.Println("Funding wallet...") + nftWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&nftWallet); err != nil { + panic(err) + } + fmt.Println("NFT wallet funded!") + fmt.Println() + + // Mint NFT + nftMint := transaction.NFTokenMint{ + BaseTx: transaction.BaseTx{ + Account: nftWallet.ClassicAddress, + TransactionType: transaction.NFTokenMintTx, + }, + NFTokenTaxon: 0, + URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com + } + nftMint.SetMutableFlag() + nftMint.SetTransferableFlag() + + responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftWallet, + }) + if err != nil { + panic(err) + } + if !responseMint.Validated { + fmt.Println("NFTokenMint txn is not in a validated ledger", responseMint) + return + } + fmt.Println("NFT minted successfully! - Hash: ", responseMint.Hash) + fmt.Println() + + metaMap, ok := responseMint.Meta.(map[string]any) + if !ok { + fmt.Println("Meta is not a map[string]any") + return + } + + nftokenID, ok := metaMap["nftoken_id"].(string) + if !ok { + fmt.Println("nftoken_id not found or not a string") + return + } + + fmt.Println("nftoken_id:", nftokenID) + fmt.Println() + + // Update NFT + nftModify := transaction.NFTokenModify{ + BaseTx: transaction.BaseTx{ + Account: nftWallet.ClassicAddress, + TransactionType: transaction.NFTokenModifyTx, + }, + URI: "68747470733A2F2F7961686F6F2E636F6D", // https://yahoo.com + NFTokenID: txnTypes.NFTokenID(nftokenID), + } + + responseModify, err := client.SubmitTxAndWait(nftModify.Flatten(), &types.SubmitOptions{ + Autofill: true, + Wallet: &nftWallet, + }) + if err != nil { + panic(err) + } + if !responseModify.Validated { + fmt.Println("NFTokenModify txn is not in a validated ledger", responseModify) + return + } + fmt.Println("NFT URI modified successfully! - Hash: ", responseModify.Hash) +} diff --git a/_code-samples/partial-payment/go/go.mod b/_code-samples/partial-payment/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/partial-payment/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/partial-payment/go/go.sum b/_code-samples/partial-payment/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/partial-payment/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/partial-payment/go/rpc/main.go b/_code-samples/partial-payment/go/rpc/main.go new file mode 100644 index 0000000000..c1c333b359 --- /dev/null +++ b/_code-samples/partial-payment/go/rpc/main.go @@ -0,0 +1,155 @@ +package main + +import ( + "fmt" + "time" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + + fmt.Println("Funding wallets...") + w1, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + w2, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&w1); err != nil { + panic(err) + } + + fmt.Println("Wallet 1 funded") + if err := client.FundWallet(&w2); err != nil { + panic(err) + } + + fmt.Println("Wallet 2 funded") + fmt.Println() + + time.Sleep(5 * time.Second) + + fmt.Println("Sending TrustSet transaction...") + ts := &transaction.TrustSet{ + BaseTx: transaction.BaseTx{ + Account: w2.ClassicAddress, + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: "FOO", + Issuer: w1.ClassicAddress, + Value: "10000000000", + }, + } + + flatTs := ts.Flatten() + + err = client.Autofill(&flatTs) + if err != nil { + panic(err) + } + + blob, _, err := w2.Sign(flatTs) + if err != nil { + panic(err) + } + + res, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("TrustSet transaction submitted!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Printf("Validated: %t\n", res.Validated) + fmt.Println() + + fmt.Println("Issuing tokens for wallet 2...") + p := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: w1.GetAddress(), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: "FOO", + Issuer: w1.GetAddress(), + Value: "50", + }, + Destination: w2.GetAddress(), + } + + flatP := p.Flatten() + + err = client.Autofill(&flatP) + if err != nil { + panic(err) + } + + blob, _, err = w1.Sign(flatP) + if err != nil { + panic(err) + } + + res, err = client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Payment transaction submitted!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Printf("Validated: %t\n", res.Validated) + fmt.Println() + + fmt.Println("Submitting Partial Payment transaction...") + pp := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: w2.GetAddress(), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: "FOO", + Issuer: w1.GetAddress(), + Value: "10", + }, + Destination: w1.GetAddress(), + } + + pp.SetPartialPaymentFlag() + + flatPP := pp.Flatten() + + err = client.Autofill(&flatPP) + if err != nil { + panic(err) + } + + blob, _, err = w2.Sign(flatPP) + if err != nil { + panic(err) + } + + res, err = client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Partial Payment transaction submitted!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Printf("Validated: %t\n", res.Validated) + fmt.Println() +} diff --git a/_code-samples/partial-payment/go/ws/main.go b/_code-samples/partial-payment/go/ws/main.go new file mode 100644 index 0000000000..965453a8ac --- /dev/null +++ b/_code-samples/partial-payment/go/ws/main.go @@ -0,0 +1,165 @@ +package main + +import ( + "fmt" + "time" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +func main() { + fmt.Println("Connecting to testnet...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + if !client.IsConnected() { + fmt.Println("Failed to connect to testnet") + return + } + + fmt.Println("Connected to testnet") + fmt.Println() + + fmt.Println("Funding wallets...") + w1, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + w2, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + if err := client.FundWallet(&w1); err != nil { + panic(err) + } + + fmt.Println("Wallet 1 funded") + if err := client.FundWallet(&w2); err != nil { + panic(err) + } + + fmt.Println("Wallet 2 funded") + fmt.Println() + + time.Sleep(5 * time.Second) + + fmt.Println("Sending TrustSet transaction...") + ts := &transaction.TrustSet{ + BaseTx: transaction.BaseTx{ + Account: w2.ClassicAddress, + }, + LimitAmount: types.IssuedCurrencyAmount{ + Currency: "FOO", + Issuer: w1.ClassicAddress, + Value: "10000000000", + }, + } + + flatTs := ts.Flatten() + + err = client.Autofill(&flatTs) + if err != nil { + panic(err) + } + + blob, _, err := w2.Sign(flatTs) + if err != nil { + panic(err) + } + + res, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("TrustSet transaction submitted!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Printf("Validated: %t\n", res.Validated) + fmt.Println() + + fmt.Println("Issuing tokens for wallet 2...") + p := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: w1.GetAddress(), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: "FOO", + Issuer: w1.GetAddress(), + Value: "50", + }, + Destination: w2.GetAddress(), + } + + flatP := p.Flatten() + + err = client.Autofill(&flatP) + if err != nil { + panic(err) + } + + blob, _, err = w1.Sign(flatP) + if err != nil { + panic(err) + } + + res, err = client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Payment transaction submitted!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Printf("Validated: %t\n", res.Validated) + fmt.Println() + + fmt.Println("Submitting Partial Payment transaction...") + pp := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: w2.GetAddress(), + }, + Amount: types.IssuedCurrencyAmount{ + Currency: "FOO", + Issuer: w1.GetAddress(), + Value: "10", + }, + Destination: w1.GetAddress(), + } + + pp.SetPartialPaymentFlag() + + flatPP := pp.Flatten() + + err = client.Autofill(&flatPP) + if err != nil { + panic(err) + } + + blob, _, err = w2.Sign(flatPP) + if err != nil { + panic(err) + } + + res, err = client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Partial Payment transaction submitted!") + fmt.Printf("Hash: %s\n", res.Hash.String()) + fmt.Printf("Validated: %t\n", res.Validated) + fmt.Println() +} diff --git a/_code-samples/paths/go/go.mod b/_code-samples/paths/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/paths/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/paths/go/go.sum b/_code-samples/paths/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/paths/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/paths/go/rpc/main.go b/_code-samples/paths/go/rpc/main.go new file mode 100644 index 0000000000..4cb880a66b --- /dev/null +++ b/_code-samples/paths/go/rpc/main.go @@ -0,0 +1,105 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/queries/path" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + + pathtypes "github.com/Peersyst/xrpl-go/xrpl/queries/path/types" +) + +const ( + DestinationAccount = types.Address("rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj") +) + +var ( + DestinationAmount = types.IssuedCurrencyAmount{ + Issuer: "rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc", + Currency: "USD", + Value: "0.001", + } +) + +func main() { + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + + wallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Funding wallet...") + if err := client.FundWallet(&wallet); err != nil { + panic(err) + } + + fmt.Println("Wallet funded") + fmt.Println() + + fmt.Println("Getting paths...") + res, err := client.GetRipplePathFind(&path.RipplePathFindRequest{ + SourceAccount: wallet.GetAddress(), + SourceCurrencies: []pathtypes.RipplePathFindCurrency{ + { + Currency: "XRP", + }, + }, + DestinationAccount: DestinationAccount, + DestinationAmount: DestinationAmount, + }) + if err != nil { + panic(err) + } + + fmt.Printf("Computed paths: %d\n", len(res.Alternatives)) + fmt.Println() + + if len(res.Alternatives) == 0 { + fmt.Println("No alternatives found") + return + } + + fmt.Println("Submitting Payment through path: ", res.Alternatives[0].PathsComputed) + p := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: wallet.GetAddress(), + }, + Destination: DestinationAccount, + Amount: DestinationAmount, + Paths: res.Alternatives[0].PathsComputed, + } + + flatP := p.Flatten() + + if err := client.Autofill(&flatP); err != nil { + panic(err) + } + + blob, hash, err := wallet.Sign(flatP) + if err != nil { + panic(err) + } + + txRes, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Payment submitted") + fmt.Printf("Hash: %s\n", hash) + fmt.Printf("Validated: %t\n", txRes.Validated) +} diff --git a/_code-samples/paths/go/ws/main.go b/_code-samples/paths/go/ws/main.go new file mode 100644 index 0000000000..f3e2d59a22 --- /dev/null +++ b/_code-samples/paths/go/ws/main.go @@ -0,0 +1,115 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/queries/path" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" + + pathtypes "github.com/Peersyst/xrpl-go/xrpl/queries/path/types" +) + +const ( + DestinationAccount = types.Address("rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj") +) + +var ( + DestinationAmount = types.IssuedCurrencyAmount{ + Issuer: "rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc", + Currency: "USD", + Value: "0.001", + } +) + +func main() { + fmt.Println("Connecting to testnet...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + if !client.IsConnected() { + fmt.Println("Failed to connect to testnet") + return + } + + fmt.Println("Connected to testnet") + fmt.Println() + + wallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Funding wallet...") + if err := client.FundWallet(&wallet); err != nil { + panic(err) + } + + fmt.Println("Wallet funded") + fmt.Println() + + fmt.Println("Getting paths...") + res, err := client.GetRipplePathFind(&path.RipplePathFindRequest{ + SourceAccount: wallet.GetAddress(), + SourceCurrencies: []pathtypes.RipplePathFindCurrency{ + { + Currency: "XRP", + }, + }, + DestinationAccount: DestinationAccount, + DestinationAmount: DestinationAmount, + }) + if err != nil { + panic(err) + } + + fmt.Printf("Computed paths: %d\n", len(res.Alternatives)) + fmt.Println() + + if len(res.Alternatives) == 0 { + fmt.Println("No alternatives found") + return + } + + fmt.Println("Submitting Payment through path: ", res.Alternatives[0].PathsComputed) + p := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: wallet.GetAddress(), + }, + Destination: DestinationAccount, + Amount: DestinationAmount, + Paths: res.Alternatives[0].PathsComputed, + } + + flatP := p.Flatten() + + if err := client.Autofill(&flatP); err != nil { + panic(err) + } + + blob, hash, err := wallet.Sign(flatP) + if err != nil { + panic(err) + } + + txRes, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Payment submitted") + fmt.Printf("Hash: %s\n", hash) + fmt.Printf("Validated: %t\n", txRes.Validated) +} diff --git a/_code-samples/secure-signing/go/go.mod b/_code-samples/secure-signing/go/go.mod new file mode 100644 index 0000000000..f220f13f8e --- /dev/null +++ b/_code-samples/secure-signing/go/go.mod @@ -0,0 +1,19 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/secure-signing/go/go.sum b/_code-samples/secure-signing/go/go.sum new file mode 100644 index 0000000000..d2520dc73a --- /dev/null +++ b/_code-samples/secure-signing/go/go.sum @@ -0,0 +1,45 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/secure-signing/go/main.go b/_code-samples/secure-signing/go/main.go new file mode 100644 index 0000000000..91913228f2 --- /dev/null +++ b/_code-samples/secure-signing/go/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + w, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + p := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: types.Address(w.GetAddress()), + Fee: types.XRPCurrencyAmount(13), + Sequence: 1, + Flags: 2147483648, + LastLedgerSequence: 7835923, + }, + Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + Amount: types.XRPCurrencyAmount(10000), + DeliverMax: types.XRPCurrencyAmount(10000), + } + + flattenedTx := p.Flatten() + + fmt.Println("Payment object created:", flattenedTx) + + signedTx, txHash, err := w.Sign(flattenedTx) + if err != nil { + panic(err) + } + + fmt.Println("Transaction signed successfully:", signedTx) + fmt.Println("Transaction hash:", txHash) +} diff --git a/_code-samples/send-a-memo/go/go.mod b/_code-samples/send-a-memo/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/send-a-memo/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/send-a-memo/go/go.sum b/_code-samples/send-a-memo/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/send-a-memo/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/send-a-memo/go/rpc/main.go b/_code-samples/send-a-memo/go/rpc/main.go new file mode 100644 index 0000000000..b1e10ee987 --- /dev/null +++ b/_code-samples/send-a-memo/go/rpc/main.go @@ -0,0 +1,107 @@ +package main + +import ( + "encoding/hex" + "fmt" + "strconv" + + "github.com/Peersyst/xrpl-go/xrpl/currency" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + transactions "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + w, err := wallet.FromSeed("sEdSMVV4dJ1JbdBxmakRR4Puu3XVZz2", "") + if err != nil { + panic(err) + } + + receiverWallet, err := wallet.FromSeed("sEd7d8Ci9nevdLCeUMctF3uGXp9WQqJ", "") + if err != nil { + panic(err) + } + + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + + balance, err := client.GetXrpBalance(w.GetAddress()) + + if err != nil || balance == "0" { + fmt.Println("Funding wallet...") + err = client.FundWallet(&w) + if err != nil { + panic(err) + } + fmt.Println("Wallet funded") + } + + balance, _ = client.GetXrpBalance(w.GetAddress()) + + fmt.Printf("Balance: %s\n", balance) + + amount, err := currency.XrpToDrops("1") + if err != nil { + panic(err) + } + + amountUint, err := strconv.ParseUint(amount, 10, 64) + if err != nil { + panic(err) + } + + fmt.Println("Sending payment...") + payment := transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(w.GetAddress()), + Memos: []types.MemoWrapper{ + { + Memo: types.Memo{ + MemoData: hex.EncodeToString([]byte("Hello, World!")), + MemoFormat: hex.EncodeToString([]byte("plain")), + MemoType: hex.EncodeToString([]byte("message")), + }, + }, + { + Memo: types.Memo{ + MemoData: hex.EncodeToString([]byte("Hello, World 2!")), + MemoFormat: hex.EncodeToString([]byte("text/plain")), + MemoType: hex.EncodeToString([]byte("message2")), + }, + }, + }, + }, + Destination: types.Address(receiverWallet.GetAddress()), + Amount: types.XRPCurrencyAmount(amountUint), + } + + flatTx := payment.Flatten() + + err = client.Autofill(&flatTx) + if err != nil { + panic(err) + } + + txBlob, _, err := w.Sign(flatTx) + if err != nil { + panic(err) + } + + response, err := client.SubmitTxBlobAndWait(txBlob, true) + if err != nil { + panic(err) + } + + fmt.Println("Payment submitted") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Printf("Validated: %t\n", response.Validated) +} diff --git a/_code-samples/send-a-memo/go/ws/main.go b/_code-samples/send-a-memo/go/ws/main.go new file mode 100644 index 0000000000..cc0e9b027b --- /dev/null +++ b/_code-samples/send-a-memo/go/ws/main.go @@ -0,0 +1,112 @@ +package main + +import ( + "encoding/hex" + "fmt" + "strconv" + + "github.com/Peersyst/xrpl-go/xrpl/currency" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + transactions "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +func main() { + w, err := wallet.FromSeed("sEdSMVV4dJ1JbdBxmakRR4Puu3XVZz2", "") + if err != nil { + panic(err) + } + + receiverWallet, err := wallet.FromSeed("sEd7d8Ci9nevdLCeUMctF3uGXp9WQqJ", "") + if err != nil { + panic(err) + } + + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + defer client.Disconnect() + + fmt.Println("Connecting to server...") + if err := client.Connect(); err != nil { + panic(err) + } + + fmt.Println("Connected to server") + fmt.Println() + + balance, err := client.GetXrpBalance(w.GetAddress()) + + if err != nil || balance == "0" { + fmt.Println("Funding wallet...") + err = client.FundWallet(&w) + if err != nil { + panic(err) + } + fmt.Println("Wallet funded") + } + + balance, _ = client.GetXrpBalance(w.GetAddress()) + + fmt.Printf("Balance: %s\n", balance) + + amount, err := currency.XrpToDrops("1") + if err != nil { + panic(err) + } + + amountUint, err := strconv.ParseUint(amount, 10, 64) + if err != nil { + panic(err) + } + + fmt.Println("Sending payment...") + payment := transactions.Payment{ + BaseTx: transactions.BaseTx{ + Account: types.Address(w.GetAddress()), + Memos: []types.MemoWrapper{ + { + Memo: types.Memo{ + MemoData: hex.EncodeToString([]byte("Hello, World!")), + MemoFormat: hex.EncodeToString([]byte("plain")), + MemoType: hex.EncodeToString([]byte("message")), + }, + }, + { + Memo: types.Memo{ + MemoData: hex.EncodeToString([]byte("Hello, World 2!")), + MemoFormat: hex.EncodeToString([]byte("text/plain")), + MemoType: hex.EncodeToString([]byte("message2")), + }, + }, + }, + }, + Destination: types.Address(receiverWallet.GetAddress()), + Amount: types.XRPCurrencyAmount(amountUint), + } + + flatTx := payment.Flatten() + + err = client.Autofill(&flatTx) + if err != nil { + panic(err) + } + + txBlob, _, err := w.Sign(flatTx) + if err != nil { + panic(err) + } + + response, err := client.SubmitTxBlobAndWait(txBlob, true) + if err != nil { + panic(err) + } + + fmt.Println("Payment submitted") + fmt.Printf("Hash: %s\n", response.Hash.String()) + fmt.Printf("Validated: %t\n", response.Validated) +} diff --git a/_code-samples/send-xrp/go/go.mod b/_code-samples/send-xrp/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/send-xrp/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/send-xrp/go/go.sum b/_code-samples/send-xrp/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/send-xrp/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/send-xrp/go/rpc/main.go b/_code-samples/send-xrp/go/rpc/main.go new file mode 100644 index 0000000000..0d16ec9f95 --- /dev/null +++ b/_code-samples/send-xrp/go/rpc/main.go @@ -0,0 +1,103 @@ +package main + +import ( + "fmt" + "strconv" + + "github.com/Peersyst/xrpl-go/xrpl/currency" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + + rpctypes "github.com/Peersyst/xrpl-go/xrpl/rpc/types" +) + +const ( + WalletSeed = "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9" +) + +func main() { + + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithMaxFeeXRP(5.0), + rpc.WithFeeCushion(1.5), + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + + w, err := wallet.FromSeed(WalletSeed, "") + if err != nil { + panic(err) + } + + fmt.Println("Funding wallet...") + if err := client.FundWallet(&w); err != nil { + panic(err) + } + + fmt.Println("Wallet funded") + fmt.Println() + + xrpAmount, err := currency.XrpToDrops("1") + if err != nil { + panic(err) + } + + xrpAmountInt, err := strconv.ParseInt(xrpAmount, 10, 64) + if err != nil { + panic(err) + } + + fmt.Println("Sending 1 XRP to rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe...") + p := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: types.Address(w.GetAddress()), + }, + Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + Amount: types.XRPCurrencyAmount(xrpAmountInt), + DeliverMax: types.XRPCurrencyAmount(xrpAmountInt), + } + + flattenedTx := p.Flatten() + + if err := client.Autofill(&flattenedTx); err != nil { + panic(err) + } + + txBlob, _, err := w.Sign(flattenedTx) + if err != nil { + panic(err) + } + + res, err := client.SubmitTxBlobAndWait(txBlob, false) + if err != nil { + panic(err) + } + + fmt.Println("Payment submitted") + fmt.Printf("Hash: %s\n", res.Hash) + fmt.Printf("Validated: %t\n", res.Validated) + fmt.Println() + fmt.Println("Using SubmitTxAndWait with wallet") + fmt.Println() + + flattenedTx2 := p.Flatten() + resp, err := client.SubmitTxAndWait(flattenedTx2, &rpctypes.SubmitOptions{ + Autofill: true, + Wallet: &w, + }) + if err != nil { + panic(err) + } + + fmt.Println("Payment submitted via SubmitTxAndWait") + fmt.Printf("Hash: %s\n", resp.Hash) + fmt.Printf("Validated: %t\n", resp.Validated) +} diff --git a/_code-samples/send-xrp/go/ws/main.go b/_code-samples/send-xrp/go/ws/main.go new file mode 100644 index 0000000000..5e07e21678 --- /dev/null +++ b/_code-samples/send-xrp/go/ws/main.go @@ -0,0 +1,110 @@ +package main + +import ( + "fmt" + "strconv" + + "github.com/Peersyst/xrpl-go/xrpl/currency" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/queries/transactions" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" + wstypes "github.com/Peersyst/xrpl-go/xrpl/websocket/types" +) + +func main() { +client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), +) +defer client.Disconnect() + +if err := client.Connect(); err != nil { + panic(err) +} + +if !client.IsConnected() { + fmt.Println("Failed to connect to testnet") + return +} + +fmt.Println("Connected to testnet") +fmt.Println() + +// Example credentials +const WalletSeed = "sEd7zwWAu7vXMCBkkzokJHEXiKw2B2s" +w, err := wallet.FromSeed(WalletSeed, "") +if err != nil { + panic(err) +} + +// Funding the wallet +fmt.Println("Funding wallet...") +if err := client.FundWallet(&w); err != nil { + panic(err) +} + +fmt.Println("Wallet funded") +fmt.Println() + +xrpAmount, err := currency.XrpToDrops("1") +if err != nil { + panic(err) +} + +xrpAmountInt, err := strconv.ParseInt(xrpAmount, 10, 64) +if err != nil { + panic(err) +} + +// Prepare a payment transaction +p := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: types.Address(w.GetAddress()), + }, + Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + Amount: types.XRPCurrencyAmount(xrpAmountInt), + DeliverMax: types.XRPCurrencyAmount(xrpAmountInt), +} + +flattenedTx := p.Flatten() + +if err := client.Autofill(&flattenedTx); err != nil { + panic(err) +} + +// Sign the transaction using the wallet +txBlob, _, err := w.Sign(flattenedTx) +if err != nil { + panic(err) +} + +// Submit the transaction and wait for the result +res_blob, err := client.SubmitTxBlobAndWait(txBlob, false) +if err != nil { + panic(err) +} + +// Example with SubmitTxAndWait +flattenedTx2 := p.Flatten() +res_flat, err := client.SubmitTxAndWait(flattenedTx2, &wstypes.SubmitOptions{ + Autofill: true, + Wallet: &w, +}) +if err != nil { + panic(err) +} +// Wait for validation ------------------------------------------------------- +// SubmitTxBlobAndWait() handles this automatically, but it can take 4-7s. + +// Check transaction results ------------------------------------------------- +fmt.Printf("Hash: %s\n", res_blob.Hash) +fmt.Printf("Meta: %t\n", res_blob.Meta) +res, _ := client.Request(&transactions.TxRequest{ + Transaction: res_flat.Hash.String(), +}) +fmt.Printf("Result: %s\n", res.Result) +} diff --git a/_code-samples/set-regular-key/go/go.mod b/_code-samples/set-regular-key/go/go.mod new file mode 100644 index 0000000000..19a736f94c --- /dev/null +++ b/_code-samples/set-regular-key/go/go.mod @@ -0,0 +1,24 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/set-regular-key/go/go.sum b/_code-samples/set-regular-key/go/go.sum new file mode 100644 index 0000000000..988da1d6c2 --- /dev/null +++ b/_code-samples/set-regular-key/go/go.sum @@ -0,0 +1,58 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/set-regular-key/go/rpc/main.go b/_code-samples/set-regular-key/go/rpc/main.go new file mode 100644 index 0000000000..8a4b7ec15b --- /dev/null +++ b/_code-samples/set-regular-key/go/rpc/main.go @@ -0,0 +1,119 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + + w1, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + w2, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + regularKeyWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Funding wallets...") + if err := client.FundWallet(&w1); err != nil { + panic(err) + } + + fmt.Println("Wallet 1 funded") + + if err := client.FundWallet(&w2); err != nil { + panic(err) + } + + fmt.Println("Wallet 2 funded") + + if err := client.FundWallet(®ularKeyWallet); err != nil { + panic(err) + } + + fmt.Println("Regular key wallet funded") + fmt.Println() + + fmt.Println("Setting regular key...") + rk := &transaction.SetRegularKey{ + BaseTx: transaction.BaseTx{ + Account: w1.GetAddress(), + }, + RegularKey: regularKeyWallet.GetAddress(), + } + + flatRk := rk.Flatten() + + err = client.Autofill(&flatRk) + if err != nil { + panic(err) + } + + blob, _, err := w1.Sign(flatRk) + if err != nil { + panic(err) + } + + res, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("SetRegularKey transaction submitted") + fmt.Printf("Hash: %s\n", res.Hash) + fmt.Printf("Validated: %t\n", res.Validated) + fmt.Println() + + fmt.Println("Checking if regular key is set...") + p := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: w1.GetAddress(), + }, + Destination: w2.GetAddress(), + Amount: types.XRPCurrencyAmount(10000), + } + + flatP := p.Flatten() + + err = client.Autofill(&flatP) + if err != nil { + panic(err) + } + + blob, _, err = regularKeyWallet.Sign(flatP) + if err != nil { + panic(err) + } + + res, err = client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Payment transaction submitted") + fmt.Printf("Hash: %s\n", res.Hash) + fmt.Printf("Validated: %t\n", res.Validated) +} diff --git a/_code-samples/set-regular-key/go/ws/main.go b/_code-samples/set-regular-key/go/ws/main.go new file mode 100644 index 0000000000..ffcf42549b --- /dev/null +++ b/_code-samples/set-regular-key/go/ws/main.go @@ -0,0 +1,129 @@ +package main + +import ( + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/transaction/types" + "github.com/Peersyst/xrpl-go/xrpl/wallet" + "github.com/Peersyst/xrpl-go/xrpl/websocket" +) + +func main() { + fmt.Println("Connecting to testnet...") + client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://s.altnet.rippletest.net:51233"). + WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + defer client.Disconnect() + + if err := client.Connect(); err != nil { + panic(err) + } + + if !client.IsConnected() { + fmt.Println("Failed to connect to testnet") + return + } + + fmt.Println("Connected to testnet") + fmt.Println() + + w1, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + w2, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + regularKeyWallet, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Funding wallets...") + if err := client.FundWallet(&w1); err != nil { + panic(err) + } + + fmt.Println("Wallet 1 funded") + + if err := client.FundWallet(&w2); err != nil { + panic(err) + } + + fmt.Println("Wallet 2 funded") + + if err := client.FundWallet(®ularKeyWallet); err != nil { + panic(err) + } + + fmt.Println("Regular key wallet funded") + fmt.Println() + + fmt.Println("Setting regular key...") + rk := &transaction.SetRegularKey{ + BaseTx: transaction.BaseTx{ + Account: w1.GetAddress(), + }, + RegularKey: regularKeyWallet.GetAddress(), + } + + flatRk := rk.Flatten() + + err = client.Autofill(&flatRk) + if err != nil { + panic(err) + } + + blob, _, err := w1.Sign(flatRk) + if err != nil { + panic(err) + } + + res, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("SetRegularKey transaction submitted") + fmt.Printf("Hash: %s\n", res.Hash) + fmt.Printf("Validated: %t\n", res.Validated) + fmt.Println() + + fmt.Println("Checking if regular key is set...") + p := &transaction.Payment{ + BaseTx: transaction.BaseTx{ + Account: w1.GetAddress(), + }, + Destination: w2.GetAddress(), + Amount: types.XRPCurrencyAmount(10000), + } + + flatP := p.Flatten() + + err = client.Autofill(&flatP) + if err != nil { + panic(err) + } + + blob, _, err = regularKeyWallet.Sign(flatP) + if err != nil { + panic(err) + } + + res, err = client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("Payment transaction submitted") + fmt.Printf("Hash: %s\n", res.Hash) + fmt.Printf("Validated: %t\n", res.Validated) +} diff --git a/_code-samples/use-tickets/go/go.mod b/_code-samples/use-tickets/go/go.mod new file mode 100644 index 0000000000..4643f9f714 --- /dev/null +++ b/_code-samples/use-tickets/go/go.mod @@ -0,0 +1,23 @@ +module github.com/XRPLF + +go 1.23.0 + +toolchain go1.23.10 + +require github.com/Peersyst/xrpl-go v0.1.11 + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/crypto v0.35.0 // indirect +) diff --git a/_code-samples/use-tickets/go/go.sum b/_code-samples/use-tickets/go/go.sum new file mode 100644 index 0000000000..44302b3a35 --- /dev/null +++ b/_code-samples/use-tickets/go/go.sum @@ -0,0 +1,56 @@ +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w= +github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys= +github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= diff --git a/_code-samples/use-tickets/go/main.go b/_code-samples/use-tickets/go/main.go new file mode 100644 index 0000000000..ccf7d05098 --- /dev/null +++ b/_code-samples/use-tickets/go/main.go @@ -0,0 +1,123 @@ +package main + +import ( + "encoding/json" + "fmt" + + "github.com/Peersyst/xrpl-go/pkg/crypto" + "github.com/Peersyst/xrpl-go/xrpl/faucet" + "github.com/Peersyst/xrpl-go/xrpl/queries/account" + "github.com/Peersyst/xrpl-go/xrpl/rpc" + "github.com/Peersyst/xrpl-go/xrpl/transaction" + "github.com/Peersyst/xrpl-go/xrpl/wallet" +) + +func main() { + cfg, err := rpc.NewClientConfig( + "https://s.altnet.rippletest.net:51234/", + rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()), + ) + if err != nil { + panic(err) + } + + client := rpc.NewClient(cfg) + + w, err := wallet.New(crypto.ED25519()) + if err != nil { + panic(err) + } + + fmt.Println("Funding wallet...") + if err := client.FundWallet(&w); err != nil { + panic(err) + } + + fmt.Println("Wallet funded") + fmt.Println() + + info, err := client.GetAccountInfo(&account.InfoRequest{ + Account: w.GetAddress(), + }) + if err != nil { + panic(err) + } + + fmt.Println("Current wallet sequence:", info.AccountData.Sequence) + fmt.Println() + + fmt.Println("Submitting TicketCreate transaction...") + tc := &transaction.TicketCreate{ + BaseTx: transaction.BaseTx{ + Account: w.GetAddress(), + Sequence: info.AccountData.Sequence, + }, + TicketCount: 10, + } + + flatTc := tc.Flatten() + + if err := client.Autofill(&flatTc); err != nil { + panic(err) + } + + blob, _, err := w.Sign(flatTc) + if err != nil { + panic(err) + } + + res, err := client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("TicketCreate transaction submitted") + fmt.Printf("Hash: %s\n", res.Hash) + fmt.Printf("Validated: %t\n", res.Validated) + fmt.Println() + + objects, err := client.GetAccountObjects(&account.ObjectsRequest{ + Account: w.GetAddress(), + }) + if err != nil { + panic(err) + } + + fmt.Println("Account objects:", objects.AccountObjects[0]["TicketSequence"]) + + seq, err := objects.AccountObjects[0]["TicketSequence"].(json.Number).Int64() + if err != nil { + panic(err) + } + + fmt.Println("Submitting AccountSet transaction...") + as := &transaction.AccountSet{ + BaseTx: transaction.BaseTx{ + Account: w.GetAddress(), + Sequence: 0, + TicketSequence: uint32(seq), + }, + } + + flatAs := as.Flatten() + + if err := client.Autofill(&flatAs); err != nil { + panic(err) + } + + flatAs["Sequence"] = uint32(0) + + blob, _, err = w.Sign(flatAs) + if err != nil { + panic(err) + } + + res, err = client.SubmitTxBlobAndWait(blob, false) + if err != nil { + panic(err) + } + + fmt.Println("AccountSet transaction submitted") + fmt.Printf("Hash: %s\n", res.Hash) + fmt.Printf("Validated: %t\n", res.Validated) +} diff --git a/about/uses.page.tsx b/about/uses.page.tsx index 7013fa498b..2e1ed3e955 100644 --- a/about/uses.page.tsx +++ b/about/uses.page.tsx @@ -26,7 +26,7 @@ const logos = { ], developer_tooling: ["cryptum", "evernode", "threezy", "tokenize"], interoperability: ["multichain"], - wallet: ["crossmark", "edge", "gem-wallet", "xumm"], + wallet: ["crossmark", "edge", "gem-wallet", "xumm", "joey-wallet"], nfts: [ "aesthetes", "audiotarky", @@ -243,6 +243,15 @@ const cardsData = [ category_name: "Wallet", link: "https://github.com/crossmarkio", }, + { + id: "joey-wallet", + title: "Joey Wallet", + description: + "Joey Wallet is a secure, self-custody cryptocurrency wallet and gateway to Web3 decentralized applications (dApps) on the XRP Ledger (XRPL).", + category_id: "wallet", + category_name: "Wallet", + link: "https://joeywallet.xyz/", + }, { id: "Edge", title: "Edge", @@ -450,7 +459,7 @@ const uses = [ { id: "wallet", title: "Wallet", - number: 4, + number: 5, description: "Build digital wallets to store passwords and interact with various blockchains to send and receive digital assets, including XRP." }, diff --git a/about/xrp.page.tsx b/about/xrp.page.tsx index ae50852e11..a69b32e3c1 100644 --- a/about/xrp.page.tsx +++ b/about/xrp.page.tsx @@ -30,6 +30,7 @@ const softwallets = [ { href: "https://gemwallet.app/", id: "wallet-gem", alt: "Gem Wallet" }, { href: "https://coin.space/", id: "wallet-coin", alt: "Coin Space" }, { href: "https://crossmark.io/", id: "wallet-crossmark", alt: "Crossmark Wallet" }, + { href: "https://joeywallet.xyz/", id: "wallet-joey", alt: "Joey Wallet" }, ]; const hardwallets = [ diff --git a/blog/2025/default-unl-migration.md b/blog/2025/default-unl-migration.md new file mode 100644 index 0000000000..dda99b49d8 --- /dev/null +++ b/blog/2025/default-unl-migration.md @@ -0,0 +1,121 @@ +--- +category: 2025 +date: "2025-09-18" +template: '../../@theme/templates/blogpost' +seo: + description: If you run a rippled node that uses the default UNL, you must migrate your configuration to the new XRPL Foundation's list by 2025-09-30. +labels: + - Advisories +markdown: + editPage: + hide: true +--- +# Default UNL Migration + +As [previously announced](./move-to-the-new-xrpl-foundation-commences.md), stewardship of the XRP Ledger has moved to a new XRPL Foundation. As part of the migration, the default UNL for XRP Ledger servers is now served from a new URL and uses a new key pair. If you run a server on the XRP Ledger mainnet and uses the default UNL, you must migrate to the new UNL settings before the old UNL publisher shuts down on September 30 (2025-09-30), to maintain service continuity. + +## Background + +As part of the XRP Ledger's consensus process, each server is configured with a Unique Node List (UNL), which is a set of validators that it trusts not to collude. To maintain the necessary safety of the network and to balance the priorities of overlap and independence in a UNL, the XRP Ledger Foundation publishes a default UNL (dUNL) with a list of vetted, independent node operators that exist in a diverse selection of countries, data centers, and so on. Node operators are not required to use the dUNL to maintain sync with the XRP Ledger, but it is widely recommended as the safest, most reliable set of validators to trust. To ensure its integrity, the dUNL is signed with a cryptographic key pair under the control of the XRP Ledger Foundation. + +As part of the migration from the old XRP Ledger Foundation to the new one, the new Foundation has begun publishing a default UNL using a new key pair from a new URL. The old Foundation is no longer publishing new dUNL updates, and the URL serving the old dUNL is scheduled to be shut down at the end of this month, on 2025-09-30. + +## Action Needed + +If you run a node (a core XRPL server, such as `rippled`) that uses the old dUNL, you must update your configuration to use the new key pair and URL. This is the case for most servers that connect to the XRP Ledger Mainnet and have been upgraded from `rippled` **2.3.x or lower**. If you created a fresh install with new config files using `rippled` version 2.4.0 or higher, your config files should already have the new Foundation's key and URL, so no update is needed. + +{% admonition type="danger" name="Warning" %} +The standard package install does not overwrite existing configuration files, so these steps are necessary if you are carrying over a config that was created under an older version, even if you have upgraded the server software. +{% /admonition %} + +This process is two steps: + +1. Edit your server's `validators.txt` file. This file is typically located at `/etc/opt/ripple/validators.txt` by default. In some configurations, it could be located at `$HOME/.config/ripple/validators.txt` (where `$HOME` is the home directory of the user running `rippled`), `$HOME/.local/ripple/validators.txt`, or the current working directory from where you start the `rippled` server. + + Update the `[validator_list_keys]` and `[validator_list_sites]` sections of the config file to remove the key and URL of the old Foundation and add the key and URL of the new Foundation, as in the following table: + + | | URL in `[validator_list_sites]` | Key in `[validator_list_keys]` | + |--------------|-------------------------|-----| + | Old (remove) | `https://vl.xrplf.org` | `ED45D1840EE724BE327ABE9146503D5848EFD5F38B6D5FEDE71E80ACCE5E6E738B` | + | New (add) | `https://unl.xrplf.org` | `ED42AEC58B701EEBB77356FFFEC26F83C1F0407263530F068C7C73D392C7E06FD1` | + + Keys and URLs for other validator publishers (such as `vl.ripple.com`) can remain the same. + + {% admonition type="success" name="Tip: HTTP vs HTTPS" %} + The URLs can also use unsecured `http://` in case there is a problem with TLS certificates. The contents of the validator list are cryptographically signed by the key listed above, so SSL/TLS is not strictly necessarity to ensure the integrity of the contents. + {% /admonition %} + +2. Restart your server. + + ```sh + sudo systemctl restart rippled.service + ``` + +3. Confirm new settings. + + After restarting, you can use the `validators` admin command to confirm the new settings. + + ```sh + /opt/ripple/bin/rippled validators + ``` + + If you are using a non-default configuration, change the path to your `rippled` executable as needed. + + The response should display the updated values in the `publisher_lists` key. The new list should be available with an expiration on 2026-02-13 (February 13, 2026). For example (response trimmed for length): + + ```json + { + "result": { + "local_static_keys": [], + "publisher_lists": [ + { + "available": true, + "expiration": "2026-Feb-13 14:15:03.000000000 UTC", + ... + "list": [ + ... + ], + "pubkey_publisher": "ED42AEC58B701EEBB77356FFFEC26F83C1F0407263530F068C7C73D392C7E06FD1", + "seq": 1, + "uri": "https://unl.xrplf.org", + "version": 1 + }, + ... + ] + ... + } + ``` + + For more information and troubleshooting steps, see [Configuration Guidance for Using the new UNL (discussion on rippled GitHub)](https://github.com/XRPLF/rippled/discussions/5463). + +## Impact of not updating the configuration + +If you do not change to the new settings, your node may stop loading the XRPL Foundation's trusted validators list on 2025-09-30 when the old URL is shut down, and your node's configured UNL will expire on 2026-01-18 (January 18, 2026). **After the list expires, your server will stop syncing with the network, but it could also lose sync as early as 2025-09-30, depending on other factors.** + +- If you have a `[validator_list_threshold]` configured, validators are only trusted if they are in more than half of your configured lists. Depending on the changes in the other lists, your server may not trust enough validators to reach a consensus with the rest of the network. +- If your server only relies on the XRPL Foundation's list and does not have the old list cached, it may not be able to determine a set of trusted validators to sync with the network during startup. + +### Log Messages + +You may see log messages such as the following in your server log: + +```text +WRN:Ignored 1 stale validator list(s) from https://vl.ripple.com +WRN:Ignored 1 untrusted validator list(s) from https://unl.ripple.com +``` + +Updating the config with the new key and site should stop or reduce the log messages. + +### Validator stuck in full state + +If you have a validator whose server state stays as `full` instead of `proposing`, it could be a symptom that your configuration is not updated appropriately. In this case, the response from the `server_info` command shows a very high validation quorum value: + +```json +"validation_quorum": 4294967295, +``` + +Updating the config with the new key and site should fix the problem. + +## Next Steps + +For more information and troubleshooting steps, see [Configuration Guidance for Using the new UNL (discussion on rippled GitHub)](https://github.com/XRPLF/rippled/discussions/5463). diff --git a/blog/2025/fortstock-xrpl-case-study-mpt-standard.md b/blog/2025/fortstock-xrpl-case-study-mpt-standard.md new file mode 100644 index 0000000000..f01c8bbd53 --- /dev/null +++ b/blog/2025/fortstock-xrpl-case-study-mpt-standard.md @@ -0,0 +1,69 @@ +--- +category: 2025 +date: "2025-09-10" +template: '../../@theme/templates/blogpost' +seo: + description: Learn how FortStock is using the XRP Ledger’s Multi-Purpose Token (MPT) standard to turn idle warehouse inventory into usable collateral. +labels: + - Development +markdown: + editPage: + hide: true +--- +# How XRP Ledger’s MPT Standard Helps FortStock Unlock Trillions in Idle Inventory + +Learn how FortStock is using the XRP Ledger’s Multi-Purpose Token (MPT) standard to turn idle warehouse inventory into usable collateral. + +Global trade moves over $25 trillion in goods every year. Containers cross oceans, fill warehouses, and wait silently at distribution centers. Yet much of this physical inventory remains frozen in financial terms - unleveraged, undocumented in capital markets, and untapped as collateral. + +This reality is more than a quirk of trade logistics. It creates a multi-trillion-dollar inefficiency. According to the ADB and WTO, the global trade finance gap now stands between $2.5 and $5 trillion - a hole that disproportionately impacts the very economies most dependent on trade: emerging markets. + +At FortStock, we believe there is a better way. We’re building an infrastructure where warehouse receipts become programmable financial assets that can be used as collateral for short-term credit. But to do that, we needed more than just tokenization. We needed a token format that could carry real-world logic - not just data. That’s where the XRP Ledger’s [Multi-Purpose Token (MPT) standard](/docs/use-cases/tokenization/creating-an-asset-backed-multi-purpose-token) comes in. + +## Why MPT Is the Missing Link Between Physical Assets and On-Chain Finance + +To bring real-world assets like warehouse receipts into on-chain finance, a token must do more than simply represent ownership. It needs to function as a true digital contract, with its rules and data deeply integrated at the ledger level. Capturing the complexity of a regulated financial instrument has been the primary challenge in bridging physical collateral with digital liquidity. + +The MPT standard is engineered to solve this, offering precisely the functionality FortStock needed: + +* A way to embed legally relevant metadata directly on-chain (e.g., warrant number, expiry date, or the hash of the original receipt). +* A token object that reflects the full lifecycle of an asset-from origination to collateralization to settlement-without requiring complex, external smart contracts. + +With MPT, we can mirror how warehouse receipts and trade credit behave in the real world-but do it in a format that is native to blockchain and global from day one. + + +## Warehouse Receipts as MPT: What It Looks Like in Practice + +Earlier this month, we minted a sample MPT token on the XRP Ledger Devnet representing a pledged warehouse asset. This wasn’t a front-end simulation or a UI preview. This was the actual logic - executed and traceable on-chain. + +![Flow Diagram of Warehouse Receipts as MPT](/blog/img/fortstock-warehouse-receipts-as-mpt-flow-diagram.jpg) + +We then transferred the token to a creditor address, mimicking the pledge of collateral in a lending transaction. Finally, we returned and burned the token to close the loop, demonstrating how the asset lifecycle can be fully managed within the MPT framework. + +These are test transactions, but the data is live, open, and verifiable by anyone: + +* Issuance of the warehouse receipt token with detailed memo fields. + + ![MPTokenIssuanceCreate Transaction](/blog/img/fortstock-mptokenissuancecreate.png) + +* Transfer to another wallet to simulate collateralization + + ![Transfer to simulate collateralization](/blog/img/fortstock-mpt-simulate-collateralization.png) + +## The Capital Flows That Follow + +This infrastructure does more than digitize documentation. It unlocks liquidity. When warehouse receipts are tokenized as MPTs, they can be linked to on-chain liquidity like RLUSD, once deployed on XRPL. + +This means real-world borrowers can obtain real-time financing - not based on their credit history, but based on their inventory and logistics. The lenders, in turn, receive transparent tokens backed by physical goods. + +A token can include context such as origin jurisdiction, commodity class, storage expiry, and audit trail, making it not only more secure but also de-risked by design. + +This allows investors to access an attractive 8–12% yield that, unlike many DeFi protocols, is securely backed by real-world physical goods. + +## What Comes Next + +FortStock is continuing to develop this architecture with real warehouse partners, regulated lending institutions, and payment rails. + +The XRP Ledger, with its native support for MPT, gives us the compliance-forward, fee-efficient, high-speed base layer we need to scale this model globally. + +Because ultimately, programmable finance should start with real assets, not speculative tokens. With MPTs, we’re building exactly that - one warehouse at a time. \ No newline at end of file diff --git a/blog/2025/rippled-2.5.1.md b/blog/2025/rippled-2.5.1.md new file mode 100644 index 0000000000..de57cd0b21 --- /dev/null +++ b/blog/2025/rippled-2.5.1.md @@ -0,0 +1,62 @@ +--- +category: 2025 +date: "2025-09-08" +template: '../../@theme/templates/blogpost' +seo: + title: Introducing XRP Ledger version 2.5.1 + description: rippled version 2.5.1 is now available. This version fixes an issue with stalled consensus rounds. +labels: + - rippled Release Notes +markdown: + editPage: + hide: true +--- +# Introducing XRP Ledger version 2.5.1 + +Version 2.5.1 of `rippled`, the reference server implementation of the XRP Ledger protocol, is now available. This release was rolled back from version 2.6.0 after issues were discovered, but retains an important fix for stalled consensus rounds. + + +## Action Required + +If you run an XRP Ledger server, upgrade to version 2.5.1 as soon as possible to ensure service continuity. + + +## Install / Upgrade + +On supported platforms, see the [instructions on installing or updating `rippled`](../../docs/infrastructure/installation/index.md). + +| Package | SHA-256 | +|:--------|:--------| +| [RPM for Red Hat / CentOS (x86-64)](https://repos.ripple.com/repos/rippled-rpm/stable/rippled-2.5.1-1.el7.x86_64.rpm) | `f16da245b417d616033e8fac8190425f1f8778f61c62fd23986e2e496c4fabf4` | +| [DEB for Ubuntu / Debian (x86-64)](https://repos.ripple.com/repos/rippled-deb/pool/stable/rippled_2.5.1-1_amd64.deb) | `1d3cd06fc08911c5efd1b9a6b1b7d06f42e806e0628df9f0552c9e71daee0af6` | + +For other platforms, please [build from source](https://github.com/XRPLF/rippled/blob/master/BUILD.md). The most recent commit in the git log should be the change setting the version: + +```text +commit 16c2ff97ccc5e78fe450bd92c431322de75aa94e +Author: Ed Hennis +Date: Wed Sep 3 10:19:38 2025 -0400 + + Set version to 2.5.1 +``` + + +## Full Changelog + +### Bug Fixes + +- Fixed stalled consensus detection to prevent false positives in situations where there were no disputed transactions. ([#5658](https://github.com/XRPLF/rippled/pull/5658)) + + +## Credits + +The following GitHub users contributed to this release: + +- @ximinez + + +## Bug Bounties and Responsible Disclosures + +We welcome reviews of the `rippled` code and urge researchers to responsibly disclose any issues they may find. + +To report a bug, please send a detailed report to: \ No newline at end of file diff --git a/blog/2025/rippled-2.6.0.md b/blog/2025/rippled-2.6.0.md new file mode 100644 index 0000000000..fd36346d57 --- /dev/null +++ b/blog/2025/rippled-2.6.0.md @@ -0,0 +1,136 @@ +--- +category: 2025 +date: "2025-08-27" +template: '../../@theme/templates/blogpost' +seo: + title: Introducing XRP Ledger version 2.6.0 + description: rippled version 2.6.0 is now available. This version contains various bug fixes and minor improvements. +labels: + - rippled Release Notes +markdown: + editPage: + hide: true +--- +# Introducing XRP Ledger version 2.6.0 +{% admonition type="danger" name="Warning" %} +The team is tracking two active issues in rippled 2.6.0—memory usage increases and Boost library upgrade problems. It is recommend that the UNL community roll back to [version 2.5.1](./rippled-2.5.1.md), which includes the fix for stalled consensus rounds from this relase. The remaining 2.6.0 changes will be included in a later release, along with fixes for the issues discovered. +{% /admonition %} + +Version 2.6.0 of `rippled`, the reference server implementation of the XRP Ledger protocol, is now available. This release adds new features and bug fixes. + + +## Action Required + +If you run an XRP Ledger server and recently upgraded to version 2.6.0, roll back to version [2.5.1](./rippled-2.5.1.md) to ensure service continuity. + + +## Full Changelog + +### Amendments + +- None + + +### New Features + +- Improved the `account_tx` method to show MPT-related transactions for an issuer. ([#5530](https://github.com/XRPLF/rippled/pull/5530)) +- Added the `network_id` field to `validations` and `ledger` subscription streams. ([#5579](https://github.com/XRPLF/rippled/pull/5579)) +- Added `nftoken_id`, `nftoken_ids`, and `offer_id` to the `meta` field of transaction streams from the `subscribe` method. ([#5230](https://github.com/XRPLF/rippled/pull/5230)) + + +### Bug Fixes + +- Fixed stalled consensus detection to prevent false positives in situations where there were no disputed transactions. ([#5627](https://github.com/XRPLF/rippled/pull/5627)) +- Added the `allowTrustLineLocking` flag as an option for the `account_info` method. ([#5535](https://github.com/XRPLF/rippled/pull/5525)) +- Removed the automatic creation of trust lines to the `Destination` account in `VaultWithdraw` transactions. ([#5572](https://github.com/XRPLF/rippled/pull/5572)) +- Removed the deprecated `type` field from the `ledger` method. ([#4934](https://github.com/XRPLF/rippled/pull/4934)) +- Fixed incorrect error and warning logs for AMM offer retrievals and IOU payment checks. ([#5686](https://github.com/XRPLF/rippled/pull/5686)) +- Fixed a crash when trace-logging in tests. ([#5529](https://github.com/XRPLF/rippled/pull/5529)) +- Removed circular includes in header files. ([#5544](https://github.com/XRPLF/rippled/pull/5544)) +- Fixed Boost Library linking to be explicit. ([#5546](https://github.com/XRPLF/rippled/pull/5546)) +- Silenced a dummy warning in GCC 12. ([#5554](https://github.com/XRPLF/rippled/pull/5554)) +- Fixed an issue where the order of `PriceDataSeries` desynced between the time a `PriceOracle` was created and when it was updated. ([#5485](https://github.com/XRPLF/rippled/pull/5485)) +- Fixed the logging logic to correctly report the specific reason (full or duplicate) for a rejected peer connection. ([#5664](https://github.com/XRPLF/rippled/pull/5664)) +- Added `-Wno-deprecated-declarations` for Clang only. ([#5680](https://github.com/XRPLF/rippled/pull/5680)) +- Fixed a crash due to a recurrent call to `Slot::deletePeer` when a peer is disconnected at just the wrong moment. ([#5635](https://github.com/XRPLF/rippled/pull/5635)) +- Fixed a MacOS pipeline issue. ([#5585](https://github.com/XRPLF/rippled/pull/5585)) + + +### Other Improvements + +- Optimized hash performance. ([#5469](https://github.com/XRPLF/rippled/pull/5469)) +- Removed release notes from the `rippled` codebase to facilitate more frequent releases. ([#5508](https://github.com/XRPLF/rippled/pull/5508)) +- Removed the obsolete `OwnerPaysFee` amendment. It was never enabled. ([#5435](https://github.com/XRPLF/rippled/pull/5435), [#5550](https://github.com/XRPLF/rippled/pull/5550)) +- Retired the `FlowCross` amendment. The functionality is now part of the core protocol unconditionally. ([#5562](https://github.com/XRPLF/rippled/pull/5562), [#5575](https://github.com/XRPLF/rippled/pull/5575)) +- Added an `XRPL_ABANDON` macro for features that were never enabled or implemented. ([#5510](https://github.com/XRPLF/rippled/pull/5510)) +- Switched some unit tests to doctests. ([#5383](https://github.com/XRPLF/rippled/pull/5383)) +- Refactored `CredentialHelpers` and removed unnecessary dependencies. ([#5487](https://github.com/XRPLF/rippled/pull/5487)) +- Fixed a compilation error with `clang-20`. ([#5543](https://github.com/XRPLF/rippled/pull/5543)) +- Downgraded the required `CMake` version for `Antithesis` SDK. ([#5548](https://github.com/XRPLF/rippled/pull/5548)) +- Removed unused headers. ([#5526](https://github.com/XRPLF/rippled/pull/5526)) +- Updated the CI workflow to use Conan 2. ([#5556](https://github.com/XRPLF/rippled/pull/5556)) +- Enabled unit tests regardless of an amendment's supported status. ([#5537](https://github.com/XRPLF/rippled/pull/5537)) +- Updated several dependencies to their latest versions. ([#5567](https://github.com/XRPLF/rippled/pull/5567)) +- Removed `include(default)` from the `libxrpl` profile. ([#5587](https://github.com/XRPLF/rippled/pull/5587)) +- Refactored `rngfill` to reduce false warnings from GCC. ([#5563](https://github.com/XRPLF/rippled/pull/5563)) +- Fixed the `clang-format` workflow. ([#5598](https://github.com/XRPLF/rippled/pull/5598)) +- Refactored `HashRouter` flags to be type-safe. ([#5371](https://github.com/XRPLF/rippled/pull/5371)) +- Renamed the `libxrpl` profile to `default`, making it more usable. ([#5599](https://github.com/XRPLF/rippled/pull/5599)) +- Switched instrumentation workflow to use dependencies. ([#5607](https://github.com/XRPLF/rippled/pull/5607)) +- Updated RocksDB to its latest version. ([#5568](https://github.com/XRPLF/rippled/pull/5568)) +- Updates Boost to version 1.86.0. ([#5264](https://github.com/XRPLF/rippled/pull/5264)) +- Removed old build options. ([#5581](https://github.com/XRPLF/rippled/pull/5581)) +- Updated Conan dependencies to temporarily build from source. ([#5623](https://github.com/XRPLF/rippled/pull/5623)) +- Added MacOS build instructions for specific versions of AppleClang. ([#5645](https://github.com/XRPLF/rippled/pull/5645)) +- Decoupled `ledger` from `xrpld/app`, modularising the ledger component. ([#5492](https://github.com/XRPLF/rippled/pull/5492)) +- Updated `BUILD.md` with instructions for Conan 2, Apple Clang 17, Clang 20, and CMake 4. ([#5478](https://github.com/XRPLF/rippled/pull/5478)) +- Removed the patched Conan recipes from the `external` directory and updated instructions for obtaining patched recipes. ([#5643](https://github.com/XRPLF/rippled/pull/5643)) +- Changed `develop` branch merge process to upload built Conan dependencies to the Conan remote. ([#5654](https://github.com/XRPLF/rippled/pull/5654)) +- Switched Conan 1 commands to Conan 2 and fixed credentials. ([#5655](https://github.com/XRPLF/rippled/pull/5655)) +- Cleaned up unused files from the `bin` directory. ([#5660](https://github.com/XRPLF/rippled/pull/5660)) +- Updated `CONAN_REMOTE_URL` to also work with PRs from forks. ([#5662](https://github.com/XRPLF/rippled/pull/5662)) +- Updated autolint behavior on all files. ([#5657](https://github.com/XRPLF/rippled/pull/5657)) +- Updated test suite names to match the folder the test files are located. ([#5597](https://github.com/XRPLF/rippled/pull/5597)) +- Updated `BUILD.md` for users who prefer to explicitly download recipes. ([#5676](https://github.com/XRPLF/rippled/pull/5676)) +- Updated `.git-blame-ignore-revs` for [#5657](https://github.com/XRPLF/rippled/pull/5657). ([#5675](https://github.com/XRPLF/rippled/pull/5675)) +- Updated the list of maintainers and common code reviewers. ([#5687](https://github.com/XRPLF/rippled/pull/5687)) +- Reverted to `std::shared_mutex` from `boost::shared_mutex`. ([#5576](https://github.com/XRPLF/rippled/pull/5576)) + + +## Credits + +The following GitHub users contributed to this release: + +- @Afformativ +- @a1q123456 +- @Bronek +- @bthomee +- @ckeshava +- @dangell7 +- @hgandhi-perfx +- @intelliot +- @kennyzlei +- @lmaisons +- @mathbunnyru +- @mounikakun +- @mvadari +- @oeggert +- @q73zhao +- @rrmanukyan +- @sgramkumar +- @shawnxie999 +- @shichengripple001 +- @Tapanito +- @tequdev +- @Vjkhannaripple +- @vlntb +- @vvysokikh1 +- @ximinez +- @yinyiqian1 + + +## Bug Bounties and Responsible Disclosures + +We welcome reviews of the `rippled` code and urge researchers to responsibly disclose any issues they may find. + +To report a bug, please send a detailed report to: \ No newline at end of file diff --git a/blog/img/fortstock-mpt-simulate-collateralization.png b/blog/img/fortstock-mpt-simulate-collateralization.png new file mode 100644 index 0000000000..f872bc0ff3 Binary files /dev/null and b/blog/img/fortstock-mpt-simulate-collateralization.png differ diff --git a/blog/img/fortstock-mptokenissuancecreate.png b/blog/img/fortstock-mptokenissuancecreate.png new file mode 100644 index 0000000000..6cccdfe1b7 Binary files /dev/null and b/blog/img/fortstock-mptokenissuancecreate.png differ diff --git a/blog/img/fortstock-warehouse-receipts-as-mpt-flow-diagram.jpg b/blog/img/fortstock-warehouse-receipts-as-mpt-flow-diagram.jpg new file mode 100644 index 0000000000..f882dc5a8a Binary files /dev/null and b/blog/img/fortstock-warehouse-receipts-as-mpt-flow-diagram.jpg differ diff --git a/blog/sidebars.yaml b/blog/sidebars.yaml index 2f01535f8f..5e89e2b424 100644 --- a/blog/sidebars.yaml +++ b/blog/sidebars.yaml @@ -10,6 +10,10 @@ - group: '2025' expanded: false items: + - page: 2025/default-unl-migration.md + - page: 2025/fortstock-xrpl-case-study-mpt-standard.md + - page: 2025/rippled-2.5.1.md + - page: 2025/rippled-2.6.0.md - page: 2025/coinpayments-xrpl-case-study-payment-processing.md - page: 2025/clio-2.5.0.md - page: 2025/dynamicnft-enabled.md diff --git a/community/events.page.tsx b/community/events.page.tsx index 810688d637..f29f90fd79 100644 --- a/community/events.page.tsx +++ b/community/events.page.tsx @@ -1239,6 +1239,28 @@ const events = [ image: require("../static/img/events/commons-france.png"), end_date: "October 14, 2025", }, + { + name: "EasyA x Flare Harvard Hackathon", + description: + "Collaborate, learn, and connect with fellow blockchain innovators and the Flare Networks team at Harvard.", + type: "hackathon", + link: "https://www.easya.io/events/easya-x-flare-harvard-hackathon", + location: "Boston, MA", + date: "September 20 - 21, 2025", + image: hackathon, + end_date: "September 21, 2025", + }, + { + name: "XRP Seoul Summit 2025", + description: + "Join XRP Seoul 2025, Asia’s largest XRP & Web3 conference, and explore the future of the industry.", + type: "conference", + link: "https://xrp-seoul.com/", + location: "Seoul, South Korea", + date: "September 21, 2025", + image: conference, + end_date: "September 21, 2025", + }, ]; @@ -1320,33 +1342,33 @@ export default function Events() {
xrp ledger events hero

- {translate("Apex 2025")} + {translate("XRP Community Night NYC")}

{translate("Save the Date")}

{translate( - "Apex, hosted by Ripple is the largest annual summit on the XRPL calendar. It unites developers, businesses, fintechs, VCs and the wider community." + "Join the XRP community in NYC—meet builders, users, and projects innovating on the XRP Ledger." )}

- {translate("Location: Singapore")} + {translate("Location: New York, NY")}
- {translate("June 10 - 12, 2025")} + {translate("November 5, 2025")}
{translate("Register Now")} diff --git a/community/index.page.tsx b/community/index.page.tsx index f364d32306..d8099a0f89 100644 --- a/community/index.page.tsx +++ b/community/index.page.tsx @@ -345,6 +345,30 @@ const events = [ start_date: "June 30, 2025", end_date: "June 30, 2025", }, + { + name: "EasyA x Flare Harvard Hackathon", + description: + "Collaborate, learn, and connect with fellow blockchain innovators and the Flare Networks team at Harvard.", + type: "hackathon", + link: "https://www.easya.io/events/easya-x-flare-harvard-hackathon", + location: "Boston, MA", + date: "September 20 - 21, 2025", + image: hackathon, + start_date: "September 20, 2025", + end_date: "September 21, 2025", + }, + { + name: "XRP Seoul Summit 2025", + description: + "Join XRP Seoul 2025, Asia’s largest XRP & Web3 conference, and explore the future of the industry.", + type: "conference", + link: "https://xrp-seoul.com/", + location: "Seoul, South Korea", + date: "September 21, 2025", + image: conference, + end_date: "September 21, 2025", + start_date: "September 21, 2025", + }, ]; @@ -592,8 +616,7 @@ const CommunityPage: React.FC = () => { {/* Community Table Section */}
-
{translate("Join the Conversation")}
-

{translate("Hot Topics Happening Now")}

+

{translate("Join the Conversation")}

@@ -602,12 +625,12 @@ const CommunityPage: React.FC = () => {
{translate( - "AMA with Edge Wallet: Learn more about Edge Wallet and how they are building on the XRP Ledger." + "Join the XRPL Discord to connect and network with builders, validators, and cryptocurrency enthusiasts." )} @@ -621,12 +644,12 @@ const CommunityPage: React.FC = () => { {translate( - "Clawback: A newly proposed feature that adds to the XRP Ledger's token asset control capabilities." + "Follow @RippleXDev on X for the latest updates on the XRP Ledger ecosystem." )} @@ -640,12 +663,12 @@ const CommunityPage: React.FC = () => { {translate( - "APEX 2023: View keynote sessions from the annual developer summit where developers, contributors, and thought leaders come together to learn, build, and celebrate all things XRP Ledger." + "APEX 2025: View keynote sessions from the Apex 2025 where developers, entrepreneurs, and industry leaders come together to learn, build, and celebrate all things XRP Ledger." )} @@ -659,12 +682,12 @@ const CommunityPage: React.FC = () => { {translate( - "Deep Dive into XRPL DeFi Course: Learn about the inner workings of decentralized finance including safety and security, auto-bridging, pathfinding, liquidity pools, and more." + "Explore DeFi-Island: A 3D open-source world on the XRPL testnet. Chat with residents, complete quests, and dive into this React.js-powered experience—all in your web browser." )} diff --git a/docs/_snippets/common-links.md b/docs/_snippets/common-links.md index de77e4d843..50d377bf6f 100644 --- a/docs/_snippets/common-links.md +++ b/docs/_snippets/common-links.md @@ -125,8 +125,6 @@ [Ledger Index]: /docs/references/protocol/data-types/basic-data-types.md#ledger-index [LedgerHashes entry]: /docs/references/protocol/ledger-data/ledger-entry-types/ledgerhashes.md [LedgerHashes object]: /docs/references/protocol/ledger-data/ledger-entry-types/ledgerhashes.md -[LedgerHashesエントリ]: /docs/references/protocol/ledger-data/ledger-entry-types/ledgerhashes.md -[LedgerHashesオブジェクト]: /docs/references/protocol/ledger-data/ledger-entry-types/ledgerhashes.md [LedgerStateFix transaction]: /docs/references/protocol/transactions/types/ledgerstatefix.md [LedgerStateFix transactions]: /docs/references/protocol/transactions/types/ledgerstatefix.md [LedgerStateFix]: /docs/references/protocol/transactions/types/ledgerstatefix.md @@ -198,13 +196,12 @@ [PermissionedDomain entry]: /docs/references/protocol/ledger-data/ledger-entry-types/permissioneddomain.md [PermissionedDomainDelete transaction]: /docs/references/protocol/transactions/types/permissioneddomaindelete.md [PermissionedDomainSet transaction]: /docs/references/protocol/transactions/types/permissioneddomainset.md -[PermissionedDomainSetトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/permissioneddomainset.md [PermissionedDomains amendment]: /resources/known-amendments.md#permissioneddomains [permissioned domain]: /docs/concepts/tokens/decentralized-exchange/permissioned-domains.md -[許可型ドメイン]: /@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-domains.md [PriceOracle amendment]: /resources/known-amendments.md#priceoracle [MPToken entry]: /docs/references/protocol/ledger-data/ledger-entry-types/mptoken.md [MPTokenAuthorize transaction]: /docs/references/protocol/transactions/types/mptokenauthorize.md +[MPTokenIssuance entry]: /docs/references/protocol/ledger-data/ledger-entry-types/mptokenissuance.md [MPTokenIssuanceCreate transaction]: /docs/references/protocol/transactions/types/mptokenissuancecreate.md [MPTokenIssuanceDestroy transaction]: /docs/references/protocol/transactions/types/mptokenissuancedestroy.md [MPTokenIssuanceSet transaction]: /docs/references/protocol/transactions/types/mptokenissuanceset.md diff --git a/docs/_snippets/etl-source-object.md b/docs/_snippets/etl-source-object.md deleted file mode 100644 index 6c44c8041e..0000000000 --- a/docs/_snippets/etl-source-object.md +++ /dev/null @@ -1,13 +0,0 @@ -### ETL Source Object - - -On a reporting mode server, each member of the `etl_sources` field is an object with the following fields: - -| Field | Type | Description | -|-----------------------------|---------|-------------| -| `connected` | Boolean | If `true`, the reporting mode server is connected to this P2P mode server. If `false`, the server is not connected. This could be due to misconfiguration, a network outage, or it could mean that the P2P mode server is down. | -| `grpc_port` | String | The port number on the P2P mode server where this reporting mode server is configured to connect and retrieve ledger data via gRPC. | -| `ip` | String | The IP address (IPv4 or IPv6) of the P2P mode server. | -| `last_message_arrival_time` | String | An ISO 8601 timestamp indicating the most recent time the reporting mode server received a message from this P2P server. | -| `validated_ledgers_range` | String | The range of validated ledger versions this P2P mode server reports that it has available, in the same format as `complete_ledgers`. | -| `websocket_port` | String | The port number on the P2P server where this reporting mode server is configured to forward WebSocket requests that cannot be served directly from reporting mode. | diff --git a/docs/_snippets/state-accounting-object.md b/docs/_snippets/state-accounting-object.md new file mode 100644 index 0000000000..3aee57bd7d --- /dev/null +++ b/docs/_snippets/state-accounting-object.md @@ -0,0 +1,9 @@ +### State Accounting Object + + +Each field in the `state_accounting` object has a key that refers to a specific [server state](/docs/references/http-websocket-apis/api-conventions/rippled-server-states), and a value that is an object with the following fields: + +| Field | Value | Description | +|---------------|-----------------|-------------| +| `duration_us` | String - Number | The number of microseconds the server has spent in this state. (This is updated whenever the server transitions into another state.) | +| `transitions` | String - Number | The number of times the server has changed into this state. | diff --git a/docs/concepts/tokens/fungible-tokens/index.md b/docs/concepts/tokens/fungible-tokens/index.md index f5f2e42bb3..6440f1e6de 100644 --- a/docs/concepts/tokens/fungible-tokens/index.md +++ b/docs/concepts/tokens/fungible-tokens/index.md @@ -1,6 +1,4 @@ --- -html: trust-lines-and-issuing.html -parent: tokens.html seo: description: Learn about the properties and rationale of trust lines. labels: @@ -72,7 +70,7 @@ If your balance is negative (you are the issuer) or the other side's settings ar Since the **Authorized** setting cannot be turned off after it has been turned on, it does not count toward the trust line's default state. ### Free Trust Lines -[[Source]](https://github.com/XRPLF/rippled/blob/72377e7bf25c4eaee5174186d2db3c6b4210946f/src/ripple/app/tx/impl/SetTrust.cpp#L148-L168) +[[Source]](https://github.com/XRPLF/rippled/blob/2df7dcfdebcb0cdbd030c1f4b09ac748af95659c/src/xrpld/app/tx/detail/SetTrust.cpp#L387-L407 "Source") Since trust lines are a powerful feature of the XRP Ledger, there is a special feature to make an account's first two trust lines "free". diff --git a/docs/index.page.tsx b/docs/index.page.tsx index 43e4d9c1ae..7632e5e6d8 100644 --- a/docs/index.page.tsx +++ b/docs/index.page.tsx @@ -334,6 +334,16 @@ export default function Docs() {
{translate('Java')}
+
+ + Go Logo +
{translate("GoLang")}
+ +
diff --git a/docs/references/client-libraries.md b/docs/references/client-libraries.md index 79ae26ece1..139b0bda2c 100644 --- a/docs/references/client-libraries.md +++ b/docs/references/client-libraries.md @@ -14,6 +14,7 @@ These client libraries simplify some of the common work of accessing and process | Language | Library Name | Get Started | API Reference | Source Code | |---------------------------------|---------------------------|-------------|--------------|-------------| | **Python** | `xrpl-py` | [Get Started Using Python](../tutorials/python/build-apps/get-started.md) | [API Reference](https://xrpl-py.readthedocs.io/) | [Repo](https://github.com/XRPLF/xrpl-py) | +| **Go** | `xrpl-go` | [Get Started Using Go](../tutorials/go/build-apps/get-started.md) | [API Reference](https://pkg.go.dev/github.com/Peersyst/xrpl-go) | [Repo](https://github.com/Peersyst/xrpl-go) | | **JavaScript** / **TypeScript** | `xrpl.js` | [Get Started](../tutorials/javascript/build-apps/get-started.md) | [API Reference](https://js.xrpl.org/) | [Repo](https://github.com/XRPLF/xrpl.js) | | **JavaScript** / **TypeScript** | `xrpl-client` | [Get Started](https://jsfiddle.net/WietseWind/35az6p1b/) | [NPM Reference](https://www.npmjs.com/package/xrpl-client) | [Repo](https://github.com/XRPL-Labs/xrpl-client) | | **JavaScript** / **TypeScript** | `xrpl-accountlib` | [Get Started](https://jsfiddle.net/WietseWind/gkefpnu0/) | [NPM Reference](https://www.npmjs.com/package/xrpl-accountlib) | [Repo](https://github.com/WietseWind/xrpl-accountlib) | diff --git a/docs/references/http-websocket-apis/public-api-methods/account-methods/account_lines.md b/docs/references/http-websocket-apis/public-api-methods/account-methods/account_lines.md index 1ff39ac46b..237c12e497 100644 --- a/docs/references/http-websocket-apis/public-api-methods/account-methods/account_lines.md +++ b/docs/references/http-websocket-apis/public-api-methods/account-methods/account_lines.md @@ -65,8 +65,8 @@ The request accepts the following parameters: | `limit` | Number | No | Limit the number of trust lines to retrieve. The server may return less than the specified limit, even if there are more pages of results. Must be within the inclusive range 10 to 400. Positive values outside this range are replaced with the closest valid option. The default is 200. | | `marker` | [Marker][] | No | Value from a previous paginated response. Resume retrieving data where that response left off. | | `peer` | String - [Address][] | No | A second account; if provided, filter results to trust lines connecting the two accounts. | -| `locked_balance` | Object | No | The total amount locked in payment channels or escrow. | -| `lock_count` | Number | UInt32 | No | the total number of lock balances on a RippleState ledger object. | +| `locked_balance` | Object | No | The total amount locked in payment channels or escrow. | +| `lock_count` | Number | No | the total number of lock balances on a RippleState ledger object. | The following parameters are deprecated and may be removed without further notice: `ledger` and `peer_index`. diff --git a/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_info.md b/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_info.md index 4f9ac003d6..5a9ef274e4 100644 --- a/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_info.md +++ b/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_info.md @@ -83,7 +83,7 @@ The `info` object may have some arrangement of the following fields: |:------------------------------------|:----------------|:---------------------| | `amendment_blocked` | Boolean | _(May be omitted)_ If `true`, this server is [amendment blocked](../../../../concepts/networks-and-servers/amendments.md#amendment-blocked-servers). If the server is not amendment blocked, the response omits this field. | | `build_version` | String | The version number of the running `rippled` server. | -| `closed_ledger` | Object | _(May be omitted)_ Information on the most recently closed ledger that has not been validated by consensus. If the most recently validated ledger is available, the response omits this field and includes `validated_ledger` instead. The member fields are the same as the `validated_ledger` field. | +| `closed_ledger` | Object | _(May be omitted)_ Information on the most recently closed ledger that has not been validated by consensus, as a [Server Ledger Object](#server-ledger-object). If the most recently validated ledger is available, the response omits this field and includes `validated_ledger` instead. | | `complete_ledgers` | String | Range expression indicating the sequence numbers of the ledger versions the local `rippled` has in its database. This may be a disjoint sequence such as `24900901-24900984,24901116-24901158`. If the server does not have any complete ledgers (for example, it recently started syncing with the network), this is the string `empty`. | | `git` | Object | _(Admin only)_ The Git details of your `rippled` build. | | `git.branch` | String | _(Admin only)_ The Git branch used to build your version of `rippled`. | @@ -104,39 +104,42 @@ The `info` object may have some arrangement of the following fields: | `load_factor_fee_escalation` | Number | _(May be omitted)_ The current multiplier to the transaction cost that a transaction must pay to get into the open ledger. | | `load_factor_fee_queue` | Number | _(May be omitted)_ The current multiplier to the transaction cost that a transaction must pay to get into the queue, if the queue is full. | | `load_factor_server` | Number | _(May be omitted)_ The current multiplier to the transaction cost based on load to the server, cluster, and network, but not factoring in the open ledger cost. | -| `peers` | Number | _(Omitted by [reporting mode][Reporting mode] servers)_ How many other `rippled` servers this one is currently connected to. | +| `network_ledger` | String | _(May be omitted)_ When [starting the server with the `--net` parameter](../../../../infrastructure/commandline-usage.md), this field contains the string `waiting` while the server is syncing to the network. The field is omitted otherwise. | +| `peers` | Number | How many other `rippled` servers this one is currently connected to. | | `ports` | Array | A list of ports where the server is listening for API commands. Each entry in the array is a [Port Descriptor object](#port-descriptor-object). {% badge href="https://github.com/XRPLF/rippled/releases/tag/1.12.0" %}New in: rippled 1.12.0{% /badge %} | | `pubkey_node` | String | Public key used to verify this server for peer-to-peer communications. This [_node key pair_](../../../../concepts/networks-and-servers/peer-protocol.md#node-key-pair) is automatically generated by the server the first time it starts up. (If deleted, the server can create a new pair of keys.) You can set a persistent value in the config file using the `[node_seed]` config option, which is useful for [clustering](../../../../concepts/networks-and-servers/clustering.md). | | `pubkey_validator` | String | _(Admin only)_ Public key used by this node to sign ledger validations. This _validation key pair_ is derived from the `[validator_token]` or `[validation_seed]` config field. | -| `reporting` | Object | _([Reporting mode](../../../../concepts/networks-and-servers/rippled-server-modes.md) servers only)_ Information about this server's reporting-mode specific configurations. | -| `reporting.etl_sources` | Array | _([Reporting mode](../../../../concepts/networks-and-servers/rippled-server-modes.md) servers only)_ A list of P2P-mode servers this reporting mode is retrieving data from. Each entry in this array is an [ETL Source object](#etl-source-object). | -| `reporting.is_writer` | Boolean | _([Reporting mode](../../../../concepts/networks-and-servers/rippled-server-modes.md) servers only)_ If `true`, this server is writing to the external database with ledger data. If `false`, it is not currently writing, possibly because another reporting mode server is currently populating a shared database, or because it's configured as read-only. | -| `reporting.last_publish_time` | String | _([Reporting mode](../../../../concepts/networks-and-servers/rippled-server-modes.md) servers only)_ An ISO 8601 timestamp indicating when this server last published a validated ledger to its [subscription streams](../subscription-methods/subscribe.md). | | `server_state` | String | A string indicating to what extent the server is participating in the network. See [Possible Server States](../../api-conventions/rippled-server-states.md) for more details. | | `server_state_duration_us` | Number | The number of consecutive microseconds the server has been in the current state. | -| `state_accounting` | Object | A map of various [server states](../../api-conventions/rippled-server-states.md) with information about the time the server spends in each. This can be useful for tracking the long-term health of your server's connectivity to the network. | -| `state_accounting.*.duration_us` | String | The number of microseconds the server has spent in this state. (This is updated whenever the server transitions into another state.) | -| `state_accounting.*.transitions` | String | The number of times the server has changed into this state. | -| `time` | String | The current time in UTC, according to the server's clock. | +| `state_accounting` | Object | A map of various [server states](../../api-conventions/rippled-server-states.md) with information about the time the server spends in each. This can be useful for tracking the long-term health of your server's connectivity to the network. The contents of this field are formatted as [State Accounting Objects](#state-accounting-object). || `time` | String | The current time in UTC, according to the server's clock. | | `uptime` | Number | Number of consecutive seconds that the server has been operational. | -| `validated_ledger` | Object | _(May be omitted)_ Information about the most recent fully-validated ledger. If the most recent validated ledger is not available, the response omits this field and includes `closed_ledger` instead. | -| `validated_ledger.age` | Number | The time since the ledger was closed, in seconds. | -| `validated_ledger.base_fee_xrp` | Number | Base fee, in XRP. This may be represented in scientific notation such as `1e-05` for 0.00001. | -| `validated_ledger.hash` | String | Unique hash for the ledger, as hexadecimal. | -| `validated_ledger.reserve_base_xrp` | Number | Minimum amount of XRP (not drops) necessary for every account to keep in reserve | -| `validated_ledger.reserve_inc_xrp` | Number | Amount of XRP (not drops) added to the account reserve for each object an account owns in the ledger. | -| `validated_ledger.seq` | Number | The [ledger index][] of the latest validated ledger. | +| `validated_ledger` | Object | _(May be omitted)_ Information about the most recent fully-validated ledger, as a [Server Ledger Object](#server-ledger-object). If the most recent validated ledger is not available, the response omits this field and includes `closed_ledger` instead. | | `validation_quorum` | Number | Minimum number of trusted validations required to validate a ledger version. Some circumstances may cause the server to require more validations. | | `validator_list_expires` | String | _(Admin only)_ Either the human readable time, in UTC, when the current validator list expires, the string `unknown` if the server has yet to load a published validator list or the string `never` if the server uses a static validator list. | | `counters` | Object | This object contains performance metrics pertaining to the RPC calls (currently executing calls and completed calls) and the JobQueue. It also contains details of the nodestore like `node_writes`, `node_reads_total`, `node_reads_hit`, etc| | `current_activity` | Object | This field lists the items currently being run in the job queue and contains two arrays for `jobs` and `methods`. | -{% admonition type="info" name="Note" %}If the `closed_ledger` field is present and has a small `seq` value (less than 8 digits), that indicates `rippled` does not currently have a copy of the validated ledger from the peer-to-peer network. This could mean your server is still syncing. Typically, it takes about 5 minutes to sync with the network, depending on your connection speed and hardware specs.{% /admonition %} - -{% partial file="/docs/_snippets/etl-source-object.md" /%} - {% partial file="/docs/_snippets/port-descriptor-object.md" /%} +{% partial file="/docs/_snippets/state-accounting-object.md" /%} + +### Server Ledger Object + +The response provides either a `validated_ledger` field or a `closed_ledger` field. Either field contains an object with the following fields: + +| Field | Value | Description | +|--------------------|-------------------|-------------| +| `age` | Number | The time since the ledger was closed, in seconds. | +| `base_fee_xrp` | Number | Base fee, in XRP (not drops). This may be represented in scientific notation such as `1e-05` for 0.00001. | +| `hash` | String - [Hash][] | Unique hash for the ledger, as hexadecimal. | +| `reserve_base_xrp` | Number | Minimum amount of XRP (not drops) necessary for every account to keep in reserve | +| `reserve_inc_xrp` | Number | Amount of XRP (not drops) added to the account reserve for each object an account owns in the ledger. | +| `seq` | Number | The [ledger index][] of the latest validated ledger. | + +Note that the [server_state method][] provides a similar object with slightly different formatting (using drops of XRP instead of decimal XRP, for example). + +{% admonition type="info" name="Note" %}If the `closed_ledger` field is present and has a small `seq` value (less than 8 digits), that indicates `rippled` does not currently have a copy of the validated ledger from the peer-to-peer network. This could mean your server is still syncing. Typically, it takes up to 15 minutes to sync with the network, depending on your connection speed and hardware specs. See [Server Doesn't Sync](/docs/infrastructure/troubleshooting/server-doesnt-sync.md) for troubleshooting information.{% /admonition %} + ## Possible Errors * Any of the [universal error types][]. diff --git a/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_state.md b/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_state.md index 3e5fd8465d..7115b6c7f2 100644 --- a/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_state.md +++ b/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_state.md @@ -276,12 +276,12 @@ The `state` object may have some arrangement of the following fields: | `amendment_blocked` | Boolean | _(May be omitted)_ If `true`, this server is [amendment blocked](../../../../concepts/networks-and-servers/amendments.md#amendment-blocked-servers). If the server is not amendment blocked, the response omits this field. | | `build_version` | String | The version number of the running `rippled` version. | | `complete_ledgers` | String | Range expression indicating the sequence numbers of the ledger versions the local `rippled` has in its database. It is possible to be a disjoint sequence, e.g. "2500-5000,32570-7695432". If the server does not have any complete ledgers (for example, it recently started syncing with the network), this is the string `empty`. | -| `closed_ledger` | Object | _(May be omitted)_ Information on the most recently closed ledger that has not been validated by consensus. If the most recently validated ledger is available, the response omits this field and includes `validated_ledger` instead. The member fields are the same as the `validated_ledger` field. | +| `closed_ledger` | Object | _(May be omitted)_ Information on the most recently closed ledger that has not been validated by consensus, as a [Server Ledger Object](#server-ledger-object). If the most recently validated ledger is available, the response omits this field and includes `validated_ledger` instead. | | `io_latency_ms` | Number | Amount of time spent waiting for I/O operations, in milliseconds. If this number is not very, very low, then the `rippled` server is probably having serious load issues. | | `jq_trans_overflow` | String - Number | The number of times this server has had over 250 transactions waiting to be processed at once. A large number here may mean that your server is unable to handle the transaction load of the XRP Ledger network. For detailed recommendations of future-proof server specifications, see [Capacity Planning](../../../../infrastructure/installation/capacity-planning.md). | | `last_close` | Object | Information about the last time the server closed a ledger, including the amount of time it took to reach a consensus and the number of trusted validators participating. | -| `last_close.converge_time` | Number | The amount of time it took to reach a consensus on the most recently validated ledger version, in milliseconds. | -| `last_close.proposers` | Number | How many trusted validators the server considered (including itself, if configured as a validator) in the consensus process for the most recently validated ledger version. | +| `last_close.converge_time` | Number | The amount of time it took to reach a consensus on the most recently validated ledger version, in milliseconds. | +| `last_close.proposers` | Number | How many trusted validators the server considered (including itself, if configured as a validator) in the consensus process for the most recently validated ledger version. | | `load` | Object | _(Admin only)_ Detailed information about the current load state of the server. | | `load.job_types` | Array | _(Admin only)_ Information about the rate of different types of jobs the server is doing and how much time it spends on each. | | `load.threads` | Number | _(Admin only)_ The number of threads in the server's main job pool. | @@ -291,37 +291,40 @@ The `state` object may have some arrangement of the following fields: | `load_factor_fee_queue` | Number | _(May be omitted)_ The current multiplier to the transaction cost to get into the queue, if the queue is full, in fee levels. | | `load_factor_fee_reference` | Number | _(May be omitted)_ The transaction cost with no load scaling, in fee levels. | | `load_factor_server` | Number | _(May be omitted)_ The load factor the server is enforcing, based on load to the server, cluster, and network, but not factoring in the open ledger cost. | -| `peers` | Number | _(Omitted by [reporting mode][Reporting mode] servers)_ How many other `rippled` servers this one is currently connected to. | +| `network_ledger` | String | _(May be omitted)_ When [starting the server with the `--net` parameter](../../../../infrastructure/commandline-usage.md), this field contains the string `waiting` while the server is syncing to the network. The field is omitted otherwise. | +| `peers` | Number | How many other `rippled` servers this one is currently connected to. | | `ports` | Array | A list of ports where the server is listening for API commands. Each entry in the array is a [Port Descriptor object](#port-descriptor-object). {% badge href="https://github.com/XRPLF/rippled/releases/tag/1.12.0" %}New in: rippled 1.12.0{% /badge %} | | `pubkey_node` | String | Public key used to verify this server for peer-to-peer communications. This _node key pair_ is automatically generated by the server the first time it starts up. (If deleted, the server can create a new pair of keys.) You can set a persistent value in the config file using the `[node_seed]` config option, which is useful for [clustering](../../../../concepts/networks-and-servers/clustering.md). | | `pubkey_validator` | String | _(Admin only)_ Public key used by this node to sign ledger validations. This _validation key pair_ is derived from the `[validator_token]` or `[validation_seed]` config field. | -| `reporting` | Object | _([Reporting mode][] servers only)_ Information about this server's reporting-mode specific configurations. | -| `reporting.etl_sources` | Array | _([Reporting mode][] servers only)_ A list of P2P-mode servers this reporting mode is retrieving data from. Each entry in this array is an [ETL Source object](#etl-source-object). | -| `reporting.is_writer` | Boolean | _([Reporting mode][] servers only)_ If `true`, this server is writing to the external database with ledger data. If `false`, it is not currently writing, possibly because another reporting mode server is currently populating a shared database, or because it's configured as read-only. | -| `reporting.last_publish_time` | String | _([Reporting mode][] servers only)_ An ISO 8601 timestamp indicating when this server last saw a new validated ledger from any of its P2P mode sources. | | `server_state` | String | A string indicating to what extent the server is participating in the network. See [Possible Server States](../../api-conventions/rippled-server-states.md) for more details. | | `server_state_duration_us` | Number | The number of consecutive microseconds the server has been in the current state. | -| `state_accounting` | Object | A map of various [server states](../../api-conventions/rippled-server-states.md) with information about the time the server spends in each. This can be useful for tracking the long-term health of your server's connectivity to the network. | -| `state_accounting.*.duration_us` | String | The number of microseconds the server has spent in this state. (This is updated whenever the server transitions into another state.) | -| `state_accounting.*.transitions` | String | The number of times the server has changed into this state. | +| `state_accounting` | Object | A map of various [server states](../../api-conventions/rippled-server-states.md) with information about the time the server spends in each. This can be useful for tracking the long-term health of your server's connectivity to the network. The contents of this field are formatted as [State Accounting Objects](#state-accounting-object). | | `time` | String | The current time in UTC, according to the server's clock. | | `uptime` | Number | Number of consecutive seconds that the server has been operational. | -| `validated_ledger` | Object | _(May be omitted)_ Information about the most recent fully-validated ledger. If the most recent validated ledger is not available, the response omits this field and includes `closed_ledger` instead. | -| `validated_ledger.base_fee` | Number | Base fee, in drops of XRP, for propagating a transaction to the network. | -| `validated_ledger.close_time` | Number | Time this ledger was closed, in [seconds since the Ripple Epoch][]. | -| `validated_ledger.hash` | String | Unique hash of this ledger version, as hexadecimal. | -| `validated_ledger.reserve_base` | Number | The minimum [account reserve](../../../../concepts/accounts/reserves.md), as of the most recent validated ledger version. | -| `validated_ledger.reserve_inc` | Number | The [owner reserve](../../../../concepts/accounts/reserves.md) for each item an account owns, as of the most recent validated ledger version. | -| `validated_ledger.seq` | Number | The [ledger index][] of the most recently validated ledger version. | +| `validated_ledger` | Object | _(May be omitted)_ Information about the most recent fully-validated ledger, as a [Server Ledger Object](#server-ledger-object). If the most recent validated ledger is not available, the response omits this field and includes `closed_ledger` instead. | | `validation_quorum` | Number | Minimum number of trusted validations required to validate a ledger version. Some circumstances may cause the server to require more validations. | | `validator_list_expires` | Number | _(Admin only)_ When the current validator list expires, in [seconds since the Ripple Epoch][], or 0 if the server has yet to load a published validator list. | -[Reporting mode]: ../../../../concepts/networks-and-servers/rippled-server-modes.md - -{% partial file="/docs/_snippets/etl-source-object.md" /%} - {% partial file="/docs/_snippets/port-descriptor-object.md" /%} +{% partial file="/docs/_snippets/state-accounting-object.md" /%} + +### Server Ledger Object + +The response provides either a `validated_ledger` field or a `closed_ledger` field. Either field contains an object with the following fields: + +| Field | Value | Description | +|-----------------|-------------------|-------------| +| `base_fee` | Number | The base fee, in drops of XRP, for propagating a transaction to the network, as of this ledger version. | +| `close_time` | Number | The official close time time of this ledger version, in [seconds since the Ripple Epoch][]. This value is rounded; see [Ledger Close Times](../../../../concepts/ledgers/ledger-close-times.md) for details. | +| `hash` | String - [Hash][] | The unique hash of this ledger version, as hexadecimal. | +| `reserve_base` | Number | The minimum [account reserve](../../../../concepts/accounts/reserves.md), as of the most recent validated ledger version. | +| `reserve_inc` | Number | The [owner reserve](../../../../concepts/accounts/reserves.md) for each item an account owns, as of the most recent validated ledger version. | +| `seq` | Number | The [ledger index][] of this ledger version. | + +Note that the [server_info method][] provides a similar object with slightly different formatting (using decimal XRP instead of drops, for example). + + ## Possible Errors * Any of the [universal error types][]. diff --git a/docs/references/http-websocket-apis/public-api-methods/subscription-methods/subscribe.md b/docs/references/http-websocket-apis/public-api-methods/subscription-methods/subscribe.md index b592f11ca2..46eb7ba360 100644 --- a/docs/references/http-websocket-apis/public-api-methods/subscription-methods/subscribe.md +++ b/docs/references/http-websocket-apis/public-api-methods/subscription-methods/subscribe.md @@ -163,6 +163,7 @@ The `ledger` stream only sends `ledgerClosed` messages when [the consensus proce "ledger_hash": "687F604EF6B2F67319E8DCC8C66EF49D84D18A1E18F948421FC24D2C7C3DB464", "ledger_index": 7125358, "ledger_time": 455751310, + "network_id": 1, "reserve_base": 20000000, "reserve_inc": 5000000, "txn_count": 7, @@ -180,6 +181,7 @@ The fields from a ledger stream message are as follows: | `ledger_hash` | String - [Hash][] | The identifying hash of the ledger version that was closed. | | `ledger_index` | Number - [Ledger Index][] | The ledger index of the ledger that was closed. | | `ledger_time` | Number | The time this ledger was closed, in [seconds since the Ripple Epoch][] | +| `network_id` | Number | The XRPL network of this stream. | | `reserve_base` | Number | The minimum [reserve](../../../../concepts/accounts/reserves.md), in [drops of XRP][], that is required for an account. If this ledger version includes a [SetFee pseudo-transaction](../../../protocol/transactions/pseudo-transaction-types/setfee.md) the new base reserve applies starting with the following ledger version. | | `reserve_inc` | Number | The [owner reserve](../../../../concepts/accounts/reserves.md#owner-reserves) for each object an account owns in the ledger, in [drops of XRP][]. If the ledger includes a [SetFee pseudo-transaction](../../../protocol/transactions/pseudo-transaction-types/setfee.md) the new owner reserve applies after this ledger. | | `txn_count` | Number | Number of new transactions included in this ledger version. | @@ -207,6 +209,7 @@ The validations stream sends messages whenever it receives validation messages, "ledger_index":"6", "load_fee":256000, "master_key": "nHUon2tpyJEHHYGmxqeGu37cvPYHzrMtUNQFVdCgGNvEkjmCpTqK", + "network_id": 1, "reserve_base":20000000, "reserve_inc":5000000, "signature":"3045022100E199B55643F66BC6B37DBC5E185321CF952FD35D13D9E8001EB2564FFB94A07602201746C9A4F7A93647131A2DEB03B76F05E426EC67A5A27D77F4FF2603B9A528E6", @@ -229,6 +232,7 @@ The fields from a validations stream message are as follows: | `ledger_index` | String - Number | The [Ledger Index][] of the proposed ledger. | | `load_fee` | Integer | _(May be omitted)_ The local load-scaled transaction cost this validator is currently enforcing, in fee units. | | `master_key` | String | _(May be omitted)_ The validator's master public key, if the validator is using a validator token, in the XRP Ledger's [base58][] format. (See also: [Enable Validation on your `rippled` Server](../../../../infrastructure/configuration/server-modes/run-rippled-as-a-validator.md#3-enable-validation-on-your-rippled-server).) | +| `network_id` | Number | The [XRPL network](../../../protocol/transactions/common-fields.md#networkid-field) of this stream. {% badge href="https://github.com/XRPLF/rippled/releases/tag/2.6.0" %}New in: rippled 2.6.0{% /badge %} | | `reserve_base` | Integer | _(May be omitted)_ The minimum reserve requirement (`account_reserve` value) this validator wants to set by [Fee Voting](../../../../concepts/consensus-protocol/fee-voting.md). | | `reserve_inc` | Integer | _(May be omitted)_ The increment in the reserve requirement (`owner_reserve` value) this validator wants to set by [Fee Voting](../../../../concepts/consensus-protocol/fee-voting.md). | | `server_version` | String - Number | _(May be omitted)_ An 64-bit integer that encodes the version number of the validating server. For example, `"1745990410175512576"`. Only provided once every 256 ledgers. {% badge href="https://github.com/XRPLF/rippled/releases/tag/1.8.1" %}New in: rippled 1.8.1{% /badge %} | diff --git a/docs/references/index.md b/docs/references/index.md index 3ce41d479e..ef06021fe0 100644 --- a/docs/references/index.md +++ b/docs/references/index.md @@ -16,6 +16,8 @@ Use these libraries to access the XRP Ledger from your programming language of c {% xrpl-card title="Python" body="xrpl.py - a pure Python library" href="https://xrpl-py.readthedocs.io/" image="/img/logos/python.svg" imageAlt="Python logo" /%} +{% xrpl-card title="Go" body="xrpl.go - a pure Go library" href="https://pkg.go.dev/github.com/Peersyst/xrpl-go" image="/img/logos/golang.svg" imageAlt="Go logo" /%} + {% xrpl-card title="Java" body="xrpl4j - a pure Java library" href="https://javadoc.io/doc/org.xrpl/" image="/img/logos/java.svg" imageAlt="Java logo" /%} {% /card-grid %} diff --git a/docs/references/protocol/binary-format.md b/docs/references/protocol/binary-format.md index 4381f16fb3..de15ea29c7 100644 --- a/docs/references/protocol/binary-format.md +++ b/docs/references/protocol/binary-format.md @@ -390,6 +390,7 @@ The following example shows the serialization format for a PathSet: [UInt96]: #uint-fields [UInt128]: #uint-fields [UInt160]: #uint-fields +[UInt192]: #uint-fields [UInt256]: #uint-fields [UInt384]: #uint-fields [UInt512]: #uint-fields diff --git a/docs/references/protocol/ledger-data/ledger-entry-types/mptokenissuance.md b/docs/references/protocol/ledger-data/ledger-entry-types/mptokenissuance.md index 26fd95fd3a..ab6355100f 100644 --- a/docs/references/protocol/ledger-data/ledger-entry-types/mptokenissuance.md +++ b/docs/references/protocol/ledger-data/ledger-entry-types/mptokenissuance.md @@ -21,14 +21,14 @@ _(Requires the [MPTokensV1 amendment][] {% not-enabled /%}.)_ "AssetScale": 2, "MaximumAmount": "100000000", "OutstandingAmount": "100", - "TransferFee": 50000, + "TransferFee": 50000, "MPTokenMetadata": "7B227469636B6572223A20225442494C4C222C20226E616D65223A2022542D42696C6C205969656C6420546F6B656E222C202264657363223A202241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C202269636F6E223A202268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C202261737365745F636C617373223A2022727761222C202261737365745F737562636C617373223A20227472656173757279222C20226973737565725F6E616D65223A20224578616D706C65205969656C6420436F2E222C202275726C73223A205B7B2275726C223A202268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C222C202274797065223A202277656273697465222C20227469746C65223A202250726F647563742050616765227D2C207B2275726C223A202268747470733A2F2F6578616D706C657969656C642E636F2F646F6373222C202274797065223A2022646F6373222C20227469746C65223A20225969656C6420546F6B656E20446F6373227D5D2C20226164646974696F6E616C5F696E666F223A207B22696E7465726573745F72617465223A2022352E303025222C2022696E7465726573745F74797065223A20227661726961626C65222C20227969656C645F736F75726365223A2022552E532E2054726561737572792042696C6C73222C20226D617475726974795F64617465223A2022323034352D30362D3330222C20226375736970223A2022393132373936525830227D7D", "OwnerNode": "74" } ``` {% admonition type="success" name="Tip" %} -By convention, the metadata should decode to JSON data describing what the MPT represents. The [XLS-89d specification](https://github.com/XRPLF/XRPL-Standards/pull/293) defines a recommended format for metadata. For example, the above `MPTokenMetadata` field encodes the sample JSON from the XLS-89d spec, as a UTF-8 string with minimal whitespace. +By convention, the metadata should decode to JSON data describing what the MPT represents. The [XLS-89 specification](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0089-multi-purpose-token-metadata-schema) defines a recommended format for metadata. The above `MPTokenMetadata` field encodes the sample JSON from the spec, as a UTF-8 string with minimal whitespace. {% /admonition %} ## MPTokenIssuance Fields @@ -76,4 +76,11 @@ The `MPTokenIssuanceID` is a 192-bit integer, concatenated in order: - The transaction sequence number. - The AccountID of the issuer. +## See Also + +- **Transactions:** + - [MPTokenIssuanceCreate transaction][] + - [MPTokenIssuanceDestroy transaction][] + - [MPTokenIssuanceSet transaction][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/ledger-data/ledger-entry-types/nftokenoffer.md b/docs/references/protocol/ledger-data/ledger-entry-types/nftokenoffer.md index 8bace205d5..fb4b57045e 100644 --- a/docs/references/protocol/ledger-data/ledger-entry-types/nftokenoffer.md +++ b/docs/references/protocol/ledger-data/ledger-entry-types/nftokenoffer.md @@ -82,4 +82,11 @@ The unique ID (`NFTokenOfferID`) of a `NFTokenOffer` object is the result of the * The `AccountID` of the account placing the offer; and * The `Sequence` (or `Ticket`) of the `NFTokenCreateOffer` transaction that created the `NFTokenOffer`. +## See Also + +- **Transactions:** + - [NFTokenAcceptOffer transaction][] + - [NFTokenCancelOffer transaction][] + - [NFTokenCreateOffer transaction][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/ledger-data/ledger-entry-types/offer.md b/docs/references/protocol/ledger-data/ledger-entry-types/offer.md index f22d9102e2..88e09e6f23 100644 --- a/docs/references/protocol/ledger-data/ledger-entry-types/offer.md +++ b/docs/references/protocol/ledger-data/ledger-entry-types/offer.md @@ -80,4 +80,10 @@ The ID of an `Offer` entry is the [SHA-512Half][] of the following values, conca If the OfferCreate transaction used a [ticket](../../../../concepts/accounts/tickets.md), use the `TicketSequence` value instead. +## See Also + +- **Transactions:** + - [OfferCancel transaction][] + - [OfferCreate transaction][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/ledger-data/ledger-entry-types/oracle.md b/docs/references/protocol/ledger-data/ledger-entry-types/oracle.md index 59099547b2..f1ad4788be 100644 --- a/docs/references/protocol/ledger-data/ledger-entry-types/oracle.md +++ b/docs/references/protocol/ledger-data/ledger-entry-types/oracle.md @@ -90,4 +90,10 @@ The `Currency` field type contains 160 bits of arbitrary data representing a cur } ``` +## See Also + +- **Transactions:** + - [OracleSet transaction][] + - [OracleDelete transaction][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/ledger-data/ledger-entry-types/paychannel.md b/docs/references/protocol/ledger-data/ledger-entry-types/paychannel.md index 8b1bb72f18..123ea3e6b0 100644 --- a/docs/references/protocol/ledger-data/ledger-entry-types/paychannel.md +++ b/docs/references/protocol/ledger-data/ledger-entry-types/paychannel.md @@ -106,4 +106,11 @@ The ID of a `PayChannel` entry is the [SHA-512Half][] of the following values, c * The Sequence number of the [PaymentChannelCreate transaction][] that created the channel If the PaymentChannelCreate transaction used a [Ticket](../../../../concepts/accounts/tickets.md), use the `TicketSequence` value instead. +## See Also + +- **Transactions:** + - [PaymentChannelClaim transaction][] + - [PaymentChannelCreate transaction][] + - [PaymentChannelFund transaction][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/ammclawback.md b/docs/references/protocol/transactions/types/ammclawback.md index f4fca83bf1..43c63f4d82 100644 --- a/docs/references/protocol/transactions/types/ammclawback.md +++ b/docs/references/protocol/transactions/types/ammclawback.md @@ -11,7 +11,7 @@ labels: Claw back tokens from a holder who has deposited your issued tokens into an AMM pool. -Clawback is disabled by default. To use clawback, you must send an [AccountSet transaction](https://xrpl.org/docs/references/protocol/transactions/types/accountset) to enable the **Allow Trust Line Clawback** setting. An issuer with any existing tokens cannot enable clawback. You can only enable **Allow Trust Line Clawback** if you have a completely empty owner directory, meaning you must do so before you set up any trust lines, offers, escrows, payment channels, checks, or signer lists. After you enable clawback, it cannot reverted: the account permanently gains the ability to claw back issued assets on trust lines. +Clawback is disabled by default. To use clawback, you must send an [AccountSet transaction][] to enable the **Allow Trust Line Clawback** setting. An issuer with any existing tokens cannot enable clawback. You can only enable **Allow Trust Line Clawback** if you have a completely empty owner directory, meaning you must do so before you set up any trust lines, offers, escrows, payment channels, checks, or signer lists. After you enable clawback, it cannot reverted: the account permanently gains the ability to claw back issued assets on trust lines. _(Added by the [AMMClawback amendment][].)_ @@ -49,7 +49,7 @@ _(Added by the [AMMClawback amendment][].)_ | `Asset` | Object | Issue | Yes | Specifies the asset that the issuer wants to claw back from the AMM pool. The asset can be XRP, a token, or an MPT (see: [Specifying Without Amounts][]). The `issuer` field must match with `Account`. | | `Asset2` | Object | Issue | Yes | Specifies the other asset in the AMM's pool. The asset can be XRP, a token, or an MPT (see: [Specifying Without Amounts][]). | | `Amount` | [Currency Amount][] | Amount | No | The maximum amount to claw back from the AMM account. The `currency` and `issuer` subfields should match the `Asset` subfields. If this field isn't specified, or the `value` subfield exceeds the holder's available tokens in the AMM, all of the holder's tokens are clawed back. | -| `Holder` | String | AccountID | Yes | The account holding the asset to be clawed back. | +| `Holder` | String - [Address][] | AccountID | Yes | The account holding the asset to be clawed back. | ## AMMClawback Flags @@ -67,7 +67,7 @@ Besides errors that can occur for all transactions, `AMMClawback` transactions c |:-------------------|:------------| | `tecNO_PERMISSION` | Occurs if you attempt to claw back tokens from an AMM without the `lsfAllowTrustlineClawback` flag enabled, or the `tfClawTwoAssets` flag is enabled when you didn't issue both assets in the AMM. Also occurs if the `Asset` issuer doesn't match `Account`. | | `tecAMM_BALANCE` | Occurs if the `Holder` doesn't hold any LP tokens from the AMM pool. | -| `temDISABLED` | Occurs if the [AMMClawback amendment](#) is not enabled. | +| `temDISABLED` | Occurs if the [AMMClawback amendment][] is not enabled. | | `temBAD_AMOUNT` | Occurs if the `Amount` field in the `AMMClawback` transaction is less than or equal to 0, or the `currency` and `issuer` subfields don't match between `Amount` and `Asset`. | | `temINVALID_FLAG` | Occurs if you try enabling flags besides `tfClawTwoAssets`. | | `temMALFORMED` | Occurs if the `issuer` subfield doesn't match between `Asset` and `Account`, `Account` is the same as the `Holder`, or `Asset` is XRP. | diff --git a/docs/references/protocol/transactions/types/mptokenissuancecreate.md b/docs/references/protocol/transactions/types/mptokenissuancecreate.md index 8211cb3497..13a71e94ab 100644 --- a/docs/references/protocol/transactions/types/mptokenissuancecreate.md +++ b/docs/references/protocol/transactions/types/mptokenissuancecreate.md @@ -41,7 +41,11 @@ This example assumes that the issuer of the token is the signer of the transacti | `AssetScale` | Number | UInt8 | No | Where to put the decimal place when displaying amounts of this MPT. More formally, the asset scale is a non-negative integer (0, 1, 2, …) such that one standard unit equals 10^(-scale) of a corresponding fractional unit. For example, if a US Dollar Stablecoin has an asset scale of _2_, then 1 unit of that MPT would equal 0.01 US Dollars. This indicates to how many decimal places the MPT can be subdivided. If omitted, the default is 0, meaning that the MPT cannot be divided into smaller than 1 unit. | | `TransferFee` | Number | UInt16 | No | The value specifies the fee to charged by the issuer for secondary sales of the Token, if such sales are allowed. Valid values for this field are between 0 and 50,000 inclusive, allowing transfer rates of between 0.000% and 50.000% in increments of 0.001. The field _must not_ be present if the tfMPTCanTransfer flag is not set. If it is, the transaction should fail and a fee should be claimed. | | `MaximumAmount` | String - Number | UInt64 | No | The maximum asset amount of this token that can ever be issued, as a base-10 number encoded as a string. The current default maximum limit is 9,223,372,036,854,775,807 (2^63-1). _This limit may increase in the future. If an upper limit is required, you must specify this field._ | -| `MPTokenMetadata` | String - Hexadecimal | Blob | No | Arbitrary metadata about this issuance. The limit for this field is 1024 bytes. By convention, the metadata should decode to JSON data describing what the MPT represents. The [XLS-89d specification](https://github.com/XRPLF/XRPL-Standards/pull/293) defines a recommended format for metadata. | +| `MPTokenMetadata` | String - Hexadecimal | Blob | No | Arbitrary metadata about this issuance. The limit for this field is 1024 bytes. By convention, the metadata should decode to JSON data describing what the MPT represents. The [XLS-89 specification](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0089-multi-purpose-token-metadata-schema) defines a recommended format for metadata. | + +{% admonition type="success" name="Tip" %} +For an example of how to encode metadata for the `MPTokenMetadata` field, see {% repo-link path="_code-samples/issue-mpt-with-metadata/" %}Code Sample: Issue MPT with Metadata{% /repo-link %}. +{% /admonition %} ## MPTokenIssuanceCreate Flags @@ -56,4 +60,8 @@ Transactions of the MPTokenIssuanceCreate type support additional values in the | `tfMPTCanTransfer` | `0x00000020` | `32` | If set, indicates that tokens can be transferred to other accounts that are not the issuer. | | `tfMPTCanClawback` | `0x00000040` | `64` | If set, indicates that the issuer can use the `Clawback` transaction to claw back value from individual holders. | +## See Also + +- [MPTokenIssuance entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/mptokenissuancedestroy.md b/docs/references/protocol/transactions/types/mptokenissuancedestroy.md index 0242c45713..86ce008d50 100644 --- a/docs/references/protocol/transactions/types/mptokenissuancedestroy.md +++ b/docs/references/protocol/transactions/types/mptokenissuancedestroy.md @@ -32,4 +32,8 @@ _(Requires the [MPTokensV1 amendment][] {% not-enabled /%}.)_ |:--------------------|:--------------------|:------------------|:-------------------| | `MPTokenIssuanceID` | String | UInt192 | Identifies the `MPTokenIssuance` object to be removed by the transaction. | +## See Also + +- [MPTokenIssuance entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/mptokenissuanceset.md b/docs/references/protocol/transactions/types/mptokenissuanceset.md index f8117b9dd9..802d015d72 100644 --- a/docs/references/protocol/transactions/types/mptokenissuanceset.md +++ b/docs/references/protocol/transactions/types/mptokenissuanceset.md @@ -39,4 +39,8 @@ Transactions of the `MPTokenIssuanceSet` type support additional values in the ` | `tfMPTLock` | `0x00000001` | 1 | Enable to lock balances of this MPT issuance. | | `tfMPTUnlock` | `0x00000002` | 2 | Enable to unlock balances of this MPT issuance. | +## See Also + +- [MPTokenIssuance entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/nftokenacceptoffer.md b/docs/references/protocol/transactions/types/nftokenacceptoffer.md index 69cf356b54..76844651ca 100644 --- a/docs/references/protocol/transactions/types/nftokenacceptoffer.md +++ b/docs/references/protocol/transactions/types/nftokenacceptoffer.md @@ -103,4 +103,8 @@ Besides errors that can occur for all transactions, {% $frontmatter.seo.title %} | `tecNFTOKEN_OFFER_TYPE_MISMATCH` | The object identified by the `NFTokenBuyOffer` is not actually a buy offer, or the object identified by the `NFTokenSellOffer` is not actually a sell offer. | | `tecNO_PERMISSION` | The seller does not own the `NFToken` being sold; or the matching offer specifies a different `Destination` account than the account accepting the offer. | +## See Also + +- [NFTokenOffer entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/nftokencanceloffer.md b/docs/references/protocol/transactions/types/nftokencanceloffer.md index 088cd19961..34e88fe5a2 100644 --- a/docs/references/protocol/transactions/types/nftokencanceloffer.md +++ b/docs/references/protocol/transactions/types/nftokencanceloffer.md @@ -57,4 +57,8 @@ Besides errors that can occur for all transactions, {% $frontmatter.seo.title %} | `temMALFORMED` | The transaction was not validly formatted. For example, the `NFTokenOffers` array was empty or contained more than the maximum number of offers that can be canceled at one time. | | `tecNO_PERMISSION` | At least one of the IDs in the `NFTokenOffers` field refers to an object that cannot be canceled. For example, the sender of this transaction is not the owner or `Destination` of the offer, or the object was not an `NFTokenOffer` type object. | +## See Also + +- [NFTokenOffer entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/nftokencreateoffer.md b/docs/references/protocol/transactions/types/nftokencreateoffer.md index dce51f18d5..42504d0492 100644 --- a/docs/references/protocol/transactions/types/nftokencreateoffer.md +++ b/docs/references/protocol/transactions/types/nftokencreateoffer.md @@ -68,4 +68,8 @@ Besides errors that can occur for all transactions, {% $frontmatter.seo.title %} | `tecUNFUNDED_OFFER` | For a buy offer, the sender does have the funds specified in the `Amount` field available. If the `Amount` is XRP, this could be due to the reserve requirement; if the `Amount` is denominated in fungible tokens, this could be because they are [frozen](../../../../concepts/tokens/fungible-tokens/freezes.md). | | `tefNFTOKEN_IS_NOT_TRANSFERABLE` | The `NFToken` has the [`lsfTransferable` flag](../../data-types/nftoken.md#nftoken-flags) disabled and this transaction would not transfer the `NFToken` to or from the issuer. | +## See Also + +- [NFTokenOffer entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/offercancel.md b/docs/references/protocol/transactions/types/offercancel.md index 9277e2b0b6..69cfd36de1 100644 --- a/docs/references/protocol/transactions/types/offercancel.md +++ b/docs/references/protocol/transactions/types/offercancel.md @@ -36,4 +36,8 @@ An OfferCancel transaction removes an Offer object from the XRP Ledger. The OfferCancel method returns [`tesSUCCESS`](../transaction-results/tes-success.md) even if it did not find an offer with the matching sequence number. +## See Also + +- [Offer entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/offercreate.md b/docs/references/protocol/transactions/types/offercreate.md index 7a6c9783db..70f5f0e087 100644 --- a/docs/references/protocol/transactions/types/offercreate.md +++ b/docs/references/protocol/transactions/types/offercreate.md @@ -77,4 +77,8 @@ Transactions of the OfferCreate type support additional values in the [`Flags` f | `temINVALID_FLAG` | The transaction specifies an invalid flag combination, such as both `tfImmediateOrCancel` and `tfFillOrKill`, or the transaction uses `tfHybrid` but omits the `DomainID` field. | | `temREDUNDANT` | The transaction would trade a token for the same token (same issuer and currency code). | +## See Also + +- [Offer entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/oracledelete.md b/docs/references/protocol/transactions/types/oracledelete.md index cdfb6a5a13..8f6e6dedbf 100644 --- a/docs/references/protocol/transactions/types/oracledelete.md +++ b/docs/references/protocol/transactions/types/oracledelete.md @@ -41,4 +41,8 @@ Besides errors that can occur for all transactions, `OracleDelete` transactions |---------------|-------------| | `tecNO_ENTRY` | The `Oracle` object doesn't exist. | +## See Also + +- [Oracle entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/oracleset.md b/docs/references/protocol/transactions/types/oracleset.md index 1453b6447f..9518b1bc8d 100644 --- a/docs/references/protocol/transactions/types/oracleset.md +++ b/docs/references/protocol/transactions/types/oracleset.md @@ -90,4 +90,8 @@ Besides errors that can occur for all transactions, `OracleSet` transactions can | `tecARRAY_EMPTY` | The `PriceDataSeries` has no `PriceData` objects. | | `temARRAY_TOO_LARGE` | The `PriceDataSeries` exceeds the ten `PriceData` objects limit. | +## See Also + +- [Oracle entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/paymentchannelclaim.md b/docs/references/protocol/transactions/types/paymentchannelclaim.md index e148708d0b..415ef1bd8f 100644 --- a/docs/references/protocol/transactions/types/paymentchannelclaim.md +++ b/docs/references/protocol/transactions/types/paymentchannelclaim.md @@ -70,4 +70,8 @@ Transactions of the `PaymentChannelClaim` type support additional values in the | `tfRenew` | `0x00010000` | 65536 | Clear the channel's `Expiration` time. (`Expiration` is different from the channel's immutable `CancelAfter` time.) Only the source address of the payment channel can use this flag. | | `tfClose` | `0x00020000` | 131072 | Request to close the channel. Only the channel source and destination addresses can use this flag. This flag closes the channel immediately if it has no more XRP allocated to it after processing the current claim, or if the destination address uses it. If the source address uses this flag when the channel still holds XRP, this schedules the channel to close after `SettleDelay` seconds have passed. (Specifically, this sets the `Expiration` of the channel to the close time of the previous ledger plus the channel's `SettleDelay` time, unless the channel already has an earlier `Expiration` time.) If the destination address uses this flag when the channel still holds XRP, any XRP that remains after processing the claim is returned to the source address. | +## See Also + +- [PayChannel entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/paymentchannelcreate.md b/docs/references/protocol/transactions/types/paymentchannelcreate.md index 55acc9e348..4fcdbc9c59 100644 --- a/docs/references/protocol/transactions/types/paymentchannelcreate.md +++ b/docs/references/protocol/transactions/types/paymentchannelcreate.md @@ -43,4 +43,8 @@ _(Added by the [PayChan amendment][].)_ If the `Destination` account is blocking incoming payment channels, the transaction fails with result code `tecNO_PERMISSION`. _(Requires the [DisallowIncoming amendment][] )_ +## See Also + +- [PayChannel entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/references/protocol/transactions/types/paymentchannelfund.md b/docs/references/protocol/transactions/types/paymentchannelfund.md index 6ad7e0c127..48a0c9a187 100644 --- a/docs/references/protocol/transactions/types/paymentchannelfund.md +++ b/docs/references/protocol/transactions/types/paymentchannelfund.md @@ -47,4 +47,8 @@ Besides errors that can occur for all transactions, {% $frontmatter.seo.title %} | `temBAD_AMOUNT` | The `Amount` field of the transaction is invalid. The amount must either be XRP or fungible tokens and cannot be zero or negative. | | `temBAD_EXPIRATION` | The `Expiration` field is invalid. | +## See Also + +- [PayChannel entry][] + {% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/tutorials/go/build-apps/get-started.md b/docs/tutorials/go/build-apps/get-started.md new file mode 100644 index 0000000000..6ba4f0d090 --- /dev/null +++ b/docs/tutorials/go/build-apps/get-started.md @@ -0,0 +1,151 @@ +--- +seo: + description: Build a Go application that interacts with the XRP Ledger. +labels: + - Development +--- + +# Get Started Using Go Library + +This tutorial walks you through the basics of building an XRP Ledger-connected application using [`xrpl-go`](https://github.com/Peersyst/xrpl-go), a pure Go library built to interact with the XRP Ledger. + +This tutorial is intended for beginners and should take no longer than 30 minutes to complete. + +## Learning Goals + +In this tutorial, you'll learn: + +- The basic building blocks of XRP Ledger-based applications. +- How to connect to the XRP Ledger using `xrpl-go`. +- How to get an account on the [Testnet](/resources/dev-tools/xrp-faucets) using `xrpl-go`. +- How to use the `xrpl-go` library to look up information about an account on the XRP Ledger. + +## Requirements + +To follow this tutorial, you should have Go version `1.22.0` or later installed. +[Download latest Go version](https://go.dev/dl/). + +## Installation + +The [`xrpl-go` library](https://github.com/Peersyst/xrpl-go) is available on [pkg.go.dev](https://pkg.go.dev/github.com/Peersyst/xrpl-go). + +Start a new project (or use an existing one) and install the `xrpl-go` library via Go modules: + +```bash +# Initialize your module (if you haven't already) +go mod init your-module-name + +# Fetch the latest version of xrpl-go +go get -u github.com/Peersyst/xrpl-go +``` + +## Start Building + +When you're working with the XRP Ledger, there are a few things you'll need to manage, whether you're adding XRP to your [account](../../../concepts/accounts/index.md), integrating with the [decentralized exchange](../../../concepts/tokens/decentralized-exchange/index.md), or [issuing tokens](../../../concepts/tokens/index.md). This tutorial walks you through basic patterns common to getting started with all of these use cases and provides sample code for implementing them. + +Here are the basic steps you'll need to cover for almost any XRP Ledger project: + +1. [Connect to the XRP Ledger.](#1.-connect-to-the-xrp-ledger) +2. [Get an account.](#2.-get-account) +3. [Query the XRP Ledger.](#3.-query-the-xrp-ledger) + +### 1. Connect to the XRP Ledger + +To make queries and submit transactions, you need to connect to the XRP Ledger. To do this with `xrpl-go`, you have two main options: + +1. Via WebSocket: + + {% code-snippet file="/_code-samples/get-started/go/base/ws/main.go" from="func main()" language="go" /%} + +2. Via RPC: + + {% code-snippet file="/_code-samples/get-started/go/base/rpc/main.go" from="func main()" language="go" /%} + +#### Connect to the production XRP Ledger + +The sample code in the previous section shows you how to connect to the Testnet, which is a [parallel network](../../../concepts/networks-and-servers/parallel-networks.md) for testing where the money has no real value. When you're ready to integrate with the production XRP Ledger, you'll need to connect to the Mainnet. You can do that in two ways: + +- By [installing the core server](../../../infrastructure/installation/index.md) (`rippled`) and running a node yourself. The core server connects to the Mainnet by default, but you can [change the configuration to use Testnet or Devnet](../../../infrastructure/configuration/connect-your-rippled-to-the-xrp-test-net.md). [There are good reasons to run your own core server](../../../concepts/networks-and-servers/index.md#reasons-to-run-your-own-server). If you run your own server, you can connect to it like so: + + ```go + import "github.com/Peersyst/xrpl-go/xrpl/websocket" + + const MY_SERVER = "ws://localhost:6006/" + + func main() { + client := websocket.NewClient(websocket.NewClientConfig().WithHost(MY_SERVER)) + + // ... custom code goes here + } + ``` + + See the example [core server config file](https://github.com/XRPLF/rippled/blob/c0a0b79d2d483b318ce1d82e526bd53df83a4a2c/cfg/rippled-example.cfg#L1562) for more information about default values. + +- By using one of the available [public servers][]: + + ```go + import "github.com/Peersyst/xrpl-go/xrpl/websocket" + + const PUBLIC_SERVER = "wss://xrplcluster.com/" + + func main() { + client := websocket.NewClient(websocket.NewClientConfig().WithHost(PUBLIC_SERVER)) + + // ... custom code goes here + } + ``` + +### 2. Get account + +In `xrpl-go`, account creation and key management live in the `wallet` package, and on Testnet you can use the built-in faucet provider on your WebSocket (or RPC) client to fund a brand-new account immediately. + +On Testnet, you can fund a new ED25519 account like this: + +```go +w, err := wallet.New(crypto.ED25519()) +if err != nil { + fmt.Println(err) + return +} +if err := client.FundWallet(&w); err != nil { + fmt.Println(err) + return +} +``` + +This constructor returns a Go `Wallet` value with the following fields: + +```go +type Wallet struct { + PublicKey string // the hex-encoded public key + PrivateKey string // the hex-encoded private key + ClassicAddress types.Address // the XRPL “r…” address + Seed string // the base58 seed +} +``` + +If you already have a seed encoded in [base58][], you can make a `Wallet` instance from it like this: + +```go + w, err := wallet.FromSeed("sn3nxiW7v8KXzPzAqzyHXbSSKNuN9", "") +``` + +### 3. Query the XRP Ledger + +You can query the XRP Ledger to get information about [a specific account](../../../references/http-websocket-apis/public-api-methods/account-methods/index.md), [a specific transaction](../../../references/http-websocket-apis/public-api-methods/transaction-methods/tx.md), the state of a [current or a historical ledger](../../../references/http-websocket-apis/public-api-methods/ledger-methods/index.md), and [the XRP Ledger's decentralized exchange](../../../references/http-websocket-apis/public-api-methods/path-and-order-book-methods/index.md). You need to make these queries, among other reasons, to look up account info to follow best practices for [reliable transaction submission](../../../concepts/transactions/reliable-transaction-submission.md). + +Use the Client's `Request()` method to access the XRP Ledger's [WebSocket API](../../../references/http-websocket-apis/api-conventions/request-formatting.md). For example: + +{% code-snippet file="/_code-samples/get-tx/go/main.go" from="// Get the latest validated ledger" language="go" /%} + +Or, use the getter methods from the [`websocket`](https://pkg.go.dev/github.com/Peersyst/xrpl-go@v0.1.12/xrpl/websocket) or [`rpc`](https://pkg.go.dev/github.com/Peersyst/xrpl-go@v0.1.12/xrpl/rpc) packages: + +{% code-snippet file="/_code-samples/get-started/go/get-acc-info/ws/main.go" from="// Get info from" before="// Get info about" language="go" /%} + +## Keep on Building + +Now that you know how to use `xrpl-go` to connect to the XRP Ledger, get an account, and look up information about it, you can also: + +- [Send XRP](../../how-tos/send-xrp.md). + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/tutorials/go/build-apps/index.md b/docs/tutorials/go/build-apps/index.md new file mode 100644 index 0000000000..7a95406085 --- /dev/null +++ b/docs/tutorials/go/build-apps/index.md @@ -0,0 +1,10 @@ +--- +metadata: + indexPage: true +--- + +# Build Applications with Go Library + +Build full-featured applications in Go. + +{% child-pages /%} diff --git a/docs/tutorials/go/index.md b/docs/tutorials/go/index.md new file mode 100644 index 0000000000..fe13267d5f --- /dev/null +++ b/docs/tutorials/go/index.md @@ -0,0 +1,21 @@ +--- +metadata: + indexPage: true +--- + +# Go + +You can create your own interface to try out the capabilities and support your specific business needs. These tutorials build a test harness interface to try out features of the XRP Ledger. + +Typically, the example functions involve four steps. + +- Connect to the XRP Ledger and instantiate your wallet. +- Make changes to the XRP Ledger using transactions. +- Get the state of accounts and tokens on the XRP Ledger using requests. +- Disconnect from the XRP Ledger. + +Once familiar with the library functions, you can build sample applications in Go. We anticipate that the applications you build greatly improve upon these examples. Your feedback and contributions are most welcome. + +## Tutorial Modules + +{% child-pages /%} diff --git a/docs/tutorials/how-tos/send-xrp.md b/docs/tutorials/how-tos/send-xrp.md index b23e5e9191..e7242ea34d 100644 --- a/docs/tutorials/how-tos/send-xrp.md +++ b/docs/tutorials/how-tos/send-xrp.md @@ -28,7 +28,7 @@ To interact with the XRP Ledger, you need to set up a dev environment with the n - **Python** with the [`xrpl-py` library](https://xrpl-py.readthedocs.io/). See [Get Started using Python](../python/build-apps/get-started.md) for setup steps. - **Java** with the [xrpl4j library](https://github.com/XRPLF/xrpl4j). See [Get Started Using Java](../java/build-apps/get-started.md) for setup steps. - **PHP** with the [XRPL_PHP library](https://github.com/AlexanderBuzz/xrpl-php). See [Get Started Using PHP](../php/build-apps/get-started.md) for setup steps. - +- **Go** with the [xrpl-go library](https://github.com/Peersyst/xrpl-go). See [Get Started Using Go](../go/build-apps/get-started.md) for setup steps. ## Send a Payment on the Test Net @@ -54,6 +54,10 @@ To transact on the XRP Ledger, you need an address and secret key, and some XRP. {% code-snippet file="/_code-samples/send-xrp/php/send-xrp.php" from="// Example credentials" before="// Create" language="php" /%} {% /tab %} +{% tab label="Go" %} +{% code-snippet file="/_code-samples/send-xrp/go/ws/main.go" from="// Example credentials" before="// Funding" language="go" /%} +{% /tab %} + {% /tabs %} The secret key shown here is for example only. For development purposes, you can get your own credentials, pre-funded with XRP, on the Testnet using the following interface: @@ -87,6 +91,10 @@ The following code connects to a public Testnet servers: {% code-snippet file="/_code-samples/send-xrp/php/send-xrp.php" from="// Create a client" before="// Transaction definition" language="php" /%} {% /tab %} +{% tab label="Go" %} +{% code-snippet file="/_code-samples/send-xrp/go/ws/main.go" from="func main()" before="if !client.IsConnected() " language="go" /%} +{% /tab %} + {% /tabs %} For this tutorial, click the following button to connect: @@ -142,6 +150,10 @@ Here's an example of preparing the above payment: {% code-snippet file="/_code-samples/send-xrp/php/send-xrp.php" from="// Transaction definition" before="// Sign" language="php" /%} {% /tab %} +{% tab label="Go" %} +{% code-snippet file="/_code-samples/send-xrp/go/ws/main.go" from="// Prepare " before="// Sign" language="go" /%} +{% /tab %} + {% /tabs %} {% interactive-block label="Prepare" steps=$frontmatter.steps %} @@ -172,6 +184,7 @@ Signing a transaction uses your credentials to authorize the transaction on your - **Python:** Use the [`xrpl.transaction.safe_sign_transaction()` method](https://xrpl-py.readthedocs.io/en/latest/source/xrpl.transaction.html#xrpl.transaction.safe_sign_transaction) with a model and `Wallet` object. - **Java:** Use a [`SignatureService`](https://javadoc.io/doc/org.xrpl/xrpl4j-crypto-core/latest/org/xrpl/xrpl4j/crypto/signing/SignatureService.html) instance to sign the transaction. For this tutorial, use the [`SingleKeySignatureService`](https://javadoc.io/doc/org.xrpl/xrpl4j-crypto-bouncycastle/latest/org/xrpl/xrpl4j/crypto/signing/SingleKeySignatureService.html). - **PHP:** Use a [`sign()` method of a `Wallet` instance](https://alexanderbuzz.github.io/xrpl-php-docs/wallet.html#signing-a-transaction) instance to sign the transaction. The input to this step is a completed array of transaction instructions. +- **Go:** Use the [`Sign()` method of the `Wallet` package](https://pkg.go.dev/github.com/Peersyst/xrpl-go@v0.1.12/xrpl/wallet) to sign the transaction. {% tabs %} @@ -191,6 +204,10 @@ Signing a transaction uses your credentials to authorize the transaction on your {% code-snippet file="/_code-samples/send-xrp/php/send-xrp.php" from="// Sign" before="// Submit" language="php" /%} {% /tab %} +{% tab label="Go" %} +{% code-snippet file="/_code-samples/send-xrp/go/ws/main.go" from="// Sign" before="// Submit" language="go" /%} +{% /tab %} + {% /tabs %} The result of the signing operation is a transaction object containing a signature. Typically, XRP Ledger APIs expect a signed transaction to be the hexadecimal representation of the transaction's canonical [binary format](../../references/protocol/binary-format.md), called a "blob". @@ -199,6 +216,7 @@ The result of the signing operation is a transaction object containing a signatu - In `xrpl-py`, you can get the transaction's hash in the response to submitting it in the next step. - In xrpl4j, `SignatureService.sign` returns a `SignedTransaction`, which contains the transaction's hash, which you can use to look up the transaction later. - In `XRPL_PHP`, the signing API also returns the transaction's ID, or identifying hash, which you can use to look up the transaction later. This is a 64-character hexadecimal string that is unique to this transaction. +- In `xrpl-go`, the signing API also returns the transaction's ID, or identifying hash, which you can use to look up the transaction later. This is a 64-character hexadecimal string that is unique to this transaction. {% interactive-block label="Sign" steps=$frontmatter.steps %} @@ -217,6 +235,7 @@ Now that you have a signed transaction, you can submit it to an XRP Ledger serve - **Python:** Use the [`xrpl.transaction.submit_and_wait()` method](https://xrpl-py.readthedocs.io/en/stable/source/xrpl.transaction.html#xrpl.transaction.submit_and_wait) to submit a transaction to the network and wait for a response. - **Java:** Use the [`XrplClient.submit(SignedTransaction)` method](https://javadoc.io/doc/org.xrpl/xrpl4j-client/latest/org/xrpl/xrpl4j/client/XrplClient.html#submit(org.xrpl.xrpl4j.crypto.signing.SignedTransaction)) to submit a transaction to the network. Use the [`XrplClient.ledger()`](https://javadoc.io/doc/org.xrpl/xrpl4j-client/latest/org/xrpl/xrpl4j/client/XrplClient.html#ledger(org.xrpl.xrpl4j.model.client.ledger.LedgerRequestParams)) method to get the latest validated ledger index. - **PHP:** Use the [`submitAndWait()` method of the Client](https://alexanderbuzz.github.io/xrpl-php-docs/client.html) to submit a transaction to the network and wait for the response. +- **Go:** Use [`SubmitTxAndWait()` or `SubmitTxBlobAndWait()` methods os the Client](https://pkg.go.dev/github.com/Peersyst/xrpl-go@v0.1.12/xrpl/websocket#Client.SubmitTxAndWait) to submit a transaction to the network and wait for the response. {% tabs %} @@ -236,6 +255,10 @@ Now that you have a signed transaction, you can submit it to an XRP Ledger serve {% code-snippet file="/_code-samples/send-xrp/php/send-xrp.php" from="// Submit" before="// Wait" language="php" /%} {% /tab %} +{% tab label="Go" %} +{% code-snippet file="/_code-samples/send-xrp/go/ws/main.go" from="// Submit" before="// Wait" language="go" /%} +{% /tab %} + {% /tabs %} This method returns the **tentative** result of trying to apply the transaction to the open ledger. This result _can_ change when the transaction is included in a validated ledger: transactions that succeed initially might ultimately fail, and transactions that fail initially might ultimately succeed. Still, the tentative result often matches the final result, so it's OK to get excited if you see `tesSUCCESS` here. 😁 @@ -273,6 +296,8 @@ Most transactions are accepted into the next ledger version after they're submit - **PHP:** If you used the [`.submitAndWait()` method](https://alexanderbuzz.github.io/xrpl-php-docs/client.html), you can wait until the returned Promise resolves. Other, more asynchronous approaches are also possible. +- **Go:** If you used the `SubmitTxAndWait()` or `SubmitTxBlobAndWait()` methods, the client will handle submission and wait until the transaction is confirmed in a ledger. Internally, these methods use a polling mechanism, querying the transaction status with the client's `Request()` method and a `TxRequest`. + {% tabs %} {% tab label="JavaScript" %} @@ -291,6 +316,10 @@ Most transactions are accepted into the next ledger version after they're submit {% code-snippet file="/_code-samples/send-xrp/php/send-xrp.php" from="// Wait" before="// Check" language="php" /%} {% /tab %} +{% tab label="Go" %} +{% code-snippet file="/_code-samples/send-xrp/go/ws/main.go" from="// Wait" before="// Check" language="go" /%} +{% /tab %} + {% /tabs %} {% partial file="/docs/_snippets/interactive-tutorials/wait-step.md" /%} @@ -310,6 +339,8 @@ To know for sure what a transaction did, you must look up the outcome of the tra - **PHP:** Use the response from `submitAndWait()` or call the `tx method` using [`$client->syncRequest()`](https://alexanderbuzz.github.io/xrpl-php-docs/client.html). +- **Go:** Use the response from `SubmitTxAndWait()` or `SubmitTxBlobAndWait()`, or manually query the transaction status using a `TxRequest` with the client's `Request()` method. + {% tabs %} {% tab label="JavaScript" %} @@ -328,6 +359,10 @@ To know for sure what a transaction did, you must look up the outcome of the tra {% code-snippet file="/_code-samples/send-xrp/php/send-xrp.php" from="// Check" language="php" /%} {% /tab %} +{% tab label="Go" %} +{% code-snippet file="/_code-samples/send-xrp/go/ws/main.go" from="// Check" language="go" /%} +{% /tab %} + {% /tabs %} {% admonition type="warning" name="Caution" %}XRP Ledger APIs may return tentative results from ledger versions that have not yet been validated. For example, in [tx method][] response, be sure to look for `"validated": true` to confirm that the data comes from a validated ledger version. Transaction results that are not from a validated ledger version are subject to change. For more information, see [Finality of Results](../../concepts/transactions/finality-of-results/index.md).{% /admonition %} @@ -391,6 +426,16 @@ print_r("Seed: " . $wallet->getSeed()); // Example: sp6JS7f14BuwFY8Mw6bTtLKWauoU ``` {% /tab %} +{% tab label="Go" %} + +```go +wallet, err := wallet.New(crypto.ED25519()) +fmt.Println("Classic Address:", wallet.ClassicAddress) // Example: r9ESeQQswbTxV8neiDTLTHXbXfUwiihyJk +fmt.Println("Seed:", wallet.Seed) // Example: sEd7XGFGSWteam777HQHvw7vHypEWy2 + +``` +{% /tab %} + {% /tabs %} {% admonition type="danger" name="Warning" %}You should only use an address and secret that you generated securely, on your local machine. If another computer generated the address and secret and sent it to you over a network, it's possible that someone else on the network may see that information. If they do, they'll have as much control over your XRP as you do. It's also recommended not to use the same address for the Testnet and Mainnet, because transactions that you created for use on one network could also be valid to execute on the other network, depending on the parameters you provided.{% /admonition %} @@ -433,6 +478,20 @@ $client = new JsonRpcClient("https://xrplcluster.com"); ``` {% /tab %} +{% tab label="Go" %} + +```go +client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("wss://xrplcluster.com") +) +if err := client.Connect(); err != nil { + fmt.Println(err) + return +} +``` +{% /tab %} + {% /tabs %} If you [install `rippled`](../../infrastructure/installation/index.md) yourself, it connects to the production network by default. (You can also [configure it to connect to the test net](../../infrastructure/configuration/connect-your-rippled-to-the-xrp-test-net.md) instead.) After the server has synced (typically within about 15 minutes of starting it up), you can connect to it locally, which has [various benefits](../../concepts/networks-and-servers/index.md). The following example shows how to connect to a server running the default configuration: @@ -469,6 +528,20 @@ $client = new JsonRpcClient("http://localhost:5005"); ``` {% /tab %} +{% tab label="Go" %} + +```go +client := websocket.NewClient( + websocket.NewClientConfig(). + WithHost("ws://localhost:6006") +) +if err := client.Connect(); err != nil { + fmt.Println(err) + return +} +``` +{% /tab %} + {% /tabs %} {% admonition type="success" name="Tip" %}The local connection uses an unencrypted protocol (`ws` or `http`) rather than the TLS-encrypted version (`wss` or `https`). This is secure only because the communications never leave the same machine, and is easier to set up because it does not require a TLS certificate. For connections on an outside network, always use `wss` or `https`.{% /admonition %} diff --git a/docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/send-a-time-held-escrow.md b/docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/send-a-time-held-escrow.md index 418f399fa7..3f82e9c66e 100644 --- a/docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/send-a-time-held-escrow.md +++ b/docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/send-a-time-held-escrow.md @@ -128,7 +128,6 @@ Response: [Sign and submit](../../../../concepts/transactions/index.md#signing-and-submitting-transactions) an [EscrowFinish transaction][] to execute the release of the funds after the `FinishAfter` time has passed. Set the `Owner` field of the transaction to the `Account` address from the EscrowCreate transaction, and the `OfferSequence` to the `Sequence` number from the EscrowCreate transaction. For an escrow held only by time, omit the `Condition` and `Fulfillment` fields. -***TODO: First half of this statement is covered by concept info already. It's also reiterated in escrow.md. The second portion about potential recipients should remain.*** {% admonition type="success" name="Tip" %} The EscrowFinish transaction is necessary because the XRP Ledger's state can only be modified by transactions. The sender of this transaction may be the recipient of the escrow, the original sender of the escrow, or any other XRP Ledger address. {% /admonition %} diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md index 124aa5c2b3..8fb00320f3 100644 --- a/docs/tutorials/index.md +++ b/docs/tutorials/index.md @@ -16,7 +16,7 @@ These tutorials walk you through the basics of building a very simple XRP Ledger {% xrpl-card title="Python" body="Using xrpl.py, a pure Python library." href="/docs/tutorials/python/" image="/img/logos/python.svg" imageAlt="Python logo" /%} -
+{% xrpl-card title="Go" body="Using xrpl-go, a pure Go library." href="/docs/tutorials/go/" image="/img/logos/golang.svg" imageAlt="Go logo" /%} {% xrpl-card title="Java" body="Using xrpl4j, a pure Java library." href="/docs/tutorials/java/" image="/img/logos/java.svg" imageAlt="Java logo" /%} diff --git a/docs/tutorials/javascript/build-apps/get-started.md b/docs/tutorials/javascript/build-apps/get-started.md index d82acff87e..48624842b3 100644 --- a/docs/tutorials/javascript/build-apps/get-started.md +++ b/docs/tutorials/javascript/build-apps/get-started.md @@ -1,6 +1,4 @@ --- -html: get-started-using-javascript-library.html -parent: javascript.html seo: description: Build an entry-level JavaScript application for querying the XRP Ledger. top_nav_name: JavaScript @@ -9,30 +7,74 @@ labels: - Development showcase_icon: assets/img/logos/javascript.svg --- + +{% code-walkthrough + filesets=[ + { + "files": ["/_code-samples/get-started/js/get-acct-info.js"], + "downloadAssociatedFiles": ["/_code-samples/get-started/js/package.json", "/_code-samples/get-started/js/get-acct-info.js", "/_code-samples/get-started/js/README.md"], + "when": { "environment": "Node" } + }, + { + "files": ["/_code-samples/get-started/js/index.html"], + "downloadAssociatedFiles": ["/_code-samples/get-started/js/index.html", "/_code-samples/get-started/js/README.md"], + "when": { "environment": "Web" } + } + ] + filters={ + "environment": { + "label": "Environment", + "items": [ + { "value": "Node" }, + { "value": "Web" }, + ] + } + } +%} + # Get Started Using JavaScript Library -This tutorial guides you through the basics of building an XRP Ledger-connected application in JavaScript or TypeScript using the [`xrpl.js`](https://github.com/XRPLF/xrpl.js/) client library in either Node.js or web browsers. +This tutorial guides you through the basics of building an XRP Ledger-connected application in JavaScript using the [`xrpl.js`](https://github.com/XRPLF/xrpl.js/) client library in either Node.js or web browsers. -The scripts and config files used in this guide are {% repo-link path="_code-samples/get-started/js/" %}available in this website's GitHub Repository{% /repo-link %}. - - -## Learning Goals +## Goals In this tutorial, you'll learn: -* The basic building blocks of XRP Ledger-based applications. -* How to connect to the XRP Ledger using `xrpl.js`. -* How to get an account on the [Testnet](/resources/dev-tools/xrp-faucets) using `xrpl.js`. -* How to use the `xrpl.js` library to look up information about an account on the XRP Ledger. -* How to put these steps together to create a JavaScript app or web-app. +- The basic building blocks of XRP Ledger-based applications. +- How to connect to the XRP Ledger using `xrpl.js`. +- How to get an account on the [Testnet](/resources/dev-tools/xrp-faucets) using `xrpl.js`. +- How to use the `xrpl.js` library to look up information about an account on the XRP Ledger. +- How to put these steps together to create a JavaScript app or web-app. +## Prerequisites -## Requirements +To complete this tutorial, you should meet the following guidelines: -To follow this tutorial, you should have some familiarity with writing code in JavaScript and managing small JavaScript projects. In browsers, any modern web browser with JavaScript support should work fine. In Node.js, **version 14** is recommended. Node.js versions 12 and 16 are also regularly tested. +- Have some familiarity with writing code in JavaScript. +- Have installed Node.js **version 20** or later in your development environment. +- If you want to build a web application, any modern web browser with JavaScript support should work fine. +## Source Code -## Install with npm +Click **Download** on the top right of the code preview panel to download the source code. + +## Steps + +Follow the steps to create a simple application with `xrpl.js`. + +### 1. Install Dependencies + + +{% step id="import-web-tag" when={ "environment": "Web" } %} +To load `xrpl.js` into your project, add a ` -``` - -You can load the library from a CDN as in the above example, or download a release and host it on your own website. - -This loads the module into the top level as `xrpl`. - -#### Node.js - -Add the library using [npm](https://www.npmjs.com/). This updates your `package.json` file, or creates a new one if it didn't already exist: - -```sh -npm install xrpl -``` - -Then import the library: - -```js -const xrpl = require("xrpl") -``` +Your `package.json` file should look something like this: +{% code-snippet file="/_code-samples/get-started/js/package.json" language="json" /%} +{% /step %} ### 2. Connect to the XRP Ledger +{% step id="connect-tag" %} +#### Connect to the XRP Ledger Testnet + To make queries and submit transactions, you need to connect to the XRP Ledger. To do this with `xrpl.js`, you create an instance of the `Client` class and use the `connect()` method. {% admonition type="success" name="Tip" %}Many network functions in `xrpl.js` use [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to return values asynchronously. The code samples here use the [`async/await` pattern](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await) to wait for the actual result of the Promises.{% /admonition %} -{% code-snippet file="/_code-samples/get-started/js/base.js" language="js" /%} +The sample code shows you how to connect to the Testnet, which is one of the available [parallel networks](../../../concepts/networks-and-servers/parallel-networks.md). +{% /step %} +{% step id="connect-mainnet-tag"%} #### Connect to the XRP Ledger Mainnet -The sample code in the previous section shows you how to connect to the Testnet, which is one of the available [parallel networks](../../../concepts/networks-and-servers/parallel-networks.md). When you're ready to move to production, you'll need to connect to the XRP Ledger Mainnet. You can do that in two ways: + When you're ready to move to production, you'll need to connect to the XRP Ledger Mainnet. You can do that in two ways: -* By [installing the core server](../../../infrastructure/installation/index.md) (`rippled`) and running a node yourself. The core server connects to the Mainnet by default, but you can [change the configuration to use Testnet or Devnet](../../../infrastructure/configuration/connect-your-rippled-to-the-xrp-test-net.md). [There are good reasons to run your own core server](../../../concepts/networks-and-servers/index.md#reasons-to-run-your-own-server). If you run your own server, you can connect to it like so: +- By [installing the core server](../../../infrastructure/installation/index.md) (`rippled`) and running a node yourself. The core server connects to the Mainnet by default, but you can [change the configuration to use Testnet or Devnet](../../../infrastructure/configuration/connect-your-rippled-to-the-xrp-test-net.md). [There are good reasons to run your own core server](../../../concepts/networks-and-servers/index.md#reasons-to-run-your-own-server). If you run your own server, you can connect to it like so: - ``` + ```javascript const MY_SERVER = "ws://localhost:6006/" const client = new xrpl.Client(MY_SERVER) await client.connect() @@ -106,55 +116,185 @@ The sample code in the previous section shows you how to connect to the Testnet, See the example [core server config file](https://github.com/XRPLF/rippled/blob/c0a0b79d2d483b318ce1d82e526bd53df83a4a2c/cfg/rippled-example.cfg#L1562) for more information about default values. -* By using one of the available [public servers][]: +- By using one of the available [public servers][]: - ``` + ```javascript const PUBLIC_SERVER = "wss://xrplcluster.com/" const client = new xrpl.Client(PUBLIC_SERVER) await client.connect() ``` - +{% /step %} ### 3. Get Account -The `xrpl.js` library has a `Wallet` class for handling the keys and address of an XRP Ledger account. On Testnet, you can fund a new account like this: +{% step id="get-account-create-wallet-tag" %} +#### Create and Fund a Wallet -{% code-snippet file="/_code-samples/get-started/js/get-acct-info.js" from="// Create a wallet" before="// Get info" language="js" /%} +The `xrpl.js` library has a `Wallet` class for handling the keys and address of an XRP Ledger account. On Testnet, you can fund a new account as shown in the example. +{% /step %} -If you only want to generate keys, you can create a new `Wallet` instance like this: +{% step id="get-account-create-wallet-b-tag" %} +#### (Optional) Generate a Wallet Only -```js -const test_wallet = xrpl.Wallet.generate() -``` +If you want to generate a wallet without funding it, you can create a new `Wallet` instance. Keep in mind that you need to send XRP to the wallet for it to be a valid account on the ledger. +{% /step %} -Or, if you already have a seed encoded in [base58][], you can make a `Wallet` instance from it like this: +{% step id="get-account-create-wallet-c-tag" %} +#### (Optional) Use Your Own Wallet Seed -```js -const test_wallet = xrpl.Wallet.fromSeed("sn3nxiW7v8KXzPzAqzyHXbSSKNuN9") // Test secret; don't use for real -``` +To use an existing wallet seed encoded in [base58][], you can create a `Wallet` instance from it. +{% /step %} ### 4. Query the XRP Ledger -Use the Client's `request()` method to access the XRP Ledger's [WebSocket API](../../../references/http-websocket-apis/api-conventions/request-formatting.md). For example: - -{% code-snippet file="/_code-samples/get-started/js/get-acct-info.js" from="// Get info" before="// Listen to ledger close events" language="js" /%} - +{% step id="query-xrpl-tag" %} +Use the Client's `request()` method to access the XRP Ledger's [WebSocket API](../../../references/http-websocket-apis/api-conventions/request-formatting.md). +{% /step %} ### 5. Listen for Events +{% step id="listen-for-events-tag" %} You can set up handlers for various types of events in `xrpl.js`, such as whenever the XRP Ledger's [consensus process](../../../concepts/consensus-protocol/index.md) produces a new [ledger version](../../../concepts/ledgers/index.md). To do that, first call the [subscribe method][] to get the type of events you want, then attach an event handler using the `on(eventType, callback)` method of the client. +{% /step %} -{% code-snippet file="/_code-samples/get-started/js/get-acct-info.js" from="// Listen to ledger close events" before="// Disconnect when done" language="js" /%} +### 6. Disconnect +{% step id="disconnect-node-tag" when={ "environment": "Node" } %} +Disconnect when done so Node.js can end the process. The example code waits 10 seconds before disconnecting to allow time for the ledger event listener to receive and display events. +{% /step %} -## Keep on Building +{% step id="disconnect-web-tag" when={ "environment": "Web" } %} +Disconnect from the ledger when done. The example code waits 10 seconds before disconnecting to allow time for the ledger event listener to receive and display events. +{% /step %} -Now that you know how to use `xrpl.js` to connect to the XRP Ledger, get an account, and look up information about it, you can also: +### 7. Run the Application -* [Send XRP](../../how-tos/send-xrp.md). -* [Issue a Fungible Token](../../how-tos/use-tokens/issue-a-fungible-token.md) -* [Set up secure signing](../../../concepts/transactions/secure-signing.md) for your account. +{% step id="run-app-node-tag" when={ "environment": "Node" } %} +Finally, in your terminal, run the application like so: +```sh +node get-acct-info.js +``` + +You should see output similar to the following: + +```sh +Connected to Testnet + +Creating a new wallet and funding it with Testnet XRP... +Wallet: rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i +Balance: 10 + +Account Testnet Explorer URL: +https://testnet.xrpl.org/accounts/rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i + +Getting account info... +{ + "api_version": 2, + "id": 4, + "result": { + "account_data": { + "Account": "rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i", + "Balance": "10000000", + "Flags": 0, + "LedgerEntryType": "AccountRoot", + "OwnerCount": 0, + "PreviousTxnID": "0FF9DB2FE141DD0DF82566A171B6AF70BB2C6EB6A53D496E65D42FC062C91A78", + "PreviousTxnLgrSeq": 9949268, + "Sequence": 9949268, + "index": "4A9C9220AE778DC38C004B2B17A08E218416D90E01456AFCF844C18838B36D01" + }, + "account_flags": { + "allowTrustLineClawback": false, + "defaultRipple": false, + "depositAuth": false, + "disableMasterKey": false, + "disallowIncomingCheck": false, + "disallowIncomingNFTokenOffer": false, + "disallowIncomingPayChan": false, + "disallowIncomingTrustline": false, + "disallowIncomingXRP": false, + "globalFreeze": false, + "noFreeze": false, + "passwordSpent": false, + "requireAuthorization": false, + "requireDestinationTag": false + }, + "ledger_hash": "304C7CC2A33B712BE43EB398B399E290C191A71FCB71784F584544DFB7C441B0", + "ledger_index": 9949268, + "validated": true + }, + "type": "response" +} + +Listening for ledger close events... +Ledger #9949269 validated with 0 transactions! +Ledger #9949270 validated with 0 transactions! +Ledger #9949271 validated with 0 transactions! + +Disconnected +``` +{% /step %} + +{% step id="run-app-web-tag" when={ "environment": "Web" } %} +Open the `index.html` file in a web browser. + +You should see output similar to the following: + +```text +Connected to Testnet +Creating a new wallet and funding it with Testnet XRP... +Wallet: rf7CWJdNssSzQk2GtypYLVhyvGe8oHS3S +Balance: 10 +View account on XRPL Testnet Explorer: rf7CWJdNssSzQk2GtypYLVhyvGe8oHS3S + +Getting account info... +{ + "api_version": 2, + "id": 5, + "result": { + "account_data": { + "Account": "rf7CWJdNssSzQk2GtypYLVhyvGe8oHS3S", + "Balance": "10000000", + "Flags": 0, + "LedgerEntryType": "AccountRoot", + "OwnerCount": 0, + "PreviousTxnID": "96E4B44F93EC0399B7ADD75489630C6A8DCFC922F20F6810D25490CC0D3AA12E", + "PreviousTxnLgrSeq": 9949610, + "Sequence": 9949610, + "index": "B5D2865DD4BF8EEDFEE2FD95DE37FC28D624548E9BBC42F9FBF61B618E98FAC8" + }, + "account_flags": { + "allowTrustLineClawback": false, + "defaultRipple": false, + "depositAuth": false, + "disableMasterKey": false, + "disallowIncomingCheck": false, + "disallowIncomingNFTokenOffer": false, + "disallowIncomingPayChan": false, + "disallowIncomingTrustline": false, + "disallowIncomingXRP": false, + "globalFreeze": false, + "noFreeze": false, + "passwordSpent": false, + "requireAuthorization": false, + "requireDestinationTag": false + }, + "ledger_hash": "7692673B8091899C3EEE6807F66B65851D3563F483A49A5F03A83608658473D6", + "ledger_index": 9949610, + "validated": true + }, + "type": "response" +} + +Listening for ledger close events... +Ledger #9949611 validated with 0 transactions +Ledger #9949612 validated with 1 transactions +Ledger #9949613 validated with 0 transactions + +Disconnected +``` +{% /step %} ## See Also @@ -163,6 +303,8 @@ Now that you know how to use `xrpl.js` to connect to the XRP Ledger, get an acco - [Client Libraries](../../../references/client-libraries.md) - **Tutorials:** - [Send XRP](../../how-tos/send-xrp.md) + - [Issue a Fungible Token](../../how-tos/use-tokens/issue-a-fungible-token.md) + - [Set up Secure Signing](../../../concepts/transactions/secure-signing.md) - **References:** - [`xrpl.js` Reference](https://js.xrpl.org/) - [Public API Methods](../../../references/http-websocket-apis/public-api-methods/index.md) @@ -171,3 +313,5 @@ Now that you know how to use `xrpl.js` to connect to the XRP Ledger, get an acco - [Transaction Formats](../../../references/protocol/transactions/index.md) {% raw-partial file="/docs/_snippets/common-links.md" /%} + +{% /code-walkthrough %} diff --git a/docs/use-cases/payments/index.page.tsx b/docs/use-cases/payments/index.page.tsx index 31074cf0a1..c9d5d001a0 100644 --- a/docs/use-cases/payments/index.page.tsx +++ b/docs/use-cases/payments/index.page.tsx @@ -43,7 +43,7 @@ const PaymentsPage: React.FC = () => { title: "Access Reliable Payments Infrastructure", contents: [ { - subtitle: "100% uptime since 2012", + subtitle: "99.99% uptime since 2012", description: "", }, { diff --git a/package-lock.json b/package-lock.json index c93596e5f1..5f2730f8ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3228,9 +3228,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz", + "integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", diff --git a/resources/dev-tools/components/AlertTemplate.tsx b/resources/dev-tools/components/AlertTemplate.tsx index 592309f9e9..b500b0444a 100644 --- a/resources/dev-tools/components/AlertTemplate.tsx +++ b/resources/dev-tools/components/AlertTemplate.tsx @@ -1,6 +1,6 @@ import clsx from 'clsx' -import * as React from 'react'; -import { useThemeHooks } from '@redocly/theme/core/hooks'; +import * as React from 'react' +import { useThemeHooks } from '@redocly/theme/core/hooks' const alertStyle = { position: "relative", @@ -30,7 +30,7 @@ interface AlertTemplateProps { } export default function AlertTemplate ({ message, options, style, close }: AlertTemplateProps): React.JSX.Element { - const { useTranslate } = useThemeHooks(); + const { useTranslate } = useThemeHooks() const { translate } = useTranslate() return(
diff --git a/resources/dev-tools/components/websocket-api/ClioOnly.tsx b/resources/dev-tools/components/websocket-api/ClioOnly.tsx new file mode 100644 index 0000000000..822592a0ca --- /dev/null +++ b/resources/dev-tools/components/websocket-api/ClioOnly.tsx @@ -0,0 +1,26 @@ +import { useThemeHooks } from '@redocly/theme/core/hooks'; + +export function ClioOnlyIcon () { + const { useTranslate } = useThemeHooks() + const { translate } = useTranslate() + return ( + + + + ) +} + +export function ClioOnlyNotice() { + const { useTranslate } = useThemeHooks() + const { translate } = useTranslate() + return ( + + + {translate("resources.dev-tools.websocket-api.clio-only-badge", " Clio only")} + + ) +} diff --git a/resources/dev-tools/components/websocket-api/curl-modal.tsx b/resources/dev-tools/components/websocket-api/curl-modal.tsx index fc718ff247..d1525f80b0 100644 --- a/resources/dev-tools/components/websocket-api/curl-modal.tsx +++ b/resources/dev-tools/components/websocket-api/curl-modal.tsx @@ -1,6 +1,6 @@ +import React, { useRef, useState } from 'react'; import { useThemeHooks } from '@redocly/theme/core/hooks'; import { Connection } from './types'; -import { useRef, useState } from 'react'; import { Modal, ModalClipboardBtn, ModalCloseBtn } from '../Modal'; interface CurlButtonProps { @@ -12,36 +12,18 @@ interface CurlProps extends CurlButtonProps{ closeCurlModal: () => void; } -const getCurl = function (currentBody, selectedConnection: Connection) { - let body; - try { - // change WS to JSON-RPC syntax - const params = JSON.parse(currentBody); - delete params.id; - const method = params.command; - delete params.command; - const body_json = { method: method, params: [params] }; - body = JSON.stringify(body_json, null, null); - } catch (e) { - alert("Can't provide curl format of invalid JSON syntax"); - return; - } - - const server = selectedConnection.jsonrpc_url; - - return `curl -H 'Content-Type: application/json' -d '${body}' ${server}`; -}; - export const CurlModal: React.FC = ({ - currentBody, - selectedConnection, + closeCurlModal, + currentBody, + selectedConnection, }) => { - const curlRef = useRef(null); const { useTranslate } = useThemeHooks(); const { translate } = useTranslate(); + const curlRef = useRef(null); + const footer = <> - {}} /> + return ( @@ -63,16 +45,16 @@ export const CurlModal: React.FC = ({ className="form-control" rows={8} ref={curlRef} - > - {getCurl(currentBody, selectedConnection)} - + value={getCurl(selectedConnection, currentBody)} + onChange={() => {}} + />
); }; -export const CurlButton = ({selectedConnection, currentBody}: CurlButtonProps) => { +export function CurlButton ({selectedConnection, currentBody}: CurlButtonProps) { const [showCurlModal, setShowCurlModal] = useState(false); const { useTranslate } = useThemeHooks(); const { translate } = useTranslate(); @@ -87,10 +69,32 @@ export const CurlButton = ({selectedConnection, currentBody}: CurlButtonProps) = > - {showCurlModal && setShowCurlModal(false)} - currentBody={currentBody} - selectedConnection={selectedConnection} - />} + {showCurlModal && ( + setShowCurlModal(false)} + currentBody={currentBody} + selectedConnection={selectedConnection} + /> + )} } + +function getCurl(selectedConnection: Connection, currentBody) { + let body : string; + try { + // change WS to JSON-RPC syntax + const params = JSON.parse(currentBody); + delete params.id; + const method = params.command; + delete params.command; + const body_json = { method: method, params: [params] }; + body = JSON.stringify(body_json, null, null); + } catch (e) { + alert("Can't provide curl format of invalid JSON syntax"); + return; + } + + const server = selectedConnection.jsonrpc_url; + + return `curl -H 'Content-Type: application/json' -d '${body}' ${server}`; +} diff --git a/resources/dev-tools/components/websocket-api/data/command-list.json b/resources/dev-tools/components/websocket-api/data/command-list.json index 6839b323c1..81bf44889a 100644 --- a/resources/dev-tools/components/websocket-api/data/command-list.json +++ b/resources/dev-tools/components/websocket-api/data/command-list.json @@ -4,7 +4,7 @@ "methods": [ { "name": "account_channels", - "description": "Returns information about an account's
payment channels.", + "description": "Returns information about an account's payment channels.", "link": "/docs/references/http-websocket-apis/public-api-methods/account-methods/account_channels", "body": { "command": "account_channels", @@ -414,7 +414,7 @@ "methods": [ { "name": "mpt_holders", - "description": "Return all holders of an MPT and their balance (Clio only).", + "description": "Return all holders of an MPT and their balance.", "link": "/docs/references/http-websocket-apis/public-api-methods/clio-methods/mpt_holders", "clio_only": true, "body": { @@ -431,7 +431,7 @@ "methods": [ { "name": "nft_history", - "description": "Get past transaction metadata for an NFT (Clio only).", + "description": "Get past transaction metadata for an NFT.", "link": "/docs/references/http-websocket-apis/public-api-methods/clio-methods/nft_history", "clio_only": true, "body": { @@ -442,7 +442,7 @@ }, { "name": "nft_info", - "description": "Get info about an NFT (Clio only).", + "description": "Get info about an NFT.", "clio_only": true, "link": "/docs/references/http-websocket-apis/public-api-methods/clio-methods/nft_info", "body": { @@ -453,7 +453,7 @@ }, { "name": "nfts_by_issuer", - "description": "Get a list of NFTs issued by a specific account, optionally filtered by taxon (Clio only).", + "description": "Get a list of NFTs issued by a specific account, optionally filtered by taxon.", "clio_only": true, "link": "/docs/references/http-websocket-apis/public-api-methods/clio-methods/nfts_by_issuer", "body": { @@ -468,18 +468,6 @@ { "group": "Payment Channel Methods", "methods": [ - { - "name": "channel_authorize", - "description": "Creates a signature that can be used to redeem a specific amount of XRP from a payment channel.", - "link": "/docs/references/http-websocket-apis/public-api-methods/payment-channel-methods/channel_authorize", - "body": { - "id": "channel_authorize_example_id1", - "command": "channel_authorize", - "channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3", - "secret": "s████████████████████████████", - "amount": "1000000" - } - }, { "name": "channel_verify", "description": "Checks the validity of a signature that can be used to redeem a specific amount of XRP from a payment channel.", diff --git a/resources/dev-tools/components/websocket-api/data/connections.json b/resources/dev-tools/components/websocket-api/data/connections.json index 1186fe5fab..4dfed06ca9 100644 --- a/resources/dev-tools/components/websocket-api/data/connections.json +++ b/resources/dev-tools/components/websocket-api/data/connections.json @@ -45,14 +45,14 @@ { "id": "connection-testnet-clio", "ws_url": "wss://clio.altnet.rippletest.net:51233/", - "jsonrpc-url": "https://clio.altnet.rippletest.net:51234/", + "jsonrpc_url": "https://clio.altnet.rippletest.net:51234/", "shortname": "Testnet-clio", "longname": "clio.altnet.rippletest.net (Testnet Public Cluster with Clio)" }, { "id": "connection-devnet-clio", "ws_url": "wss://clio.devnet.rippletest.net:51233/", - "jsonrpc-url": "https://clio.devnet.rippletest.net:51234/", + "jsonrpc_url": "https://clio.devnet.rippletest.net:51234/", "shortname": "Devnet-clio", "longname": "clio.devnet.rippletest.net (Devnet Public Cluster with Clio)" } diff --git a/resources/dev-tools/components/websocket-api/permalink-modal.tsx b/resources/dev-tools/components/websocket-api/permalink-modal.tsx index fd3c44d2f0..307d5172f2 100644 --- a/resources/dev-tools/components/websocket-api/permalink-modal.tsx +++ b/resources/dev-tools/components/websocket-api/permalink-modal.tsx @@ -9,7 +9,7 @@ interface PermaLinkButtonProps { } interface PermaLinkProps extends PermaLinkButtonProps { - closePermalinkModal: any; + closePermalinkModal: () => void; } const PermalinkModal: React.FC = ({ @@ -43,6 +43,7 @@ const PermalinkModal: React.FC = ({